263 lines
7.8 KiB
Plaintext
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
|
|
|