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