Files
luckytyphlosion e1659ecd41 Introduce linkerscript.
Addresses of sections will now be added to the linkerscript via `org`, and the section name will be the path/to/file. If there is more than one section in the file, then add a @SectionName after the path/to/file to describe the section.
2018-07-03 17:07:05 -04:00

617 lines
12 KiB
NASM

INCLUDE "constants.asm"
SECTION "home/vcopy.asm", ROM0
RedrawRowOrColumn:: ; 123a (0:123a)
; This function redraws a BG row of height 2 or a BG column of width 2.
; One of its main uses is redrawing the row or column that will be exposed upon
; scrolling the BG when the player takes a step. Redrawing only the exposed
; row or column is more efficient than redrawing the entire screen.
; However, this function is also called repeatedly to redraw the whole screen
; when necessary. It is also used in trade animation and elevator code.
; This also implements the flashlight drawing distance effect, which takes
; multiple frames in either direction to complete
ldh a, [hRedrawRowOrColumnMode]
and a
ret z
cp $03
jr nc, .flashlight_effect
ld b, a
xor a
ldh [hRedrawRowOrColumnMode], a
dec b
jr nz, .redrawRow
.redrawColumn
ld hl, wRedrawRowOrColumnSrcTiles
ldh a, [hRedrawRowOrColumnDest]
ld e, a
ldh a, [hRedrawRowOrColumnDest + 1]
ld d, a
ld c, SCREEN_HEIGHT
.col_loop
ld a, [hli]
ld [de], a
inc de
ld a, [hli]
ld [de], a
ld a, BG_MAP_WIDTH - 1
add e
ld e, a
jr nc, .noCarry
inc d
.noCarry
; the following 4 lines wrap us from bottom to top if necessary
ld a, d
and HIGH(vBGMap1 - vBGMap0 - $01)
or HIGH(vBGMap0)
ld d, a
dec c
jr nz, .col_loop
xor a
ldh [hRedrawRowOrColumnMode], a
ret
.redrawRow
ld hl, wRedrawRowOrColumnSrcTiles
ldh a, [hRedrawRowOrColumnDest]
ld e, a
ldh a, [hRedrawRowOrColumnDest + 1]
ld d, a
push de
call .DrawHalf
pop de
ld a, BG_MAP_WIDTH ; width of VRAM background map
add e
ld e, a
; fallthrough (draw lower half)
.DrawHalf
ld c, SCREEN_WIDTH / 2
.row_loop
ld a, [hli]
ld [de], a
inc de
ld a, [hli]
ld [de], a
ld a, e
inc a
; the following 6 lines wrap us from the right edge to the left edge if necessary
and BG_MAP_WIDTH - 1 ; mask lower address bits
ld b, a
ld a, e
and ($FF ^ (BG_MAP_WIDTH - 1)) ; mask upper address bits
or b
ld e, a
dec c
jr nz, .row_loop
ret
.flashlight_effect
dec a
dec a
dec a
ld c, a
ld b, $00
ld hl, .flashlight_effect_table
add hl, bc
add hl, bc
ld a, [hli]
ld h, [hl]
ld l, a
jp hl
.flashlight_effect_table
dw RedrawFlashlightRow0 ; $1310
dw RedrawFlashlightRow0 ; $1310
dw RedrawFlashlightColumn0 ; $12C3
dw RedrawFlashlightColumn0 ; $12C3
dw RedrawFlashlightRow1 ; $1329
dw RedrawFlashlightRow1 ; $1329
dw RedrawFlashlightColumn1 ; $12DC
dw RedrawFlashlightColumn1 ; $12DC
dw RedrawFlashlightRow2 ; $1335
dw RedrawFlashlightRow2 ; $1335
dw RedrawFlashlightColumn2 ; $12E8
dw RedrawFlashlightColumn2 ; $12E8
dw RedrawFlashlightRow3 ; $134E
dw RedrawFlashlightRow3 ; $134E
dw RedrawFlashlightColumn3 ; $1301
dw RedrawFlashlightColumn3 ; $1301
RedrawFlashlightColumn0:: ; 12c3 (0:12c3)
ldh a, [hSCX]
and $07
ret nz ; wait till we moved one complete tile in X
ld a, [wRedrawFlashlightDst0]
ld e, a
ld a, [wRedrawFlashlightDst0 + 1]
ld d, a
ld a, [wRedrawFlashlightSrc0]
ld l, a
ld a, [wRedrawFlashlightSrc0 + 1]
ld h, a
call _RedrawFlashlightColumn
ret
RedrawFlashlightColumn1:: ; 12dc (0:12dc)
ld a, [wRedrawFlashlightBlackDst0]
ld e, a
ld a, [wRedrawFlashlightBlackDst0 + 1]
ld d, a
call _RedrawFlashlightColumnBlack
ret
; 0x12e8
RedrawFlashlightColumn2:: ; 12e8 (0:12e8)
ldh a, [hSCX]
and $0f
ret nz ; wait till we moved two complete tiles in X
ld a, [wRedrawFlashlightDst1]
ld e, a
ld a, [wRedrawFlashlightDst1 + 1]
ld d, a
ld a, [wRedrawFlashlightSrc1]
ld l, a
ld a, [wRedrawFlashlightSrc1 + 1]
ld h, a
call _RedrawFlashlightColumn
ret
RedrawFlashlightColumn3:: ; 1301 (0:1301)
ld a, [wRedrawFlashlightBlackDst1]
ld e, a
ld a, [wRedrawFlashlightBlackDst1 + 1]
ld d, a
call _RedrawFlashlightColumnBlack
xor a
ldh [hRedrawRowOrColumnMode], a ; end flashlight redraw
ret
RedrawFlashlightRow0:: ; 1310 (0:1310)
ldh a, [hSCY]
and $07
ret nz ; wait till we moved one complete tile in Y
ld a, [wRedrawFlashlightDst0]
ld e, a
ld a, [wRedrawFlashlightDst0 + 1]
ld d, a
ld a, [wRedrawFlashlightSrc0]
ld l, a
ld a, [wRedrawFlashlightSrc0 + 1]
ld h, a
call _RedrawFlashlightRow
ret
RedrawFlashlightRow1:: ; 1329 (0:1329)
ld a, [wRedrawFlashlightBlackDst0]
ld e, a
ld a, [wRedrawFlashlightBlackDst0 + 1]
ld d, a
call _RedrawFlashlightRowBlack
ret
; 0x12e8
RedrawFlashlightRow2:: ; 1335 (0:1335)
ldh a, [hSCY]
and $0f
ret nz ; wait till we moved two complete tiles in Y
ld a, [wRedrawFlashlightDst1]
ld e, a
ld a, [wRedrawFlashlightDst1 + 1]
ld d, a
ld a, [wRedrawFlashlightSrc1]
ld l, a
ld a, [wRedrawFlashlightSrc1 + 1]
ld h, a
call _RedrawFlashlightRow
ret
RedrawFlashlightRow3:: ; 134e (0:134e)
ld a, [wRedrawFlashlightBlackDst1]
ld e, a
ld a, [wRedrawFlashlightBlackDst1 + 1]
ld d, a
call _RedrawFlashlightRowBlack
xor a
ldh [hRedrawRowOrColumnMode], a ; end flashlight redraw
ret
_RedrawFlashlightColumn:: ; 135d (0:135d)
ld a, [wRedrawFlashlightWidthHeight]
add a
ld c, a
.loop
ld a, [hli]
ld [de], a
ld a, SCREEN_WIDTH - 1
add l
ld l, a
jr nc, .noCarryScreen
inc h
.noCarryScreen
ld a, BG_MAP_WIDTH
add e
ld e, a
jr nc, .noCarryBG
inc d
.noCarryBG
; the following 4 lines wrap us from bottom to top if necessary
ld a, d
and HIGH(vBGMap1 - vBGMap0 - $01)
or HIGH(vBGMap0)
ld d, a
dec c
jr nz, .loop
ldh a, [hRedrawRowOrColumnMode]
add $04 ; inc by 4, because flashlight redraw
ldh [hRedrawRowOrColumnMode], a ; has four directions
ret
_RedrawFlashlightRow:: ; 1382 (0:1382)
ld a, [wRedrawFlashlightWidthHeight]
ld c, a
.loop
ld a, [hli]
ld [de], a
inc de
ld a, [hli]
ld [de], a
ld a, e
inc a
; the following 6 lines wrap us from the right edge to the left edge if necessary
and BG_MAP_WIDTH - 1 ; mask lower address bits
ld b, a
ld a, e
and ($FF ^ (BG_MAP_WIDTH - 1)) ; mask upper address bits
or b
ld e, a
dec c
jr nz, .loop
ldh a, [hRedrawRowOrColumnMode]
add $04 ; inc by 4, because flashlight redraw
ldh [hRedrawRowOrColumnMode], a ; has four directions
ret
_RedrawFlashlightColumnBlack:: ; 139f (0:139f)
ld l, e
ld h, d
ld b, "■"
ld de, BG_MAP_WIDTH
ld a, [wRedrawFlashlightWidthHeight]
add a
ld c, a
.loop
ld [hl], b
add hl, de
; the following 4 lines wrap us from bottom to top if necessary
ld a, h
and HIGH(vBGMap1 - vBGMap0 - $01)
or HIGH(vBGMap0)
ld h, a
dec c
jr nz, .loop
ldh a, [hRedrawRowOrColumnMode]
add $04 ; inc by 4, because flashlight redraw
ldh [hRedrawRowOrColumnMode], a ; has four directions
ret
_RedrawFlashlightRowBlack:: ; 13bd (0:13bd)
ld l, e
ld h, d
ld b, "■"
ld a, [wRedrawFlashlightWidthHeight]
ld c, a
.loop
ld [hl], b
inc hl
ld [hl], b
ld a, l
inc a
; the following 6 lines wrap us from the right edge to the left edge if necessary
and BG_MAP_WIDTH - 1 ; mask lower address bits
ld d, a
ld a, l
and ($FF ^ (BG_MAP_WIDTH - 1)) ; mask upper address bits
or d
ld l, a
dec c
jr nz, .loop
ldh a, [hRedrawRowOrColumnMode]
add $04 ; inc by 4, because flashlight redraw
ldh [hRedrawRowOrColumnMode], a ; has four directions
ret
WaitForAutoBgMapTransfer:: ; 13dc (0:13dc)
.loop
ldh a, [hBGMapMode]
and a
ret z
ldh a, [hBGMapTransferPosition]
and a
jr z, .done
call DelayFrame
jr .loop
.done
xor a
ldh [hBGMapMode], a
ret
; This function automatically transfers tile number data from the tile map at
; wTileMap to VRAM during V-blank. Note that it only transfers one third of the
; background per V-blank. It cycles through which third it draws.
; This transfer is turned off when walking around the map, but is turned
; on when talking to sprites, battling, using menus, etc. This is because
; the above function, RedrawRowOrColumn, is used when walking to
; improve efficiency.
AutoBgMapTransfer:: ; 13ee (0:13ee)
ldh a, [hBGMapMode]
and a
ret z
ld [hSPTemp], sp
ldh a, [hBGMapTransferPosition]
and a
jr z, .transferTopThird
dec a
jr z, .transferMiddleThird
.transferBottomThird
coord hl, 0, 12
ld sp, hl
ldh a, [hBGMapAddress + 1]
ld h, a
ldh a, [hBGMapAddress]
ld l, a
ld de, 12 * BG_MAP_WIDTH
add hl, de
xor a
jr .doTransfer
.transferTopThird
coord hl, 0, 0
ld sp, hl
ldh a, [hBGMapAddress + 1]
ld h, a
ldh a, [hBGMapAddress]
ld l, a
ld a, $01
jr .doTransfer
.transferMiddleThird
coord hl, 0, 6
ld sp, hl
ldh a, [hBGMapAddress + 1]
ld h, a
ldh a, [hBGMapAddress]
ld l, a
ld de, 6 * BG_MAP_WIDTH
add hl, de
ld a, $02
.doTransfer
ldh [hBGMapTransferPosition], a
ld a, $06 ; 6 rows of SCREEN_WIDTH each
; fallthrough
TransferBgRows:: ; 1430 (0:1430)
ld bc, BG_MAP_WIDTH - SCREEN_WIDTH + 1
.loop
rept SCREEN_WIDTH / 2 - 1 ; two bytes per pop minus last block
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, .loop
ldh a, [hSPTemp]
ld l, a
ldh a, [hSPTemp + 1]
ld h, a
ld sp, hl
ret
VBlankCopyDouble:: ; 1470 (0:1470)
; Copy [wVBCopyDoubleSize] 1bpp tiles
; from wVBCopyDoubleSrc to wVBCopyDoubleDst.
; wVBCopyDoubleDst must be aligned to 0x10 bytes.
; While we're here, convert to 2bpp.
; The process is straightforward:
; copy each byte twice.
ld a, [wVBCopyDoubleSize]
and a
ret z
ld [hSPTemp], sp
ld hl, wVBCopyDoubleSrc
ld a, [hli]
ld h, [hl]
ld l, a
ld sp, hl
ld hl, wVBCopyDoubleDst
ld a, [hli]
ld h, [hl]
ld l, a
ld a, [wVBCopyDoubleSize]
ld b, a
xor a
ld [wVBCopyDoubleSize], a
.loop
rept 16/4 - 1 ; 16 bytes per 2bpp tile at 2 bytes per pop
pop de ; copied twice minus last block
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, .loop
ld a, l
ld [wVBCopyDoubleDst], a
ld a, h
ld [wVBCopyDoubleDst + 1], a
ld [wVBCopyDoubleSrc], sp
ldh a, [hSPTemp]
ld l, a
ldh a, [hSPTemp + 1]
ld h, a
ld sp, hl
ret
VBlankCopy:: ; 14c7 (0:14c7)
; Copy 16 * [wVBCopySize] bytes
; from wVBCopySrc to wVBCopyDst.
; wVBCopyDst must be aligned to 0x10 bytes.
; Source and destination addresses are updated,
; so transfer can continue in subsequent calls.
ld a, [wVBCopySize]
and a
ret z
ld [hSPTemp], sp
ld hl, wVBCopySrc
ld a, [hli]
ld h, [hl]
ld l, a
ld sp, hl
ld hl, wVBCopyDst
ld a, [hli]
ld h, [hl]
ld l, a
ld a, [wVBCopySize]
ld b, a
xor a
ld [wVBCopySize], a
.loop
rept 16/2 - 1 ; 16 bytes per transfer at 2 bytes per pop
pop de ; minus last block
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, .loop
ld a, l
ld [wVBCopyDst], a
ld a, h
ld [wVBCopyDst + 1], a
ld [wVBCopySrc], sp
ldh a, [hSPTemp]
ld l, a
ldh a, [hSPTemp + 1]
ld h, a
ld sp, hl
ret
AnimateTileset:: ; 1522 (0:1522)
ldh a, [hROMBank]
push af
ld a, BANK(AnimateTilesetImpl)
call Bankswitch
call AnimateTilesetImpl
pop af
jp Bankswitch
; 0x1531
EnableSprites:: ; 1531 (0:1531)
nop
ld hl, rLCDC
set rLCDC_SPRITES_ENABLE, [hl]
ret
; 0x1538
TransferToolgearRow: ; 1538 (0:1538)
; TransferToolgearRow
; Copy second line of toolgear to window
ld a, [wToolgearFlags]
bit 0, a
ret z
bit 7, a
ret nz
bit 2, a
res 2, a
ret z
ld [wToolgearFlags], a
ld [hSPTemp], sp
bgcoord hl, 0, 1, wToolgearBuffer
ld sp, hl
bgcoord hl, 0, 1, vBGMap1
ld a, $01
jp TransferBgRows
VBlankCopyFar:: ; 1558 (0:1558)
; Copy 0x10 * [wVBCopyFarSize] bytes
; from wVBCopyFarSrcBank::wVBCopyFarSrc to wVBCopyFarDst.
; wVBCopyFarDst must be aligned to 0x10 bytes.
; Source and destination addresses are updated,
; so transfer can continue in subsequent calls.
ld a, [wVBCopyFarSize]
and a
ret z
ld a, [wVBCopyFarSrcBank]
call Bankswitch
ld [hSPTemp], sp
ld hl, wVBCopyFarSrc
ld a, [hli]
ld h, [hl]
ld l, a
ld sp, hl
ld hl, wVBCopyFarDst
ld a, [hli]
ld h, [hl]
ld l, a
ld a, [wVBCopyFarSize]
ld b, a
xor a
ld [wVBCopyFarSize], a
.loop
rept 16/2 - 1 ; 16 bytes per transfer at 2 bytes per pop
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, .loop
ld [wVBCopyFarSrc], sp
ld sp, hl
ld [wVBCopyFarDst], sp
ldh a, [hSPTemp]
ld l, a
ldh a, [hSPTemp + 1]
ld h, a
ld sp, hl
ret
; 0x15b5