89 lines
2.7 KiB
NASM
89 lines
2.7 KiB
NASM
; Like the NES and Super NES, DMA on the Game Boy takes access to RAM
|
|
; and ROM away from the CPU. But unlike those two, the CPU continues
|
|
; to run. So store a tiny subroutine in HRAM (tightly coupled
|
|
; memory) to keep the CPU busy until OAM DMA is done.
|
|
SECTION "hram_tools", HRAM
|
|
RunDMA: ds 11
|
|
|
|
SECTION "Tools", ROM0
|
|
|
|
InitTools:
|
|
; Copy the sprite DMA routine
|
|
ld de, dma_routine_start
|
|
ld hl, RunDMA
|
|
ld bc, dma_routine_end - dma_routine_start
|
|
call Memcpy
|
|
ret
|
|
|
|
; Memory copier
|
|
; @param de - Address source to start of data to be copied
|
|
; @param hl - Address destomatopm where to copy the data to
|
|
; @param bc - The total amount of bytes to copy
|
|
; @return a = Zero
|
|
; @return bc = Zero
|
|
; @return de = Address Source to the byte after the last byte from source (garbage)
|
|
; @return hl = Address Target to the byte after the last byte on the target (garbage)
|
|
Memcpy:
|
|
ld a, [de] ; Load the value at [de] to accumilator
|
|
ld [hli], a ; Load the value from accumilator to the destination address and increment it by one
|
|
inc de ; Increment de to point to next byte to copy
|
|
dec bc ; Decrement bc the total amount of bytes to copy
|
|
ld a, b ; Load the first half of total amount of bytes to write to accumilator
|
|
or c ; OR together the second half of total amount with the first half
|
|
jr nz, Memcpy ; Loop back to Memcpy if not zero
|
|
ret
|
|
|
|
Memfill:
|
|
; Fill an area in memory at position hl with value a for b amount of times
|
|
;
|
|
; @param hl - Starting address in memory to fill
|
|
; @param a - The value to fill said address space with
|
|
; @param b - How many bytes we should fill starting from said address space
|
|
; @return a - garbage
|
|
; @return b - PosX on where to draw text
|
|
; @return c - PosY on where to draw text
|
|
; @return hl - Workram position for text pointer
|
|
; @return de - Memory address to source string
|
|
.repeatFill
|
|
ld [hli], a
|
|
dec b
|
|
jr nz, .repeatFill
|
|
ret
|
|
|
|
Memfill16:
|
|
; Fill an area in memory at position hl with value a for bc amount of times
|
|
;
|
|
; @param hl - Starting address in memory to fill
|
|
; @param a - The value to fill said address space with
|
|
; @param b - How many bytes we should fill starting from said address space
|
|
; @return a - garbage
|
|
; @return b - PosX on where to draw text
|
|
; @return c - PosY on where to draw text
|
|
; @return hl - Workram position for text pointer
|
|
; @return de - Memory address to source string
|
|
.repeatFill
|
|
ld [hli], a
|
|
dec bc
|
|
jr nz, .repeatFill
|
|
ret
|
|
|
|
;;
|
|
; Waits for the vblank ISR to increment the count of vertical blanks.
|
|
; Will lock up if DI, vblank IRQ off, or LCD off.
|
|
; Clobbers A, HL
|
|
WaitVBlank:
|
|
.wait
|
|
halt
|
|
ret
|
|
|
|
;;
|
|
; The routine gets copied to high RAM
|
|
dma_routine_start:
|
|
ld a,shadow_oam >> 8
|
|
ld [rDMA],a
|
|
ld a,40
|
|
.loop:
|
|
dec a
|
|
jr nz,.loop
|
|
ret
|
|
dma_routine_end:
|