progress on the safe copy routine
This commit is contained in:
parent
de58b8f8af
commit
4b100cf2a2
261
tarot.asm
261
tarot.asm
@ -9,11 +9,32 @@ DEF SCENE_SETUP EQU $FF81
|
||||
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 rMYBTN EQU $FF90
|
||||
DEF rMYBTN EQU $FFA0
|
||||
DEF rMYBTNP EQU rMYBTN + 1
|
||||
DEF vSelectedTileIndex EQU $FF90+2
|
||||
DEF vPreviousCardIndex EQU $FF90+3
|
||||
|
||||
DEF INTERRUPT_LCD EQU $FF91
|
||||
|
||||
|
||||
; tile index variables
|
||||
DEF vSelectedTileIndex EQU $FFA0+2
|
||||
DEF vPreviousCardIndex EQU $FFA0+3
|
||||
|
||||
; variables for safe transfer async function
|
||||
DEF vSafeCopySource EQU $FFA0+4
|
||||
DEF vSafeCopyDest EQU vSafeCopySource + 2
|
||||
DEF vSafeCopyCount EQU vSafeCopyDest + 2 ; check this for safe transfer being complete
|
||||
; stash previous interrupt state before using the interrupts
|
||||
DEF vSafeCopyLYC EQU vSafeCopyCount + 2 ; stashes $FF45, the LYC register
|
||||
DEF vSafeCopySTAT EQU vSafeCopyLYC + 1 ; stashes $FF41, the STAT register
|
||||
DEF vSafeCopyInterruptFirst EQU vSafeCopySTAT + 1 ; stashes $0048 the STAT interrupt
|
||||
DEF vSafeCopyInterruptSecond EQU vSafeCopyInterruptFirst + 1
|
||||
DEF vSafeCopyInterruptEnable EQU vSafeCopyInterruptSecond + 1 ; stashes $FFFF, which interrupts are enabled
|
||||
|
||||
INCLUDE "hardware.inc"
|
||||
SECTION "Interrupts", ROM0[$0]
|
||||
ds $48 - @, 0
|
||||
call INTERRUPT_LCD - 1
|
||||
ret
|
||||
|
||||
SECTION "Header", ROM0[$100]
|
||||
|
||||
@ -35,6 +56,8 @@ EntryPoint:
|
||||
ld [hl], a
|
||||
ld hl, SCENE_TEARDOWN - 1
|
||||
ld [hl], a
|
||||
ld hl, INTERRUPT_LCD - 1
|
||||
ld [hl], a
|
||||
|
||||
ld a, [Instructions + 3] ; get the value of a ret instruction
|
||||
ld hl, SCENE_SETUP + 2
|
||||
@ -45,6 +68,8 @@ EntryPoint:
|
||||
ld [hl], a
|
||||
ld hl, SCENE_TEARDOWN + 2
|
||||
ld [hl], a
|
||||
ld hl, INTERRUPT_LCD + 2
|
||||
ld [hl], a
|
||||
|
||||
; set up our scene vectors
|
||||
ld hl, SCENE_SETUP
|
||||
@ -72,6 +97,14 @@ EntryPoint:
|
||||
ld a, d
|
||||
ld [hl+], a
|
||||
|
||||
; set up the interrupt vector to just be ret.
|
||||
ld hl, INTERRUPT_LCD
|
||||
ld de, INTERRUPT_LCD + 2
|
||||
ld a, e
|
||||
ld [hl+], a
|
||||
ld a, d
|
||||
ld [hl+], a
|
||||
|
||||
; Do not turn the LCD off outside of VBlank
|
||||
WaitVBlank:
|
||||
ld a, [rLY]
|
||||
@ -81,6 +114,7 @@ WaitVBlank:
|
||||
call SCENE_SETUP - 1
|
||||
|
||||
Loop:
|
||||
di
|
||||
ld hl, rP1
|
||||
ld [hl], P1F_GET_DPAD
|
||||
ld a, [hl]
|
||||
@ -107,13 +141,15 @@ Loop:
|
||||
ld a, b
|
||||
ld [rMYBTN], a
|
||||
|
||||
di
|
||||
call SCENE_UPDATE - 1
|
||||
|
||||
ei
|
||||
ld b, 144
|
||||
call AwaitLine
|
||||
|
||||
di
|
||||
call SCENE_DRAW - 1
|
||||
|
||||
ei
|
||||
jp Loop
|
||||
|
||||
|
||||
@ -126,17 +162,17 @@ CardReadSetup:
|
||||
ld hl, UITiles ; source
|
||||
ld de, $8800 ; destination of copy
|
||||
ld bc, UITilesEnd - UITiles ; length to copy
|
||||
call CopyRange
|
||||
call CopyRangeUnsafe
|
||||
|
||||
ld hl, LetterTiles ; map the small font into vram at ascii locations
|
||||
ld de, $8000 + (127 + $21)*16
|
||||
ld bc, LetterTilesEnd - LetterTiles
|
||||
call CopyRange
|
||||
call CopyRangeUnsafe
|
||||
|
||||
ld hl, BigLetterTiles
|
||||
ld de, $8000 + (128 + 16 + 32)*16
|
||||
ld bc, BigLetterTilesEnd - BigLetterTiles
|
||||
; call CopyRange
|
||||
; call CopyRangeUnsafe
|
||||
|
||||
ld de, UITilemap ; origin
|
||||
ld hl, $9800 ; destination
|
||||
@ -150,11 +186,6 @@ CardReadSetup:
|
||||
ld c, 8
|
||||
call CopyTilesToMap
|
||||
|
||||
ld a, $FF
|
||||
ld [vPreviousCardIndex], a
|
||||
ld a, 0
|
||||
call LoadCardData
|
||||
|
||||
; Turn the LCD on
|
||||
ld a, LCDCF_BLK01 | LCDCF_ON | LCDCF_BGON
|
||||
ld [rLCDC], a
|
||||
@ -163,43 +194,44 @@ CardReadSetup:
|
||||
ld a, %11100100
|
||||
ld [rBGP], a
|
||||
|
||||
ld a, $FF
|
||||
ldh [vPreviousCardIndex], a
|
||||
ld a, 0
|
||||
ldh [vSelectedTileIndex], a
|
||||
|
||||
call LoadCardData
|
||||
ei
|
||||
ret ; return from cardreadsetup
|
||||
|
||||
CardReadUpdate:
|
||||
ldh a, [rMYBTNP]
|
||||
and a, %0000_1000 ; check if down is held
|
||||
and a, %0000_1000 ; select the down key
|
||||
jp z, CardReadUpdateDoneDown
|
||||
ldh a, [vSelectedTileIndex]
|
||||
inc a ; increment when they press down because the stack has card 0 at the top
|
||||
ldh [vSelectedTileIndex], a
|
||||
CardReadUpdateDoneDown:
|
||||
ldh a, [rMYBTNP]
|
||||
and a, %0000_0100
|
||||
and a, %0000_0100 ; select the up key
|
||||
jp z, CardReadUpdateDoneUp
|
||||
ldh a, [vSelectedTileIndex]
|
||||
dec a ; decrement when they press up because the stack has card 0 at the top
|
||||
ldh [vSelectedTileIndex], a
|
||||
CardReadUpdateDoneUp:
|
||||
ldh a, [vSelectedTileIndex]
|
||||
cp a, 22
|
||||
cp a, 2
|
||||
jp nz, CardReadUpdateDoneZero
|
||||
ld a, 0
|
||||
ldh [vSelectedTileIndex], a
|
||||
CardReadUpdateDoneZero:
|
||||
cp a, $FF
|
||||
jp nz, CardReadUpdateReturn
|
||||
ld a, 21
|
||||
ld a, 1
|
||||
ldh [vSelectedTileIndex], a
|
||||
CardReadUpdateReturn:
|
||||
ret
|
||||
|
||||
CardReadDraw:
|
||||
ldh a, [vSelectedTileIndex]
|
||||
call LoadCardData
|
||||
ld b, 11 ; 11 rows, and we stop before drawing row zero
|
||||
ld b, 1 ; 11 rows, and we stop before drawing row zero
|
||||
ld hl, $9800+32*4+19 ; start point
|
||||
ld de, 32 ; stride
|
||||
CardReadDrawCopyTile:
|
||||
@ -240,33 +272,23 @@ CardReadDraw_PickTileWithTop:
|
||||
ld a, $82
|
||||
ld [hl], a
|
||||
CardReadDrawReturn:
|
||||
ld a, [vSelectedTileIndex]
|
||||
call LoadCardData
|
||||
ldh a, [vSelectedTileIndex]
|
||||
ld hl, vPreviousCardIndex
|
||||
cp a, [hl]
|
||||
call nz, LoadCardData ; only load new card data if the selected card has changed
|
||||
ret
|
||||
|
||||
CardReadTeardown:
|
||||
ret
|
||||
|
||||
LoadCardData:
|
||||
ld hl, vPreviousCardIndex
|
||||
cp a, [hl]
|
||||
ret z
|
||||
ld a, [vSelectedTileIndex]
|
||||
ld [vPreviousCardIndex], a
|
||||
ld [vSelectedTileIndex], a
|
||||
|
||||
ld a, [rLCDC]
|
||||
cp 0
|
||||
jp z, LoadCardData_DoneTurningOff
|
||||
|
||||
ld b, 144
|
||||
call AwaitLine ; put the line you want to reach in b
|
||||
|
||||
ld a, 0
|
||||
ld [rLCDC], a ; turn off the lcd so we don't cause memory corruption
|
||||
call AwaitLine ; wait for vblank before starting to work
|
||||
LoadCardData_DoneTurningOff:
|
||||
|
||||
ld a, [vSelectedTileIndex]
|
||||
|
||||
ld b, 0
|
||||
ld c, a ; load bc from a. coming into this we have the number of the card in the card array in a
|
||||
ld hl, Cards + 1 ; skip the length prefix
|
||||
@ -316,7 +338,7 @@ LoadCardData_DoneTurningOff:
|
||||
|
||||
ld de, $8000 ; always load tile data into the same spot in vram
|
||||
|
||||
call CopyRange
|
||||
call CopyRangeSafe
|
||||
|
||||
pop hl
|
||||
ld a, [hl+]
|
||||
@ -337,8 +359,7 @@ LoadCardData_DoneTurningOff:
|
||||
ld c, 8 ; width
|
||||
call CopyTilesToMap
|
||||
|
||||
ld a, LCDCF_BLK01 | LCDCF_ON | LCDCF_BGON
|
||||
ld [rLCDC], a
|
||||
ret
|
||||
|
||||
|
||||
Instructions:
|
||||
@ -368,7 +389,7 @@ AwaitLine: ; put the line you want to reach in b
|
||||
jp nz, AwaitLine
|
||||
ret
|
||||
|
||||
CopyRange:
|
||||
CopyRangeUnsafe:
|
||||
; hl is source
|
||||
; de is destination
|
||||
; bc is length to copy
|
||||
@ -378,7 +399,161 @@ CopyRange:
|
||||
dec bc
|
||||
ld a, b
|
||||
or a, c ; check if bc is zero
|
||||
jp nz, CopyRange
|
||||
jp nz, CopyRangeUnsafe
|
||||
ret
|
||||
|
||||
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 [vSafeCopyInterruptFirst], a
|
||||
ld a, [INTERRUPT_LCD + 1]
|
||||
ld [vSafeCopyInterruptSecond], a ; stashes $0048 the STAT interrupt handler
|
||||
ld a, [$ffff]
|
||||
and a, %0000_0010
|
||||
ld [vSafeCopyInterruptEnable], a ; stashes whether LCD interrupt are enabled
|
||||
|
||||
ld a, 148 ; adjust this to change timing of copy
|
||||
ld [$ff45], a
|
||||
|
||||
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, 148 ; 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
|
||||
ei
|
||||
ret ; return address of bytes remaining to copy
|
||||
|
||||
CopyRangeSafe_EnterSafeMode:
|
||||
ld hl, CopyRangeSafe_ExitSafeMode
|
||||
ld a, l
|
||||
ld [INTERRUPT_LCD], a
|
||||
ld a, h
|
||||
ld [INTERRUPT_LCD+1], a
|
||||
ld a, 153 ; 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!
|
||||
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, 148 ; CHANGE ME TO ADJUST SAFE TRANSFER TIMING
|
||||
ld [$ff45], a ; set lcd interrupt handler to ENTER SAFE MODE on line 148
|
||||
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
|
||||
ldh a, [vSafeCopySTAT]
|
||||
ldh [$ff41], a
|
||||
ldh a, [vSafeCopyLYC]
|
||||
ldh [$ff45], a
|
||||
ldh a, [vSafeCopyInterruptFirst]
|
||||
ld [INTERRUPT_LCD], a
|
||||
ldh a, [vSafeCopyInterruptSecond]
|
||||
ldh [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:
|
||||
ret
|
||||
|
||||
CopyTilesToMap:
|
||||
@ -438,7 +613,7 @@ TheFool:
|
||||
dw FoolTilesEnd - FoolTiles
|
||||
dw FoolTiles
|
||||
dw FoolMapEnd - FoolMap
|
||||
dw FoolMap, FoolMapEnd
|
||||
dw FoolMap
|
||||
FoolTiles:
|
||||
db $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,$01,$00,$01,$00,$02
|
||||
|
Loading…
Reference in New Issue
Block a user