2025-01-08 14:03:54 -05:00
|
|
|
; 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
|
2025-01-11 12:45:13 -05:00
|
|
|
DEF SCENE_SETUP EQU $c101
|
2025-01-08 14:03:54 -05:00
|
|
|
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
|
|
|
|
|
2025-01-11 12:45:13 -05:00
|
|
|
DEF INTERRUPT_LCD EQU $c111
|
2025-01-08 14:03:54 -05:00
|
|
|
|
|
|
|
DEF rMYBTN EQU $FFA8
|
|
|
|
DEF rMYBTNP EQU rMYBTN + 1
|
2025-01-09 15:39:07 -05:00
|
|
|
DEF rDELTAT EQU rMYBTNP + 1
|
|
|
|
DEF VARIABLES_START EQU rDELTAT+1
|
2025-01-08 14:03:54 -05:00
|
|
|
|
|
|
|
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
|
2025-01-09 15:39:07 -05:00
|
|
|
ld [rNR52], a ; shut down audio
|
|
|
|
ldh [rDIV], a ; reset timer just in case??
|
2025-01-08 14:03:54 -05:00
|
|
|
|
2025-01-11 12:45:13 -05:00
|
|
|
; 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
|
2025-01-08 14:03:54 -05:00
|
|
|
ld hl, SCENE_SETUP - 1
|
2025-01-11 12:45:13 -05:00
|
|
|
ld [SCENE_SETUP - 1], a
|
2025-01-08 14:03:54 -05:00
|
|
|
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
|
2025-01-11 12:45:13 -05:00
|
|
|
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
|
2025-01-08 14:03:54 -05:00
|
|
|
ld hl, SCENE_SETUP + 2
|
|
|
|
ld [hl], a
|
|
|
|
ld hl, SCENE_UPDATE + 2
|
|
|
|
ld [hl], a
|
|
|
|
ld hl, SCENE_DRAW + 2
|
|
|
|
ld [hl], a
|
2025-01-11 12:45:13 -05:00
|
|
|
ld hl, SCENE_TEARDOWN + 2
|
2025-01-08 14:03:54 -05:00
|
|
|
ld [hl], a
|
|
|
|
ld hl, INTERRUPT_LCD + 2
|
2025-01-11 12:45:13 -05:00
|
|
|
ld [hl], a
|
2025-01-08 14:03:54 -05:00
|
|
|
|
|
|
|
; set up our scene vectors
|
2025-01-11 12:45:13 -05:00
|
|
|
ld hl, ScreenMainMenu
|
|
|
|
call ChangeScene
|
2025-01-08 14:03:54 -05:00
|
|
|
|
|
|
|
Loop:
|
|
|
|
di
|
2025-01-09 15:39:07 -05:00
|
|
|
; 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
|
2025-01-08 14:03:54 -05:00
|
|
|
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
|
2025-01-09 15:39:07 -05:00
|
|
|
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!
|
2025-01-08 14:03:54 -05:00
|
|
|
|
|
|
|
ld b, 144
|
|
|
|
call AwaitLine
|
|
|
|
|
2025-01-09 15:39:07 -05:00
|
|
|
call SCENE_DRAW - 1 ; hope this takes fewer than 9 scanlines!
|
|
|
|
; either way it's going to eat into the update timing
|
2025-01-08 14:03:54 -05:00
|
|
|
jp Loop
|
2025-01-11 12:45:13 -05:00
|
|
|
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
|
|
|
|
|
2025-01-08 14:03:54 -05:00
|
|
|
AwaitLine: ; put the line you want to reach in b
|
|
|
|
ld a, [rLY]
|
|
|
|
cp b
|
|
|
|
jp nz, AwaitLine
|
|
|
|
ret
|
|
|
|
|
2025-01-09 15:39:07 -05:00
|
|
|
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
|
|
|
|
|
2025-01-08 14:03:54 -05:00
|
|
|
PrintString: ; write ascii string which has been prefixed by its length.
|
|
|
|
ld b, [hl]
|
|
|
|
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
|
2025-01-11 12:45:13 -05:00
|
|
|
|
|
|
|
;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:
|
|
|
|
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
|
|
|
|
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
|
2025-01-08 14:03:54 -05:00
|
|
|
|
|
|
|
Instructions:
|
2025-01-11 12:45:13 -05:00
|
|
|
call SCENE_UPDATE + 2
|
2025-01-08 14:03:54 -05:00
|
|
|
ret
|
|
|
|
|
2025-01-11 12:45:13 -05:00
|
|
|
INCLUDE "ScreenMainMenu.inc"
|
|
|
|
INCLUDE "ScreenCardRead.inc"
|
|
|
|
INCLUDE "ScreenSpreadSelect.inc"
|