; FF80 CALL ; FF81 LOW ; FF82 HIGH ; FF83 RET ; pattern repeats for the first 16 bytes so we can have some call vectors for the scene system DEF SCENE_SETUP EQU $c101 DEF SCENE_UPDATE EQU SCENE_SETUP + 4 ; call then ret is 3+1 bytes DEF SCENE_DRAW EQU SCENE_UPDATE + 4 DEF SCENE_TEARDOWN EQU SCENE_DRAW + 4 DEF INTERRUPT_LCD EQU $c111 def ZEROES equ $D000 def ONES equ $D200 DEF rMYBTN EQU $FFA8 DEF rMYBTNP EQU rMYBTN + 1 DEF rDELTAT EQU rMYBTNP + 1 DEF VARIABLES_START EQU rDELTAT+1 INCLUDE "hardware.inc" SECTION "Interrupts", ROM0[$0] ds $48 - @, 0 call INTERRUPT_LCD - 1 ret SECTION "Header", ROM0[$100] jp EntryPoint ds $150 - @, 0 ; Make room for the header EntryPoint: ; Shut down audio circuitry ld a, 0 ldh [rNR52], a ; shut down audio ldh [rDIV], a ; reset timer just in case?? ldh [rLCDC], a ; shut down screen ld a, 0 ld hl, ZEROES ld bc, $200 .buildZeros ld a, 0 ld [hl+], a ld a, b or a, c dec bc jp nz, .buildZeros ld a, 1 ld hl, ONES ld bc, $200 .buildOnes ld a, 1 ld [hl+], a ld a, b or a, c dec bc jp nz, .buildOnes ld hl, UITiles ld de, $8000 + $100*16 ld bc, (UITilesEnd - UITiles) call CopyRangeUnsafe ld hl, LetterTiles ; map the small font into vram at ascii locations ld de, $8000 + (127 + $21)*16 ld bc, LetterTilesEnd - LetterTiles call CopyRangeUnsafe ; set up the scene and interrupt vectors ld hl, Instructions ld a, [hl] ; get the value of a call instruction so we can shove it into our handles ld hl, SCENE_SETUP - 1 ld [SCENE_SETUP - 1], a ld hl, SCENE_UPDATE - 1 ld [hl], a ld hl, SCENE_DRAW - 1 ld [hl], a ld hl, SCENE_TEARDOWN - 1 ld [hl], a ld hl, INTERRUPT_LCD - 1 ld [hl], a ld hl, Instructions inc hl ld a, [hl] ; get the value of a call instruction so we can shove it into our handles ld hl, SCENE_SETUP ld [hl], a ld hl, SCENE_UPDATE ld [hl], a ld hl, SCENE_DRAW ld [hl], a ld hl, SCENE_TEARDOWN ld [hl], a ld hl, INTERRUPT_LCD ld [hl], a ld hl, Instructions inc hl inc hl ld a, [hl] ; get the value of a call instruction so we can shove it into our handles ld hl, SCENE_SETUP + 1 ld [hl], a ld hl, SCENE_UPDATE + 1 ld [hl], a ld hl, SCENE_DRAW + 1 ld [hl], a ld hl, SCENE_TEARDOWN + 1 ld [hl], a ld hl, INTERRUPT_LCD + 1 ld [hl], a ld hl, Instructions inc hl inc hl inc hl ld a, [hl] ; get the value of a call instruction so we can shove it into our handles ld hl, SCENE_SETUP + 2 ld [hl], a ld hl, SCENE_UPDATE + 2 ld [hl], a ld hl, SCENE_DRAW + 2 ld [hl], a ld hl, SCENE_TEARDOWN + 2 ld [hl], a ld hl, INTERRUPT_LCD + 2 ld [hl], a ; set up our scene vectors ld hl, ScreenMainMenu call ChangeScene Loop: ; okay this is kinda sketchy. we want a delta time variable. ; we've got two eight-bit counters, one at 4096hz and one at 16384hz ; we can definitely reset the faster counter. ; but! that's gonna overflow every frame. ; however! it should always overflow the same amount ; because we're basically running once per frame (AwaitLine call later) ; if we assume it overflows once per frame, then the total value should be ; 256 + [rDIV]. so if we divide by two (or more!) the total value will be ; 256/2 + [rDIV]/2. so we just have to right shift and add 128. ; or right shift twice and add 64. this loses us precision but we didn't need ; it anyway. ldh a, [rDIV] ldh [rDIV], a ; this will reset the timer sra a sra a add a, 64 ldh [rDELTAT], a xor a, a ; zero a out in one cycle ; store dpad and btn state in the rMYBTN register ld hl, rP1 ld [hl], P1F_GET_DPAD ld a, [hl] ld a, [hl] ld a, [hl] ld a, [hl] cpl and a, %00001111 ld b, a ld [hl], P1F_GET_BTN ld a, [hl] ld a, [hl] ld a, [hl] ld a, [hl] cpl and a, %00001111 swap a or a, b ld b, a ; put new input state in b ldh a, [rMYBTN] ; previous input state in a cpl ; a holds buttons which weren't pressed last frame and a, b ; select buttons which were pressed this frame, but not last frame ldh [rMYBTNP], a ; save that as btnp state ld a, b ; select buttons which were pressed this frame ldh [rMYBTN], a ; save that as btn state call SCENE_UPDATE - 1 ; hope this takes not too many scanlines! ld b, 144 call AwaitLine call SCENE_DRAW - 1 ; hope this takes fewer than 9 scanlines! ; either way it's going to eat into the update timing ; at this point we want to make sure that scanline 153 has passed ; we should check if we're past there and skip this await if necessary ld b, 10 call AwaitLine jp Loop ChangeScene: ; hl should be a pointer to, in sequence, setup update draw teardown call SCENE_TEARDOWN - 1 ld a, [hl+] ld [SCENE_SETUP], a ld a, [hl+] ld [SCENE_SETUP+1], a ld a, [hl+] ld [SCENE_UPDATE], a ld a, [hl+] ld [SCENE_UPDATE+1], a ld a, [hl+] ld [SCENE_DRAW], a ld a, [hl+] ld [SCENE_DRAW+1], a ld a, [hl+] ld [SCENE_TEARDOWN], a ld a, [hl+] ld [SCENE_TEARDOWN+1], a call SCENE_SETUP - 1 ret AwaitLine: ; put the line you want to reach in b ld a, [rLY] cp b jp nz, AwaitLine ret ArrayClampLooping: ; loops a to be in the array, assuming hl points to the length cp a, [hl] ; if a == length... jp nz, :+ ld a, 0 ; set it to 0 : cp a, $FF ; otherwise if a == $FF... jp nz, :+ ld a, [hl] dec a ; then set it to length-1 : ret ; a is return value PassList: ; hl has the address of a list. step past it. ld b, 0 ld c, [hl] ; bc has length inc hl ; step over length add hl, bc ; step past all the entries ret PrintString: ; write ascii string which has been prefixed by its length. at hl ; de should be location in tile map to write ld b, [hl] ld a, b cp a, 0 ret z inc hl PrintBChars: ;write ascii characters. will not respect newlines or anything like that ; hl should be the source of ascii text ; de should be the location in the tile map to start writing at ; b should be the length ld a, [hli] or a, %10000000 ld [de], a inc de dec b jp nz, PrintBChars ret ;thanks to https://gbdev.io/pandocs/OAM_DMA_Transfer.html for this routine ; a should be the high byte of where we're DMAing from (ld a, $c0 in my case probably) ; de should have the address in hram for where to paste to RunDMA: di push de push af ld hl, run_dma_tail ld bc, run_dma_tail.run_dma_tail_end - run_dma_tail call CopyRangeUnsafe pop af run_dma: ; This part must be in ROM. ld bc, $2846 ; B: wait time; C: LOW($FF46) ret ; we pushed de before, so this should "return" to execute that (HRAM) address run_dma_tail: ; This part must be in HRAM. ldh [c], a .wait dec b jr nz, .wait ei ret z ; Conditional `ret` is 1 M-cycle slower, which avoids ; reading from the stack on the last M-cycle of DMA. .run_dma_tail_end Instructions: call SCENE_UPDATE + 2 ret UITiles: db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 db $05,$00,$05,$00,$05,$00,$05,$00,$05,$00,$fd,$00,$00,$00,$fd,$00 db $00,$ff,$ff,$ff,$ff,$ff,$ff,$00,$00,$ff,$00,$00,$00,$00,$00,$00 db $70,$e8,$70,$e8,$70,$e8,$70,$e8,$70,$e8,$70,$e8,$70,$e8,$70,$e8 db $0e,$17,$0e,$17,$0e,$17,$0e,$17,$0e,$17,$0e,$17,$0e,$17,$0e,$17 db $00,$00,$00,$00,$00,$00,$00,$ff,$ff,$00,$ff,$ff,$ff,$ff,$00,$ff db $70,$e8,$70,$e8,$70,$e8,$70,$ef,$7f,$f0,$3f,$7f,$1f,$3f,$00,$1f db $0e,$17,$0e,$17,$0e,$17,$0e,$f7,$fe,$0f,$fc,$fe,$f8,$fc,$00,$f8 db $00,$f8,$f8,$fc,$fc,$fe,$fe,$0f,$0e,$f7,$0e,$17,$0e,$17,$0e,$17 db $00,$1f,$1f,$3f,$3f,$7f,$7f,$f0,$70,$ef,$70,$e8,$70,$e8,$70,$e8 db $00,$00,$ff,$00,$ff,$00,$aa,$55,$00,$ff,$00,$ff,$ff,$ff,$ff,$ff db $63,$1f,$73,$0f,$63,$1f,$73,$0f,$63,$1f,$73,$0f,$63,$1f,$73,$0f db $ce,$f0,$c6,$f8,$ce,$f0,$c6,$f8,$ce,$f0,$c6,$f8,$ce,$f0,$c6,$f8 db $ff,$ff,$ff,$ff,$00,$ff,$00,$ff,$55,$aa,$ff,$00,$ff,$00,$00,$00 db $00,$00,$3f,$00,$7f,$00,$7a,$05,$68,$17,$70,$0f,$63,$1f,$73,$0f db $00,$00,$fc,$00,$fe,$00,$ae,$50,$1e,$e0,$06,$f8,$ce,$f0,$c6,$f8 db $ce,$f0,$c6,$f8,$0e,$f0,$16,$e8,$5e,$a0,$fe,$00,$fc,$00,$00,$00 db $63,$1f,$73,$0f,$60,$1f,$78,$07,$75,$0a,$7f,$00,$3f,$00,$00,$00 db $00,$0f,$00,$10,$00,$10,$00,$10,$00,$0f,$00,$10,$00,$10,$00,$10 db $00,$7f,$00,$80,$00,$80,$00,$80,$00,$7f,$00,$10,$00,$10,$00,$10 db $00,$0f,$00,$10,$00,$10,$00,$10,$00,$7f,$00,$80,$00,$80,$00,$80 db $00,$7f,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 db $00,$0f,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 db $56,$c3,$6a,$c3,$56,$c3,$6a,$c3,$56,$c3,$6a,$c3,$7e,$ff,$00,$ff db $00,$ff,$7e,$ff,$56,$c3,$6a,$c3,$56,$c3,$6a,$c3,$56,$c3,$6a,$c3 db $99,$5a,$99,$5a,$99,$5a,$99,$5a,$99,$5a,$81,$42,$81,$7e,$ff,$00 db $ff,$00,$81,$7e,$81,$42,$99,$5a,$99,$5a,$99,$5a,$99,$5a,$99,$5a UITilesEnd: LetterTiles: db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 db $03,$03,$07,$07,$0f,$0f,$0e,$0e,$1c,$1c,$30,$30,$c0,$c0,$c0,$c0 db $24,$24,$6c,$6c,$6c,$6c,$48,$48,$00,$00,$00,$00,$00,$00,$00,$00 db $1a,$1a,$1a,$1a,$7f,$7f,$34,$34,$34,$34,$fe,$fe,$68,$68,$68,$68 db $08,$08,$3c,$3c,$6a,$6a,$68,$68,$3c,$3c,$0a,$0a,$6a,$6a,$3c,$3c db $63,$63,$a6,$a6,$ac,$ac,$d8,$d8,$1b,$1b,$35,$35,$65,$65,$c6,$c6 db $18,$18,$24,$24,$28,$28,$18,$18,$2c,$2c,$66,$66,$67,$67,$39,$39 db $18,$18,$18,$18,$18,$18,$30,$30,$00,$00,$00,$00,$00,$00,$00,$00 db $04,$04,$0c,$0c,$18,$18,$10,$10,$10,$10,$18,$18,$0c,$0c,$04,$04 db $20,$20,$30,$30,$18,$18,$08,$08,$08,$08,$18,$18,$30,$30,$20,$20 db $00,$00,$08,$08,$28,$28,$1e,$1e,$78,$78,$14,$14,$10,$10,$00,$00 db $00,$00,$00,$00,$18,$18,$18,$18,$7e,$7e,$18,$18,$18,$18,$00,$00 db $00,$00,$00,$00,$00,$00,$00,$00,$0c,$0c,$0c,$0c,$0c,$0c,$18,$18 db $00,$00,$00,$00,$00,$00,$1c,$1c,$38,$38,$00,$00,$00,$00,$00,$00 db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$18,$18,$18,$00,$00 db $04,$04,$0c,$0c,$0c,$0c,$18,$18,$18,$18,$30,$30,$30,$30,$20,$20 db $00,$00,$38,$38,$64,$64,$64,$64,$64,$64,$64,$64,$64,$64,$38,$38 db $08,$08,$18,$18,$38,$38,$18,$18,$18,$18,$18,$18,$18,$18,$3c,$3c db $00,$00,$38,$38,$4c,$4c,$0c,$0c,$0c,$0c,$18,$18,$30,$30,$7c,$7c db $00,$00,$3c,$3c,$06,$06,$06,$06,$1c,$1c,$06,$06,$06,$06,$3c,$3c db $00,$00,$04,$04,$26,$26,$26,$26,$3e,$3e,$06,$06,$06,$06,$04,$04 db $00,$00,$7c,$7c,$64,$64,$60,$60,$78,$78,$44,$44,$04,$04,$38,$38 db $00,$00,$20,$20,$30,$30,$30,$30,$3c,$3c,$32,$32,$32,$32,$1c,$1c db $00,$00,$7c,$7c,$4c,$4c,$0c,$0c,$3e,$3e,$18,$18,$30,$30,$20,$20 db $00,$00,$78,$78,$64,$64,$64,$64,$38,$38,$64,$64,$64,$64,$3c,$3c db $00,$00,$38,$38,$4c,$4c,$4c,$4c,$3c,$3c,$0c,$0c,$0c,$0c,$18,$18 db $00,$00,$00,$00,$18,$18,$18,$18,$00,$00,$18,$18,$18,$18,$00,$00 db $00,$00,$00,$00,$0c,$0c,$0c,$0c,$00,$00,$0c,$0c,$0c,$0c,$18,$18 db $00,$00,$0c,$0c,$18,$18,$30,$30,$60,$60,$30,$30,$18,$18,$0c,$0c db $00,$00,$00,$00,$3c,$3c,$3c,$3c,$00,$00,$3c,$3c,$3c,$3c,$00,$00 db $00,$00,$30,$30,$18,$18,$0c,$0c,$06,$06,$0c,$0c,$18,$18,$30,$30 db $38,$38,$6c,$6c,$24,$24,$0c,$0c,$18,$18,$18,$18,$00,$00,$18,$18 db $3c,$3c,$62,$62,$59,$59,$45,$45,$5d,$5d,$5d,$5d,$63,$63,$38,$38 db $00,$00,$38,$38,$34,$34,$32,$32,$3e,$3e,$32,$32,$32,$32,$32,$32 db $00,$00,$7c,$7c,$32,$32,$32,$32,$3c,$3c,$32,$32,$32,$32,$1c,$1c db $00,$00,$3c,$3c,$72,$72,$62,$62,$60,$60,$60,$60,$62,$62,$3c,$3c db $00,$00,$f8,$f8,$64,$64,$62,$62,$62,$62,$62,$62,$62,$62,$3c,$3c db $00,$00,$fc,$fc,$60,$60,$60,$60,$78,$78,$60,$60,$60,$60,$3c,$3c db $00,$00,$fc,$fc,$60,$60,$60,$60,$78,$78,$60,$60,$60,$60,$20,$20 db $00,$00,$78,$78,$64,$64,$60,$60,$60,$60,$6e,$6e,$64,$64,$3c,$3c db $00,$00,$40,$40,$62,$62,$62,$62,$7e,$7e,$62,$62,$62,$62,$22,$22 db $00,$00,$10,$10,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$08,$08 db $00,$00,$08,$08,$0c,$0c,$0c,$0c,$0c,$0c,$4c,$4c,$6c,$6c,$3c,$3c db $00,$00,$40,$40,$64,$64,$68,$68,$70,$70,$68,$68,$64,$64,$22,$22 db $00,$00,$20,$20,$30,$30,$30,$30,$30,$30,$30,$30,$32,$32,$1e,$1e db $00,$00,$3e,$3e,$6a,$6a,$6a,$6a,$6a,$6a,$62,$62,$62,$62,$22,$22 db $00,$00,$72,$72,$6a,$6a,$6a,$6a,$6a,$6a,$66,$66,$62,$62,$22,$22 db $00,$00,$3c,$3c,$66,$66,$62,$62,$62,$62,$62,$62,$32,$32,$1e,$1e db $00,$00,$f8,$f8,$64,$64,$64,$64,$7c,$7c,$60,$60,$60,$60,$20,$20 db $00,$00,$38,$38,$64,$64,$62,$62,$62,$62,$6a,$6a,$64,$64,$3b,$3b db $00,$00,$f8,$f8,$64,$64,$64,$64,$7c,$7c,$68,$68,$64,$64,$23,$23 db $00,$00,$38,$38,$64,$64,$60,$60,$38,$38,$04,$04,$64,$64,$38,$38 db $00,$00,$7e,$7e,$5a,$5a,$18,$18,$18,$18,$18,$18,$18,$18,$08,$08 db $00,$00,$40,$40,$62,$62,$62,$62,$62,$62,$62,$62,$62,$62,$3c,$3c db $00,$00,$40,$40,$62,$62,$62,$62,$62,$62,$24,$24,$34,$34,$18,$18 db $00,$00,$c3,$c3,$62,$62,$62,$62,$6a,$6a,$6a,$6a,$6a,$6a,$34,$34 db $00,$00,$42,$42,$62,$62,$34,$34,$18,$18,$3c,$3c,$66,$66,$42,$42 db $00,$00,$4c,$4c,$4c,$4c,$4c,$4c,$3c,$3c,$0c,$0c,$4c,$4c,$78,$78 db $00,$00,$7e,$7e,$46,$46,$0c,$0c,$18,$18,$30,$30,$62,$62,$7e,$7e db $7c,$7c,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$60,$7c,$7c db $20,$20,$30,$30,$30,$30,$18,$18,$18,$18,$0c,$0c,$0c,$0c,$04,$04 db $3e,$3e,$06,$06,$06,$06,$06,$06,$06,$06,$06,$06,$06,$06,$3e,$3e db $18,$18,$3c,$3c,$66,$66,$42,$42,$00,$00,$00,$00,$00,$00,$00,$00 db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7c,$7c,$3e,$3e db $30,$30,$18,$18,$0c,$0c,$04,$04,$00,$00,$00,$00,$00,$00,$00,$00 db $00,$00,$00,$00,$38,$38,$0c,$0c,$3c,$3c,$4c,$4c,$3a,$3a,$00,$00 db $00,$00,$30,$30,$30,$30,$3c,$3c,$32,$32,$32,$32,$3c,$3c,$00,$00 db $00,$00,$00,$00,$1c,$1c,$30,$30,$30,$30,$30,$30,$1c,$1c,$00,$00 db $00,$00,$0c,$0c,$0c,$0c,$3c,$3c,$4c,$4c,$4c,$4c,$3c,$3c,$00,$00 db $00,$00,$00,$00,$38,$38,$64,$64,$78,$78,$60,$60,$3c,$3c,$00,$00 db $00,$00,$0e,$0e,$18,$18,$3c,$3c,$18,$18,$18,$18,$18,$18,$00,$00 db $00,$00,$00,$00,$3c,$3c,$4c,$4c,$4c,$4c,$3c,$3c,$0c,$0c,$38,$38 db $00,$00,$60,$60,$60,$60,$78,$78,$64,$64,$64,$64,$64,$64,$00,$00 db $00,$00,$10,$10,$00,$00,$38,$38,$18,$18,$18,$18,$3c,$3c,$00,$00 db $00,$00,$08,$08,$00,$00,$0c,$0c,$0c,$0c,$0c,$0c,$2c,$2c,$18,$18 db $00,$00,$60,$60,$68,$68,$68,$68,$70,$70,$68,$68,$64,$64,$00,$00 db $00,$00,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$18,$18,$00,$00 db $00,$00,$00,$00,$74,$74,$6a,$6a,$6a,$6a,$6a,$6a,$6a,$6a,$00,$00 db $00,$00,$00,$00,$78,$78,$64,$64,$64,$64,$64,$64,$64,$64,$00,$00 db $00,$00,$00,$00,$38,$38,$64,$64,$64,$64,$64,$64,$38,$38,$00,$00 db $00,$00,$00,$00,$78,$78,$64,$64,$64,$64,$78,$78,$60,$60,$60,$60 db $00,$00,$00,$00,$3c,$3c,$4c,$4c,$4c,$4c,$3c,$3c,$0c,$0c,$0e,$0e db $00,$00,$00,$00,$1c,$1c,$30,$30,$30,$30,$30,$30,$30,$30,$00,$00 db $00,$00,$00,$00,$38,$38,$60,$60,$38,$38,$0c,$0c,$78,$78,$00,$00 db $00,$00,$30,$30,$78,$78,$30,$30,$30,$30,$30,$30,$1c,$1c,$00,$00 db $00,$00,$00,$00,$64,$64,$64,$64,$64,$64,$64,$64,$3c,$3c,$00,$00 db $00,$00,$00,$00,$64,$64,$64,$64,$64,$64,$28,$28,$10,$10,$00,$00 db $00,$00,$00,$00,$62,$62,$6a,$6a,$6a,$6a,$6a,$6a,$34,$34,$00,$00 db $00,$00,$00,$00,$64,$64,$38,$38,$18,$18,$2c,$2c,$46,$46,$00,$00 db $00,$00,$00,$00,$4c,$4c,$4c,$4c,$4c,$4c,$3c,$3c,$0c,$0c,$38,$38 db $00,$00,$00,$00,$7e,$7e,$0c,$0c,$18,$18,$30,$30,$7e,$7e,$00,$00 db $3c,$3c,$60,$60,$30,$30,$60,$60,$60,$60,$30,$30,$60,$60,$3c,$3c db $20,$20,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$10,$10 db $3c,$3c,$06,$06,$0c,$0c,$06,$06,$06,$06,$0c,$0c,$06,$06,$3c,$3c db $00,$00,$00,$00,$31,$31,$7b,$7b,$de,$de,$8c,$8c,$00,$00,$00,$00 db $c0,$c0,$a0,$a0,$b8,$b8,$b0,$b0,$da,$da,$12,$12,$1a,$1a,$03,$03 LetterTilesEnd: INCLUDE "Async.inc" INCLUDE "CopyRangeSafe.inc" INCLUDE "CopyTilesSafe.inc" INCLUDE "ScreenMainMenu.inc" INCLUDE "ScreenSpreadSelect.inc" INCLUDE "ScreenCardRead.inc" INCLUDE "CardLibrary.inc"