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 CopyTilesToMapUnsafe: ; 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. 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, CopyTilesToMapUnsafe 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 ret