better interrupt handling, rendering in hbl still too slow, much faster automata update by only reading necessary neighbors

This commit is contained in:
2018-12-31 02:09:14 +01:00
parent 798e11c1d4
commit da8f88d72c

View File

@@ -82,9 +82,7 @@ Start:
ld a, IEF_VBLANK ld a, IEF_VBLANK
ld [rIE], a ld [rIE], a
; enable interrupts while clearing interrupt flags
xor a xor a
ei
ldh [rIF], a ldh [rIF], a
; wait for v-blank ; wait for v-blank
@@ -147,8 +145,7 @@ Start:
.mainloop .mainloop
; enable v-blank and lcd stat interrupt for h-blank ; enable v-blank and lcd stat interrupt for h-blank
di ld a, IEF_VBLANK; | IEF_LCDC
ld a, IEF_VBLANK | IEF_LCDC
ld [rIE], a ld [rIE], a
xor a xor a
ei ei
@@ -314,7 +311,6 @@ Start:
ld a, IEF_VBLANK ld a, IEF_VBLANK
ld [rIE], a ld [rIE], a
xor a xor a
ei
ldh [rIF], a ldh [rIF], a
; wait v-blank ; wait v-blank
@@ -379,6 +375,71 @@ Start:
jp .mainloop jp .mainloop
CountLiveNeighbors: MACRO
; 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]
ld b, a
; add to alive
ldh a, [Alive]
add a, b
ldh [Alive], a
ENDM
Conway: MACRO
; reset alive counter
xor a
ldh [Alive], a
CountLiveNeighbors 0, \1
CountLiveNeighbors (1 + (\2 + 0) % 8), \3
CountLiveNeighbors (1 + (\2 + 1) % 8), \4
CountLiveNeighbors (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
; load alive count
ldh a, [Alive]
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
ldh a, [Result]
or a, b
ldh [Result], a
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 SECTION "Load cell group and 8 neighbors to HRAM, then compute", ROM0
; hl = pointer to neighbor offsets ; hl = pointer to neighbor offsets
; destroys all registers ; destroys all registers
@@ -453,17 +514,10 @@ ConwayGroup:
ldh [Result], a ldh [Result], a
; compute all 4 cells ; compute all 4 cells
ld hl, TopLeftMask Conway 14, 4, 10, 8, 12
call Conway Conway 13, 6, 12, 4, 5
Conway 11, 2, 3, 2, 10
ld hl, TopRightMask Conway 7, 0, 5, 1, 3
call Conway
ld hl, BottomLeftMask
call Conway
ld hl, BottomRightMask
call Conway
; load new pointer ; load new pointer
ld hl, New ld hl, New
@@ -479,92 +533,12 @@ ConwayGroup:
ret ret
SECTION "Conway cell compute", ROM0
; hl = pointer to cell group masks
Conway:
; reset alive counter
xor a
ldh [Alive], a
; load cells pointer
ld c, LOW(Cells)
.loop
; load next mask
ld a, [hl+]
; move mask to d
ld d, a
; load data
ld a, [$FF00+c]
; mask data
and a, d
; count bits set
ld de, BitsSet
add a, e
ld e, a
ld a, [de]
ld b, a
; add to alive
ldh a, [Alive]
add a, b
ldh [Alive], a
; increment cells pointer
inc c
; loop over all neighbors
ld a, c
cp a, LOW(Cells + 9)
jr nz, .loop
.decide
; load current group mask
ld b, [hl]
; load current cell group
ldh a, [Cells]
; mask data
and a, b
; load alive count
ldh a, [Alive]
jr z, .dead
.alive
; check if there is two or three neighbors
cp a, 2
ret c
cp a, 4
ret nc
.writealive
; add mask to result
ldh a, [Result]
or a, b
ldh [Result], a
ret
.dead
; check if there is three neighbors
cp a, 3
jr z, .writealive
.writedead
ret
SECTION "V-Blank Interrupt Handler", ROM0[$40] SECTION "V-Blank Interrupt Handler", ROM0[$40]
VBlankInterruptHandler: VBlankInterruptHandler:
; save registers ; save registers
push af push af
push de
push bc push bc
push de
push hl push hl
; render ; render
@@ -574,8 +548,8 @@ SECTION "LCD Stat Interrupt Handler", ROM0[$48]
LCDStatInterruptHandler: LCDStatInterruptHandler:
; save registers ; save registers
push af push af
push de
push bc push bc
push de
push hl push hl
; render ; render
@@ -583,14 +557,11 @@ LCDStatInterruptHandler:
SECTION "Render", ROM0 SECTION "Render", ROM0
Render: Render:
; check there are lines to render
ldh a, [LinesLeft]
and a
jr z, .exit
; check there are tiles to render ; check there are tiles to render
ldh a, [LinesLeft]
ld b, a
ldh a, [TilesLeft] ldh a, [TilesLeft]
and a or b
jr z, .exit jr z, .exit
.render .render
@@ -628,11 +599,12 @@ Render:
jr nz, .loop jr nz, .loop
; go to next line ; go to next line
push de ld a, l
ld de, 32 - 20 add a, 32 - 20
add hl, de ld l, a
pop de jr nc, .nocarry
ld c, 20 inc h
.nocarry
; loop while there are lines to render ; loop while there are lines to render
ld c, LOW(LinesLeft) ld c, LOW(LinesLeft)
@@ -643,6 +615,7 @@ Render:
ld a, 20 ld a, 20
ldh [TilesLeft], a ldh [TilesLeft], a
ld c, a
jr .nextline jr .nextline
@@ -661,8 +634,8 @@ Render:
.exit .exit
; restore registers saved in interrupt handler ; restore registers saved in interrupt handler
pop hl pop hl
pop bc
pop de pop de
pop bc
pop af pop af
; return from v-blank or lcd interrupt ; return from v-blank or lcd interrupt
@@ -708,13 +681,6 @@ LeftColumn: dw 1, 21, 20, 39, 19, -1, -20, -19
RightColumn: dw -19, 1, 20, 19, -1, -21, -20, -39 RightColumn: dw -19, 1, 20, 19, -1, -21, -20, -39
Inner: dw 1, 21, 20, 19, -1, -21, -20, -19 Inner: dw 1, 21, 20, 19, -1, -21, -20, -19
SECTION "Game of Life neighboring masks", ROM0
; order matters I, R, BR, B, BL, L, TL, T, TR, SELF
TopLeftMask: db 14, 0, 0, 0, 0, 10, 8, 12, 0, 1
TopRightMask: db 13, 5, 0, 0, 0, 0, 0, 12, 4, 2
BottomLeftMask: db 11, 0, 0, 3, 2, 10, 0, 0, 0, 4
BottomRightMask: db 7, 5, 1, 3, 0, 0, 0, 0, 0, 8
SECTION "Bits Set", ROM0, ALIGN[4] SECTION "Bits Set", ROM0, ALIGN[4]
BitsSet: BitsSet:
db 0; 0 = 0000 db 0; 0 = 0000
@@ -737,9 +703,9 @@ BitsSet:
SECTION "Default Map", ROM0 SECTION "Default Map", ROM0
DefaultMap: DefaultMap:
; 20x18 map with a glider on the top left corner ; 20x18 map with a glider on the top left corner
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 db 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
db 0, 1, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 db 3, 1, 0, 0, 0, 0, 0, 1, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
db 0, 9,12, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 db 0, 0, 0, 0, 0, 0, 0, 9,12, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
db 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 db 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0