2025-01-07 13:23:32 -05:00
|
|
|
CopyTilesSafe:
|
2025-01-07 11:34:53 -05:00
|
|
|
; 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]
|
2025-01-08 14:03:54 -05:00
|
|
|
ld [vSafeCopyInterrupt], a
|
|
|
|
ld a, [INTERRUPT_LCD+1]
|
|
|
|
ld [vSafeCopyInterrupt+1], a ; stashes the current STAT interrupt handler
|
2025-01-07 11:34:53 -05:00
|
|
|
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"
|
2025-01-13 15:44:01 -05:00
|
|
|
ld a, SAFE_TRANSFER_START ; CHANGE ME TO ADJUST SAFE TRANSFER TIMING
|
2025-01-07 11:34:53 -05:00
|
|
|
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
|
2025-01-13 15:44:01 -05:00
|
|
|
ld a, SAFE_TRANSFER_END ; CHANGE ME TO ADJUST SAFE TRANSFER TIMING
|
2025-01-07 11:34:53 -05:00
|
|
|
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
|
2025-01-13 15:44:01 -05:00
|
|
|
ld a, SAFE_TRANSFER_START ; CHANGE ME TO ADJUST SAFE TRANSFER TIMING
|
2025-01-07 11:34:53 -05:00
|
|
|
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
|
2025-01-13 15:44:01 -05:00
|
|
|
ld a, SAFE_TRANSFER_START ; CHANGE ME TO ADJUST SAFE TRANSFER TIMING
|
2025-01-07 11:34:53 -05:00
|
|
|
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
|
2025-01-08 14:03:54 -05:00
|
|
|
ldh a, [vSafeCopyInterrupt]
|
2025-01-07 11:34:53 -05:00
|
|
|
ld [INTERRUPT_LCD], a
|
2025-01-08 14:03:54 -05:00
|
|
|
ldh a, [vSafeCopyInterrupt+1]
|
2025-01-11 12:45:13 -05:00
|
|
|
ld [INTERRUPT_LCD+1], a
|
2025-01-07 11:34:53 -05:00
|
|
|
|
|
|
|
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
|
2025-01-08 14:03:54 -05:00
|
|
|
|
|
|
|
|
|
|
|
CopyTilesToMapUnsafe:
|
2025-01-13 15:44:01 -05:00
|
|
|
; copy tiles from where they are linearly packed at an origin (hl)
|
|
|
|
; to a rectangle in the tilemap in vram (de)
|
2025-01-08 14:03:54 -05:00
|
|
|
; assuming it has height in b and width in c.
|
|
|
|
push bc
|
2025-01-13 15:44:01 -05:00
|
|
|
.copyTile
|
2025-01-08 14:03:54 -05:00
|
|
|
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
|
2025-01-13 15:44:01 -05:00
|
|
|
jp nz, .copyTile
|
|
|
|
.doneWithLine
|
2025-01-08 14:03:54 -05:00
|
|
|
pop bc
|
|
|
|
|
|
|
|
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, CopyTilesToMapUnsafe
|
2025-01-13 15:44:01 -05:00
|
|
|
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
|
|
|
|
|
|
|
|
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
|
2025-01-14 23:48:23 -05:00
|
|
|
ei
|
|
|
|
nop
|
|
|
|
nop
|
|
|
|
|
2025-01-08 14:03:54 -05:00
|
|
|
ret
|