DEF vPreviousSpreadIndex EQU VARIABLES_START def vPreviousSpreadCard equ vPreviousSpreadIndex + 1 ScreenSpreadSelect: dw SpreadSelectSetup dw SpreadSelectUpdate dw SpreadSelectDraw dw SpreadSelectTeardown SpreadSelectSetup: ld a, 0 ldh [vSelectedSpreadIndex], a ldh [vPreviousSpreadIndex], a ldh [vSelectedSpreadCard], a ldh [vPreviousSpreadCard], 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 ret .loadUIMap 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 .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 ret SpreadSelectUpdate: ld hl, rMYBTNP bit 4, [hl] jp z, .doneB ld hl, ScreenMainMenu call ChangeScene ret .doneB bit 5, [hl] jp z, .doneA ld hl, ScreenCardRead call ChangeScene ret .doneA ;up and down ld a, [vSelectedSpreadIndex] bit 3, [hl] ; select the down key jp z, .doneDown ; skip the following code if down is not pressed inc a ; increment when they press down .doneDown bit 2, [hl] ; select up key jp z, .doneUp ; skip the following code if up is not pressed dec a ; decrement when they press up because the deck has card 0 at the top .doneUp ld hl, Spreads call ArrayClampLooping ldh [vSelectedSpreadIndex], a ; save clamped index ; left and righgt ldh a, [vSelectedSpreadCard] ld hl, rMYBTNP bit 1, [hl] jp z, .doneLeft ; skip the following code if left is not pressed dec a .doneLeft bit 0, [hl] jp z, .doneRight ; skip the following code if right is not pressed inc a .doneRight ld hl, vCurrentSpread ld c, [hl] inc hl ld b, [hl] ld h, b ld l, c ; hl has current spread, a has index call ArrayClampLooping ldh [vSelectedSpreadCard], a ld hl, vTime ldh a, [rDELTAT] ld b, a ldh a, [vTime] add a, b ldh [vTime], a ldh a, [vTime+1] adc a, 0 ldh [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] 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 hl, SquaresTiles ldh a, [vFrameCountSquares] inc a call ArrayClampLooping ldh [vFrameCountSquares], a .doneTimer ldh a, [vSelectedSpreadIndex] ld hl, vPreviousSpreadIndex cp a, [hl] jp nz, .spreadChanged ; update the spread if the spread changed ldh a, [vSelectedSpreadCard] ld hl, vPreviousSpreadCard cp a, [hl] jp nz, .cardChanged ; update the spread if the card changed 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, [vSelectedSpreadIndex] ld [vPreviousSpreadIndex], a ld a, 0 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 ret .cardChanged 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, [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 ret UpdateCurrentSpread: ; find the correct spread address ld hl, Spreads inc hl ; skip length of spreads ld a, [vSelectedSpreadIndex] inc a ; we're decing at the start so we inc first to prepare... ld d, 0 .findSpread dec a jp z, .spreadFound ld e, [hl] ; skip cards in spread inc hl 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 add hl, de ld e, [hl] ; skip description inc hl add hl, de jp .findSpread .spreadFound ld a, l ld [vCurrentSpread], a ld a, h ld [vCurrentSpread+1], a ; save the current spread (hl) into vcurrentspread. ret DrawSpreadAsync: ldh a, [vSelectedSpreadIndex] ldh [vPreviousSpreadIndex], a 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 ret ; return from async execution now that we've registered desire ; to call copytilestomapthreadsafe ; and then drawspread .afterClear 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 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 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 ret DrawSpreadALittleAsync: ld hl, $9800 + 32*5 + 3 ldh 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 ret .drawSpreadPositionDescription di ld a, [vCurrentSpread] ld l, a ld a, [vCurrentSpread+1] ld h, a ; hl points at beginning of card list call PassList ; hl points at first card description ld a, [vSelectedSpreadCard] ld e, a cp a, 0 jp z, .printIt .stepForwardCardDescription call PassList call PassList 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 ret .drawSecondDescription 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 ret SpreadSelectDraw: di ld hl, SquaresTiles + 1 ld b, 0 ldh a, [vFrameCountSquares] ld c, a add hl, bc add hl, bc ld c, [hl] inc hl ld b, [hl] ld h, b ld l, c ld de, $8000 + $1000 + $10 ld a, [hl+] ld [de], a inc de ld a, [hl+] ld [de], a inc de ld a, [hl+] ld [de], a inc de ld a, [hl+] ld [de], a inc de ld a, [hl+] ld [de], a inc de ld a, [hl+] ld [de], a inc de ld a, [hl+] ld [de], a inc de ld a, [hl+] ld [de], a inc de ld a, [hl+] ld [de], a inc de ld a, [hl+] ld [de], a inc de ld a, [hl+] ld [de], a inc de ld a, [hl+] ld [de], a inc de ld a, [hl+] ld [de], a inc de ld a, [hl+] ld [de], a inc de ld a, [hl+] ld [de], a inc de ld a, [hl+] ld [de], a reti SpreadSelectTeardown: ret DrawSpreadBigAndThreadsafe: ; 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] ld b, a ld a, [bc] cp a, 0 ; length of spread jp z, .doneDrawingSpread ; return early if the spread is empty 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 push hl ; need this bc drawsmallcard changes hl ld a, [bc] call DrawBigCard pop hl jp .drawCards .doneWithSpread ; stack has spread address ; d is zero ; e should have currently selected index ld b, h ld c, l ; stash hl in bc for a mo; this should be a location in vram ld a, [vCurrentSpread] ld l, a ld a, [vCurrentSpread+1] ld h, a ;spread address in hl inc hl ; skip the tiles length ld d, 0 ld a, [vSelectedSpreadCard] ld e, a add hl, de ld a, [hl] ; load card descriptor into a ld h, b ld l, c; retrieve vram address ei nop di nop nop call DrawBigCardSelected .doneDrawingSpread ei 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 and a, %0000_1111 sla a ld e, a ld a, d and a, %0000_1111 ld d, 0 add hl, de ; step right ld e, 64 jp z, .drawCard .stepDown add hl, de ; step down dec a jp nz, .stepDown .drawCard ld de, 32 ld [hl], -16 + $1 inc hl ld [hl], -16 + $2 add hl, de ld [hl], -16 + $4 dec hl ld [hl], -16 + $3 add hl, de ld [hl], -16 + $3 inc hl ld [hl], -16 + $4 add hl, de ld [hl], -16 + $6 dec hl ld [hl], -16 + $5 pop de ret DrawBigCardSelected: ; starting from screen location hl, draw a card at ;the location described in a push de push af swap a ld d, 0 and a, %0000_1111 sla a ld e, a add hl, de ; step right ld e, 64 pop af and a, %0000_1111 jp z, .drawCard .stepDown add hl, de ; step down dec a jp nz, .stepDown .drawCard ld de, 32 ld [hl], -16 + $7 inc hl ld [hl], -16 + $8 add hl, de ld [hl], -16 + $a dec hl ld [hl], -16 + $9 add hl, de ld [hl], -16 + $b inc hl ld [hl], -16 + $c add hl, de ld [hl], -16 + $e dec hl ld [hl], -16 + $d pop de ret DrawSpreadMinimap: ; hl for location on screen ; bc for current spread address ; a for index of selected card push af push bc ld a, [bc] ld d, 0 ld e, a ; length of spread in de .drawCards ld a, e cp a, 0 jp z, .doneWithSpread ; if we're drawing zero remaining cards, stop drawing dec e inc bc ; step forward push hl ; need this bc drawsmallcard changes hl push bc ld a, [bc] ld bc, $1817 call DrawSmallCard pop bc pop hl jp .drawCards .doneWithSpread ; stack has hl, bc, af at the time of jumping here pop bc ; stack: af pop af ld d, 0 ld e, a ; index of selected card in spread inc e ; skip the length push hl ; stack: hl ld h, b ld l, c ; put bc in hl temporarily so we can add to hl add hl, de ld a, [hl] pop hl ; stack: empty ld bc, $1a19 call DrawSmallCard ret DrawSmallCard: ; starting from screen location hl, draw a card at ;the location described in a, top and bottom sprite in b and c push de push af swap a ld d, 0 and a, %0000_1111 ld e, a add hl, de ; step right ld e, 32 pop af and a, %0000_1111 jp z, .drawCard : dec a add hl, de ; step down cp a, 0 jp nz, :- .drawCard ld [hl], b add hl, de ld [hl], c pop de ret CardPartTiles: db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 db $00,$ff,$7f,$ff,$7f,$ff,$60,$ff,$6f,$ff,$6d,$fa,$6a,$fd,$6d,$fa db $00,$ff,$fe,$ff,$fe,$ff,$06,$ff,$f6,$ff,$56,$bf,$b6,$5f,$56,$bf db $6a,$fd,$6d,$fa,$6a,$fd,$6d,$fa,$6a,$fd,$6d,$fa,$6a,$fd,$6d,$fa db $b6,$5f,$56,$bf,$b6,$5f,$56,$bf,$b6,$5f,$56,$bf,$b6,$5f,$56,$bf db $6a,$fd,$6d,$fa,$6a,$fd,$6f,$ff,$60,$ff,$7f,$ff,$7f,$ff,$00,$ff db $b6,$5f,$56,$bf,$b6,$5f,$f6,$ff,$06,$ff,$fe,$ff,$fe,$ff,$00,$ff db $ff,$00,$80,$7f,$80,$7f,$9f,$7f,$9f,$7f,$98,$78,$99,$79,$9a,$7a db $ff,$00,$01,$fe,$01,$fe,$f9,$fe,$f9,$fe,$19,$1e,$19,$1e,$d9,$de db $9a,$7a,$99,$79,$98,$78,$9c,$78,$99,$78,$9b,$79,$9b,$7a,$9b,$7a db $d9,$de,$99,$9e,$d9,$de,$f9,$de,$99,$9e,$d9,$9e,$d9,$9e,$d9,$5e db $98,$78,$98,$7b,$99,$7a,$9a,$7c,$9f,$7b,$99,$79,$99,$79,$98,$78 db $59,$5e,$19,$fe,$f9,$1e,$19,$1e,$d9,$de,$d9,$de,$59,$5e,$19,$1e db $98,$79,$98,$79,$98,$78,$9f,$7f,$9f,$7f,$80,$7f,$80,$7f,$ff,$00 db $19,$9e,$19,$9e,$19,$1e,$f9,$fe,$f9,$fe,$01,$fe,$01,$fe,$ff,$00 CardPartTilesEnd: SpreadSelectTilemap: db $09, $02, $02, $02, $02, $02, $02, $02, $02, $02, $02, $02, $02, $02, $02, $02, $02, $02, $02, $08 db $03, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $04 db $03, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $04 db $06, $05, $05, $05, $05, $05, $05, $05, $05, $05, $05, $05, $05, $05, $05, $05, $05, $05, $05, $07 db $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01 db $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01 db $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01 db $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01 db $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01 db $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01 db $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01 db $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01 db $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01 db $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01, $01 db $01, $01, $01, $01, $01, $09, $02, $02, $02, $02, $02, $02, $02, $02, $08, $01, $01, $01, $01, $01 db $01, $01, $01, $01, $01, $03, $00, $00, $00, $00, $00, $00, $00, $00, $04, $01, $01, $01, $01, $01 db $01, $01, $01, $01, $01, $03, $00, $00, $00, $00, $00, $00, $00, $00, $04, $01, $01, $01, $01, $01 db $01, $01, $01, $01, $01, $06, $05, $05, $05, $05, $05, $05, $05, $05, $07, $01, $01, $01, $01, $01 SpreadSelectTilemapEnd: