pokecrystal/home/video.asm

460 lines
5.8 KiB
NASM

; Functions dealing with VRAM.
DMATransfer::
; Return carry if the transfer is completed.
ldh a, [hDMATransfer]
and a
ret z
; Start transfer
ldh [rHDMA5], a
; Execution is halted until the transfer is complete.
xor a
ldh [hDMATransfer], a
scf
ret
UpdateBGMapBuffer::
; Copy [hBGMapTileCount] 16x8 tiles from wBGMapBuffer
; to bg map addresses in wBGMapBufferPtrs.
; [hBGMapTileCount] must be even since this is done in pairs.
; Return carry on success.
ldh a, [hBGMapUpdate]
and a
ret z
ldh a, [rVBK]
push af
; Relocate the stack pointer to wBGMapBufferPtrs
ld [hSPBuffer], sp
ld hl, wBGMapBufferPtrs
ld sp, hl
; We can now pop the addresses of affected spots on the BG Map
ld hl, wBGMapPalBuffer
ld de, wBGMapBuffer
.next
; Copy a pair of 16x8 blocks (one 16x16 block)
rept 2
; Get our BG Map address
pop bc
; Palettes
ld a, 1
ldh [rVBK], a
ld a, [hli]
ld [bc], a
inc c
ld a, [hli]
ld [bc], a
dec c
; Tiles
ld a, 0
ldh [rVBK], a
ld a, [de]
inc de
ld [bc], a
inc c
ld a, [de]
inc de
ld [bc], a
endr
; We've done 2 16x8 blocks
ldh a, [hBGMapTileCount]
dec a
dec a
ldh [hBGMapTileCount], a
jr nz, .next
; Restore the stack pointer
ldh a, [hSPBuffer]
ld l, a
ldh a, [hSPBuffer + 1]
ld h, a
ld sp, hl
pop af
ldh [rVBK], a
xor a
ldh [hBGMapUpdate], a
scf
ret
WaitTop::
; Wait until the top third of the BG Map is being updated.
ldh a, [hBGMapMode]
and a
ret z
ldh a, [hBGMapThird]
and a
jr z, .done
call DelayFrame
jr WaitTop
.done
xor a
ldh [hBGMapMode], a
ret
UpdateBGMap::
; Update the BG Map, in thirds, from wTilemap and wAttrmap.
ldh a, [hBGMapMode]
and a ; 0
ret z
; BG Map 0
dec a ; 1
jr z, .Tiles
dec a ; 2
jr z, .Attr
; BG Map 1
dec a ; useless
ldh a, [hBGMapAddress]
ld l, a
ldh a, [hBGMapAddress + 1]
ld h, a
push hl
xor a ; LOW(vBGMap1)
ldh [hBGMapAddress], a
ld a, HIGH(vBGMap1)
ldh [hBGMapAddress + 1], a
ldh a, [hBGMapMode]
push af
cp 3
call z, .Tiles
pop af
cp 4
call z, .Attr
pop hl
ld a, l
ldh [hBGMapAddress], a
ld a, h
ldh [hBGMapAddress + 1], a
ret
.Attr:
ld a, 1
ldh [rVBK], a
hlcoord 0, 0, wAttrmap
call .update
ld a, 0
ldh [rVBK], a
ret
.Tiles:
hlcoord 0, 0
.update
ld [hSPBuffer], sp
; Which third?
ldh a, [hBGMapThird]
and a ; 0
jr z, .top
dec a ; 1
jr z, .middle
; 2
THIRD_HEIGHT EQU SCREEN_HEIGHT / 3
; bottom
ld de, 2 * THIRD_HEIGHT * SCREEN_WIDTH
add hl, de
ld sp, hl
ldh a, [hBGMapAddress + 1]
ld h, a
ldh a, [hBGMapAddress]
ld l, a
ld de, 2 * THIRD_HEIGHT * BG_MAP_WIDTH
add hl, de
; Next time: top third
xor a
jr .start
.middle
ld de, THIRD_HEIGHT * SCREEN_WIDTH
add hl, de
ld sp, hl
ldh a, [hBGMapAddress + 1]
ld h, a
ldh a, [hBGMapAddress]
ld l, a
ld de, THIRD_HEIGHT * BG_MAP_WIDTH
add hl, de
; Next time: bottom third
ld a, 2
jr .start
.top
ld sp, hl
ldh a, [hBGMapAddress + 1]
ld h, a
ldh a, [hBGMapAddress]
ld l, a
; Next time: middle third
ld a, 1
.start
; Which third to update next time
ldh [hBGMapThird], a
; Rows of tiles in a third
ld a, THIRD_HEIGHT
; Discrepancy between wTilemap and BGMap
ld bc, BG_MAP_WIDTH - (SCREEN_WIDTH - 1)
.row
; Copy a row of 20 tiles
rept SCREEN_WIDTH / 2 - 1
pop de
ld [hl], e
inc l
ld [hl], d
inc l
endr
pop de
ld [hl], e
inc l
ld [hl], d
add hl, bc
dec a
jr nz, .row
ldh a, [hSPBuffer]
ld l, a
ldh a, [hSPBuffer + 1]
ld h, a
ld sp, hl
ret
Serve1bppRequest::
; Only call during the first fifth of VBlank
ld a, [wRequested1bppSize]
and a
ret z
; Back out if we're too far into VBlank
ldh a, [rLY]
cp LY_VBLANK
ret c
cp LY_VBLANK + 2
ret nc
; Copy [wRequested1bppSize] 1bpp tiles from [wRequested1bppSource] to [wRequested1bppDest]
ld [hSPBuffer], sp
; Source
ld hl, wRequested1bppSource
ld a, [hli]
ld h, [hl]
ld l, a
ld sp, hl
; Destination
ld hl, wRequested1bppDest
ld a, [hli]
ld h, [hl]
ld l, a
; # tiles to copy
ld a, [wRequested1bppSize]
ld b, a
xor a
ld [wRequested1bppSize], a
.next
rept 3
pop de
ld [hl], e
inc l
ld [hl], e
inc l
ld [hl], d
inc l
ld [hl], d
inc l
endr
pop de
ld [hl], e
inc l
ld [hl], e
inc l
ld [hl], d
inc l
ld [hl], d
inc hl
dec b
jr nz, .next
ld a, l
ld [wRequested1bppDest], a
ld a, h
ld [wRequested1bppDest + 1], a
ld [wRequested1bppSource], sp
ldh a, [hSPBuffer]
ld l, a
ldh a, [hSPBuffer + 1]
ld h, a
ld sp, hl
ret
Serve2bppRequest::
; Only call during the first fifth of VBlank
ld a, [wRequested2bppSize]
and a
ret z
; Back out if we're too far into VBlank
ldh a, [rLY]
cp LY_VBLANK
ret c
cp LY_VBLANK + 2
ret nc
jr _Serve2bppRequest
Serve2bppRequest_VBlank::
ld a, [wRequested2bppSize]
and a
ret z
_Serve2bppRequest::
; Copy [wRequested2bppSize] 2bpp tiles from [wRequested2bppSource] to [wRequested2bppDest]
ld [hSPBuffer], sp
; Source
ld hl, wRequested2bppSource
ld a, [hli]
ld h, [hl]
ld l, a
ld sp, hl
; Destination
ld hl, wRequested2bppDest
ld a, [hli]
ld h, [hl]
ld l, a
; # tiles to copy
ld a, [wRequested2bppSize]
ld b, a
xor a
ld [wRequested2bppSize], a
.next
rept 7
pop de
ld [hl], e
inc l
ld [hl], d
inc l
endr
pop de
ld [hl], e
inc l
ld [hl], d
inc hl
dec b
jr nz, .next
ld a, l
ld [wRequested2bppDest], a
ld a, h
ld [wRequested2bppDest + 1], a
ld [wRequested2bppSource], sp
ldh a, [hSPBuffer]
ld l, a
ldh a, [hSPBuffer + 1]
ld h, a
ld sp, hl
ret
AnimateTileset::
; Only call during the first fifth of VBlank
ldh a, [hMapAnims]
and a
ret z
; Back out if we're too far into VBlank
ldh a, [rLY]
cp LY_VBLANK
ret c
cp LY_VBLANK + 7
ret nc
ldh a, [hROMBank]
push af
ld a, BANK(_AnimateTileset)
rst Bankswitch
ldh a, [rSVBK]
push af
ld a, BANK(wTilesetAnim)
ldh [rSVBK], a
ldh a, [rVBK]
push af
ld a, 0
ldh [rVBK], a
call _AnimateTileset
pop af
ldh [rVBK], a
pop af
ldh [rSVBK], a
pop af
rst Bankswitch
ret