gigatron/rom/Contrib/at67/gasm/life/life.gasm
2025-01-28 19:17:01 +03:00

381 lines
10 KiB
Plaintext

; game of life coded by at67, original algorithm by John Conway
vram EQU 0x0800
buffer0 EQU 0x08A0
buffer1 EQU 0x08C0
cells0 EQU 0x30
cells1 EQU 0x32
x EQU 0x34
y EQU 0x35
i EQU 0x36
j EQU 0x37
neighbours EQU 0x38
cell EQU 0x39
cbase0 EQU 0x3A
cbase1 EQU 0x3C
vbase EQU 0x3E
pixels EQU 0x40
xy_addr EQU 0x42
x_add_addr EQU 0x44
y_add_addr EQU 0x46
one EQU 0x48
test EQU 0x4A
watch EQU 0x4C
scratch EQU 0x4E
mask EQU 0x50
ones EQU 0x52
gliders EQU 0x54
lut_modify EQU 0x56
_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
; *NOTE* gt1 spec only allows for one zero page segment, .vasm files use this for the call table
; do *NOT* make this address higher than 0x00BE, it will conflict with future ROM loading mechanisms
; do *NOT* define constants, (DB or DW), between 0x30 -> 0x44 and 0xc0 -> 0xFF, these addresses are
; used by the loader and the vCPU stack, you can create variables in these areas as long as you don't
; corrupt your nested CALL return addresses on the stack
_singleStepWatch_ EQU watch ; the single step debugger watches this variable location to decide when to step,
; choose a variable that is updated often
data EQU 0x08A2 ; custom address for constant data space defined with DB and/or DW
n_lut EQU 0x0060
n_l_t EQU 0x0300
get_cell EQU 0x0400
LDI 0x00 ; look up table that is used to evaluate neighbour counts
ST n_lut
ST n_lut+1
ST n_lut+2 ; self modifying code updates this location with previous generation cell
ST n_lut+4
ST n_lut+5
ST n_lut+6
ST n_lut+7
ST n_lut+8
LDI 0xFF
ST n_lut+3
LDWI vram
STW vbase ; vram base address
STW pixels ; pixel address
LDWI buffer0
STW cbase0
LDWI buffer1
STW cbase1
LDWI 0x1F1F
STW mask
LDWI 0x0001
STW one
LDWI 0x0100
STW ones
LDWI lut + 1 ; self modifying address
STW lut_modify
clear LDI 0x00 ; clear screen and array
POKE vbase
LDW vbase
ADDW one
STW vbase
LD vbase+1
SUBI 0x80
BLT clear
LDWI 0x08A2
STW gliders
LDI 0x05
ST i
init LDW gliders ; glider
STW test
LDI 0xFF
POKE test
LDW ones
ADDW test
STW test
LDI 0xFF
POKE test
LDW ones
ADDW test
STW test
LDI 0xFF
POKE test
LD test
SUBI 0x01
ST test
LDI 0xFF
POKE test
LDW test
SUBW ones
STW test
LD test
SUBI 0x01
ST test
LDI 0xFF
POKE test
LD gliders
ADDI 0x04
ST gliders
LD i
SUBI 0x01
ST i
BGT init
LDWI 0x354A ; position in screen to render life
STW vbase
LDI 0x00
ST i
ST j
CALL n_l_t
n_l_t LDI 0x00 ; reset neighbour count
ST neighbours
LD i ; -1, -1 neighbour
SUBI 0x01
ST i
LD j
SUBI 0x01
ST j
;CALL get_cell
LDW i
ANDW mask
ADDW cbase0
PEEK
BEQ n_m_t
INC neighbours
n_m_t INC i ; 0, -1 neighbour
;CALL get_cell
LDW i
ANDW mask
ADDW cbase0
PEEK
BEQ n_r_t
INC neighbours
n_r_t INC i ; 1, -1 neighbour
;CALL get_cell
LDW i
ANDW mask
ADDW cbase0
PEEK
BEQ n_r_m
INC neighbours
n_r_m INC j ; 1, 0 neighbour
;CALL get_cell
LDW i
ANDW mask
ADDW cbase0
PEEK
BEQ n_r_b
INC neighbours
n_r_b INC j ; 1, 1 neighbour
;CALL get_cell
LDW i
ANDW mask
ADDW cbase0
PEEK
BEQ n_m_b
INC neighbours
n_m_b LD i ; 0, 1 neighbour
SUBI 0x01
ST i
;CALL get_cell
LDW i
ANDW mask
ADDW cbase0
PEEK
BEQ n_l_b
INC neighbours
n_l_b LD i ; -1, 1 neighbour
SUBI 0x01
ST i
;CALL get_cell
LDW i
ANDW mask
ADDW cbase0
PEEK
BEQ n_l_m
INC neighbours
n_l_m LD j ; -1, 0 neighbour
SUBI 0x01
ST j
;CALL get_cell
LDW i
ANDW mask
ADDW cbase0
PEEK
BEQ cell00
INC neighbours
cell00 INC i
;CALL get_cell00 ; 0, 0 cell
LDW i
ADDW cbase0
STW cells0
PEEK
ST cell
ST 0x62
;CALL set_cells
LDW i
ADDW cbase1
STW cells1
LD neighbours
ADDI 0x60
POKE lut_modify ; lut_modify points to operand in "LD n_lut"
lut LD 0x60 ; self modifying code
;check_3 LD neighbours
; SUBI 0x03
; BNE check_<2
; LDI 0xFF ; birth
; BRA draw
;check_<2 LD neighbours
; SUBI 0x02
; BGE check_>3
; LDI 0x00 ; death
; BRA draw
;check_>3 LD neighbours
; SUBI 0x03
; BLE old_cell
; LDI 0x00 ; death
; BRA draw
;old_cell LD cell
draw POKE cells1
ST cell
;CALL draw_1x1
;CALL draw_2x2
LDW i
ADDW vbase
STW pixels
LD cell
POKE pixels
LD i ; inc i
ADDI 0x01
ANDI 0x1F
ST i
BNE n_l_t
LD j ; inc j
ADDI 0x01
ANDI 0x1F
ST j
BNE n_l_t
LDW cbase0 ; toggle buffers between 0x08A0 and 0x08C0
STW test
LDW cbase1
STW cbase0
LDW test
STW cbase1
BRA n_l_t
get_cell LDW i
;LD i
;ANDI 0x1F
;ST xy_addr
;LD j
;ANDI 0x1F
;ST xy_addr+1
;LDW xy_addr
;ADDW cbase0
;STW cells0
;PEEK
ANDW mask
ADDW cbase0
STW cells0
PEEK
RET
get_cell00 LD i
ST xy_addr
LD j
ST xy_addr+1
LDW xy_addr
ADDW cbase0
STW cells0
RET
set_cells LD i
ST xy_addr
LD j
ST xy_addr+1
LDW xy_addr
ADDW cbase1
STW cells1
RET
draw_1x1 LD i
ST xy_addr
LD j
ST xy_addr+1
LDW xy_addr
ADDW vbase
STW pixels
LD cell
POKE pixels
RET
draw_2x2 LD i
LSLW
ST xy_addr
LD j
LSLW
ST xy_addr+1
LDW xy_addr
ADDW vbase
STW pixels
STW scratch
LD cell
POKE pixels
INC pixels
POKE pixels
LDW scratch
STW pixels
INC pixels+1
LD cell
POKE pixels
INC pixels
POKE pixels
RET
; an example of how to define your own data
data DB 0xFF 0xFF 0xFF