Last active
December 26, 2015 12:18
-
-
Save Measter/7149728 to your computer and use it in GitHub Desktop.
CoreRL written on the DCPU-16.Requires the library at https://github.com/Measter/lib
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; ----------------------- | |
; Title: Core RL | |
; Author: Measter | |
; Date: 2013/10/25 | |
; | |
; Based on Core: A Minimal Roguelike. | |
; http://http://roguelikeeducation.org/1.html | |
; ----------------------- | |
; Revisions | |
; 1 - Map generation. | |
; 2 - Added game logic. | |
; 3 - Fixes stack not being restored on exit of | |
; handle_player and handle_evil. | |
; 4 - Fixed fencpost errors in wall and floor generation. | |
; 5 - Changed calls to int_dec_conv to int_text_conv. | |
; 6 - Appended _func to all library calls. | |
; 7 - Fixed bug in keyboard input. | |
set pc, start | |
.include <memory/alloc.asm> | |
.include <find_device.asm> | |
.include <random.asm> | |
.include <init_lem.asm> | |
.include <int_text_conv.asm> | |
; A is string address. | |
:print_message | |
jsr clear_screen | |
set i, [lem_buffer] | |
:.loop_start | |
set [i], 0xF | |
shl [i], 12 | |
bor [i], [a] | |
add a, 1 | |
add i, 1 | |
ifn [a], 0 | |
set pc, .loop_start | |
set pc, end | |
:print_death_message | |
set push, dead_message | |
add [sp], 14 | |
set push, [level] | |
set push, 10 | |
jsr int_text_conv_func | |
add sp, 2 | |
set a, dead_message | |
set pc, print_message | |
:print_quit_message | |
set push, quit_message | |
add [sp], 13 | |
set push, [level] | |
set push, 10 | |
jsr int_text_conv_func | |
add sp, 2 | |
set a, quit_message | |
set pc, print_message | |
; After exit, B will be one of the following: | |
; 0 : Do nothing. | |
; 1 : Arrow press. | |
:int_handler | |
; Get pressed key. | |
set a, 1 | |
hwi [keyboard_port] | |
; Arrow keys | |
ifg c, 0x79 | |
ifl c, 0x84 | |
set pc, .handle_arrows | |
ife c, 0x71 | |
set pc, .handle_q | |
set b, 0 | |
set pc, .exit | |
:.handle_q | |
set pc, print_quit_message | |
:.handle_arrows | |
ife c, 0x80 ; Up Arrow | |
sub [next_row], 1 | |
ife c, 0x81 ; Down Arrow | |
add [next_row], 1 | |
ife c, 0x82 ; Left Arrow | |
sub [next_col], 1 | |
ife c, 0x83 ; Right Arrow | |
add [next_col], 1 | |
set b, 1 | |
set pc, .exit | |
:.exit | |
rfi 0 | |
; Input | |
; SP+4 : R0 | |
; SP+3 : C0 | |
; SP+2 : R1 | |
; SP+1 : C1 | |
; SP+0 : Character | |
:fill | |
set push, z | |
set z, sp | |
add z, 2 | |
set push, i | |
set push, j | |
set push, a | |
set i, [z+4] | |
:.outer_loop | |
ife i, [z+2] | |
set pc, .exit_outer | |
set j, [z+3] | |
:.inner_loop | |
ife j, [z+1] | |
set pc, .exit_inner | |
set a, [map_width] | |
mul a, i | |
add a, j | |
add a, [map_buffer] | |
set [a], [z+0] | |
add j, 1 | |
set pc, .inner_loop | |
:.exit_inner | |
add i, 1 | |
set pc, .outer_loop | |
:.exit_outer | |
set a, pop | |
set j, pop | |
set i, pop | |
set z, pop | |
set pc, pop | |
; Input | |
; SP+5 : R0 | |
; SP+4 : C0 | |
; SP+3 : R1 | |
; SP+2 : C1 | |
; SP+1 : G0 | |
; SP+0 : G1 | |
:swap | |
set push, z | |
set z, sp | |
add z, 2 | |
set push, a | |
set push, b | |
set push, i | |
; A = row | |
; B = col | |
:.swap_loop_start | |
; Set row. | |
set i, [z+3] | |
sub i, [z+5] | |
jsr rand_func | |
set a, [rand_seed] | |
mod a, i | |
add a, [z+5] | |
; Set column. | |
set i, [z+2] | |
sub i, [z+4] | |
jsr rand_func | |
set b, [rand_seed] | |
mod b, i | |
add b, [z+4] | |
; Get tile. | |
set i, [map_width] | |
mul i, a | |
add i, b | |
add i, [map_buffer] | |
ifn [i], [z+1] | |
set pc, .swap_loop_start | |
set [i], [z+0] | |
set i, pop | |
set b, pop | |
set a, pop | |
set z, pop | |
set pc, pop | |
:new_level | |
set push, z | |
set z, sp | |
add z, 2 | |
set push, a | |
set push, b | |
set push, i | |
; Outer wall. | |
set push, 0 | |
set push, 0 | |
set push, [map_height] | |
set push, [map_width] | |
set push, [k_wall] | |
jsr fill | |
add sp, 5 | |
; Floor | |
set push, 1 | |
set push, 1 | |
set push, [map_height] | |
sub [sp], 1 | |
set push, [map_width] | |
sub [sp], 1 | |
set push, [k_floor] | |
jsr fill | |
add sp, 5 | |
; Row | |
set i, [map_height] | |
sub i, 5 | |
jsr rand_func | |
set a, [rand_seed] | |
mod a, i | |
add a, 2 | |
; Col | |
set i, [map_width] | |
sub i, 6 | |
jsr rand_func | |
set b, [rand_seed] | |
mod b, i | |
add b, 2 | |
; Horizontal walls. | |
set push, a | |
set push, 1 | |
set push, a | |
add [sp], 1 | |
set push, [map_width] | |
sub [sp], 1 | |
set push, [k_wall] | |
jsr fill | |
add sp, 5 | |
; Horizontal doors | |
set push, a | |
set push, 1 | |
set push, a | |
add [sp], 1 | |
set push, b | |
set push, [k_wall] | |
set push, [k_floor] | |
jsr swap | |
add sp, 6 | |
set push, a | |
set push, b | |
add [sp], 1 | |
set push, a | |
add [sp], 1 | |
set push, [map_width] | |
sub [sp], 1 | |
set push, [k_wall] | |
set push, [k_floor] | |
jsr swap | |
add sp, 6 | |
; Vertical walls. | |
set push, 1 | |
set push, b | |
set push, [map_height] | |
sub [sp], 1 | |
set push, b | |
add [sp], 1 | |
set push, [k_wall] | |
jsr fill | |
add sp, 5 | |
; Vertical doors | |
set push, 1 | |
set push, b | |
set push, a | |
set push, b | |
add [sp], 1 | |
set push, [k_wall] | |
set push, [k_floor] | |
jsr swap | |
add sp, 6 | |
set push, a | |
add [sp], 1 | |
set push, b | |
set push, [map_height] | |
sub [sp], 1 | |
set push, b | |
add [sp], 1 | |
set push, [k_wall] | |
set push, [k_floor] | |
jsr swap | |
add sp, 6 | |
; Stairs | |
set push, 1 | |
set push, 1 | |
set push, [map_height] | |
sub [sp], 1 | |
set push, [map_width] | |
sub [sp], 1 | |
set push, [k_floor] | |
set push, [k_stairs] | |
jsr swap | |
add sp, 6 | |
add [level], 1 | |
set i, 0 | |
:.actor_reset_start | |
set a, [map_actor_row] | |
add a, i | |
set [a], -1 | |
add i, 1 | |
ifl i, [map_max_actors] | |
set pc, .actor_reset_start | |
jsr place | |
set i, 0 | |
set b, [level] | |
ifl 10, b | |
set b, 10 | |
:.evil_loop_start | |
jsr place | |
add i, 1 | |
ifl i, b | |
set pc, .evil_loop_start | |
set i, pop | |
set b, pop | |
set a, pop | |
set z, pop | |
set pc, pop | |
; Input | |
; SP+1 : Row | |
; SP+0 : Col | |
:new_actor | |
set push, z | |
set z, sp | |
add z, 2 | |
set push, i | |
set push, j | |
; Search for empty entry. | |
set i, 0 | |
:.loop_start | |
ife i, [map_max_actors] | |
set pc, .loop_end | |
set j, [map_actor_row] | |
add j, i | |
ife [j], -1 | |
set pc, .loop_end | |
add i, 1 | |
set pc, .loop_start | |
:.loop_end | |
ife i, [map_max_actors] | |
set pc, .exit | |
; Found empty entry. | |
; Set row. | |
set [j], [z+1] | |
; Set column. | |
set j, [map_actor_col] | |
add j, i | |
set [j], [z+0] | |
; Set tile. | |
set j, [z+1] | |
mul j, [map_width] | |
add j, [z+0] | |
add j, [map_buffer] | |
ife i, 0 | |
set [j], [k_player] | |
ifn i, 0 | |
set [j], [k_evil] | |
:.exit | |
set j, pop | |
set i, pop | |
set z, pop | |
set pc, pop | |
:place | |
set push, i | |
set push, a | |
set push, b | |
:.place_loop_start | |
; Row | |
set i, [map_height] | |
sub i, 1 | |
jsr rand_func | |
set a, [rand_seed] | |
mod a, i | |
add a, 1 | |
; Column | |
set i, [map_width] | |
sub i, 2 | |
jsr rand_func | |
set b, [rand_seed] | |
mod b, i | |
add b, 2 | |
; Tile address | |
set i, [map_width] | |
mul i, a | |
add i, b | |
add i, [map_buffer] | |
ifn [i], [k_floor] | |
set pc, .place_loop_start | |
set push, a | |
set push, b | |
jsr new_actor | |
add sp, 2 | |
set b, pop | |
set a, pop | |
set i, pop | |
set pc, pop | |
; X = Actor ID. | |
:at_pos | |
set push, a | |
set push, b | |
set push, i | |
set x, 0 | |
:.actor_loop_start | |
set a, [map_actor_row] | |
add a, x | |
ifn [a], [next_row] | |
set pc, .next | |
set a, [map_actor_col] | |
add a, x | |
ifn [a], [next_col] | |
set pc, .next | |
; Actor found. | |
set pc, .exit_loop | |
:.next | |
add x, 1 | |
ifl x, [map_max_actors] | |
set pc, .actor_loop_start | |
; No actor at coordinates. | |
set x, 0xFFFF | |
:.exit_loop | |
set i, pop | |
set b, pop | |
set a, pop | |
set pc, pop | |
:clear_screen | |
set push, z | |
set z, sp | |
add z, 2 | |
set push, a | |
set push, i | |
set i, 0 | |
:.clear_loop_start | |
set a, [lem_buffer] | |
add a, i | |
set [a], 0x0000 | |
add i, 1 | |
ifl i, 0x180 | |
set pc, .clear_loop_start | |
set i, pop | |
set a, pop | |
set z, pop | |
set pc, pop | |
:draw_map | |
set push, z | |
set z, sp | |
add z, 2 | |
set push, a | |
set push, b | |
set push, i | |
set push, j | |
; A, B = Read buffer. | |
; X, Y = Destination buffer. | |
; I = Destination character. | |
; J = Source character. | |
set a, 0 | |
:.outer_loop | |
ife a, [map_height] | |
set pc, .exit_outer | |
set b, 0 | |
:.inner_loop | |
ife b, [map_width] | |
set pc, .exit_inner | |
set j, [map_width] | |
mul j, a ; Row | |
add j, b ; Plus column | |
add j, [map_buffer] | |
set i, 32 | |
mul i, a ; Row | |
add i, b ; Plus column | |
add i, [lem_buffer] | |
set [i], [j] | |
add b, 1 | |
set pc, .inner_loop | |
:.exit_inner | |
add a, 1 | |
set pc, .outer_loop | |
:.exit_outer | |
set j, pop | |
set i, pop | |
set b, pop | |
set a, pop | |
set z, pop | |
set pc, pop | |
:main_loop | |
set i, 0 | |
:main_actor_loop | |
ife i, [map_max_actors] | |
set pc, .actor_loop_end | |
set x, [map_actor_row] | |
add x, i | |
set [next_row], [x] | |
set x, [map_actor_col] | |
add x, i | |
set [next_col], [x] | |
ife i, 0 | |
jsr handle_player | |
ifg i, 0 | |
jsr handle_evil | |
; Move actor. | |
set a, [next_row] | |
mul a, [map_width] | |
add a, [next_col] | |
add a, [map_buffer] | |
; A = Next tile address. | |
ifn [a], [k_floor] | |
set pc, .continue | |
set y, [map_actor_row] | |
add y, i | |
set z, [y] | |
; Z = Actor current row. | |
mul z, [map_width] | |
set y, [map_actor_col] | |
add y, i | |
add z, [y] | |
add z, [map_buffer] | |
; Z = Actor current tile. | |
; Move actor. | |
set [a], [z] | |
set [z], [k_floor] | |
set [y], [next_col] ; Set column. | |
set y, [map_actor_row] | |
add y, i | |
set [y], [next_row] ; Set row. | |
:.continue | |
add i, 1 | |
set pc, main_actor_loop | |
:.actor_loop_end | |
set pc, main_loop | |
:handle_player | |
jsr draw_map | |
; Clear keyboard buffer. | |
set a, 0 | |
hwi [keyboard_port] | |
; Turn on interrupt queueing for input. | |
ias int_handler | |
set b, 0 | |
:.input_wait_loop | |
ifn b, 1 | |
set pc, .input_wait_loop | |
; Ignore all input. | |
ias 0 | |
; Has pressed arrow key. | |
set a, [next_row] | |
mul a, [map_width] | |
add a, [next_col] | |
add a, [map_buffer] | |
ife [a], [k_player] | |
set pc, .self_or_wall | |
ife [a], [k_wall] | |
set pc, .self_or_wall | |
ife [a], [k_stairs] | |
set pc, .stairs | |
ife [a], [k_evil] | |
set pc, .evil | |
set pc, .exit | |
:.self_or_wall | |
sub i, 1 | |
set pc, .continue | |
:.stairs | |
jsr new_level | |
set pc, .break | |
:.evil | |
jsr at_pos | |
; X = Actor ID. | |
ife x, 0xFFFF | |
set pc, .exit | |
; Kill enemy. | |
set [a], [k_floor] ; Set tile. | |
set a, [map_actor_row] | |
add a, x | |
set [a], 0xFFFF ; Kill enemy. | |
set pc, .continue | |
:.exit | |
set pc, pop | |
:.continue | |
add i, 1 | |
add sp, 1 ; Handle stack. | |
set pc, main_actor_loop | |
:.break | |
add sp, 1 ; Handle stack. | |
set pc, main_loop | |
:handle_evil | |
ife [next_row], 0xFFFF | |
set pc, .continue | |
; Vertical check. | |
set x, [map_actor_row] ; Player. | |
set x, [x] | |
sub x, [next_row] | |
ife ex, 0xFFFF ; Underflow. | |
set x, 0xFFFF | |
ife ex, 0 ; No underflow, with remainder. | |
ifg x, 0 | |
set x, 1 | |
; X = Target row. | |
set a, [next_row] | |
add a, x | |
mul a, [map_width] | |
add a, [next_col] | |
add a, [map_buffer] | |
; A = Next row tile. | |
ife [a], [k_player] | |
set pc, .move_ver | |
ifn x, 0 | |
ife [a], [k_floor] | |
set pc, .move_ver | |
; Horizontal check. | |
set x, [map_actor_col] ; Player. | |
set x, [x] | |
sub x, [next_col] | |
ife ex, 0xFFFF ; Underflow. | |
set x, 0xFFFF | |
ife ex, 0 ; No underflow, with remainder. | |
ifg x, 0 | |
set x, 1 | |
; X = Target row. | |
set a, [next_row] | |
mul a, [map_width] | |
add a, [next_col] | |
add a, x | |
add a, [map_buffer] | |
; A = Next column tile. | |
ife [a], [k_player] | |
set pc, .move_hor | |
ifn x, 0 | |
ife [a], [k_floor] | |
set pc, .move_hor | |
set pc, .check_kill | |
:.move_hor | |
add [next_col], x | |
set pc, .check_kill | |
:.move_ver | |
add [next_row], x | |
:.check_kill | |
set a, [next_row] | |
mul a, [map_width] | |
add a, [next_col] | |
add a, [map_buffer] | |
ife [a], [k_player] | |
set pc, print_death_message | |
:.exit | |
set pc, pop | |
:.continue | |
add i, 1 | |
add sp, 1 ; Handle stack. | |
set pc, main_actor_loop | |
:.break | |
add sp, 1 ; Handle stack. | |
set pc, main_loop | |
; After exit, J will be one of the following: | |
; 0 : Do nothing. | |
; 2 : Enter key or 5 digits. | |
:seed_int_handler | |
; Get pressed key. | |
set a, 1 | |
hwi [keyboard_port] | |
ifg c, 0x29 ; Digit 0 less 1 | |
ifl c, 0x41 ; Digit 9 plus 1 | |
set pc, .digit | |
ife c, 0x11 ; Enter | |
set pc, .enter | |
set pc, .exit | |
:.digit | |
set [i], 0xF000 | |
bor [i], c | |
add i, 1 | |
mul [rand_seed], 10 | |
sub c, 0x30 | |
add [rand_seed], c | |
set pc, .exit | |
:.enter | |
set j, 2 | |
:.exit | |
rfi 0 | |
:get_seed | |
set push, i | |
set push, j | |
set push, a | |
set push, c | |
set i, [lem_buffer] | |
set j, enter_seed_message | |
:.print_loop_start | |
set [i], 0xF000 | |
bor [i], [j] | |
add i, 1 | |
add j, 1 | |
ifn [j], 0 | |
set pc, .print_loop_start | |
ias seed_int_handler | |
set j, 0 | |
:.input_wait_loop | |
ifn j, 2 | |
set pc, .input_wait_loop | |
ias 0 | |
set c, pop | |
set a, pop | |
set j, pop | |
set i, pop | |
set pc, pop | |
:start | |
set [mem_start], heap_start | |
; Find LEM. | |
set push, 0x7349 | |
set push, 0xF615 | |
jsr find_device_func | |
set [lem_port], pop | |
add sp, 1 | |
ife [lem_port], 0xFFFF | |
set pc, end | |
; Display buffer. | |
set push, 384 | |
jsr mem_alloc_func | |
set [lem_buffer], pop | |
ife [lem_buffer], 0xFFFF | |
set pc, end | |
set push, 0x0 | |
set push, 0x0 | |
set push, [lem_buffer] | |
set push, [lem_port] | |
jsr init_lem_func | |
add sp, 4 | |
; Find keyboard. | |
set push, 0x30CF | |
set push, 0x7406 | |
jsr find_device_func | |
set [keyboard_port], pop | |
add sp, 1 | |
ife [keyboard_port], 0xFFFF | |
set pc, keyboard_error | |
; Speficy keyboard interrupt message. | |
set a, 3 | |
set b, 1 | |
hwi [keyboard_port] | |
set [rand_seed], 0 | |
jsr get_seed | |
; Map buffer. | |
set a, [map_width] | |
mul a, [map_height] | |
set push, a | |
jsr mem_alloc_func | |
set [map_buffer], pop | |
; Actor arrays. | |
set push, [map_max_actors] | |
jsr mem_alloc_func | |
set [map_actor_row], pop | |
set push, [map_max_actors] | |
jsr mem_alloc_func | |
set [map_actor_col], pop | |
jsr new_level | |
set pc, main_loop | |
:end | |
set pc, end | |
:keyboard_error | |
set a, keyboard_error_string | |
set pc, print_message | |
:lem_port | |
dat 0 | |
:lem_buffer | |
dat 0 | |
:keyboard_port | |
dat 0 | |
:map_width | |
dat 21 | |
:map_height | |
dat 12 | |
:map_max_actors | |
dat 16 | |
:map_buffer | |
dat 0 | |
:map_actor_row | |
dat 0 | |
:map_actor_col | |
dat 0 | |
:level | |
dat 0 | |
:k_floor | |
dat 0xF02E | |
:k_wall | |
dat 0xF023 | |
:k_stairs | |
dat 0xF03C | |
:k_player | |
dat 0xF040 | |
:k_evil | |
dat 0xF045 | |
:next_row | |
dat 0 | |
:next_col | |
dat 0 | |
:keyboard_error_string | |
.asciiz "No keyboard detected." | |
:quit_message | |
.asciiz "Quit on level " | |
.pad 18, 0 | |
:dead_message | |
.asciiz "Died on level " | |
.pad 18, 0 | |
:enter_seed_message | |
.asciiz "Enter seed: " | |
:heap_start | |
dat 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Could do you check why hangs in dcpu-vm ??