diff --git a/00TheFool.inc b/00TheFool.inc index a18231a..4fad592 100644 --- a/00TheFool.inc +++ b/00TheFool.inc @@ -29,42 +29,42 @@ TheFool: ld [hl+], a ; $c201 = timer for big zero .fUpdate: - ldh a, [rDELTAT] + ld a, [rDELTAT] ld b, a - ld a, [$c300] + ld a, [CARD_VARS_START] add a, b - ld [$c200], a - ld a, [$c300+1] + ld [CARD_VARS_START], a + ld a, [CARD_VARS_START+1] adc a, 0 - ld [$c300+1], a ; increment time. when the 16bit time register is greater + ld [CARD_VARS_START+1], a ; increment time. when the 16bit time register is greater - ld a, [$c300+1] + ld a, [CARD_VARS_START+1] cp a, $08 ; $10 00 = 1 second jp c, .doneWithTimer1 ; if the timer is less than $0800, skip to end ;otherwise reset the timer ld a, 0 - ld [$c300], a - ld [$c300+1], a + ld [CARD_VARS_START], a + ld [CARD_VARS_START+1], a .doneWithTimer1 - ld a, [$c302] + ld a, [CARD_VARS_START+2] add a, b - ld [$c302], a - ld a, [$c302+1] + ld [CARD_VARS_START+2], a + ld a, [CARD_VARS_START+2+1] adc a, 0 ld [$c302+1], a - ld a, [$c302+1] + ld a, [CARD_VARS_START+2+1] cp a, $10 ; $10 00 = 1 second jp c, .doneWithTimer2 ; if the timer is less than $0800, skip to end ;otherwise reset the timer ld a, 0 - ld [$c302], a - ld [$c302+1], a + ld [CARD_VARS_START+2], a + ld [CARD_VARS_START+2+1], a .doneWithTimer2 diff --git a/Async.inc b/Async.inc index 12c84a6..ddd9447 100644 --- a/Async.inc +++ b/Async.inc @@ -1,55 +1,120 @@ -; async variables from ff80-ff8f! -def vAsyncAF equ $ff80 -def vAsyncHL EQU $ff82 -def vAsyncDE EQU $ff84 -def vAsyncBC equ $ff86 -def vAsyncPC equ $ff88 -def vAsyncNext equ $ff8a -def vAsyncAfter equ $ff8c -def vAsyncProgress equ $ff8e +; async variables somewhere in RAM +def vAsyncAF equ ASYNC_VARS_START +def vAsyncHL EQU vAsyncAF+2 +def vAsyncDE EQU vAsyncHL+2 +def vAsyncBC equ vAsyncDE+2 +def vAsyncPC equ vAsyncBC+2 +def vAsyncNext equ vAsyncPC+2 +def vAsyncAfter equ vAsyncNext+2 +def vAsyncProgress equ vAsyncAfter+2 +def vAsyncMainSP equ vAsyncProgress+2 +def vAsyncThreadSP equ vAsyncMainSP+2 -def SAFE_ASYNC_START EQU 146 -def SAFE_ASYNC_END EQU 152 +; canonical ordering to push should be: AF, BC, DE, HL, -DoInAsyncVBlank: +def ASYNC_STACK_TOP equ $ffc0 +; stack top is ffc0 +; first value on the stack is the early return pointer, at ffbe = ffc0-2 +; second value is the destination of the async call, at ffbc = ffbe-2 = ffc0-2-2 +def ASYNC_THREAD_CALL equ ASYNC_STACK_TOP - 2 - 2 + +def SAFE_ASYNC_START EQU 148 +def SAFE_ASYNC_END EQU 153 + +Async_Spawn_HL: di - push af - - ld a, l - ldh [vAsyncHL], a + ld a, l + ld [ASYNC_THREAD_CALL], a ld a, h - ldh [vAsyncHL+1], a - ld a, e - ldh [vAsyncDE], a - ld a, d - ldh [vAsyncDE+1], a - ld a, c - ldh [vAsyncBC], a - ld a, b - ldh [vAsyncBC+1], a + ld [ASYNC_THREAD_CALL+1], a +Async_Spawn: + di + nop + ; save all the registers + push af + ld a, l + ld [vAsyncHL], a + ld a, h + ld [vAsyncHL+1], a + ld a, e + ld [vAsyncDE], a + ld a, d + ld [vAsyncDE+1], a + ld a, c + ld [vAsyncBC], a + ld a, b + ld [vAsyncBC+1], a pop hl ld a, l - ldh [vAsyncAF], a + ld [vAsyncAF], a ld a, h - ldh [vAsyncAF+1], a + ld [vAsyncAF+1], a - ; set pu the next call! - ldh a, [vAsyncNext] - ldh [vAsyncPC], a - ldh a, [vAsyncNext+1] - ldh [vAsyncPC+1], a ; put next into pc - ldh a, [vAsyncAfter] - ldh [vAsyncNext], a - ldh a, [vAsyncAfter+1] - ldh [vAsyncNext+1], a ; puut after into next - ld a, 0 - ldh [vAsyncAfter], a ; unless this gets overwritten later, end execution after that - ldh [vAsyncAfter+1], a + ; save main sp + ld hl, sp+0 + ld a, l + ld [vAsyncMainSP], a + ld a, h + ld [vAsyncMainSP+1], a - ld a, LOW(DoInAsyncVBlank_EnterThread) + ; switch to thread sp + ld a, LOW(ASYNC_STACK_TOP) + ld l, a + ld a, HIGH(ASYNC_STACK_TOP) + ld h, a + ld sp, hl + + + ; push early return onto thread stack + ld l, LOW(Async_EarlyReturn) + ld h, HIGH(Async_EarlyReturn) + push hl + + ; requestedd pc is expected to be set at ASYNC_THREAD_CALL by the calling func + ld hl, sp-2 + ld sp, hl + + ; push registers + ; canonical ordering to push should be: AF, BC, DE, HL, + ld a, [vAsyncAF] + ld l, a + ld a, [vAsyncAF+1] + ld h, a + push hl + + ld a, [vAsyncBC] + ld l, a + ld a, [vAsyncBC+1] + ld h, a + push hl + + ld a, [vAsyncDE] + ld l, a + ld a, [vAsyncDE+1] + ld h, a + push hl + + ld a, [vAsyncHL] + ld l, a + ld a, [vAsyncHL+1] + ld h, a + push hl + + ; save current sp to vAsyncThreadSP + ld hl, sp+0 + ld a, l + ld [vAsyncThreadSP], a + ld a, h + ld [vAsyncThreadSP+1], a + + ; now the stack looks like: early return, ASYNC_THREAD_CALL, AF, BC, DE, HL + ; switch back to main thread. + + ; register enterthread + ld a, LOW(Async_EnterThread) ld [INTERRUPT_LCD], a - ld a, HIGH(DoInAsyncVBlank_EnterThread) + ld a, HIGH(Async_EnterThread) ld [INTERRUPT_LCD + 1], a; set interrupt handler to "ENTER THREAD" ld a, SAFE_ASYNC_START ; CHANGE ME TO ADJUST SAFE TRANSFER TIMING ld [rLYC], a ; set LYC @@ -59,204 +124,177 @@ DoInAsyncVBlank: set 6, [hl] ; set the stat interrupt to LYC mode ld hl, rIF res 1, [hl] ; clear the interrupt so we don't immediately fire it - ei + + + ; restore main sp + ld a, [vAsyncMainSP] + ld l, a + ld a, [vAsyncMainSP+1] + ld h, a + ld sp, hl + + ; restore registers from memory + ld a, [vAsyncAF] + ld l, a + ld a, [vAsyncAF+1] + ld h, a + push hl ; this is so we can pop af when we're done + + ld a, [vAsyncHL] + ld l, a + ld a, [vAsyncHL+1] + ld h, a + + ld a, [vAsyncDE] + ld e, a + ld a, [vAsyncDE+1] + ld d, a + + ld a, [vAsyncBC] + ld c, a + ld a, [vAsyncBC+1] + ld b, a + + pop af + + ei ret -DoInAsyncVBlank_EnterThread: +Async_EnterThread: ;stack looks like: ;c113 (SMC int @ LYC 90 pc), 004b (hw int @ LYC 90 pc), outer context pc - push hl + push af push bc push de - push af - + push hl + + ; check if there's anything queued up for executing; if no, just clean up + ld a, LOW(ASYNC_STACK_TOP) ; we're checkng if the current async stack is empty + ld hl, vAsyncThreadSP ; comparing to the current thread sp + cp a, [hl] ; are they equal? + jp z, Async_CleanUpThread + ;af, de, bc, hl, c113 (SMC interrupt pc), 004b (hardwired interrput pc), outer context pc - ; check if there's anything queued up for next execution - ldh a, [vAsyncPC] - ld l, a - ldh a, [vAsyncPC+1] - ld h, a - or a, l - jp z, DoInAsyncVBlank_EndThread ; if nothing is queued up, jump to cleanup - - ld a, LOW(DoInAsyncVBlank_ExitThread) + ld a, LOW(Async_ExitThread) ld [INTERRUPT_LCD], a - ld a, HIGH(DoInAsyncVBlank_ExitThread) + ld a, HIGH(Async_ExitThread) ld [INTERRUPT_LCD+1], a ld a, SAFE_ASYNC_END ; CHANGE ME TO ADJUST SAFE TRANSFER TIMING ld [rLYC], a ; set lcd interrupt handler to EXIT SAFE MODE on line 153 + + ; save main thread stack pointer + ld hl, sp+0 + ld a, l + ld [vAsyncMainSP], a + ld a, h + ld [vAsyncMainSP+1], a - ; what if our async thread calls return? - ; we need to have a PC to return to. if that happens, we will want to - ; reti. - ld hl, DoInAsyncVBlank_EarlyReturn - push hl ; address for if the thread retrns - - ldh a, [vAsyncPC] + ; load side thread stack pointer + ld a, [vAsyncThreadSP] ld l, a - ldh a, [vAsyncPC+1] + ld a, [vAsyncThreadSP+1] ld h, a - push hl ; put vAsyncPC on the stack! for jumping to it! - ; stack looks like: vasyncpc, early return, af, de, bc, hll, SMC interrput pc, hardwired interrupt pc, outer context pc + ld sp, hl - ldh a, [vAsyncAF] - ld l, a - ldh a, [vAsyncAF+1] - ld h, a - push hl - - ldh a, [vAsyncHL] - ld l, a - ldh a, [vAsyncHL+1] - ld h, a - ldh a, [vAsyncDE] - ld e, a - ldh a, [vAsyncDE+1] - ld d, a - ldh a, [vAsyncBC] - ld c, a - ldh a, [vAsyncBC+1] - ld b, a - - pop af; putting vAsyncAF into af requires this hoop-jumping - - ei - ret ; "return" to the vAsyncPC wee put on the stack previously. + ; pop registers + ; canonical ordering to push should be: AF, BC, DE, HL, + ; pop is HL, DE, BC, AF + pop hl + pop de + pop bc + pop af + + reti ; "return" to the vAsyncPC wee put on the stack previously. ; this is more or less a jump, not a return. ; is that the source of our problems? ; after this instruction executes, stack looks like: ; early return, af, de, bc, hl, PC (smc int), PC (hardwired int), PC (outer context) ; and we'll be in the async thread, executing + +Async_ExitThread: + ; save interrupt registers (AF, BC, DE, HL) + push af + push bc + push de + push hl -DoInAsyncVBlank_EarlyReturn: - ; stack: - ; af, de, bc, hl, PC (smc int @ LYC90), PC (hw int @ LYC 90), PC (outer context) - ;PRINTln "early return handle is ", DoInAsyncVBlank_EarlyReturn - ; save state of registers - di - push af + ;af, de, bc, hl, c113 (SMC interrupt pc), 004b (hardwired interrput pc), thread pc, return - ld a, l - ldh [vAsyncHL], a - ld a, h - ldh [vAsyncHL+1], a - ld a, e - ldh [vAsyncDE], a - ld a, d - ldh [vAsyncDE+1], a - ld a, c - ldh [vAsyncBC], a - ld a, b - ldh [vAsyncBC+1], a - - pop hl - ld a, l - ldh [vAsyncAF], a - ld a, h - ldh [vAsyncAF+1], a - - - - ; set pu the next call! - ldh a, [vAsyncNext] - ldh [vAsyncPC], a - ldh a, [vAsyncNext+1] - ldh [vAsyncPC+1], a ; put next into pc - ldh a, [vAsyncAfter] - ldh [vAsyncNext], a - ldh a, [vAsyncAfter+1] - ldh [vAsyncNext+1], a ; puut after into next - ld a, 0 - ldh [vAsyncAfter], a ; unless this gets overwritten later, end execution after that - ldh [vAsyncAfter+1], a - - ld a, LOW(DoInAsyncVBlank_EnterThread) ; set up next call + ld a, LOW(Async_EnterThread) ld [INTERRUPT_LCD], a - ld a, HIGH(DoInAsyncVBlank_EnterThread) + ld a, HIGH(Async_EnterThread) ld [INTERRUPT_LCD+1], a - ld a, SAFE_ASYNC_START - ld [rLYC], a + ld a, SAFE_ASYNC_START ; CHANGE ME TO ADJUST SAFE TRANSFER TIMING + ld [rLYC], a ; set lcd interrupt handler to EXIT SAFE MODE on line 153 + + ; save side thread stack pointer + ld hl, sp+0 + ld a, l + ld [vAsyncThreadSP], a + ld a, h + ld [vAsyncThreadSP+1], a + + ; load main thread stack pointer + ld a, [vAsyncMainSP] + ld l, a + ld a, [vAsyncMainSP+1] + ld h, a + ld sp, hl + + ; pop registers + ; canonical ordering to push should be: AF, BC, DE, HL, + ; pop is HL, DE, BC, AF + pop hl + pop de + pop bc + pop af + + reti + + +Async_EarlyReturn: + di + ; don't care about current registers bc we're done executing. + + ; store side thread SP, so everyone knows that the side thread stack is empty + ld hl, sp+0 + ld a, l + ld [vAsyncThreadSP], a + ld a, h + ld [vAsyncThreadSP+1], a + + ; unset next call + ld hl, rIE + res 1, [hl] ; disable vblank + ld hl, rIF + res 1, [hl] ; clear the interrupt + + ; load main thread stack pointer + ld a, [vAsyncMainSP] + ld l, a + ld a, [vAsyncMainSP+1] + ld h, a + ld sp, hl ; restore the pre-interrupt registers, return and enable interrupts pop af pop de pop bc pop hl + reti -DoInAsyncVBlank_EndThread: - ; end execution of the thread by disabling the interrupt - ; and restore the state for the outer thread - ld hl, rIE - res 1, [hl] ; disable STAT/vblank interrupt - pop af + + +Async_CleanUpThread: + ;stack looks like: + ;hl, de, bc, af, c113 (SMC int @ LYC 90 pc), 004b (hw int @ LYC 90 pc), outer context pc + pop hl pop de pop bc - pop hl - reti - -DoInAsyncVBlank_ExitThread: - ; at this point, it's an interrpt being called from inside the interrupt - ; our stack probably looks like this: - ; PC (smc int), PC (hardwired int), PC (inside thread), early return, af, de, bc, hl, PC (smc int), PC (hardwired int), PC (outer context) - ; first, save the interrpt thread registers. - push af + pop af - ld a, l - ldh [vAsyncHL], a - ld a, h - ldh [vAsyncHL+1], a - ld a, e - ldh [vAsyncDE], a - ld a, d - ldh [vAsyncDE+1], a - ld a, c - ldh [vAsyncBC], a - ld a, b - ldh [vAsyncBC+1], a - - pop hl - ld a, l - ldh [vAsyncAF], a - ld a, h - ldh [vAsyncAF+1], a - - ;god i'm such a genius - ; this was called as an interrupt inside the interrupt - ;so our stack looks like this: - ; PC (smc int), PC (hardwired int), PC (inside thread), early return, af, de, bc, hl, PC (smc int), PC (hardwired int), PC (outer context) - ; we've got the two PCs from the inner interrupt call stack. - ; get rid of them! we're running without handrails! i know what i'm doing! I hope! - pop hl - pop hl - ; now, save the interrupt thread's pc., which is on the stack from this - ; interrupt being called. - pop hl - ld a, l - ldh [vAsyncPC], a - ld a, h - ldh [vAsyncPC+1], a - ; now we are done with this entire execution of thread. now we need to set up - ; the next execution of this thread. - ld a, LOW(DoInAsyncVBlank_EnterThread) - ld [INTERRUPT_LCD], a - ld a, HIGH(DoInAsyncVBlank_EnterThread) - ld [INTERRUPT_LCD+1], a - ld a, SAFE_ASYNC_START ; CHANGE ME TO ADJUST SAFE TRANSFER TIMING - ld [rLYC], a ; set lcd interrupt handler to EXIT SAFE MODE on line 153 - - ;at present the stack looks like: - ; early return, af, de, bc, hl, pc (smc int @ LYC 90), pc (hardwired int at LYC 90), PC (outer context) - ; pop the early return and discard it. - pop hl - ; and finally, we can restore the state of the registers to what they were - ; before this whole handler got called. - pop af - pop de - pop bc - pop hl - reti ; this is a proper return - \ No newline at end of file + reti \ No newline at end of file diff --git a/CardHelpers.inc b/CardHelpers.inc index 91aea69..69585f1 100644 --- a/CardHelpers.inc +++ b/CardHelpers.inc @@ -1,9 +1,8 @@ -LoadCardDataAsync: ; to be called as async +LoadCardData: +LoadCardDataAsync: ei - ld a, 1 - ldh [vBlocked], a - ldh a, [vSelectedCardIndex] - ldh [vPreviousCardIndex], a + ld a, [vSelectedCardIndex] + ld [vPreviousCardIndex], a ld b, 0 ld c, a ; load bc from a, the number of the card in the cards list @@ -23,20 +22,7 @@ LoadCardDataAsync: ; to be called as async ld h, b ld l, c ; hl now contains the address of the card data. - ld a, LOW(.duringDraw) - ld [vAsyncNext], a - ld a, HIGH(.duringDraw) - ld [vAsyncNext+1], a - ld a, 0 - ld [vAsyncAfter], a - ld [vAsyncAfter+1], a - di - nop - nop - ret .duringDraw - di ; these function calls should be fast so we'll disable interrupts and do them - nop ; synchronously ; hl points to a card struct. @@ -55,8 +41,6 @@ LoadCardDataAsync: ; to be called as async ld de, $9800 + 32*16 + 10 call PrintString - ei - ; hl now contains the address after all the strings. ; [hl+] and [hl+] read the length first, into bc ld a, [hl+] @@ -74,22 +58,10 @@ LoadCardDataAsync: ; to be called as async ld b, 16 ; height ld c, 8 ; width - ld a, LOW(CopyTilesToMapThreadsafe) - ld [vAsyncNext], a - ld a, HIGH(CopyTilesToMapThreadsafe) - ld [vAsyncNext+1], a - ld a, LOW(.afterCopyTiles) - ld [vAsyncAfter], a - ld a, HIGH(.afterCopyTiles) - ld [vAsyncAfter+1], a - di - nop - nop - ret -.afterCopyTiles - ei - ldh a, [vSelectedCardIndex] - ldh [vPreviousCardIndex], a + call CopyTilesToMapUnsafe + + ld a, [vSelectedCardIndex] + ld [vPreviousCardIndex], a ld b, 0 ld c, a ; load bc from a, the number of the card in the cards list @@ -108,13 +80,11 @@ LoadCardDataAsync: ; to be called as async ld h, b ld l, c ; hl now contains the address of the card data. - di call PassList call PassList call PassList call PassList call PassList ; skip the strings - ei inc hl inc hl ; skip tile map width inc hl @@ -132,30 +102,8 @@ LoadCardDataAsync: ; to be called as async ld l, e ; hl takes the source ld de, $9000 + VARIABLE_TILES_START*$10 ; always load tile data into the same spot in vram - ld a, LOW(CopyRangeUnsafe) - ld [vAsyncNext], a - ld a, HIGH(CopyRangeUnsafe) - ld [vAsyncNext+1], a - ld a, LOW(.afterLoadingTiles) - ld [vAsyncAfter], a - ld a, HIGH(.afterLoadingTiles) - ld [vAsyncAfter+1], a + call CopyRangeUnsafe + di nop - nop - ret -.afterLoadingTiles - ei - ld a, 0 - ldh [vBlocked], a - - ld a, 0 - ld [vAsyncNext], a - ld [vAsyncNext+1], a - ld [vAsyncAfter], a - ld [vAsyncAfter+1], a - di - nop - nop - ret diff --git a/CopyRangeSafe.inc b/CopyRangeSafe.inc index 687018c..97762b1 100644 --- a/CopyRangeSafe.inc +++ b/CopyRangeSafe.inc @@ -212,9 +212,6 @@ CopyRangeUnsafe: ; this is threadsafe but not vblank safe ld a, b or a, c ; check if bc is zero jp nz, CopyRangeUnsafe - di - nop - nop ret diff --git a/Random.inc b/Random.inc index 4edfdc3..3e6dc2d 100644 --- a/Random.inc +++ b/Random.inc @@ -1,6 +1,6 @@ ClockLFSR: ; uses af, bc and clocks one bit of the LFSR. ; at return time, a holds the bottom eight of lfsr state. - ldh a, [rLFSR] ; + ld a, [rLFSR] ; ld b, a ; b has shifted value ; 1 cycle srl b ; second tap is two shifts ; 2 cycles @@ -21,12 +21,12 @@ ClockLFSR: ; uses af, bc and clocks one bit of the LFSR. jr nz, .noComplementCarry ; 2 or 3 cycles ccf ; 1 cycle if prev was 2 cycles :) .noComplementCarry - ldh a, [rLFSR+1] ; 2 cycles + ld a, [rLFSR+1] ; 2 cycles rra ; 1 cycle ; this should populate with the carry flag - ldh [rLFSR+1], a ; 2 cycles - ldh a, [rLFSR] ; 2 cycles + ld [rLFSR+1], a ; 2 cycles + ld a, [rLFSR] ; 2 cycles rra ; 1 cycle - ldh [rLFSR], a ; 2 cycles + ld [rLFSR], a ; 2 cycles ret ; 37 cycles total. can call roughly three of these per scanline OneRandomByte: ; clocks LFSR 8 times so a is diff --git a/ScreenCardBrowse.inc b/ScreenCardBrowse.inc index 4f044fb..a6da19b 100644 --- a/ScreenCardBrowse.inc +++ b/ScreenCardBrowse.inc @@ -1,6 +1,5 @@ -; screen variables already ddefined in screencardread +; screen variables shared with screencardread ;DEF vPreviousCardIndex EQU VARIABLES_START -;def vBlocked equ vPreviousCardIndex + 1 ScreenCardBrowse: dw CardBrowseSetup @@ -10,68 +9,54 @@ ScreenCardBrowse: CardBrowseSetup: ld a, 1 - ldh [vBlocked], a + ld [vBlocked], a - ld a, LOW(RunDMA) ; zero out the OAM - ld [vAsyncNext], a - ld a, HIGH(RunDMA) - ld [vAsyncNext+1], a - ld a, LOW(.loadUIMap) - ld [vAsyncAfter], a - ld a, HIGH(.loadUIMap) - ld [vAsyncAfter+1], a - - ld a, HIGH(ZEROES) - ld de, $ffc0 ; arguments to the first async call. - - call DoInAsyncVBlank + ld hl, .loadUIMap + call Async_Spawn_HL ret .loadUIMap + ld a, HIGH(ZEROES) + ld de, SAFE_DMA_LOCATION ; arguments to the first async call. + call RunDMA ld hl, CardBrowse.UITilemap ; origin ld de, $9800 ; destination ld b, 18 ; height ld c, 20 ; width - ld a, LOW(CopyTilesToMapThreadsafe) - ld [vAsyncNext], a - ld a, HIGH(CopyTilesToMapThreadsafe) - ld [vAsyncNext+1], a + call CopyTilesToMapUnsafe - ld a, LOW(LoadCardDataAsync) - ld [vAsyncAfter], a - ld a, HIGH(LoadCardDataAsync) - ld [vAsyncAfter+1], a + call LoadCardData ret CardBrowseUpdate: ld hl, vTime - ldh a, [rDELTAT] + ld a, [rDELTAT] ld b, a - ldh a, [vTime] + ld a, [vTime] add a, b - ldh [vTime], a - ldh a, [vTime+1] + ld [vTime], a + ld a, [vTime+1] adc a, 0 - ldh [vTime+1], a ; increment time. when the 16bit time register is greater + ld [vTime+1], a ; increment time. when the 16bit time register is greater ; than 4096 ($10_00) then one second has passed. so that's satisfied when ; vTime+1 is equal to or greater than $10 - ldh a, [vTime+1] + ld a, [vTime+1] cp a, $01 jp c, .doneTimer ; if the timer is less than $0100, skip to end ;otherwise reset the timer ld a, 0 - ldh [vTime], a - ldh [vTime+1], a + ld [vTime], a + ld [vTime+1], a ld hl, SquaresTiles - ldh a, [vFrameCountSquares] + ld a, [vFrameCountSquares] inc a call ArrayClampLooping - ldh [vFrameCountSquares], a + ld [vFrameCountSquares], a .doneTimer ld hl, rMYBTNP @@ -82,7 +67,7 @@ CardBrowseUpdate: ret .doneWithB - ldh a, [vSelectedCardIndex] + ld a, [vSelectedCardIndex] ld hl, rMYBTNP bit 3, [hl] jp z, :+ ; skip the following code if down is not pressed @@ -92,36 +77,40 @@ CardBrowseUpdate: jp z, :+ ; skip the following code if up is not pressed dec a : - ldh [vSelectedCardIndex], a + ld [vSelectedCardIndex], a ld hl, Cards call ArrayClampLooping - ldh [vSelectedCardIndex], a + ld [vSelectedCardIndex], a - ldh a, [vSelectedCardIndex] + ld a, [vSelectedCardIndex] ld hl, vPreviousCardIndex cp a, [hl] ret z ; if the selected card diddn't change, nothing to do - ldh a, [vBlocked] + ld a, [vBlocked] cp a, 0 ret nz - ld a, LOW(LoadCardDataAsync) - ld [vAsyncAfter], a - ld a, HIGH(LoadCardDataAsync) - ld [vAsyncAfter+1], a - call DoInAsyncVBlank - + ld hl, LoadCardTask + call Async_Spawn ret +LoadCardTask: + ld a, 1 + ld [vBlocked], a + call LoadCardData + ld a, 0 + ld [vBlocked], a + ret + CardBrowseDraw: ; the card data is loaded asynchronously, initiated in CardReadUpdate ld hl, SquaresTiles inc hl ld b, 0 - ldh a, [vFrameCountSquares] + ld a, [vFrameCountSquares] ld c, a add hl, bc add hl, bc diff --git a/ScreenCardRead.inc b/ScreenCardRead.inc index ea470b1..5963a3b 100644 --- a/ScreenCardRead.inc +++ b/ScreenCardRead.inc @@ -1,6 +1,5 @@ ; screen variables -DEF vPreviousCardIndex EQU VARIABLES_START -def vBlocked equ vPreviousCardIndex + 1 +DEF vPreviousCardIndex EQU SCREEN_VARS_START+16 ScreenCardRead: dw CardReadSetup @@ -10,53 +9,48 @@ ScreenCardRead: CardReadSetup: ld a, 1 - ldh [vBlocked], a + ld [vBlocked], a - ld [vAsyncAfter+1], a + ld hl, CardReadSetupAsyncTask + call Async_Spawn_HL + ret + +CardReadSetupAsyncTask: ld hl, UITilemap ; origin ld de, $9800 ; destination ld b, 18 ; height ld c, 20 ; width - - ld a, LOW(CopyTilesToMapThreadsafe) - ld [vAsyncNext], a - ld a, HIGH(CopyTilesToMapThreadsafe) - ld [vAsyncNext+1], a - - ld a, LOW(LoadCardDataAsync) - ld [vAsyncAfter], a - ld a, HIGH(LoadCardDataAsync) - ld [vAsyncAfter+1], a - call DoInAsyncVBlank + call CopyTilesToMapUnsafe + call ChangedCardTask ret CardReadUpdate: ld hl, vTime - ldh a, [rDELTAT] + ld a, [rDELTAT] ld b, a - ldh a, [vTime] + ld a, [vTime] add a, b - ldh [vTime], a - ldh a, [vTime+1] + ld [vTime], a + ld a, [vTime+1] adc a, 0 - ldh [vTime+1], a ; increment time. when the 16bit time register is greater + ld [vTime+1], a ; increment time. when the 16bit time register is greater ; than 4096 ($10_00) then one second has passed. so that's satisfied when ; vTime+1 is equal to or greater than $10 - ldh a, [vTime+1] + ld a, [vTime+1] cp a, $01 jp c, .doneTimer ; if the timer is less than $0100, skip to end ;otherwise reset the timer ld a, 0 - ldh [vTime], a - ldh [vTime+1], a + ld [vTime], a + ld [vTime+1], a ld hl, SquaresTiles - ldh a, [vFrameCountSquares] + ld a, [vFrameCountSquares] inc a call ArrayClampLooping - ldh [vFrameCountSquares], a + ld [vFrameCountSquares], a .doneTimer ld hl, rMYBTNP @@ -67,7 +61,7 @@ CardReadUpdate: ret .doneWithB - ldh a, [vSelectedSpreadCard] + ld a, [vSelectedSpreadCard] ld hl, rMYBTNP bit 1, [hl] jp z, :+ ; skip the following code if left is not pressed @@ -77,39 +71,34 @@ CardReadUpdate: jp z, :+ ; skip the following code if right is not pressed inc a : - ldh [vSelectedSpreadCard], a - ldh a, [vCurrentSpread] + ld [vSelectedSpreadCard], a + ld a, [vCurrentSpread] ld l, a - ldh a, [vCurrentSpread+1] + ld a, [vCurrentSpread+1] ld h, a - ldh a, [vSelectedSpreadCard] + ld a, [vSelectedSpreadCard] call ArrayClampLooping - ldh [vSelectedSpreadCard], a - ldh [vSelectedCardIndex], a - ldh a, [vSelectedCardIndex] - ld hl, vPreviousCardIndex + ld [vSelectedSpreadCard], a + ld hl, vPreviousSpreadCard cp a, [hl] ret z ; if the selected card diddn't change, nothing to do - ldh a, [vBlocked] + ld a, [vBlocked] cp a, 0 ret nz - ld a, LOW(LoadCardDataAsync) - ld [vAsyncAfter], a - ld a, HIGH(LoadCardDataAsync) - ld [vAsyncAfter+1], a - call DoInAsyncVBlank - - + ld a, 1 + ld [vBlocked], a + ld hl, ChangedCardTask + call Async_Spawn_HL ret CardReadDraw: ld hl, SquaresTiles inc hl ld b, 0 - ldh a, [vFrameCountSquares] + ld a, [vFrameCountSquares] ld c, a add hl, bc add hl, bc @@ -121,23 +110,31 @@ CardReadDraw: ld de, $8000+$100*16 + 1*16 ld bc, (SquaresTileset8 - SquaresTileset7) / 8 call CopyRangeUnsafeBy8s - - ; then draw the spread minimap - ldh a, [vCurrentSpread] - ld c, a - ldh a, [vCurrentSpread+1] - ld b, a - ld hl, $9800 + (32*1)+11 - ldh a, [vSelectedSpreadCard] - call DrawSpreadMinimap + ; the card data is loaded asynchronously, initiated in CardReadUpdate + ret + +CardReadTeardown: + ret - ldh a, [vCurrentSpread] +ChangedCardTask: + ld a, [vSelectedSpreadCard] + ld [vPreviousSpreadCard], a + + ld a, [vCurrentSpread] + ld c, a + ld a, [vCurrentSpread+1] + ld b, a ; gett bc as cuurrent spread address + ld hl, $9800 + (32*1)+11 + ld a, [vSelectedSpreadCard] + call DrawSpreadMinimap + + ld a, [vCurrentSpread] ld l, a - ldh a, [vCurrentSpread+1] + ld a, [vCurrentSpread+1] ld h, a call PassList ; skip spread layout - ldh a, [vSelectedSpreadCard] + ld a, [vSelectedSpreadCard] or a, a .loopThroughSpreadPositions jp z, .foundSpreadPositionDescription @@ -151,11 +148,21 @@ CardReadDraw: ld de, $9800 + 32*6 + 11 call PrintString - ; the card data is loaded asynchronously, initiated in CardReadUpdate - ret - -CardReadTeardown: + ld hl, SHUFFLED_DECK+1 + ld a, [vSelectedSpreadCard] + ld c, a + ld b, 0 + add hl, bc + ld a, [hl] + ld [vSelectedCardIndex], a + ld [vPreviousCardIndex], a + + call LoadCardData + + ld a, 0 + ld [vBlocked], a ret + UITilemap: db $0e, $0a, $0a, $0a, $0a, $0a, $0a, $0a, $0a, $0f, $09, $02, $02, $02, $02, $02, $02, $02, $08, $01 diff --git a/ScreenMainMenu.inc b/ScreenMainMenu.inc index f635f16..ab4f550 100644 --- a/ScreenMainMenu.inc +++ b/ScreenMainMenu.inc @@ -5,11 +5,12 @@ def vSelectedSpreadCard equ vSelectedSpreadIndex + 1 ; ff93 def vSelectedCardIndex equ vSelectedSpreadCard+1 ; ff94 DEF vFrameCountSquares EQU vSelectedCardIndex+1 ; ff95 DEF vTime EQU vFrameCountSquares+1 ; 16bit ; ff96 -println "after vTime is ", vTime+2 ; ff98 +def vBlocked EQU vTime+2 +println "vBlocked is ", vBlocked ; ; screen-specific variables -DEF vFrameCount1 EQU VARIABLES_START +DEF vFrameCount1 EQU SCREEN_VARS_START DEF vFrameCount2 equ vFrameCount1+1 DEF vFrameCount3 EQU vFrameCount2+1 DEF vMenuIndex equ vFrameCount3+1 @@ -118,24 +119,26 @@ MainMenuSetup_ScreenOff: cp a, l jp nz, :- - ld de, vTime+2 + ld de, SAFE_DMA_LOCATION ld a, $c0 call RunDMA ; set LCD and display registers ld a, %11100100 - ld [rBGP], a - ld [rOBP0], a + ldh [rBGP], a + ldh [rOBP0], a ld a, LCDCF_BLK21 | LCDCF_ON | LCDCF_BGON | LCDCF_OBJON | LCDCF_OBJ16 ldh [rLCDC], a ld a, 0 - ldh [vFrameCount1], a ; first starts at 0 - ldh [vTime], a - ldh [vTime+1], a - ldh [vMenuIndex], a - ldh [vMenuIndexPrevious], a + ld [vFrameCount1], a ; first starts at 0 + ld [vTime], a + ld [vTime+1], a + ld [vMenuIndex], a + ld [vMenuIndexPrevious], a + + ld [vSelectedSpreadCard], a ; second starts at 1/3 length which is approximately L/2 - L/4 - L/8 + L/16 ? @@ -157,7 +160,7 @@ MainMenuSetup_ScreenOff: srl b add a, b ; L - L/2 - L/4 + L/8 - L/16 + L/32 - L/64 + L/128 ; that should be approx 1/3 of L ! - ldh [vFrameCount2], a + ld [vFrameCount2], a ; third starts at 2/3 length which is approximately L/2 - L/4 + L/8 - L/16 ? ld hl, Coords @@ -178,7 +181,7 @@ MainMenuSetup_ScreenOff: srl b sub a, b ; L - L/2 + L/4 - L/8 + L/16 - L/32 + L/64 - L/128 ; that should be just about 2/3 of L ! - ldh [vFrameCount3], a + ld [vFrameCount3], a ;ld hl, Coords ;ld a, [hl] @@ -186,7 +189,7 @@ MainMenuSetup_ScreenOff: ;ldh [vFrameCount4], a ld a, 0 - ldh [vFrameCountSquares], a + ld [vFrameCountSquares], a ; load graphics into vram for deck face @@ -202,7 +205,7 @@ MainMenuUpdate: ; if timer is max, turn off animation state and unblock? ld hl, rMYBTNP - ldh a, [vMenuIndex] + ld a, [vMenuIndex] bit 3, [hl] ; select the down key jp z, .doneWithDownInput ; skip the following code if down is not pressed inc a @@ -213,7 +216,7 @@ MainMenuUpdate: .doneWithUpInput ld hl, MenuCount call ArrayClampLooping - ldh [vMenuIndex], a + ld [vMenuIndex], a ld hl, rMYBTNP @@ -230,7 +233,7 @@ MainMenuUpdate: jp .doneWithMenuSelect .option1 ld a, 0 - ldh [vSelectedSpreadIndex], a + ld [vSelectedSpreadIndex], a ld hl, ScreenSpreadSelect call ChangeScene ret @@ -240,56 +243,56 @@ MainMenuUpdate: ret .option3 ld a, 0 - ldh [vSelectedCardIndex], a + ld [vSelectedCardIndex], a ld hl, ScreenCardBrowse call ChangeScene ret .doneWithMenuSelect - ldh a, [rDELTAT] + ld a, [rDELTAT] ld b, a - ldh a, [vTime] + ld a, [vTime] add a, b - ldh [vTime], a - ldh a, [vTime+1] + ld [vTime], a + ld a, [vTime+1] adc a, 0 - ldh [vTime+1], a ; increment time. when the 16bit time register is greater + ld [vTime+1], a ; increment time. when the 16bit time register is greater ; than 4096 ($10_00) then one second has passed. so that's satisfied when ; vTime+1 is equal to or greater than $10 - ldh a, [vTime+1] + ld a, [vTime+1] cp a, $01 jp c, MainMenuUpdate_Done ; if the timer is less than $0100, skip to end ;otherwise reset the timer ld a, 0 - ldh [vTime], a - ldh [vTime+1], a + ld [vTime], a + ld [vTime+1], a ld hl, Coords ; and advance the frame counts - ldh a, [vFrameCount1] + ld a, [vFrameCount1] inc a call ArrayClampLooping - ldh [vFrameCount1], a + ld [vFrameCount1], a - ldh a, [vFrameCount2] + ld a, [vFrameCount2] inc a call ArrayClampLooping - ldh [vFrameCount2], a + ld [vFrameCount2], a - ldh a, [vFrameCount3] + ld a, [vFrameCount3] inc a call ArrayClampLooping - ldh [vFrameCount3], a + ld [vFrameCount3], a ld hl, SquaresTiles - ldh a, [vFrameCountSquares] + ld a, [vFrameCountSquares] inc a call ArrayClampLooping - ldh [vFrameCountSquares], a + ld [vFrameCountSquares], a @@ -381,7 +384,7 @@ MainMenuDraw: ld hl, SquaresTiles inc hl ld b, 0 - ldh a, [vFrameCountSquares] + ld a, [vFrameCountSquares] ld c, a add hl, bc add hl, bc diff --git a/ScreenShuffle.inc b/ScreenShuffle.inc index 2b2d151..97156f6 100644 --- a/ScreenShuffle.inc +++ b/ScreenShuffle.inc @@ -1,7 +1,7 @@ ; screen variables already ddefined in screencardread ;DEF vPreviousCardIndex EQU VARIABLES_START ;def vBlocked equ vPreviousCardIndex + 1 -def vAnimationFrame EQU VARIABLES_START +def vAnimationFrame EQU SCREEN_VARS_START def vAnimationState EQU vAnimationFrame+1 def vCurrentAnimation EQU vAnimationState+1 ; 2 bytes def vShuffleIndex equ vCurrentAnimation+2 @@ -17,71 +17,44 @@ ShuffleSetup: ld hl, SHUFFLED_DECK ld a, [hl] dec a - ldh [vShuffleIndex], a + ld [vShuffleIndex], a ld a, 0 - ldh [vAnimationFrame], a - ldh [vAnimationState], a + ld [vAnimationFrame], a + ld [vAnimationState], a + + ld hl, .asyncTask + call Async_Spawn_HL + ret +.asyncTask ld a, LOW(ShuffleAnimationRight) - ldh [vCurrentAnimation], a + ld [vCurrentAnimation], a ld a, HIGH(ShuffleAnimationRight) - ldh [vCurrentAnimation+1], a + ld [vCurrentAnimation+1], a - ld a, LOW(RunDMA) ; zero out the OAM - ld [vAsyncNext], a - ld a, HIGH(RunDMA) - ld [vAsyncNext+1], a - ld a, LOW(.loadUIMap) - ld [vAsyncAfter], a - ld a, HIGH(.loadUIMap) - ld [vAsyncAfter+1], a - - ld a, HIGH(ZEROES) - ld de, vMenuIndexPrevious+2 ; arguments to the first async call. - - call DoInAsyncVBlank - - ld hl, ZEROES ; hl is source - ld de, $c000 ; de is destination - ld bc, $100 ; length to copy + ld hl, ZEROES + ld de, MY_OAM + ld bc, $100 call CopyRangeUnsafe - ret - -.loadUIMap + ld de, SAFE_DMA_LOCATION + ld a, HIGH(ZEROES) + call RunDMA ld hl, Shuffle.UITilemap ; origin ld de, $9800 ; destination ld b, 18 ; height ld c, 20 ; width - - ld a, LOW(CopyTilesToMapThreadsafe) - ld [vAsyncNext], a - ld a, HIGH(CopyTilesToMapThreadsafe) - ld [vAsyncNext+1], a - - ld a, LOW(.loadTiles) - ld [vAsyncAfter], a - ld a, HIGH(.loadTiles) - ld [vAsyncAfter+1], a - ret -.loadTiles + call CopyTilesToMapUnsafe + ld hl, Shuffle.UITileData ld de, $9000 + VARIABLE_TILES_START*16 ld bc, Shuffle.UITileDataEnd - Shuffle.UITileData + call CopyRangeUnsafe - ld a, LOW(CopyRangeUnsafe) - ldh [vAsyncNext], a - ld a, HIGH(CopyRangeUnsafe) - ldh [vAsyncNext+1], a - ld a, LOW(.drawBigCard) - ld [vAsyncAfter], a - ld a, HIGH(.drawBigCard) - ld [vAsyncAfter+1], a - ret -.drawBigCard - ld hl, $9800 + $20*5 + 8 + ; manually drawing the Big Card + ld hl, $9800 + $20*5 + 7 ld a, VARIABLE_TILES_START ld [hl+], a inc a @@ -93,7 +66,6 @@ ShuffleSetup: ld c, 32 - 4 add hl, bc - inc a ld [hl+], a inc a @@ -159,7 +131,7 @@ ShuffleSetup: ShuffleUpdate: ld hl, vShuffleTime - ldh a, [rDELTAT] + ld a, [rDELTAT] ld b, a ld a, [hl] add a, b @@ -171,7 +143,7 @@ ShuffleUpdate: ld hl, vTime - ldh a, [rDELTAT] + ld a, [rDELTAT] ld b, a ld a, [hl] add a, b @@ -192,10 +164,10 @@ ShuffleUpdate: ld [hl], a ld hl, SquaresTiles - ldh a, [vFrameCountSquares] + ld a, [vFrameCountSquares] inc a call ArrayClampLooping - ldh [vFrameCountSquares], a + ld [vFrameCountSquares], a .doneTimer @@ -204,10 +176,10 @@ ShuffleUpdate: ld a, 0 cp a, [hl] jr z, .noButtons - ldh a, [rLFSR] - ldh [rLFSR+1], a ; lfsr = (lfsr << 8) + (vShuffleTime & $ff) - ldh a, [vShuffleTime] - ldh [rLFSR], a + ld a, [rLFSR] + ld [rLFSR+1], a ; lfsr = (lfsr << 8) + (vShuffleTime & $ff) + ld a, [vShuffleTime] + ld [rLFSR], a .noButtons @@ -221,14 +193,14 @@ ShuffleUpdate: jp z, .doneWithRight ld a, 1 - ldh [vAnimationState], a + ld [vAnimationState], a ld a, 0 - ldh [vAnimationFrame], a + ld [vAnimationFrame], a ld a, LOW(ShuffleAnimationRight) - ldh [vCurrentAnimation], a + ld [vCurrentAnimation], a ld a, HIGH(ShuffleAnimationRight) - ldh [vCurrentAnimation+1], a + ld [vCurrentAnimation+1], a call DoSomeShuffling .doneWithRight @@ -236,43 +208,43 @@ ShuffleUpdate: jp z, .doneWithLeft ld a, 1 - ldh [vAnimationState], a + ld [vAnimationState], a ld a, 0 - ldh [vAnimationFrame], a + ld [vAnimationFrame], a ld a, LOW(ShuffleAnimationRightReturn) - ldh [vCurrentAnimation], a + ld [vCurrentAnimation], a ld a, HIGH(ShuffleAnimationRightReturn) - ldh [vCurrentAnimation+1], a + ld [vCurrentAnimation+1], a .doneWithLeft ;animation logic! - ldh a, [vCurrentAnimation] + ld a, [vCurrentAnimation] ld l, a - ldh a, [vCurrentAnimation+1] + ld a, [vCurrentAnimation+1] ld h, a ; fetch current animation - ldh a, [vAnimationState] + ld a, [vAnimationState] or a, a jp z, .doneWithAnimation - ldh a, [vAnimationFrame] + ld a, [vAnimationFrame] inc a cp a, [hl] jp nz, .animNotDone dec a - ldh [vAnimationFrame], a + ld [vAnimationFrame], a ld a, 0 ld [vAnimationState], a - ldh a, [vAnimationFrame] + ld a, [vAnimationFrame] .animNotDone call ArrayClampLooping - ldh [vAnimationFrame], a + ld [vAnimationFrame], a .doneWithAnimation inc hl ld b, 0 - ldh a, [vAnimationFrame] + ld a, [vAnimationFrame] ld c, a add hl, bc add hl, bc ; two bytes per entry @@ -288,17 +260,21 @@ ShuffleUpdate: ld a, 32 ld e, a ld hl, $c000 - call DrawWholeCard + call DrawWholeCard ; hl memory location, b y, c x, e width, d wiggle ret ShuffleDraw: + ld de, SAFE_DMA_LOCATION ; safe bytes in hram for dma code to live at + ld a, HIGH(MY_OAM) + call RunDMA + ; the card data is loaded asynchronously, initiated in CardReadUpdate ld hl, SquaresTiles inc hl ld b, 0 - ldh a, [vFrameCountSquares] + ld a, [vFrameCountSquares] ld c, a add hl, bc add hl, bc @@ -310,10 +286,7 @@ ShuffleDraw: ld de, $8000+$100*16 + 1*16 ; tile number $101 is the sliding background ld bc, (SquaresTileset8 - SquaresTileset7) / 8 call CopyRangeUnsafeBy8s - - ld de, vMenuIndexPrevious+2 ; safe bytes in hram for dma code to live at - ld a, $c0 - call RunDMA + ret @@ -331,7 +304,7 @@ DoSomeShuffling: OneSwap: ; shuffles once and decrements vshuffleindex ; vShuffleIndex holds the index of the next card to swap with something - ldh a, [vShuffleIndex] + ld a, [vShuffleIndex] cp a, 1 jp z, .zeroIndex ; if we're swapping index 1 with index 0 skip it @@ -344,15 +317,15 @@ OneSwap: ; shuffles once and decrements vshuffleindex ld hl, SHUFFLED_DECK call SwapCards ; arguments c and e as indices to swap, hl as array in memory - ldh a, [vShuffleIndex] + ld a, [vShuffleIndex] dec a - ldh [vShuffleIndex], a ; decrement vshuffleindex so the next time around + ld [vShuffleIndex], a ; decrement vshuffleindex so the next time around ; we do the next step of the shuffle ret .zeroIndex ld a, [SHUFFLED_DECK] dec a - ldh [vShuffleIndex], a + ld [vShuffleIndex], a ret diff --git a/ScreenSpreadSelect.inc b/ScreenSpreadSelect.inc index e363eae..c12594a 100644 --- a/ScreenSpreadSelect.inc +++ b/ScreenSpreadSelect.inc @@ -1,4 +1,4 @@ -DEF vPreviousSpreadIndex EQU VARIABLES_START +DEF vPreviousSpreadIndex EQU SCREEN_VARS_START def vPreviousSpreadCard equ vPreviousSpreadIndex + 1 ScreenSpreadSelect: @@ -8,60 +8,40 @@ ScreenSpreadSelect: dw SpreadSelectTeardown SpreadSelectSetup: - ld a, 0 - ldh [vPreviousSpreadIndex], a - ldh [vSelectedSpreadCard], a - ldh [vPreviousSpreadCard], a + ld a, [vSelectedSpreadIndex] + ld [vPreviousSpreadIndex], a + ld a, [vSelectedSpreadCard] + ld [vPreviousSpreadCard], a + ld a, 1 + ld [vBlocked], a call UpdateCurrentSpread - ld a, LOW(RunDMA) ; zero out the OAM - ld [vAsyncNext], a - ld a, HIGH(RunDMA) - ld [vAsyncNext+1], a - ld a, LOW(.loadUIMap) - ld [vAsyncAfter], a - ld a, HIGH(.loadUIMap) - ld [vAsyncAfter+1], a - - ld a, HIGH(ZEROES) - ld de, $ffc0 ; arguments to the first async call. - - call DoInAsyncVBlank + ld hl, .asyncTask + call Async_Spawn_HL ret -.loadUIMap - +.asyncTask ; setup task to be executed async + ld a, HIGH(ZEROES) + ld de, SAFE_DMA_LOCATION + call RunDMA + ld hl, SpreadSelectTilemap ld de, $9800 ld b, 18 ld c, 20 - - ld a, LOW(CopyTilesToMapThreadsafe) - ld [vAsyncNext], a - ld a, HIGH(CopyTilesToMapThreadsafe) - ld [vAsyncNext+1], a - ld a, LOW(.loadFaceCardTiles) - ld [vAsyncAfter], a - ld a, HIGH(.loadFaceCardTiles) - ld [vAsyncAfter+1], a - - ret + call CopyTilesToMapUnsafe -.loadFaceCardTiles ld hl, CardPartTiles ld de, $9000 - ($10)*16 ld bc, CardPartTilesEnd - CardPartTiles - ld a, LOW(CopyRangeUnsafe) - ld [vAsyncNext], a - ld a, HIGH(CopyRangeUnsafe) - ld [vAsyncNext+1], a - ld a, LOW(DrawSpreadAsync) - ld [vAsyncAfter], a - ld a, HIGH(DrawSpreadAsync) - ld [vAsyncAfter+1], a + call CopyRangeUnsafe + + call DrawSpreadTask + ld a, 0 + ld [vBlocked], a ret SpreadSelectUpdate: @@ -92,10 +72,10 @@ SpreadSelectUpdate: .doneUp ld hl, Spreads call ArrayClampLooping - ldh [vSelectedSpreadIndex], a ; save clamped index + ld [vSelectedSpreadIndex], a ; save clamped index ; left and righgt - ldh a, [vSelectedSpreadCard] + ld a, [vSelectedSpreadCard] ld hl, rMYBTNP bit 1, [hl] jp z, .doneLeft ; skip the following code if left is not pressed @@ -113,43 +93,43 @@ SpreadSelectUpdate: ld l, c ; hl has current spread, a has index call ArrayClampLooping - ldh [vSelectedSpreadCard], a + ld [vSelectedSpreadCard], a ld hl, vTime - ldh a, [rDELTAT] + ld a, [rDELTAT] ld b, a - ldh a, [vTime] + ld a, [vTime] add a, b - ldh [vTime], a - ldh a, [vTime+1] + ld [vTime], a + ld a, [vTime+1] adc a, 0 - ldh [vTime+1], a ; increment time. when the 16bit time register is greater + ld [vTime+1], a ; increment time. when the 16bit time register is greater ; than 4096 ($10_00) then one second has passed. so that's satisfied when ; vTime+1 is equal to or greater than $10 - ldh a, [vTime+1] + ld a, [vTime+1] cp a, $01 jp c, .doneTimer ; if the timer is less than $0100, skip to end ;otherwise reset the timer ld a, 0 - ldh [vTime], a - ldh [vTime+1], a + ld [vTime], a + ld [vTime+1], a ld hl, SquaresTiles - ldh a, [vFrameCountSquares] + ld a, [vFrameCountSquares] inc a call ArrayClampLooping - ldh [vFrameCountSquares], a + ld [vFrameCountSquares], a .doneTimer - ldh a, [vSelectedSpreadIndex] + ld a, [vSelectedSpreadIndex] ld hl, vPreviousSpreadIndex cp a, [hl] jp nz, .spreadChanged ; update the spread if the spread changed - ldh a, [vSelectedSpreadCard] + ld a, [vSelectedSpreadCard] ld hl, vPreviousSpreadCard cp a, [hl] jp nz, .cardChanged ; update the spread if the card changed @@ -157,50 +137,41 @@ SpreadSelectUpdate: ret .spreadChanged - ld a, [vAsyncPC] - ld b, a - ld a, [vAsyncPC+1] - or a, b - ret nz ; early return if the async threadd is in use + ld a, [vBlocked] + cp a, 0 + ret nz ; early return if we're blocked + ld a, 1 + ld [vBlocked], a ; block! ld a, [vSelectedSpreadIndex] ld [vPreviousSpreadIndex], a ld a, 0 - ld [vSelectedSpreadCard], a + ld [vSelectedSpreadCard], a ld [vPreviousSpreadCard], a call UpdateCurrentSpread ; execute an async call to DrawSpreadAsync. - ld a, LOW(DrawSpreadAsync) - ld [vAsyncNext], a - ld a, HIGH(DrawSpreadAsync) - ld [vAsyncNext+1], a - - call DoInAsyncVBlank + ld hl, DrawSpreadTask + call Async_Spawn_HL ret .cardChanged - ld a, [vAsyncPC] - ld b, a - ld a, [vAsyncPC+1] - or a, b + ld a, [vBlocked] + cp a, 0 ret nz ; early return if the async threadd is in use + ld a, 1 + ld [vBlocked], a ; block! ld a, [vSelectedSpreadIndex] ld [vPreviousSpreadIndex], a ld a, [vSelectedSpreadCard] ld [vPreviousSpreadCard], a - call UpdateCurrentSpread - ; execute an async call to DrawSpreadAsync. - ld a, LOW(DrawSpreadALittleAsync) - ld [vAsyncNext], a - ld a, HIGH(DrawSpreadALittleAsync) - ld [vAsyncNext+1], a - - call DoInAsyncVBlank + ; execute an async call to DrawSpread. + ld hl, DrawSpreadTaskWithoutRefreshingBackgroundFirst + call Async_Spawn_HL ret @@ -220,12 +191,10 @@ UpdateCurrentSpread: add hl, de .skipCardDescription ; e has number of cards in spread - di call PassList call PassList ; one card description has two strings dec e ; this will not work if the spreadd had zero cardss. i will overflow. jp nz, .skipCardDescription - ei ld e, [hl] ; skip title of spread inc hl @@ -243,101 +212,54 @@ UpdateCurrentSpread: ld [vCurrentSpread+1], a ; save the current spread (hl) into vcurrentspread. ret -DrawSpreadAsync: - ldh a, [vSelectedSpreadIndex] - ldh [vPreviousSpreadIndex], a - +DrawSpreadTask: ; draw the spread large in the middle of the screen, and descs + ; clear the space to scrolling background tiles ld de, $9800 + 32*5 + 3 ld hl, ONES ld b, 8 ld c, 14 - - ld a, LOW(CopyTilesToMapThreadsafe) - ld [vAsyncNext], a - ld a, HIGH(CopyTilesToMapThreadsafe) - ld [vAsyncNext+1], a - ld a, LOW(.afterClear) - ld [vAsyncAfter], a - ld a, HIGH(.afterClear) - ld [vAsyncAfter+1], a - di - nop - ret ; return from async execution now that we've registered desire - ; to call copytilestomapthreadsafe - ; and then drawspread - -.afterClear + call CopyTilesToMapUnsafe +DrawSpreadTaskWithoutRefreshingBackgroundFirst: + ; step past the spread layout to get to the spread description ld a, [vCurrentSpread] ld l, a ld a, [vCurrentSpread+1] ld h, a ld e, [hl] ; e holds length of spread - di call PassList ; step past spread layout - ei - nop - nop .PassCardPositionDescriptions - di call PassList ; step past one pdesc call PassList ; step past two pdesc - ei dec e ; we've looked at one jp nz, .PassCardPositionDescriptions -.foundSpreadTitle + + ; now hl is pointing at the title string ld de, $9800 + 32 + 1 - ld a, LOW(PrintString) - ld [vAsyncNext], a - ld a, HIGH(PrintString) - ld [vAsyncNext+1], a - ld a, LOW(.afterTitle) - ld [vAsyncAfter], a - ld a, HIGH(.afterTitle) - ld [vAsyncAfter+1], a - di - nop + call PrintString + + ; now hl is pointing at the description + ld de, $9800 + (32*2) + 1 + call PrintString + + call DrawSpreadCards + + ld a, 0 + ld [vBlocked], a ret -.afterTitle - ld de, $9800 + (32*2) + 1 - ld a, LOW(PrintString) - ld [vAsyncNext], a - ld a, HIGH(PrintString) - ld [vAsyncNext+1], a - ld a, LOW(DrawSpreadALittleAsync) - ld [vAsyncAfter], a - ld a, HIGH(DrawSpreadALittleAsync) - ld [vAsyncAfter+1], a - di - nop - ret - -DrawSpreadALittleAsync: - +DrawSpreadCards: ld hl, $9800 + 32*5 + 3 - ldh a, [vSelectedSpreadCard] + ld a, [vSelectedSpreadCard] ld d, 0 ld e, a ; e contains the selected index - - ld a, LOW(DrawSpreadBigAndThreadsafe) - ld [vAsyncNext], a - ld a, HIGH(DrawSpreadBigAndThreadsafe) - ld [vAsyncNext+1], a - ld a, LOW(.drawSpreadPositionDescription) - ld [vAsyncAfter], a - ld a, HIGH(.drawSpreadPositionDescription) - ld [vAsyncAfter+1], a - di - nop - ret + call DrawSpreadBig ; draw the large cards for the spread .drawSpreadPositionDescription - di ld a, [vCurrentSpread] ld l, a ld a, [vCurrentSpread+1] - ld h, a ; hl points at beginning of card list + ld h, a ; hl points at beginning of card postion list call PassList ; hl points at first card description ld a, [vSelectedSpreadCard] ld e, a @@ -349,41 +271,18 @@ DrawSpreadALittleAsync: dec e jp nz, .stepForwardCardDescription .printIt - ei - nop - nop -.drawFirstDescription ld de, $9800+32*15 + 6 - ld a, LOW(PrintString) - ld [vAsyncNext], a - ld a, HIGH(PrintString) - ld [vAsyncNext+1], a - ld a, LOW(.drawSecondDescription) - ld [vAsyncAfter], a - ld a, HIGH(.drawSecondDescription) - ld [vAsyncAfter+1], a - di - nop - ret - -.drawSecondDescription + call PrintString ld de, $9800+32*16 + 6 - ld a, LOW(PrintString) - ld [vAsyncNext], a - ld a, HIGH(PrintString) - ld [vAsyncNext+1], a - ld a, 0 - ld [vAsyncAfter], a - ld [vAsyncAfter+1], a - di - nop + call PrintString + ret SpreadSelectDraw: ld hl, SquaresTiles inc hl ld b, 0 - ldh a, [vFrameCountSquares] + ld a, [vFrameCountSquares] ld c, a add hl, bc add hl, bc @@ -400,11 +299,10 @@ SpreadSelectDraw: SpreadSelectTeardown: ret -DrawSpreadBigAndThreadsafe: +DrawSpreadBig: ; hl for location on screen ; current spread address in vCurrentSpread ; e for index of selected card - di ld a, [vCurrentSpread] ld c, a ld a, [vCurrentSpread+1] @@ -415,10 +313,7 @@ DrawSpreadBigAndThreadsafe: ld d, a ; length of spread in d inc d .drawCards - ei - nop - nop - di + dec d jp z, .doneWithSpread ; if we're drawing zero remaining cards, stop drawing inc bc ; step forward @@ -451,22 +346,13 @@ DrawSpreadBigAndThreadsafe: ld h, b ld l, c; retrieve vram address - ei - nop - di - nop - nop call DrawBigCardSelected .doneDrawingSpread - di - nop - nop ret DrawBigCard: ; starting from screen location hl, draw a card at ;the location described in a -; saves de and is therefore not threadsafe push de ld d, a swap a @@ -573,7 +459,7 @@ DrawSpreadMinimap: pop hl jp .drawCards -.doneWithSpread ; stack has hl, bc, af at the time of jumping here +.doneWithSpread pop bc ; stack: af pop af ld d, 0 diff --git a/main.asm b/main.asm index 94c174d..7de367d 100644 --- a/main.asm +++ b/main.asm @@ -4,45 +4,54 @@ ; moss for keeping me from working sixteen hours a day and burning out ; yuri for letting me bounce ideas off you at all times + + ; 0xc100 CALL ; 0xc101 LOW - SCENE_SETUP points to this ; 0xc102 HIGH ; 0xc103 RET ; 0xc104 CALL ... def MY_OAM equ $c000 + +; $c100 - c120 call handles, scene stack and interrupt DEF SCENE_SETUP EQU $c101 -DEF SCENE_UPDATE EQU SCENE_SETUP + 4 ; call then ret is 3+1 bytes +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 SCENE_TEARDOWN + 4 -DEF INTERRUPT_LCD EQU $c111 -def SHUFFLED_DECK equ $c200 ; location for the shuffled deck -def CARD_VARIABLES equ $c300 +; each of these sections is way bgger than it needs to be +; i doubt any of them will hold more than $20 bytes at all +; but might as well put them at round numbers for now +def ASYNC_VARS_START equ $c200 ; this space's layout defined manually in async.inc +def SYSTEM_VARS_START equ $c300 ; system variables like buttons pressed, rng, time +def GLOBAL_VARS_START equ $c400 ; defined mostly in mainmenu, program-wide state +def SCREEN_VARS_START equ $c500 ; per-screen variables like animation stuff +def CARD_VARS_START equ $c600 ; variables for animation of individual cards + +def SHUFFLED_DECK equ $c700 ; location for the shuffled deck def ZEROES equ $D000 def ONES equ $D200 -DEF ASYNC_VARS_START equ $ff80 ; these are defined manually in async.inc -DEF SYSTEM_VARS_START equ ASYNC_VARS_START + $10 -; allocating $8 spaces for system variables, currently only using $3 bytes +; allocating $8 spaces for system variables, currently only using $4 bytes DEF rMYBTN EQU SYSTEM_VARS_START DEF rMYBTNP EQU rMYBTN + 1 DEF rDELTAT EQU rMYBTNP + 1 ; delta_t where $1000 = 1 second def rLFSR equ rDELTAT + 1 ; 16 bit -DEF GLOBAL_VARS_START EQU SYSTEM_VARS_START + $8 -; global app-wide variables go after GLOBAL_VARS_START. allocated $10 for them -def VARIABLES_START equ GLOBAL_VARS_START + $10 -; screen-specific variables live after VARIABLES_START + ; WRAM Layout looks like this: ; $c000 - $c100 OAM DMA source ; $c100 - $c114 self-modifying code interrupts ; $c200 - $c21a shuffled deck ; $c300 - $c400 card display variables -; $c300-$c30f timers + ; $c300 - $c30f timers ; $c300 - $c400 card display variables ; $d000 - $d400 zeroes and ones, just because they're handy! +def SAFE_DMA_LOCATION equ $ffc1 + def VARIABLE_TILES_START equ 26 @@ -103,8 +112,8 @@ EntryPoint: ; initialize global variables ld a, 0 - ldh [vSelectedSpreadIndex], a - ldh [vSelectedCardIndex], a + ld [vSelectedSpreadIndex], a + ld [vSelectedCardIndex], a ld hl, Cards ld b, [hl] ld hl, SHUFFLED_DECK @@ -117,7 +126,7 @@ EntryPoint: jr nz, .writeCard ld a, %1010_1010 - ldh [rLFSR], a + ld [rLFSR], a ; move on to framework stuff @@ -205,7 +214,7 @@ Loop: sra a sra a add a, 64 - ldh [rDELTAT], a + ld [rDELTAT], a xor a, a ; zero a out in one cycle ; store dpad and btn state in the rMYBTN register @@ -228,12 +237,12 @@ Loop: swap a or a, b ld b, a ; put new input state in b - ldh a, [rMYBTN] ; previous input state in a + ld 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 [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 + ld [rMYBTN], a ; save that as btn state call SCENE_UPDATE - 1 ; hope this takes not too many scanlines! diff --git a/screendesigns.aseprite b/screendesigns.aseprite index 51fb7f0..34bdc8d 100644 Binary files a/screendesigns.aseprite and b/screendesigns.aseprite differ diff --git a/source.zip b/source.zip index adec502..901e789 100644 Binary files a/source.zip and b/source.zip differ