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

263 lines
7.8 KiB
Plaintext

; game of life coded by at67, original algorithm by John Conway
; 32X32 runs about 1 fps on a 6.25MHz Gigatron TTL
; some optimisation, pointer arithmetic with offsets and a look up table to evalute neighbours count
; this world has boundaries
vram EQU 0x0800
buff0 EQU 0x09A0
buff1 EQU 0x09D0
cells0 EQU 0x30
cells1 EQU 0x32
i EQU 0x34
j EQU 0x35
neighbours EQU 0x36
cell EQU 0x37
buffer0 EQU 0x38
buffer1 EQU 0x3A
vbase EQU 0x3C
pixels EQU 0x3E
pattern EQU 0x40
watch EQU 0x42
scratch EQU 0x44
mask EQU 0x46
gliders EQU 0x48
lut_modify EQU 0x4A
j_one EQU 0x4C
offset0 EQU 0x4E
offset1 EQU 0x50
offset2 EQU 0x52
offset3 EQU 0x54
offset4 EQU 0x56
offset5 EQU 0x58
offset6 EQU 0x5A
offset7 EQU 0x5C
ij_mask EQU 0x1F1F ; determines max size of world, limited by available ram in blank scanlines,
; using bytes per cell and two buffers means 0x20*0x20 is maximum size
_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* define any data/constants in zero page using DB or DW, it will not work! (use code)
; do *NOT* make this address higher than 0x00BE, it will conflict with future ROM loading mechanisms
_singleStepWatch_ EQU watch ; the single step debugger watches this variable location to decide when to step,
; choose a variable that is updated often
n_lut EQU 0x60
n_lut_cell EQU 0x62
n_l_t EQU 0x0300
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 buff0
STW buffer0
LDWI buff1
STW buffer1
LDWI ij_mask
STW mask
LDWI lut + 1 ; self modifying address
STW lut_modify
LDWI 0x0100
STW j_one
clear LDI 0x00 ; clear screen and buffers
POKE vbase
LDWI 0x0001
ADDW vbase
STW vbase
LD vbase+1
SUBI 0x80
BLT clear
LDWI 0x09A3
STW gliders
LDI 0x06 ; number of gliders
ST i
glider LDW gliders
STW pattern
LDI 0xFF
POKE pattern
LDW j_one
ADDW pattern
STW pattern
LDI 0xFF
POKE pattern
LDW j_one
ADDW pattern
STW pattern
LDI 0xFF
POKE pattern
LD pattern
SUBI 0x01
ST pattern
LDI 0xFF
POKE pattern
LDW pattern
SUBW j_one
STW pattern
LD pattern
SUBI 0x01
ST pattern
LDI 0xFF
POKE pattern
LD gliders ; gap between gliders
ADDI 0x05
ST gliders
LD i
SUBI 0x01
ST i
BGT glider
LDWI 0x354A ; position in screen to render life
STW vbase
LDI 0x00
ST i
ST j
LDWI 0x0101 ; -ve
STW offset0
LDWI 0x0100 ; -ve
STW offset1
LDWI 0x00FF ; -ve
STW offset2
LDWI 0x0001 ; +ve
STW offset3
LDWI 0x0101 ; +ve
STW offset4
LDWI 0x0100 ; +ve
STW offset5
LDWI 0x00FF ; +ve
STW offset6
LDWI 0x0001 ; -ve
STW offset7
CALL n_l_t
n_l_t LDI 0x00 ; reset neighbour count
ST neighbours
LDW i ; buffer0
ADDW buffer0
STW cells0
LDW i ; buffer1
ADDW buffer1
STW cells1
LDW cells0 ; -1, -1 neighbour
SUBW offset0
PEEK
BEQ n_m_t
INC neighbours
n_m_t LDW cells0 ; 0, -1 neighbour
SUBW offset1
PEEK
BEQ n_r_t
INC neighbours
n_r_t LDW cells0 ; 1, -1 neighbour
SUBW offset2
PEEK
BEQ n_r_m
INC neighbours
n_r_m LDW cells0 ; 1, 0 neighbour
ADDW offset3
PEEK
BEQ n_r_b
INC neighbours
n_r_b LDW cells0 ; 1, 1 neighbour
ADDW offset4
PEEK
BEQ n_m_b
INC neighbours
n_m_b LDW cells0 ; 0, 1 neighbour
ADDW offset5
PEEK
BEQ n_l_b
INC neighbours
n_l_b LDW cells0 ; -1, 1 neighbour
ADDW offset6
PEEK
BEQ n_l_m
INC neighbours
n_l_m LDW cells0 ; -1, 0 neighbour
SUBW offset7
PEEK
BEQ cell_00
INC neighbours
cell_00 LDW cells0 ; 0, 0 cell
PEEK ; get buffer0 cell
ST n_lut_cell ; save cell into neighbours lut
LD neighbours ; lut evaluates neighbours count
ADDI n_lut
POKE lut_modify ; lut_modify points to operand in "LD n_lut"
lut LD n_lut ; self modifying code
POKE cells1 ; save new cell
ST cell
LDW i ; draw cell
ADDW vbase
STW pixels
LD cell
POKE pixels
LD i ; inc i
ADDI 0x01
ANDI ij_mask
ST i
BNE n_l_t
LD j ; inc j
ADDI 0x01
ANDI ij_mask
ST j
BNE n_l_t
LDW buffer0 ; swap buffers
STW scratch
LDW buffer1
STW buffer0
LDW scratch
STW buffer1
BRA n_l_t