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

263 lines
7.9 KiB
Plaintext

; game of life coded by at67, original algorithm by John Conway
; 32X32 runs about 1 fps on a 6.25MHz Gigatron TTL
; non-optimised apart from a look up table to evalute neighbours count
; this is an overlapping world
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
pattern EQU 0x42
watch EQU 0x44
scratch EQU 0x46
mask EQU 0x48
gliders EQU 0x4A
lut_modify EQU 0x4C
j_one EQU 0x4E
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* 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
n_lut EQU 0x0060
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 buffer0
STW cbase0
LDWI buffer1
STW cbase1
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 0x08A2
STW gliders
LDI 0x07 ; 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 0x04
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
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
LDW i
ANDW mask
ADDW cbase0
PEEK
BEQ n_m_t
INC neighbours
n_m_t INC i ; 0, -1 neighbour
LDW i
ANDW mask
ADDW cbase0
PEEK
BEQ n_r_t
INC neighbours
n_r_t INC i ; 1, -1 neighbour
LDW i
ANDW mask
ADDW cbase0
PEEK
BEQ n_r_m
INC neighbours
n_r_m INC j ; 1, 0 neighbour
LDW i
ANDW mask
ADDW cbase0
PEEK
BEQ n_r_b
INC neighbours
n_r_b INC j ; 1, 1 neighbour
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
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
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
LDW i
ANDW mask
ADDW cbase0
PEEK
BEQ cell_00
INC neighbours
cell_00 INC i ; 0, 0 cell
LDW i
ADDW cbase0
STW cells0 ; save buffer0 address
PEEK ; get buffer0 cell
ST 0x62 ; save cell into neighbours lut
LDW i
ADDW cbase1
STW cells1 ; save buffer1 address
LD neighbours ; lut computes neighbours count
ADDI 0x60
POKE lut_modify ; lut_modify points to operand in "LD n_lut"
lut LD 0x60 ; 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 cbase0 ; swap buffers
STW scratch
LDW cbase1
STW cbase0
LDW scratch
STW cbase1
BRA n_l_t