use L register to store result, not C, how could that have ever worked huh? I must have forgot to reload the rom when testing... Also, I now use a macro to load neighbors to avoid the loop, much faster. We're now down to "12 VBLs" to update the automata
This commit is contained in:
353
Code/main.asm
353
Code/main.asm
@@ -29,6 +29,150 @@ MemorySet:
|
|||||||
jr nz, MemorySet
|
jr nz, MemorySet
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
AddLiveNeighbors: MACRO
|
||||||
|
; H register will be incremented with number of alive neighbors
|
||||||
|
; destroys A, B, C, D, E, does not touch L
|
||||||
|
|
||||||
|
; load current 2x2 cell and mask out bits that are not neighbors
|
||||||
|
ld c, LOW(Cells + \1)
|
||||||
|
ld a, [$FF00+c]
|
||||||
|
ld b, \2
|
||||||
|
and a, b
|
||||||
|
|
||||||
|
; count bits set
|
||||||
|
ld de, BitsSet
|
||||||
|
add a, e
|
||||||
|
ld e, a
|
||||||
|
ld a, [de]
|
||||||
|
|
||||||
|
; add to alive
|
||||||
|
add a, h
|
||||||
|
ld h, a
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
Conway: MACRO
|
||||||
|
; \1 = mask for neighbors in inner cell
|
||||||
|
; \2 = first useful neighbor 2x2 cell
|
||||||
|
; \3 = mask for first useful neighbor 2x2 cell
|
||||||
|
; \4 = mask for second useful neighbor 2x2 cell
|
||||||
|
; \5 = mask for third useful neighbor 2x2 cell
|
||||||
|
;
|
||||||
|
; L will be updated with cell result
|
||||||
|
; destroys all other registers
|
||||||
|
|
||||||
|
; reset alive counter
|
||||||
|
ld h, 0
|
||||||
|
|
||||||
|
; Check all neighbors
|
||||||
|
AddLiveNeighbors 0, \1
|
||||||
|
AddLiveNeighbors (1 + (\2 + 0) % 8), \3
|
||||||
|
AddLiveNeighbors (1 + (\2 + 1) % 8), \4
|
||||||
|
AddLiveNeighbors (1 + (\2 + 2) % 8), \5
|
||||||
|
|
||||||
|
; load current group mask
|
||||||
|
ld b, (~\1) & $F
|
||||||
|
|
||||||
|
; load current cell group
|
||||||
|
ldh a, [Cells]
|
||||||
|
|
||||||
|
; mask data
|
||||||
|
and a, b
|
||||||
|
|
||||||
|
; put alive neighbors in A
|
||||||
|
ld a, h
|
||||||
|
|
||||||
|
jr z, .dead\@
|
||||||
|
;.alive
|
||||||
|
; check if there is two or three neighbors
|
||||||
|
cp a, 2
|
||||||
|
jr c, .writedead\@
|
||||||
|
cp a, 4
|
||||||
|
jr nc, .writedead\@
|
||||||
|
|
||||||
|
.writealive\@
|
||||||
|
; add mask to result
|
||||||
|
ld a, l
|
||||||
|
add a, b
|
||||||
|
ld l, a
|
||||||
|
jr .writedead\@
|
||||||
|
|
||||||
|
.dead\@
|
||||||
|
; check if there is three neighbors
|
||||||
|
cp a, 3
|
||||||
|
jr z, .writealive\@
|
||||||
|
|
||||||
|
.writedead\@
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
LoadCellToHRAM: MACRO
|
||||||
|
; \1 = offset to Old pointer
|
||||||
|
; destroys A, D, E, H, L
|
||||||
|
; increments C
|
||||||
|
|
||||||
|
; load old pointer into hl
|
||||||
|
ld hl, Old
|
||||||
|
ld a, [hl+]
|
||||||
|
ld h, [hl]
|
||||||
|
ld l, a
|
||||||
|
|
||||||
|
; add offset
|
||||||
|
IF \1 != 0
|
||||||
|
ld de, \1
|
||||||
|
add hl, de
|
||||||
|
ENDC
|
||||||
|
|
||||||
|
; load neighbor
|
||||||
|
ld a, [hl]
|
||||||
|
|
||||||
|
; store in HRAM
|
||||||
|
ld [$FF00+c], a
|
||||||
|
|
||||||
|
; increment hram pointer
|
||||||
|
inc c
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
SECTION "Load cell group and 8 neighbors to HRAM, then compute", ROM0
|
||||||
|
; \1..\8 offset to neighbors
|
||||||
|
; destroys all registers
|
||||||
|
ConwayGroup: MACRO
|
||||||
|
|
||||||
|
; pointer to HRAM
|
||||||
|
ld c, LOW(Cells)
|
||||||
|
|
||||||
|
; load current 2x2 cell then neighbor 2x2 cells to HRAM from old buffer
|
||||||
|
LoadCellToHRAM 0
|
||||||
|
LoadCellToHRAM \1
|
||||||
|
LoadCellToHRAM \2
|
||||||
|
LoadCellToHRAM \3
|
||||||
|
LoadCellToHRAM \4
|
||||||
|
LoadCellToHRAM \5
|
||||||
|
LoadCellToHRAM \6
|
||||||
|
LoadCellToHRAM \7
|
||||||
|
LoadCellToHRAM \8
|
||||||
|
|
||||||
|
; reset result
|
||||||
|
xor a
|
||||||
|
ld l, a
|
||||||
|
|
||||||
|
; compute all 4 cells in current 2x2 cell
|
||||||
|
Conway 14, 4, 10, 8, 12
|
||||||
|
Conway 13, 6, 12, 4, 5
|
||||||
|
Conway 11, 2, 3, 2, 10
|
||||||
|
Conway 7, 0, 5, 1, 3
|
||||||
|
|
||||||
|
; move result to B
|
||||||
|
ld b, l
|
||||||
|
|
||||||
|
; load new pointer
|
||||||
|
ld hl, New
|
||||||
|
ld a, [hl+]
|
||||||
|
ld h, [hl]
|
||||||
|
ld l, a
|
||||||
|
|
||||||
|
; save result to new buffer
|
||||||
|
ld [hl], b
|
||||||
|
ENDM
|
||||||
|
|
||||||
SECTION "Timer Interrupt Handler", ROM0[$50]
|
SECTION "Timer Interrupt Handler", ROM0[$50]
|
||||||
TimerInterruptHandler:
|
TimerInterruptHandler:
|
||||||
reti
|
reti
|
||||||
@@ -153,8 +297,7 @@ Start:
|
|||||||
|
|
||||||
.topleft
|
.topleft
|
||||||
; handle top left corner
|
; handle top left corner
|
||||||
ld hl, TopLeftCorner
|
ConwayGroup 1, 21, 20, 39, 19, 359, 340, 341
|
||||||
call ConwayGroup
|
|
||||||
|
|
||||||
; advance to next cell in top row
|
; advance to next cell in top row
|
||||||
ld hl, New
|
ld hl, New
|
||||||
@@ -168,8 +311,7 @@ Start:
|
|||||||
ld [XLoop], a
|
ld [XLoop], a
|
||||||
|
|
||||||
; handle top row cell
|
; handle top row cell
|
||||||
ld hl, TopRow
|
ConwayGroup 1, 21, 20, 19, -1, 339, 340, 341
|
||||||
call ConwayGroup
|
|
||||||
|
|
||||||
; advance to next cell in top row
|
; advance to next cell in top row
|
||||||
ld hl, New
|
ld hl, New
|
||||||
@@ -180,12 +322,11 @@ Start:
|
|||||||
; loop horizontally
|
; loop horizontally
|
||||||
ld a, [XLoop]
|
ld a, [XLoop]
|
||||||
dec a
|
dec a
|
||||||
jr nz, .top
|
jp nz, .top
|
||||||
|
|
||||||
; handle top right corner
|
; handle top right corner
|
||||||
.topright
|
.topright
|
||||||
ld hl, TopRightCorner
|
ConwayGroup -19, 1, 20, 19, -1, 339, 340, 321
|
||||||
call ConwayGroup
|
|
||||||
|
|
||||||
; advance pointers to next row
|
; advance pointers to next row
|
||||||
ld hl, New
|
ld hl, New
|
||||||
@@ -198,8 +339,7 @@ Start:
|
|||||||
ld [YLoop], a
|
ld [YLoop], a
|
||||||
|
|
||||||
; handle first element in row
|
; handle first element in row
|
||||||
ld hl, LeftColumn
|
ConwayGroup 1, 21, 20, 39, 19, -1, -20, -19
|
||||||
call ConwayGroup
|
|
||||||
|
|
||||||
; advance to next cell
|
; advance to next cell
|
||||||
ld hl, New
|
ld hl, New
|
||||||
@@ -212,8 +352,7 @@ Start:
|
|||||||
ld [XLoop], a
|
ld [XLoop], a
|
||||||
|
|
||||||
; handle element inside row
|
; handle element inside row
|
||||||
ld hl, Inner
|
ConwayGroup 1, 21, 20, 19, -1, -21, -20, -19
|
||||||
call ConwayGroup
|
|
||||||
|
|
||||||
; advance to next cell
|
; advance to next cell
|
||||||
ld hl, New
|
ld hl, New
|
||||||
@@ -230,12 +369,11 @@ Start:
|
|||||||
; loop horizontally
|
; loop horizontally
|
||||||
ld a, [XLoop]
|
ld a, [XLoop]
|
||||||
dec a
|
dec a
|
||||||
jr nz, .inner
|
jp nz, .inner
|
||||||
|
|
||||||
; handle last element in row
|
; handle last element in row
|
||||||
.rightcolumn
|
.rightcolumn
|
||||||
ld hl, RightColumn
|
ConwayGroup -19, 1, 20, 19, -1, -21, -20, -39
|
||||||
call ConwayGroup
|
|
||||||
|
|
||||||
; advance to next row
|
; advance to next row
|
||||||
ld hl, New
|
ld hl, New
|
||||||
@@ -246,12 +384,11 @@ Start:
|
|||||||
; loop vertically
|
; loop vertically
|
||||||
ld a, [YLoop]
|
ld a, [YLoop]
|
||||||
dec a
|
dec a
|
||||||
jr nz, .leftcolumn
|
jp nz, .leftcolumn
|
||||||
|
|
||||||
; handle bottom left element
|
; handle bottom left element
|
||||||
.bottomleft
|
.bottomleft
|
||||||
ld hl, BottomLeftCorner
|
ConwayGroup 1, -339, -340, -321, 19, -1, -20, -19
|
||||||
call ConwayGroup
|
|
||||||
|
|
||||||
; advance to next cell in bottom row
|
; advance to next cell in bottom row
|
||||||
ld hl, New
|
ld hl, New
|
||||||
@@ -265,8 +402,7 @@ Start:
|
|||||||
ld [XLoop], a
|
ld [XLoop], a
|
||||||
|
|
||||||
; handle top row cell
|
; handle top row cell
|
||||||
ld hl, BottomRow
|
ConwayGroup 1, -339, -340, -341, -1, -21, -20, -19
|
||||||
call ConwayGroup
|
|
||||||
|
|
||||||
; advance to next cell in top row
|
; advance to next cell in top row
|
||||||
ld hl, New
|
ld hl, New
|
||||||
@@ -277,12 +413,11 @@ Start:
|
|||||||
; loop horizontally
|
; loop horizontally
|
||||||
ld a, [XLoop]
|
ld a, [XLoop]
|
||||||
dec a
|
dec a
|
||||||
jr nz, .bottom
|
jp nz, .bottom
|
||||||
|
|
||||||
; handle last element
|
; handle last element
|
||||||
.bottomright
|
.bottomright
|
||||||
ld hl, BottomRightCorner
|
ConwayGroup -19, -359, -340, -341, -1, -21, -20, -39
|
||||||
call ConwayGroup
|
|
||||||
|
|
||||||
; increment old pointer to first byte after buffer
|
; increment old pointer to first byte after buffer
|
||||||
ld hl, Old
|
ld hl, Old
|
||||||
@@ -375,167 +510,6 @@ Start:
|
|||||||
|
|
||||||
jp .mainloop
|
jp .mainloop
|
||||||
|
|
||||||
AddLiveNeighbors: MACRO
|
|
||||||
; H register will store number of alive neighbors
|
|
||||||
|
|
||||||
; load current cell and mask out bits that are not neighbors
|
|
||||||
ld c, LOW(Cells + \1)
|
|
||||||
ld a, [$FF00+c]
|
|
||||||
ld b, \2
|
|
||||||
and a, b
|
|
||||||
|
|
||||||
; count bits set
|
|
||||||
ld de, BitsSet
|
|
||||||
add a, e
|
|
||||||
ld e, a
|
|
||||||
ld a, [de]
|
|
||||||
|
|
||||||
; add to alive
|
|
||||||
add a, h
|
|
||||||
ld h, a
|
|
||||||
ENDM
|
|
||||||
|
|
||||||
Conway: MACRO
|
|
||||||
; \1 = mask for neighbors in inner cell
|
|
||||||
; \2 = first useful neighbor 2x2 cell
|
|
||||||
; \3 = mask for first useful neighbor 2x2 cell
|
|
||||||
; \4 = mask for second useful neighbor 2x2 cell
|
|
||||||
; \5 = mask for third useful neighbor 2x2 cell
|
|
||||||
;
|
|
||||||
; C will store final 2x2 updated cell
|
|
||||||
|
|
||||||
; reset alive counter
|
|
||||||
ld h, 0
|
|
||||||
|
|
||||||
; Check all neighbors
|
|
||||||
AddLiveNeighbors 0, \1
|
|
||||||
AddLiveNeighbors (1 + (\2 + 0) % 8), \3
|
|
||||||
AddLiveNeighbors (1 + (\2 + 1) % 8), \4
|
|
||||||
AddLiveNeighbors (1 + (\2 + 2) % 8), \5
|
|
||||||
|
|
||||||
; load current group mask
|
|
||||||
ld b, (~\1) & $F
|
|
||||||
|
|
||||||
; load current cell group
|
|
||||||
ldh a, [Cells]
|
|
||||||
|
|
||||||
; mask data
|
|
||||||
and a, b
|
|
||||||
|
|
||||||
; put alive neighbors in A
|
|
||||||
ld a, h
|
|
||||||
|
|
||||||
jr z, .dead\@
|
|
||||||
;.alive
|
|
||||||
; check if there is two or three neighbors
|
|
||||||
cp a, 2
|
|
||||||
jr c, .writedead\@
|
|
||||||
cp a, 4
|
|
||||||
jr nc, .writedead\@
|
|
||||||
|
|
||||||
.writealive\@
|
|
||||||
; add mask to result
|
|
||||||
inc c
|
|
||||||
jr .writedead\@
|
|
||||||
|
|
||||||
.dead\@
|
|
||||||
; check if there is three neighbors
|
|
||||||
cp a, 3
|
|
||||||
jr z, .writealive\@
|
|
||||||
|
|
||||||
.writedead\@
|
|
||||||
ENDM
|
|
||||||
|
|
||||||
SECTION "Load cell group and 8 neighbors to HRAM, then compute", ROM0
|
|
||||||
; hl = pointer to neighbor offsets
|
|
||||||
; destroys all registers
|
|
||||||
ConwayGroup:
|
|
||||||
; save pointer to neighbors
|
|
||||||
push hl
|
|
||||||
|
|
||||||
; pointer to HRAM
|
|
||||||
ld c, LOW(Cells)
|
|
||||||
|
|
||||||
; load old pointer into hl
|
|
||||||
ld hl, Old
|
|
||||||
ld a, [hl+]
|
|
||||||
ld h, [hl]
|
|
||||||
ld l, a
|
|
||||||
|
|
||||||
; load cell group
|
|
||||||
ld a, [hl]
|
|
||||||
|
|
||||||
; write cell group into hram
|
|
||||||
ld [$FF00+c], a
|
|
||||||
|
|
||||||
; increment hram pointer
|
|
||||||
inc c
|
|
||||||
|
|
||||||
; counter to 8
|
|
||||||
ld b, 8
|
|
||||||
|
|
||||||
.loop
|
|
||||||
; restore pointer to neighbors
|
|
||||||
pop hl
|
|
||||||
|
|
||||||
; load offset into de
|
|
||||||
ld a, [hl+]
|
|
||||||
ld e, a
|
|
||||||
ld a, [hl+]
|
|
||||||
ld d, a
|
|
||||||
|
|
||||||
; save incremented pointer to neighbors
|
|
||||||
push hl
|
|
||||||
|
|
||||||
; load old pointer into hl
|
|
||||||
ld hl, Old
|
|
||||||
ld a, [hl+]
|
|
||||||
ld h, [hl]
|
|
||||||
ld l, a
|
|
||||||
|
|
||||||
; add offset
|
|
||||||
add hl, de
|
|
||||||
|
|
||||||
; load neighbor
|
|
||||||
ld a, [hl]
|
|
||||||
|
|
||||||
; store neighbor into hram
|
|
||||||
ld [$FF00+c], a
|
|
||||||
|
|
||||||
; increment pointer into hram
|
|
||||||
inc c
|
|
||||||
|
|
||||||
; decrement counter
|
|
||||||
dec b
|
|
||||||
|
|
||||||
; continue to next neighbor if any
|
|
||||||
jr nz, .loop
|
|
||||||
|
|
||||||
.compute
|
|
||||||
; remove pointer to offsets from stack
|
|
||||||
pop hl
|
|
||||||
|
|
||||||
; reset result
|
|
||||||
xor a
|
|
||||||
ld c, a
|
|
||||||
|
|
||||||
; compute all 4 cells
|
|
||||||
Conway 14, 4, 10, 8, 12
|
|
||||||
Conway 13, 6, 12, 4, 5
|
|
||||||
Conway 11, 2, 3, 2, 10
|
|
||||||
Conway 7, 0, 5, 1, 3
|
|
||||||
|
|
||||||
; load new pointer
|
|
||||||
ld hl, New
|
|
||||||
ld a, [hl+]
|
|
||||||
ld h, [hl]
|
|
||||||
ld l, a
|
|
||||||
|
|
||||||
; save result to new buffer
|
|
||||||
ld [hl], c
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
SECTION "V-Blank Interrupt Handler", ROM0[$40]
|
SECTION "V-Blank Interrupt Handler", ROM0[$40]
|
||||||
VBlankInterruptHandler:
|
VBlankInterruptHandler:
|
||||||
; save registers
|
; save registers
|
||||||
@@ -669,19 +643,6 @@ TilesLeft: ds 1 ; number of tiles left to render in current line
|
|||||||
Video: ds 2 ; progressing pointer in tilemap (VRAM)
|
Video: ds 2 ; progressing pointer in tilemap (VRAM)
|
||||||
Rendered: ds 2 ; progressing pointer in old buffer
|
Rendered: ds 2 ; progressing pointer in old buffer
|
||||||
|
|
||||||
SECTION "Game of Life neighboring cells offset tables", ROM0
|
|
||||||
; for a looping grid of 20x18 cells
|
|
||||||
; order matters R, BR, B, BL, L, TL, T, TR
|
|
||||||
TopLeftCorner: dw 1, 21, 20, 39, 19, 359, 340, 341
|
|
||||||
TopRightCorner: dw -19, 1, 20, 19, -1, 339, 340, 321
|
|
||||||
BottomLeftCorner: dw 1, -339, -340, -321, 19, -1, -20, -19
|
|
||||||
BottomRightCorner: dw -19, -359, -340, -341, -1, -21, -20, -39
|
|
||||||
TopRow: dw 1, 21, 20, 19, -1, 339, 340, 341
|
|
||||||
BottomRow: dw 1, -339, -340, -341, -1, -21, -20, -19
|
|
||||||
LeftColumn: dw 1, 21, 20, 39, 19, -1, -20, -19
|
|
||||||
RightColumn: dw -19, 1, 20, 19, -1, -21, -20, -39
|
|
||||||
Inner: dw 1, 21, 20, 19, -1, -21, -20, -19
|
|
||||||
|
|
||||||
SECTION "Bits Set", ROM0, ALIGN[4]
|
SECTION "Bits Set", ROM0, ALIGN[4]
|
||||||
BitsSet:
|
BitsSet:
|
||||||
db 0; 0 = 0000
|
db 0; 0 = 0000
|
||||||
|
|||||||
Reference in New Issue
Block a user