From 9478fd7e2458deb9126da9b7533e35dadf8a6306 Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Mon, 31 Dec 2018 14:01:35 +0100 Subject: [PATCH] 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 --- Code/main.asm | 353 ++++++++++++++++++++++---------------------------- 1 file changed, 157 insertions(+), 196 deletions(-) diff --git a/Code/main.asm b/Code/main.asm index 9528acc..eb06eab 100644 --- a/Code/main.asm +++ b/Code/main.asm @@ -29,6 +29,150 @@ MemorySet: jr nz, MemorySet 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] TimerInterruptHandler: reti @@ -153,8 +297,7 @@ Start: .topleft ; handle top left corner - ld hl, TopLeftCorner - call ConwayGroup + ConwayGroup 1, 21, 20, 39, 19, 359, 340, 341 ; advance to next cell in top row ld hl, New @@ -168,8 +311,7 @@ Start: ld [XLoop], a ; handle top row cell - ld hl, TopRow - call ConwayGroup + ConwayGroup 1, 21, 20, 19, -1, 339, 340, 341 ; advance to next cell in top row ld hl, New @@ -180,12 +322,11 @@ Start: ; loop horizontally ld a, [XLoop] dec a - jr nz, .top + jp nz, .top ; handle top right corner .topright - ld hl, TopRightCorner - call ConwayGroup + ConwayGroup -19, 1, 20, 19, -1, 339, 340, 321 ; advance pointers to next row ld hl, New @@ -198,8 +339,7 @@ Start: ld [YLoop], a ; handle first element in row - ld hl, LeftColumn - call ConwayGroup + ConwayGroup 1, 21, 20, 39, 19, -1, -20, -19 ; advance to next cell ld hl, New @@ -212,8 +352,7 @@ Start: ld [XLoop], a ; handle element inside row - ld hl, Inner - call ConwayGroup + ConwayGroup 1, 21, 20, 19, -1, -21, -20, -19 ; advance to next cell ld hl, New @@ -230,12 +369,11 @@ Start: ; loop horizontally ld a, [XLoop] dec a - jr nz, .inner + jp nz, .inner ; handle last element in row .rightcolumn - ld hl, RightColumn - call ConwayGroup + ConwayGroup -19, 1, 20, 19, -1, -21, -20, -39 ; advance to next row ld hl, New @@ -246,12 +384,11 @@ Start: ; loop vertically ld a, [YLoop] dec a - jr nz, .leftcolumn + jp nz, .leftcolumn ; handle bottom left element .bottomleft - ld hl, BottomLeftCorner - call ConwayGroup + ConwayGroup 1, -339, -340, -321, 19, -1, -20, -19 ; advance to next cell in bottom row ld hl, New @@ -265,8 +402,7 @@ Start: ld [XLoop], a ; handle top row cell - ld hl, BottomRow - call ConwayGroup + ConwayGroup 1, -339, -340, -341, -1, -21, -20, -19 ; advance to next cell in top row ld hl, New @@ -277,12 +413,11 @@ Start: ; loop horizontally ld a, [XLoop] dec a - jr nz, .bottom + jp nz, .bottom ; handle last element .bottomright - ld hl, BottomRightCorner - call ConwayGroup + ConwayGroup -19, -359, -340, -341, -1, -21, -20, -39 ; increment old pointer to first byte after buffer ld hl, Old @@ -375,167 +510,6 @@ Start: 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] VBlankInterruptHandler: ; 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) 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] BitsSet: db 0; 0 = 0000