414 lines
14 KiB
Plaintext
414 lines
14 KiB
Plaintext
%include ../../at67/gasm/macros/gigatron.i
|
|
%include ../../at67/gasm/macros/macros.i
|
|
|
|
vram EQU 0x0800
|
|
|
|
vpc EQU 0x16
|
|
|
|
rand_x1 EQU 0x06
|
|
rand_y1 EQU 0x07
|
|
rand_x2 EQU 0x08
|
|
rand_y2 EQU 0x0b
|
|
rand EQU 0x06
|
|
|
|
base EQU 0x30
|
|
|
|
xypos EQU 0x32
|
|
x EQU 0x32
|
|
y EQU 0x33
|
|
tryxypos EQU 0x34
|
|
tryx EQU 0x34
|
|
tryy EQU 0x35
|
|
visited_pix EQU 0x36
|
|
direction EQU 0x38 ; 0 = right, 1 = down, 2 = left, 3 = top
|
|
dir_count EQU 0x39
|
|
|
|
RIGHT EQU 0x00
|
|
DOWN EQU 0x01
|
|
LEFT EQU 0x02
|
|
TOP EQU 0x03
|
|
|
|
CLEAR EQU 0x00
|
|
VISITED EQU 0x0F
|
|
BACKTRACKED EQU 0x0C
|
|
WALL EQU 0x3F
|
|
|
|
MAZE_WIDTH EQU 79
|
|
MAZE_HEIGHT EQU 59
|
|
WAY_LEN EQU 0x03
|
|
|
|
|
|
|
|
_startAddress_ EQU 0x0200 ; entry point for the code, if this is missing defaults to 0x0200
|
|
|
|
_callTable_ EQU 0x007E ; call addresses are automatically stored here by the assembler, it grows downwards,
|
|
; make sure it doesn't crash into anything important
|
|
_singleStepWatch_ EQU vpc ; the single step debugger watches this variable location to decide when to step,
|
|
; choose a variable that is updated often
|
|
start EQU 0x0200
|
|
init_startpixel EQU 0x0300
|
|
find_visited EQU 0x0400
|
|
|
|
ii EQU 0x30
|
|
jj EQU 0x31
|
|
kk EQU 0x32
|
|
ll EQU 0x33
|
|
xx EQU 0x34
|
|
yy EQU 0x35
|
|
|
|
; clears the viewable screen
|
|
; created by at67, see https://github.com/kervinck/gigatron-rom/blob/master/Contrib/at67/gasm/clearscreen.gasm
|
|
clearScreen LDWI SYS_Draw4_30 ; setup 4 pixel SYS routine
|
|
STW giga_sysFn
|
|
LDWI 0x0000 ; 4 y of colour
|
|
STW giga_sysArg0
|
|
STW giga_sysArg2
|
|
|
|
LDI giga_yres / 2 ; counters
|
|
ST jj
|
|
LDI giga_xres / 4
|
|
ST ii
|
|
|
|
LDWI 0x0800 ; top line
|
|
STW xx
|
|
LDWI 0x7F00 ; bottom line
|
|
STW kk
|
|
|
|
clearS_loop LDW xx
|
|
STW giga_sysArg4 ; top line
|
|
SYS 0xFF ; SYS_Draw4_30, 270 - 30/2 = 0xFF
|
|
|
|
LDW kk
|
|
STW giga_sysArg4 ; bottom line
|
|
SYS 0xFF ; SYS_Draw4_30, 270 - 30/2 = 0xFF
|
|
|
|
LD xx ; 4 horizontal y
|
|
ADDI 0x04
|
|
ST xx
|
|
LD kk ; 4 horizontal y
|
|
ADDI 0x04
|
|
ST kk
|
|
LoopCounterTo1 ii clearS_loop
|
|
|
|
INC yy ; next top line
|
|
LD ll ; next bottom line
|
|
SUBI 0x01
|
|
ST ll
|
|
|
|
LDI 0x00 ; reset xx, kk and ii
|
|
ST xx
|
|
ST kk
|
|
LDI giga_xres / 4
|
|
ST ii
|
|
LoopCounterTo1 jj clearS_loop
|
|
|
|
; initialize the maze walls and starting point
|
|
CALL init_walls
|
|
CALL init_startpixel
|
|
|
|
step_maze LDW xypos ; detect if at least one neighboring pixel is still CLEAR
|
|
STW tryxypos ; if so: continue drawing a path
|
|
; if not: mark the current pixel as BACKTRACKED
|
|
; continue backtracking with the neighbouring pixel with state VISITED
|
|
CALL find_clear ; vAC will be "0" if we found a clear pixel
|
|
BEQ cont_drawing ; if so, continue with drawing the next step
|
|
|
|
; if not:
|
|
LDW xypos ; detect if at least one neighboring pixel is VISITED and try backtracking one step
|
|
STW tryxypos
|
|
|
|
CALL find_visited ; try to find a visited pixel next to the current one. when no VISITED pixel is found, the labyrinth is done!
|
|
BEQ clearScreen ; if so (when find_visited returns with 0 in vAC): restart from scratch
|
|
LDW tryxypos
|
|
STW xypos
|
|
BRA step_maze
|
|
|
|
cont_drawing LD dir_count ; test if we should change the preferred direction
|
|
BNE cont_right
|
|
CALL rand_dir
|
|
|
|
cont_right LDW xypos
|
|
STW tryxypos
|
|
LD direction
|
|
BNE cont_with_down ; direction = 0?
|
|
CALL try_right ; --> right
|
|
BRA step_maze
|
|
cont_with_down LD direction
|
|
SUBI 1
|
|
BNE cont_with_left ; direction = 1?
|
|
CALL try_down ; --> down
|
|
BRA step_maze
|
|
cont_with_left LD direction
|
|
SUBI 2
|
|
BNE cont_with_up ; direction = 2?
|
|
CALL try_left ; --> left
|
|
BRA step_maze
|
|
cont_with_up CALL try_up ; else --> up
|
|
BRA step_maze
|
|
|
|
|
|
; -- 0x0300 initialization and drawing forward --
|
|
|
|
; Initialize the maze walls and the start position
|
|
init_walls LDWI vram
|
|
STW xypos
|
|
horiz_walls LDI WALL
|
|
POKE xypos
|
|
LD y
|
|
ADDI MAZE_HEIGHT * 2
|
|
ST y
|
|
LDI WALL
|
|
POKE xypos
|
|
LD y
|
|
SUBI MAZE_HEIGHT * 2
|
|
ST y
|
|
INC x
|
|
LD x
|
|
SUBI MAZE_WIDTH * 2
|
|
BEQ init_vert_walls
|
|
BRA horiz_walls
|
|
init_vert_walls LDWI vram
|
|
STW xypos
|
|
vert_walls LDI WALL
|
|
POKE xypos
|
|
LD x
|
|
ADDI MAZE_WIDTH * 2
|
|
ST x
|
|
LDI WALL
|
|
POKE xypos
|
|
LD x
|
|
SUBI MAZE_WIDTH * 2
|
|
ST x
|
|
INC y
|
|
LD y
|
|
SUBI MAZE_HEIGHT * 2 + 9
|
|
BNE vert_walls
|
|
RET
|
|
|
|
init_startpixel LDWI vram ; mark the start pixel as visited
|
|
STW xypos
|
|
INC x
|
|
INC x
|
|
INC y
|
|
INC y
|
|
LDI VISITED
|
|
POKE xypos
|
|
LDI 0x00
|
|
ST direction ; initialize direction and counter for times a certain direction was chosen
|
|
LDI WAY_LEN
|
|
ST dir_count
|
|
RET
|
|
|
|
# maze calculation functions
|
|
rand_dir LDWI SYS_Random_34 ; randomize a new direction
|
|
STW 0x22
|
|
SYS 253
|
|
LD rand
|
|
ANDI 0x03
|
|
ST direction
|
|
LDI WAY_LEN
|
|
ST dir_count
|
|
RET
|
|
|
|
try_right INC tryx ; test if the pixel is still clear
|
|
INC tryx
|
|
LDW tryxypos
|
|
PEEK
|
|
BEQ mark_right ; if the pixel is clear: draw a way to this pixel
|
|
BRA rand_dir ; if not: try a new random direction and return
|
|
mark_right INC x
|
|
LDI VISITED
|
|
POKE xypos
|
|
INC x
|
|
POKE xypos
|
|
BRA ret_after_mark
|
|
|
|
try_down INC tryy ; test if the pixel is still clear
|
|
INC tryy
|
|
LDW tryxypos
|
|
PEEK
|
|
BEQ mark_down ; if the pixel is clear: draw a way to this pixel
|
|
BRA rand_dir ; if not: try a new random direction and return
|
|
mark_down INC y
|
|
LDI VISITED
|
|
POKE xypos
|
|
INC y
|
|
POKE xypos
|
|
BRA ret_after_mark
|
|
|
|
try_left LD tryx ; test if the pixel is still clear
|
|
SUBI 2
|
|
ST tryx
|
|
LDW tryxypos
|
|
PEEK
|
|
BEQ mark_left ; if the pixel is clear: draw a way to this pixel
|
|
BRA rand_dir ; if not: try a new random direction and return
|
|
mark_left LD x
|
|
SUBI 1
|
|
ST x
|
|
LDI VISITED
|
|
POKE xypos
|
|
LD x
|
|
SUBI 1
|
|
ST x
|
|
LDI VISITED
|
|
POKE xypos
|
|
BRA ret_after_mark
|
|
|
|
|
|
try_up LD tryy ; test if the pixel is still clear
|
|
SUBI 2
|
|
ST tryy
|
|
LDW tryxypos
|
|
PEEK
|
|
BEQ mark_up ; if the pixel is clear: draw a way to this pixel
|
|
BRA rand_dir ; if not: try a new random direction and return
|
|
RET
|
|
mark_up LD y
|
|
SUBI 1
|
|
ST y
|
|
LDI VISITED
|
|
POKE xypos
|
|
LD y
|
|
SUBI 1
|
|
ST y
|
|
LDI VISITED
|
|
POKE xypos
|
|
|
|
ret_after_mark LD dir_count
|
|
SUBI 1
|
|
ST dir_count
|
|
RET
|
|
|
|
; find a clear pixel around tryxypos
|
|
find_clear LD tryx ; is left pixel clear?
|
|
SUBI 2
|
|
ST tryx
|
|
LDW tryxypos
|
|
PEEK
|
|
BEQ ret_clear_found
|
|
|
|
LD tryx ; is right pixel clear?
|
|
ADDI 4
|
|
ST tryx
|
|
LDW tryxypos
|
|
PEEK
|
|
BEQ ret_clear_found
|
|
|
|
LD tryx ; is upper pixel clear
|
|
SUBI 2
|
|
ST tryx
|
|
LD tryy
|
|
SUBI 2
|
|
ST tryy
|
|
LDW tryxypos
|
|
PEEK
|
|
BEQ ret_clear_found
|
|
|
|
LD tryy ; is lower pixel clear
|
|
ADDI 4
|
|
ST tryy
|
|
LDW tryxypos
|
|
PEEK
|
|
BEQ ret_clear_found
|
|
LDI 1 ; We didn't find a clear pixel, return with 1 in vAC
|
|
RET
|
|
ret_clear_found LDI 0 ; indicate that we found a clear pixel and don't need to backtrack
|
|
RET
|
|
|
|
; 0x400
|
|
; find a visited pixel around tryxypos
|
|
find_visited LD tryx ; is left pixel VISITED?
|
|
SUBI 1
|
|
ST tryx
|
|
LDW tryxypos
|
|
PEEK
|
|
SUBI VISITED
|
|
BEQ left_visited
|
|
|
|
LD tryx ; is right pixel VISITED?
|
|
ADDI 2
|
|
ST tryx
|
|
LDW tryxypos
|
|
PEEK
|
|
SUBI VISITED
|
|
BEQ right_visited
|
|
|
|
LD tryx ; is upper pixel VISITED
|
|
SUBI 1
|
|
ST tryx
|
|
LD tryy
|
|
SUBI 1
|
|
ST tryy
|
|
LDW tryxypos
|
|
PEEK
|
|
SUBI VISITED
|
|
BEQ up_visited
|
|
|
|
LD tryy ; is lower pixel VISITED
|
|
ADDI 2
|
|
ST tryy
|
|
LDW tryxypos
|
|
PEEK
|
|
SUBI VISITED
|
|
BEQ down_visited
|
|
|
|
; no pixel was visited!
|
|
LD tryy
|
|
SUBI 1
|
|
ST tryy
|
|
LDI 0 ; return with 0 in vAC
|
|
RET
|
|
|
|
left_visited INC tryx
|
|
LDI BACKTRACKED
|
|
POKE tryxypos
|
|
LD tryx
|
|
SUBI 1
|
|
ST tryx
|
|
LDI BACKTRACKED
|
|
POKE tryxypos
|
|
LD tryx
|
|
SUBI 1
|
|
ST tryx
|
|
LDI 1 ; return with 1 in vAC
|
|
RET
|
|
|
|
right_visited LD tryx
|
|
SUBI 1
|
|
ST tryx
|
|
LDI BACKTRACKED
|
|
POKE tryxypos
|
|
INC tryx
|
|
LDI BACKTRACKED
|
|
POKE tryxypos
|
|
INC tryx
|
|
LDI 1 ; return with 1 in vAC
|
|
RET
|
|
|
|
up_visited INC tryy
|
|
LDI BACKTRACKED
|
|
POKE tryxypos
|
|
LD tryy
|
|
SUBI 1
|
|
ST tryy
|
|
LDI BACKTRACKED
|
|
POKE tryxypos
|
|
LD tryy
|
|
SUBI 1
|
|
ST tryy
|
|
LDI 1 ; return with 1 in vAC
|
|
RET
|
|
|
|
down_visited LD tryy
|
|
SUBI 1
|
|
ST tryy
|
|
LDI BACKTRACKED
|
|
POKE tryxypos
|
|
INC tryy
|
|
LDI BACKTRACKED
|
|
POKE tryxypos
|
|
INC tryy
|
|
LDI 1 ; return with 1 in vAC
|
|
RET
|