diff --git a/00TheFool.inc b/00TheFool.inc index 4fad592..8fa394c 100644 --- a/00TheFool.inc +++ b/00TheFool.inc @@ -5,28 +5,61 @@ ; then a 16bit value of the offset between tile map and end ; then the 16bit address of the tile map TheFool: +def Card_Offset_title equ @-TheFool db 10, "THE FOOL " db 10, " " +def Card_Offset_description equ @-TheFool db 9, "beginning" db 9, "leap " db 9, "naivete " +def Card_Offset_tilemap equ @-TheFool dw .BackgroundCopyEnd - .BackgroundCopy dw .BackgroundCopy +def Card_Offset_keytiles equ @-TheFool dw .KeyArtTilesEnd - .KeyArtTiles dw .KeyArtTiles +def Card_Offset_spritetiles equ @-TheFool dw .SpriteTilesEnd - .SpriteTiles dw .SpriteTiles +def Card_Offset_functions equ @-TheFool dw .fInit dw .fUpdate dw .fDraw - - ; original export script by gabriel reis, modified by shoofle + +; CARD_VARS_START: timer +; CARD_VARS_START+2: timer 2 +; CARD_VARS_START+4: animation frame for dog +; CARD_VARS_START+5: +; CARD_VARS_START+6: y of zero +; CARD_VARS_START+7: .fInit: - ld h, $c2 - ld l, $00 + ld a, [rLCDC] + xor a, %0000_0100 + ld [rLCDC], a + ld hl, CARD_VARS_START ld a, 0 - ld [hl+], a ; $c200 = timer for dog - ld [hl+], a ; $c201 = timer for big zero + ld [hl+], a ; timer for dog @ +0 + ld [hl+], a + ld [hl+], a ; timer for big zero @ +2 + ld [hl+], a + ld [hl+], a ; frame of dog animation + ld [hl+], a + ld [hl+], a ; y of zero + ld [hl+], a ; x of zero + + ld hl, .doggie1 + ld de, MY_OAM + ld b, 134 + ld c, 34 + ld a, $23 + ; takkes similar args as copytilestomapunsafe but builds several sprites + ; instead. + ; location of source tile map: hl + ; location in memory to write to: de + ; y and x in b and c + ; height and width in a & %11110000 and a & %00001111 ??? that's deranged + call BuildMetaSprite + ret .fUpdate: ld a, [rDELTAT] @@ -47,6 +80,9 @@ TheFool: ld a, 0 ld [CARD_VARS_START], a ld [CARD_VARS_START+1], a + ; and make the dog dance + + call .dogDance .doneWithTimer1 @@ -55,7 +91,7 @@ TheFool: ld [CARD_VARS_START+2], a ld a, [CARD_VARS_START+2+1] adc a, 0 - ld [$c302+1], a + ld [CARD_VARS_START+2+1], a ld a, [CARD_VARS_START+2+1] cp a, $10 ; $10 00 = 1 second @@ -69,27 +105,76 @@ TheFool: .doneWithTimer2 ret +println "card vars start is ", CARD_VARS_START .fDraw: ret + +.dogDance: + + ld hl, CARD_VARS_START+4 + inc [hl] + ld a, 2 + cp a, [hl] + jp nz, :+ + ld [hl], 0 +: + ld a, [hl] ; a now holds the frame of the animation. + + cp a, 0 + jp z, .frame1 + cp a, 1 + jp z, .frame2 + ret + +.frame1 + ld hl, .doggie1 + ld de, MY_OAM + ld b, 134 + ld c, 34 + ld a, $23 + ; takkes similar args as copytilestomapunsafe but builds several sprites + ; instead. + ; location of source tile map: hl + ; location in memory to write to: de + ; y and x in b and c + ; height and width in a & %11110000 and a & %00001111 ??? that's deranged + call BuildMetaSprite + ret +.frame2 + ld hl, .doggie2 + ld de, MY_OAM + ld b, 133 + ld c, 34 + ld a, $23 + call BuildMetaSprite + ret + .SpriteTiles: db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 - db $00,$00,$01,$01,$01,$01,$01,$01,$0f,$0f,$1f,$10,$1f,$10,$0f,$0c - db $a0,$a0,$f8,$58,$fc,$04,$5e,$a2,$ff,$01,$ff,$00,$ff,$00,$ff,$00 - db $00,$00,$00,$00,$00,$00,$02,$02,$07,$05,$ff,$fd,$ff,$01,$ff,$01 - db $03,$03,$01,$01,$01,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 - db $ff,$00,$ff,$00,$ff,$00,$ff,$80,$ff,$93,$7e,$52,$3c,$34,$08,$08 - db $ff,$01,$ff,$01,$ff,$01,$ff,$01,$ff,$c9,$3f,$29,$1e,$1a,$04,$04 - db $00,$00,$00,$00,$00,$00,$04,$04,$0e,$0a,$ff,$fd,$ff,$01,$ff,$01 - db $ff,$00,$ff,$00,$ff,$00,$ff,$80,$ff,$93,$fc,$94,$78,$58,$20,$20 - db $ff,$01,$ff,$01,$ff,$01,$ff,$01,$ff,$c9,$7e,$4a,$3c,$2c,$10,$10 + db $01,$01,$01,$01,$01,$01,$01,$01,$1f,$1f,$1f,$10,$1f,$10,$1f,$1c + db $f0,$f0,$fc,$5c,$fe,$06,$5f,$a3,$ff,$01,$ff,$00,$ff,$00,$ff,$00 + db $00,$00,$00,$00,$00,$00,$07,$07,$87,$85,$ff,$fd,$ff,$01,$ff,$01 + db $07,$07,$01,$01,$01,$01,$01,$01,$00,$00,$00,$00,$00,$00,$00,$00 + db $ff,$00,$ff,$00,$ff,$00,$ff,$80,$ff,$93,$fe,$d2,$7e,$76,$1c,$1c + db $ff,$01,$ff,$01,$ff,$01,$ff,$01,$ff,$c9,$7f,$69,$3f,$3b,$0e,$0e + db $00,$00,$00,$00,$00,$00,$0e,$0e,$8f,$8b,$ff,$fd,$ff,$01,$ff,$01 + db $ff,$00,$ff,$00,$ff,$00,$ff,$80,$ff,$93,$fe,$96,$fc,$dc,$70,$70 + db $ff,$01,$ff,$01,$ff,$01,$ff,$01,$ff,$c9,$7f,$4b,$7e,$6e,$38,$38 db $00,$00,$03,$03,$0c,$0c,$10,$10,$20,$20,$20,$20,$40,$40,$40,$40 db $00,$00,$c0,$c0,$30,$30,$08,$08,$04,$04,$04,$04,$02,$02,$02,$02 db $40,$40,$40,$40,$20,$20,$20,$20,$10,$10,$0c,$0c,$03,$03,$00,$00 db $02,$02,$02,$02,$04,$04,$04,$04,$08,$08,$30,$30,$c0,$c0,$00,$00 .SpriteTilesEnd: +.doggie1: ; tiles start at 0 + db $01, $02, $03 + db $04, $08, $06 +.doggie2: + db $01, $02, $07 + db $04, $05, $09 + .KeyArtTiles: db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 db $1f,$00,$0f,$00,$0f,$00,$0f,$00,$07,$00,$07,$00,$07,$00,$07,$00 diff --git a/00thefool.aseprite b/00thefool.aseprite index c313d4a..4e173d2 100644 Binary files a/00thefool.aseprite and b/00thefool.aseprite differ diff --git a/00thefool.asm b/00thefool.asm index 69b87ad..38a53ab 100644 --- a/00thefool.asm +++ b/00thefool.asm @@ -3,15 +3,15 @@ .SpriteTiles: db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 - db $00,$00,$01,$01,$01,$01,$01,$01,$0f,$0f,$1f,$10,$1f,$10,$0f,$0c - db $a0,$a0,$f8,$58,$fc,$04,$5e,$a2,$ff,$01,$ff,$00,$ff,$00,$ff,$00 - db $00,$00,$00,$00,$00,$00,$02,$02,$07,$05,$ff,$fd,$ff,$01,$ff,$01 - db $03,$03,$01,$01,$01,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 - db $ff,$00,$ff,$00,$ff,$00,$ff,$80,$ff,$93,$7e,$52,$3c,$34,$08,$08 - db $ff,$01,$ff,$01,$ff,$01,$ff,$01,$ff,$c9,$3f,$29,$1e,$1a,$04,$04 - db $00,$00,$00,$00,$00,$00,$04,$04,$0e,$0a,$ff,$fd,$ff,$01,$ff,$01 - db $ff,$00,$ff,$00,$ff,$00,$ff,$80,$ff,$93,$fc,$94,$78,$58,$20,$20 - db $ff,$01,$ff,$01,$ff,$01,$ff,$01,$ff,$c9,$7e,$4a,$3c,$2c,$10,$10 + db $01,$01,$01,$01,$01,$01,$01,$01,$1f,$1f,$1f,$10,$1f,$10,$1f,$1c + db $f0,$f0,$fc,$5c,$fe,$06,$5f,$a3,$ff,$01,$ff,$00,$ff,$00,$ff,$00 + db $00,$00,$00,$00,$00,$00,$07,$07,$87,$85,$ff,$fd,$ff,$01,$ff,$01 + db $07,$07,$01,$01,$01,$01,$01,$01,$00,$00,$00,$00,$00,$00,$00,$00 + db $ff,$00,$ff,$00,$ff,$00,$ff,$80,$ff,$93,$fe,$d2,$7e,$76,$1c,$1c + db $ff,$01,$ff,$01,$ff,$01,$ff,$01,$ff,$c9,$7f,$69,$3f,$3b,$0e,$0e + db $00,$00,$00,$00,$00,$00,$0e,$0e,$8f,$8b,$ff,$fd,$ff,$01,$ff,$01 + db $ff,$00,$ff,$00,$ff,$00,$ff,$80,$ff,$93,$fe,$96,$fc,$dc,$70,$70 + db $ff,$01,$ff,$01,$ff,$01,$ff,$01,$ff,$c9,$7f,$4b,$7e,$6e,$38,$38 db $00,$00,$03,$03,$0c,$0c,$10,$10,$20,$20,$20,$20,$40,$40,$40,$40 db $00,$00,$c0,$c0,$30,$30,$08,$08,$04,$04,$04,$04,$02,$02,$02,$02 db $40,$40,$40,$40,$20,$20,$20,$20,$10,$10,$0c,$0c,$03,$03,$00,$00 @@ -19,22 +19,6 @@ .SpriteTilesEnd: .Sprites: ; tiles start at 0 - db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 - db $00, $00, $00, $00, $0a, $0b, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 - db $00, $00, $00, $00, $0c, $0d, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 - db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 - db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 - db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 - db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 - db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 - db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 - db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 - db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 - db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 - db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 - db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 - db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 - db $00, $00, $00, $01, $02, $03, $01, $02, $07, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 - db $00, $00, $00, $04, $08, $06, $04, $05, $09, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 - db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 + db $01, $02, $07 + db $04, $05, $09 .SpritesEnd: diff --git a/Async.inc b/Async.inc index ddd9447..e7280c1 100644 --- a/Async.inc +++ b/Async.inc @@ -18,7 +18,7 @@ def ASYNC_STACK_TOP equ $ffc0 ; 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_START EQU 150 def SAFE_ASYNC_END EQU 153 Async_Spawn_HL: diff --git a/CardHelpers.inc b/CardHelpers.inc index 69585f1..f84714c 100644 --- a/CardHelpers.inc +++ b/CardHelpers.inc @@ -1,6 +1,27 @@ +; CARD_HELPER_VARS_START defines the beginning of the $100 bytes set aside for system usage +def cvCardAddress equ 0 ; location of the current card's struct + + + + LoadCardData: LoadCardDataAsync: - ei + ; first and foremost, clear the card init, update, and draw handles, so there's + ; no chance of trying to jump into code from a previous card. + ld bc, Instructions + ld hl, CARD_INIT + ld [hl], c + inc hl + ld [hl], b + ld hl, CARD_UPDATE + ld [hl], c + inc hl + ld [hl], b + ld hl, CARD_DRAW + ld [hl], c + inc hl + ld [hl], b + ld a, [vSelectedCardIndex] ld [vPreviousCardIndex], a @@ -13,19 +34,19 @@ LoadCardDataAsync: ld a, [hl+] ld [rROMB0], a ; select the specified bank - ; follow the pointer we're looking at + ; follow the pointer we're looking at, and write it to cvCardAddress ld a, [hl+] + ld [CARD_HELPER_VARS_START + cvCardAddress], a ld c, a ld a, [hl+] + ld [CARD_HELPER_VARS_START + cvCardAddress + 1], a ld b, a ld h, b ld l, c ; hl now contains the address of the card data. - -.duringDraw - ; synchronously - ; hl points to a card struct. + + ; card struct starts with a sequence of length-prefixed strings in memory ; so when we're done writing one, hl will be correctly placed to read the next ; length-prefixed print doesn't require passing a length @@ -60,35 +81,15 @@ LoadCardDataAsync: 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 - ld hl, Cards + 1 ; skip the length prefix - add hl, bc - add hl, bc - add hl, bc ; triple add bc entries are bank, addr, addr + ld a, [CARD_HELPER_VARS_START + cvCardAddress] + ld l, a + ld a, [CARD_HELPER_VARS_START + cvCardAddress + 1] + ld h, a ; hl now contains the address of the card data. + + ld b, 0 + ld c, Card_Offset_keytiles ; jump straight to keytiles length and location! + add hl, bc - ld a, [hl+] - ld [rROMB0], a ; select the specified bank - ; follow the pointer we're looking at - ld a, [hl+] - ld c, a - ld a, [hl+] - ld b, a - - ld h, b - ld l, c ; hl now contains the address of the card data. - call PassList - call PassList - call PassList - call PassList - call PassList ; skip the strings - inc hl - inc hl ; skip tile map width - inc hl - inc hl ; skip tile map pointer ld a, [hl+] ld c, a ld a, [hl+] @@ -104,6 +105,54 @@ LoadCardDataAsync: ld de, $9000 + VARIABLE_TILES_START*$10 ; always load tile data into the same spot in vram call CopyRangeUnsafe - di - nop + + ld a, [CARD_HELPER_VARS_START + cvCardAddress] + ld l, a + ld a, [CARD_HELPER_VARS_START + cvCardAddress + 1] + ld h, a ; hl now contains the address of the card data. + + ld b, 0 + ld c, Card_Offset_spritetiles ; jump straight to sprite tiles length and location! + add hl, bc + + ld a, [hl+] + ld c, a + ld a, [hl+] + ld b, a ; bc has length of tile data + ld a, [hl+] + ld e, a + ld a, [hl+] + ld d, a ; de has source of tile range copy + + ld h, d + ld l, e ; hl takes the source + + ld de, $8000 ; sprite tiles get loaded into the bottom of vram + call CopyRangeUnsafe + + ld a, [CARD_HELPER_VARS_START + cvCardAddress] + ld l, a + ld a, [CARD_HELPER_VARS_START + cvCardAddress + 1] + ld h, a ; hl now contains the address of the card data. + + ld b, 0 + ld c, Card_Offset_functions ; jump straight to sprite tiles length and location! + + add hl, bc ; hl now points to the card functions + + ld a, [hl+] + ld [CARD_INIT], a + ld a, [hl+] + ld [CARD_INIT+1], a + ld a, [hl+] + ld [CARD_UPDATE], a + ld a, [hl+] + ld [CARD_UPDATE+1], a + ld a, [hl+] + ld [CARD_DRAW], a + ld a, [hl+] + ld [CARD_DRAW+1], a + + call CARD_INIT - 1 + ret diff --git a/CopyRangeSafe.inc b/CopyRangeSafe.inc index 97762b1..ac732cd 100644 --- a/CopyRangeSafe.inc +++ b/CopyRangeSafe.inc @@ -12,194 +12,6 @@ DEF vSafeCopyInterruptEnable EQU vSafeCopyInterrupt + 2 ; stashes $FFFF, which i DEF SAFE_TRANSFER_START EQU 145 DEF SAFE_TRANSFER_END EQU 153 -CopyRangeSafe: - ; hl is source - ; de is destination - ; bc is length to copy -; copy an array of bytes to a destination in memory. -; this is completely different from CopyRangeUnsafe. -; this initiates an asynchronous, interrupt-driven copy of BC bytes of memory -; from HL to DE. -; it may return a memory address to look at for progress of the transfer, -; or else it's just going to do it with a hard-coded address. -; check the transfer status address for zero; when it's zero, the transfer is done! -; this works by using the STAT interrupt in LYC mode to interrupt its own execution at -; two scanlines inside the vblank interval to know when to start and stop. - ; stash arguments in memory - di - ld a, l - ldh [vSafeCopySource], a - ld a, h - ldh [vSafeCopySource+1], a - ld a, e - ldh [vSafeCopyDest], a - ld a, d - ldh [vSafeCopyDest+1], a - ld a, c - ldh [vSafeCopyCount], a - ld a, b - ldh [vSafeCopyCount+1], a - - ; stash interrupt state in memory - ldh a, [$ff41] - ldh [vSafeCopySTAT], a ; stashes $FF41, the STAT register - ldh a, [$ff45] - ldh [vSafeCopyLYC], a ; stashes $FF45, the LYC register - ld a, [INTERRUPT_LCD] - ld [vSafeCopyInterrupt], a - ld a, [INTERRUPT_LCD+1] - ld [vSafeCopyInterrupt+1], a ; stashes the current STAT interrupt handler - ld a, [$ffff] - and a, %0000_0010 - ld [vSafeCopyInterruptEnable], a ; stashes whether LCD interrupt are enabled - - ld hl, CopyRangeSafe_EnterSafeMode - ld a, l - ld [INTERRUPT_LCD], a - ld a, h - ld [INTERRUPT_LCD + 1], a; set interrupt handler to "ENTER SAFE MODE" - ld a, SAFE_TRANSFER_START ; CHANGE ME TO ADJUST SAFE TRANSFER TIMING - ld [$ff45], a - ld hl, $ffff - set 1, [hl] - ld a, %0100_0000 - ld [$ff41], a - - ld hl, vSafeCopyCount - - ld a, 0 - ld [$ff0f], a - - ei - nop - ret ; return address of bytes remaining to copy - -CopyRangeSafe_EnterSafeMode: - push hl - push bc - push de - push af - ld hl, CopyRangeSafe_ExitSafeMode - ld a, l - ld [INTERRUPT_LCD], a - ld a, h - ld [INTERRUPT_LCD+1], a - ld a, SAFE_TRANSFER_END ; CHANGE ME TO ADJUST SAFE TRANSFER TIMING - ld [$ff45], a ; set lcd interrupt handler to EXIT SAFE MODE on line 153 - ldh a, [vSafeCopySource] - ld l, a - ldh a, [vSafeCopySource+1] - ld h, a ; fetch the source - ldh a, [vSafeCopyDest] - ld e, a - ldh a, [vSafeCopyDest+1] - ld d, a ; fetch the dest - ldh a, [vSafeCopyCount] - ld c, a - ldh a, [vSafeCopyCount+1] - ld b, a ; fetch the count - - - ; before starting transfer, make sure the zero flag is false. - ld a, 1 - cp a, 0 -CopyRangeSafe_TransferLoop: - ei - nop ; ei only sets the flag one instruction later apparently. safety nop! - di ; process interrupts - jp z, CopyRangeSafe_CleanUp ; zero flag will only be set if the exitsafemode handler fired - ld a, [hl+] - ld [de], a ; - inc de - dec bc - ld a, b - or a, c - jp nz, CopyRangeSafe_TransferLoop - jp CopyRangeSafe_Done - -CopyRangeSafe_ExitSafeMode: - ld a, 0 - cp a, 0 ; set the zero flag, which we're using as a signal to stop transferring - reti ; set a to zero and set the zero flag true. now the transfer loop will end - -CopyRangeSafe_CleanUp: - ld a, l - ldh [vSafeCopySource], a - ld a, h - ldh [vSafeCopySource+1], a ; store new source - ld a, e - ldh [vSafeCopyDest], a - ld a, d - ldh [vSafeCopyDest+1], a ; store new dest - ld a, c - ldh [vSafeCopyCount], a - ld a, b - ldh [vSafeCopyCount+1], a ; store new count - - ld hl, CopyRangeSafe_EnterSafeMode - ld a, l - ld [INTERRUPT_LCD], a - ld a, h - ld [INTERRUPT_LCD+1], a - ld a, SAFE_TRANSFER_START ; CHANGE ME TO ADJUST SAFE TRANSFER TIMING - ld [$ff45], a ; set lcd interrupt handler to ENTER SAFE MODE on line 148 - pop af - pop de - pop bc - pop hl - reti ; we're done with this memcpy cycle so we return from interrupt. - -CopyRangeSafe_Done: ; called when the complete transfer is finished, -; this restores interrupts to how they were. - ; stash interrupt state in memory - ld a, l - ldh [vSafeCopySource], a - ld a, h - ldh [vSafeCopySource+1], a ; store new source - ld a, e - ldh [vSafeCopyDest], a - ld a, d - ldh [vSafeCopyDest+1], a ; store new dest - ld a, c - ldh [vSafeCopyCount], a - ld a, b - ldh [vSafeCopyCount+1], a ; store new count - - ld hl, CopyRangeSafe_EnterSafeMode - ld a, l - ld [INTERRUPT_LCD], a - ld a, h - ld [INTERRUPT_LCD+1], a - ld a, SAFE_TRANSFER_START ; CHANGE ME TO ADJUST SAFE TRANSFER TIMING - ld [$ff45], a ; set lcd interrupt handler to ENTER SAFE MODE on line 148 - pop af - pop de - pop bc - pop hl - - ldh a, [vSafeCopySTAT] - ldh [$ff41], a - ldh a, [vSafeCopyLYC] - ldh [$ff45], a - ldh a, [vSafeCopyInterrupt] - ld [INTERRUPT_LCD], a - ldh a, [vSafeCopyInterrupt+1] - ld [INTERRUPT_LCD+1], a - - ld hl, $ffff - ld a, [hl] - cpl - set 1, a - cpl ; turn off the lcd interrupt enable - ld [hl], a - - ld a, [vSafeCopyInterruptEnable] - cp a, 0 ; if the stashed enable was 0 return. if the stashed enable was 1 then turn it on - jp z, CopyRangeSafe_Return - set 1, [hl] ; turn on the lcd interrupt - -CopyRangeSafe_Return: - reti CopyRangeUnsafe: ; this is threadsafe but not vblank safe ; hl is source diff --git a/CopyTilesSafe.inc b/CopyTilesSafe.inc index a479858..899bd24 100644 --- a/CopyTilesSafe.inc +++ b/CopyTilesSafe.inc @@ -1,216 +1,4 @@ -CopyTilesSafe: - ; hl is source - ; de is destination - ; bc is length to copy -; copy an array of bytes to the bgmap in vram. -; this is the safe-copy analogue of CopyTilesToMap - ; stash arguments in memory - di - ld a, l - ldh [vSafeCopySource], a - ld a, h - ldh [vSafeCopySource+1], a - ld a, e - ldh [vSafeCopyDest], a - ld a, d - ldh [vSafeCopyDest+1], a - ld a, c - ldh [vSafeCopyCount], a - ldh [vSafeCopyOriginalCount], a - ld a, b - ldh [vSafeCopyCount+1], a - ldh [vSafeCopyOriginalCount+1], a - - - ; stash interrupt state in memory - ldh a, [$ff41] - ldh [vSafeCopySTAT], a ; stashes $FF41, the STAT register - ldh a, [$ff45] - ldh [vSafeCopyLYC], a ; stashes $FF45, the LYC register - ld a, [INTERRUPT_LCD] - ld [vSafeCopyInterrupt], a - ld a, [INTERRUPT_LCD+1] - ld [vSafeCopyInterrupt+1], a ; stashes the current STAT interrupt handler - ld a, [$ffff] - and a, %0000_0010 - ld [vSafeCopyInterruptEnable], a ; stashes whether LCD interrupt are enabled - - ld hl, CopyTilesSafe_EnterSafeMode - ld a, l - ld [INTERRUPT_LCD], a - ld a, h - ld [INTERRUPT_LCD + 1], a; set interrupt handler to "ENTER SAFE MODE" - ld a, SAFE_TRANSFER_START ; CHANGE ME TO ADJUST SAFE TRANSFER TIMING - ld [$ff45], a - ld hl, $ffff - set 1, [hl] - ld a, %0100_0000 - ld [$ff41], a - - ld hl, vSafeCopyCount - - ld a, 0 - ld [$ff0f], a - - ei - ret ; return address of bytes remaining to copy - -CopyTilesSafe_EnterSafeMode: - push hl ; stash registers! we just took over as an interrupt! - push bc - push de - push af - ld hl, CopyTilesSafe_ExitSafeMode - ld a, l - ld [INTERRUPT_LCD], a - ld a, h - ld [INTERRUPT_LCD+1], a - ld a, SAFE_TRANSFER_END ; CHANGE ME TO ADJUST SAFE TRANSFER TIMING - ld [$ff45], a ; set lcd interrupt handler to EXIT SAFE MODE on line 153 - ldh a, [vSafeCopySource] - ld l, a - ldh a, [vSafeCopySource+1] - ld h, a ; fetch the source - ldh a, [vSafeCopyDest] - ld e, a - ldh a, [vSafeCopyDest+1] - ld d, a ; fetch the dest - ldh a, [vSafeCopyCount] - ld c, a - ldh a, [vSafeCopyCount+1] - ld b, a ; fetch the count - - ; before starting transfer, make sure the zero flag is false. - ld a, 1 - cp a, 0 -CopyTilesSafe_TransferLoop: - ei - nop ; ei only sets the flag one instruction later apparently. safety nop! - nop ; we're processing interrupts here - di - jp z, CopyTilesSafe_CleanUp ; zero flag will only be set if the exit handler fired - - ld a, [hl] ; load from the tile map into a - ld [de], a ; load from a into the destination - inc hl ; this is slower than using hli but i'm trying to work with this here - inc de - dec c - ; check if we've completed a line? - ld a, 0 - or a, c ; check if c is zero, if it's not zero go back and copy more bytes - jp nz, CopyTilesSafe_TransferLoop -CopyTilesSafe_DoneWithLine: - ldh a, [vSafeCopyOriginalCount] - ld c, a - ldh a, [vSafeCopyOriginalCount+1] - ld b, a - - ld a, e - add a, 32 - ld e, a - ld a, d - adc a, 0 - ld d, a - ld a, e - sub a, c - ld e, a - ld a, d - sbc a, 0 - ld d, a - - dec b - ld a, b - - ldh [vSafeCopyOriginalCount+1], a ; store the decremented line count - jp nz, CopyTilesSafe_TransferLoop - jp CopyTilesSafe_Done - - -CopyTilesSafe_ExitSafeMode: - ld a, 0 - cp a, 0 ; set the zero flag, which we're using as a signal to stop transferring - reti ; set a to zero and set the zero flag true. now the transfer loop will end - -CopyTilesSafe_CleanUp: - ld a, l - ldh [vSafeCopySource], a - ld a, h - ldh [vSafeCopySource+1], a ; store new source - ld a, e - ldh [vSafeCopyDest], a - ld a, d - ldh [vSafeCopyDest+1], a ; store new dest - ld a, c - ldh [vSafeCopyCount], a - ld a, b - ldh [vSafeCopyCount+1], a ; store new count - - ld hl, CopyTilesSafe_EnterSafeMode - ld a, l - ld [INTERRUPT_LCD], a - ld a, h - ld [INTERRUPT_LCD+1], a - ld a, SAFE_TRANSFER_START ; CHANGE ME TO ADJUST SAFE TRANSFER TIMING - ld [$ff45], a ; set lcd interrupt handler to ENTER SAFE MODE on line 148 - pop af - pop de - pop bc - pop hl - reti ; we're done with this memcpy cycle so we return from interrupt. - -CopyTilesSafe_Done: ; called when the complete transfer is finished, -; this restores interrupts to how they were. - ; stash interrupt state in memory - ld a, l - ldh [vSafeCopySource], a - ld a, h - ldh [vSafeCopySource+1], a ; store new source - ld a, e - ldh [vSafeCopyDest], a - ld a, d - ldh [vSafeCopyDest+1], a ; store new dest - ld a, 0 - ldh [vSafeCopyCount], a - ld a, 0 - ldh [vSafeCopyCount+1], a ; store new count - - ld hl, CopyRangeSafe_EnterSafeMode - ld a, l - ld [INTERRUPT_LCD], a - ld a, h - ld [INTERRUPT_LCD+1], a - ld a, SAFE_TRANSFER_START ; CHANGE ME TO ADJUST SAFE TRANSFER TIMING - ld [$ff45], a ; set lcd interrupt handler to ENTER SAFE MODE on line 148 - pop af - pop de - pop bc - pop hl - - ldh a, [vSafeCopySTAT] - ldh [$ff41], a - ldh a, [vSafeCopyLYC] - ldh [$ff45], a - ldh a, [vSafeCopyInterrupt] - ld [INTERRUPT_LCD], a - ldh a, [vSafeCopyInterrupt+1] - ld [INTERRUPT_LCD+1], a - - ld hl, $ffff - ld a, [hl] - cpl - set 1, a - cpl ; turn off the lcd interrupt enable - ld [hl], a - - ld a, [vSafeCopyInterruptEnable] - cp a, 0 ; check if the stat interrupt was active before we took over - jp z, CopyRangeSafe_Return - set 1, [hl] ; turn on the lcd interrupt - -CopyTilesSafe_Return: - reti - - +CopyTilesToMap: CopyTilesToMapUnsafe: ; copy tiles from where they are linearly packed at an origin (hl) ; to a rectangle in the tilemap in vram (de) @@ -245,51 +33,77 @@ CopyTilesToMapUnsafe: dec b ld a, b cp a, 0 - jp nz, CopyTilesToMapUnsafe + jp nz, CopyTilesToMap ret -CopyTilesToMapThreadsafe: - ; copy tiles from where they are linearly packed at an origin (hl) - ; to a rectangle in the tilemap in vram (de) - ; assuming it has height in b and width in c. - di - ei - nop - di - push bc -.copyTile - ld a, [hl] ; load from the tile map into a - ld [de], a ; load from a into the destination - inc hl ; this is slower than using hli but i'm trying to work with this here - inc de - dec c - ; check if we've completed a line? - ld a, 0 - or a, c ; check if c is zero, if it's not zero go back and copy more bytes - jp nz, .copyTile -.doneWithLine - pop bc - ei +BuildMetaSprite: + ; takkes similar args as copytilestomapunsafe but builds several sprites + ; instead. + ; location of source tile map: hl + ; location in memory to write to: de + ; y and x in b and c + ; height and width in a & %11110000 and a & %00001111 ??? that's deranged + push hl + push de + pop hl ; want hl and de to be swapped just for the sake of consistent apis + pop de ; hl now holds the OAM location, de holds the sprite map + push af ; save to the stack so we can retrieve it for row-wise decrement + push bc ; hold onto the upper-left corner so we can update it each row - ld a, e - add a, 32 - ld e, a - ld a, d - adc a, 0 - ld d, a - ld a, e - sub a, c - ld e, a - ld a, d - sbc a, 0 - ld d, a - - dec b - ld a, b - cp a, 0 - jp nz, CopyTilesToMapThreadsafe - di - nop - nop - ret \ No newline at end of file +.writeRow + pop bc + pop af + push af + push bc ; refresh af and bc from their authoritative stack versions + and a, $0F ; take only the horizontal tile count + +.buildSprite + ; + ld [hl], b ; write y byte + inc hl + ld [hl], c ; write x byte + inc hl + push af ; save a before we use it for transferring de to hl + ld a, [de] + inc de ; move to the next sprite + ld [hl], a + inc hl + inc hl ; skip the attributes byte + ; we're going to wait to get our a value (number of tiles left to draw in this + ; row) until after we've used a for changing c + + ;we've written a whole sprite. hl and de are in the right state, we need to + ; update a and bc. + + ; update bc + ld a, c + add a, 8 + ld c, a + pop af ; get back the number of tiles to draw in this row + dec a + jp nz, .buildSprite ; if there are still tiles left to draw in this row, do it! + + ; otherwise we have no more tiles to write this row bc needs to be updated + + + pop bc + ld a, b + add a, 8 + ld b, a ; add 8 to the y coordinate + + pop af + sub a, $10 + push af + push bc + + and a, $F0 + ; stakc has bc and af, ready for repeating from the top + jp nz, .writeRow ; last numerical operation was and a, $F0 so checking if upper byte is zero + + pop bc + pop af + + ret + + \ No newline at end of file diff --git a/ScreenCardBrowse.inc b/ScreenCardBrowse.inc index b980fbe..ad30350 100644 --- a/ScreenCardBrowse.inc +++ b/ScreenCardBrowse.inc @@ -11,11 +11,11 @@ CardBrowseSetup: ld a, 1 ld [vBlocked], a - ld hl, .loadUIMap + ld hl, .asyncTask call Async_Spawn_HL ret -.loadUIMap +.asyncTask ld a, HIGH(ZEROES) ld de, SAFE_DMA_LOCATION ; arguments to the first async call. call RunDMA @@ -24,10 +24,12 @@ CardBrowseSetup: ld de, $9800 ; destination ld b, 18 ; height ld c, 20 ; width - call CopyTilesToMapUnsafe - call LoadCardTask + call RefreshCardTask + + ld a, 0 + ld [vBlocked], a ret CardBrowseUpdate: @@ -91,18 +93,11 @@ CardBrowseUpdate: cp a, 0 ret nz - ld hl, LoadCardTask + ld hl, RefreshCardTask call Async_Spawn_HL 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 @@ -123,9 +118,14 @@ CardBrowseDraw: ld bc, (SquaresTileset8 - SquaresTileset7) / 8 call CopyRangeUnsafeBy8s - call DrawDeckMinimap + call RunDMA ret +RefreshCardTask: + call DrawDeckMinimap + call LoadCardData + ret + DrawDeckMinimap: ld hl, Cards ld c, [hl] ; count of cards diff --git a/ScreenCardRead.inc b/ScreenCardRead.inc index 5963a3b..d42bf13 100644 --- a/ScreenCardRead.inc +++ b/ScreenCardRead.inc @@ -13,18 +13,28 @@ CardReadSetup: ld hl, CardReadSetupAsyncTask call Async_Spawn_HL + + ld hl, ZEROES + ld de, MY_OAM + ld bc, $100 + call CopyRangeUnsafe + ret CardReadSetupAsyncTask: - ld hl, UITilemap ; origin + + ld hl, CardRead.UITilemap ; origin ld de, $9800 ; destination ld b, 18 ; height ld c, 20 ; width call CopyTilesToMapUnsafe + call ChangedCardTask ret CardReadUpdate: + call CARD_UPDATE - 1 + ld hl, vTime ld a, [rDELTAT] ld b, a @@ -88,10 +98,9 @@ CardReadUpdate: cp a, 0 ret nz - ld a, 1 - ld [vBlocked], a ld hl, ChangedCardTask call Async_Spawn_HL + ret CardReadDraw: @@ -110,8 +119,11 @@ CardReadDraw: ld de, $8000+$100*16 + 1*16 ld bc, (SquaresTileset8 - SquaresTileset7) / 8 call CopyRangeUnsafeBy8s + + ld de, SAFE_DMA_LOCATION + ld a, HIGH(MY_OAM) + call RunDMA - ; the card data is loaded asynchronously, initiated in CardReadUpdate ret CardReadTeardown: @@ -158,13 +170,11 @@ ChangedCardTask: ld [vPreviousCardIndex], a call LoadCardData - - ld a, 0 - ld [vBlocked], a + ret -UITilemap: +CardRead.UITilemap: db $0e, $0a, $0a, $0a, $0a, $0a, $0a, $0a, $0a, $0f, $09, $02, $02, $02, $02, $02, $02, $02, $08, $01 db $0b, $00, $00, $00, $00, $00, $00, $00, $00, $0c, $03, $00, $00, $00, $00, $00, $00, $00, $04, $01 db $0b, $00, $00, $00, $00, $00, $00, $00, $00, $0c, $03, $00, $00, $00, $00, $00, $00, $00, $04, $01 @@ -183,4 +193,4 @@ UITilemap: db $0b, $00, $00, $00, $00, $00, $00, $00, $00, $0c, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 db $0b, $00, $00, $00, $00, $00, $00, $00, $00, $0c, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 db $11, $0d, $0d, $0d, $0d, $0d, $0d, $0d, $0d, $10, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 -UITilemapEnd: +CardRead.UITilemapEnd: diff --git a/main.asm b/main.asm index 7de367d..86aa7e3 100644 --- a/main.asm +++ b/main.asm @@ -13,12 +13,16 @@ ; 0xc104 CALL ... def MY_OAM equ $c000 -; $c100 - c120 call handles, scene stack and interrupt +; $c100 - c120 call handles, scene stack, interrupt, card functions 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 SCENE_TEARDOWN + 4 +def CARD_INIT equ INTERRUPT_LCD + 4 +def CARD_UPDATE equ CARD_INIT + 4 +def CARD_DRAW equ CARD_UPDATE + 4 +println "Card Draw is ", CARD_DRAW ; 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 @@ -27,9 +31,9 @@ def ASYNC_VARS_START equ $c200 ; this space's layout defined manually in async.i 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 CARD_HELPER_VARS_START equ $c600 +def CARD_VARS_START equ $c700 ; variables for animation of individual cards +def SHUFFLED_DECK equ $c800 ; location for the shuffled deck def ZEROES equ $D000 def ONES equ $D200 @@ -41,14 +45,6 @@ DEF rDELTAT EQU rMYBTNP + 1 ; delta_t where $1000 = 1 second def rLFSR equ rDELTAT + 1 ; 16 bit -; 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 - $c400 card display variables -; $d000 - $d400 zeroes and ones, just because they're handy! def SAFE_DMA_LOCATION equ $ffc1 @@ -144,6 +140,12 @@ EntryPoint: ld [hl], a ld hl, INTERRUPT_LCD - 1 ld [hl], a + ld hl, CARD_INIT - 1 + ld [hl], a + ld hl, CARD_UPDATE - 1 + ld [hl], a + ld hl, CARD_DRAW - 1 + ld [hl], a ld hl, Instructions inc hl @@ -159,6 +161,12 @@ EntryPoint: ld [hl], a ld hl, INTERRUPT_LCD ld [hl], a + ld hl, CARD_INIT + ld [hl], a + ld hl, CARD_UPDATE + ld [hl], a + ld hl, CARD_DRAW + ld [hl], a ld hl, Instructions inc hl @@ -175,6 +183,12 @@ EntryPoint: ld [hl], a ld hl, INTERRUPT_LCD + 1 ld [hl], a + ld hl, CARD_INIT + 1 + ld [hl], a + ld hl, CARD_UPDATE + 1 + ld [hl], a + ld hl, CARD_DRAW + 1 + ld [hl], a ld hl, Instructions inc hl @@ -192,8 +206,14 @@ EntryPoint: ld [hl], a ld hl, INTERRUPT_LCD + 2 ld [hl], a + ld hl, CARD_INIT + 2 + ld [hl], a + ld hl, CARD_UPDATE + 2 + ld [hl], a + ld hl, CARD_DRAW + 2 + ld [hl], a - ; set up our scene vectors + ; set up our scene handle ld hl, ScreenMainMenu call ChangeScene @@ -353,7 +373,7 @@ run_dma_tail: ; This part must be in HRAM. .run_dma_tail_end Instructions: - call SCENE_UPDATE + 2 + call Instructions+3 ret