ref: 6d8c6055b5d5910d4da6997199f0984f8cd9149f
parent: d424eb44385c8f9e02d982b715a658e395e56c4b
author: yenatch <yenatch@gmail.com>
date: Fri May 30 21:22:15 EDT 2014
Split more code out of home.asm.
--- /dev/null
+++ b/data/collision.asm
@@ -1,0 +1,24 @@
+Underground_Coll:: INCBIN "gfx/tilesets/underground.tilecoll"
+Overworld_Coll:: INCBIN "gfx/tilesets/overworld.tilecoll"
+RedsHouse1_Coll::
+RedsHouse2_Coll:: INCBIN "gfx/tilesets/reds_house.tilecoll"
+Mart_Coll::
+Pokecenter_Coll:: INCBIN "gfx/tilesets/pokecenter.tilecoll"
+Dojo_Coll::
+Gym_Coll:: INCBIN "gfx/tilesets/gym.tilecoll"
+Forest_Coll:: INCBIN "gfx/tilesets/forest.tilecoll"
+House_Coll:: INCBIN "gfx/tilesets/house.tilecoll"
+ForestGate_Coll::
+Museum_Coll::
+Gate_Coll:: INCBIN "gfx/tilesets/gate.tilecoll"
+Ship_Coll:: INCBIN "gfx/tilesets/ship.tilecoll"
+ShipPort_Coll:: INCBIN "gfx/tilesets/ship_port.tilecoll"
+Cemetery_Coll:: INCBIN "gfx/tilesets/cemetery.tilecoll"
+Interior_Coll:: INCBIN "gfx/tilesets/interior.tilecoll"
+Cavern_Coll:: INCBIN "gfx/tilesets/cavern.tilecoll"
+Lobby_Coll:: INCBIN "gfx/tilesets/lobby.tilecoll"
+Mansion_Coll:: INCBIN "gfx/tilesets/mansion.tilecoll"
+Lab_Coll:: INCBIN "gfx/tilesets/lab.tilecoll"
+Club_Coll:: INCBIN "gfx/tilesets/club.tilecoll"
+Facility_Coll:: INCBIN "gfx/tilesets/facility.tilecoll"
+Plateau_Coll:: INCBIN "gfx/tilesets/plateau.tilecoll"
--- a/home.asm
+++ b/home.asm
@@ -909,30 +909,7 @@
jp CopyVideoData
-Underground_Coll:: INCBIN "gfx/tilesets/underground.tilecoll"
-Overworld_Coll:: INCBIN "gfx/tilesets/overworld.tilecoll"
-RedsHouse1_Coll::
-RedsHouse2_Coll:: INCBIN "gfx/tilesets/reds_house.tilecoll"
-Mart_Coll::
-Pokecenter_Coll:: INCBIN "gfx/tilesets/pokecenter.tilecoll"
-Dojo_Coll::
-Gym_Coll:: INCBIN "gfx/tilesets/gym.tilecoll"
-Forest_Coll:: INCBIN "gfx/tilesets/forest.tilecoll"
-House_Coll:: INCBIN "gfx/tilesets/house.tilecoll"
-ForestGate_Coll::
-Museum_Coll::
-Gate_Coll:: INCBIN "gfx/tilesets/gate.tilecoll"
-Ship_Coll:: INCBIN "gfx/tilesets/ship.tilecoll"
-ShipPort_Coll:: INCBIN "gfx/tilesets/ship_port.tilecoll"
-Cemetery_Coll:: INCBIN "gfx/tilesets/cemetery.tilecoll"
-Interior_Coll:: INCBIN "gfx/tilesets/interior.tilecoll"
-Cavern_Coll:: INCBIN "gfx/tilesets/cavern.tilecoll"
-Lobby_Coll:: INCBIN "gfx/tilesets/lobby.tilecoll"
-Mansion_Coll:: INCBIN "gfx/tilesets/mansion.tilecoll"
-Lab_Coll:: INCBIN "gfx/tilesets/lab.tilecoll"
-Club_Coll:: INCBIN "gfx/tilesets/club.tilecoll"
-Facility_Coll:: INCBIN "gfx/tilesets/facility.tilecoll"
-Plateau_Coll:: INCBIN "gfx/tilesets/plateau.tilecoll"
+INCLUDE "data/collision.asm"
FarCopyData2::
@@ -1166,783 +1143,12 @@
INCLUDE "home/text.asm"
+INCLUDE "home/vcopy.asm"
+INCLUDE "home/init.asm"
+INCLUDE "home/vblank.asm"
+INCLUDE "home/fade.asm"
-; this function seems to be used only once
-; it store the address of a row and column of the VRAM background map in hl
-; INPUT: h - row, l - column, b - high byte of background tile map address in VRAM
-GetRowColAddressBgMap:: ; 1cdd (0:1cdd)
- xor a
- srl h
- rr a
- srl h
- rr a
- srl h
- rr a
- or l
- ld l,a
- ld a,b
- or h
- ld h,a
- ret
-
-; clears a VRAM background map with blank space tiles
-; INPUT: h - high byte of background tile map address in VRAM
-ClearBgMap:: ; 1cf0 (0:1cf0)
- ld a," "
- jr .next
- ld a,l
-.next
- ld de,$400 ; size of VRAM background map
- ld l,e
-.loop
- ld [hli],a
- dec e
- jr nz,.loop
- dec d
- jr nz,.loop
- ret
-
-; When the player takes a step, a row or column of 2x2 tile blocks at the edge
-; of the screen toward which they moved is exposed and has to be redrawn.
-; This function does the redrawing.
-RedrawExposedScreenEdge:: ; 1d01 (0:1d01)
- ld a,[H_SCREENEDGEREDRAW]
- and a
- ret z
- ld b,a
- xor a
- ld [H_SCREENEDGEREDRAW],a
- dec b
- jr nz,.redrawRow
-.redrawColumn
- ld hl,wScreenEdgeTiles
- ld a,[H_SCREENEDGEREDRAWADDR]
- ld e,a
- ld a,[H_SCREENEDGEREDRAWADDR + 1]
- ld d,a
- ld c,18 ; screen height
-.loop1
- ld a,[hli]
- ld [de],a
- inc de
- ld a,[hli]
- ld [de],a
- ld a,31
- 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 a,$03
- or a,$98
- ld d,a
- dec c
- jr nz,.loop1
- xor a
- ld [H_SCREENEDGEREDRAW],a
- ret
-.redrawRow
- ld hl,wScreenEdgeTiles
- ld a,[H_SCREENEDGEREDRAWADDR]
- ld e,a
- ld a,[H_SCREENEDGEREDRAWADDR + 1]
- ld d,a
- push de
- call .drawHalf ; draw upper half
- pop de
- ld a,32 ; width of VRAM background map
- add e
- ld e,a
- ; draw lower half
-.drawHalf
- ld c,10
-.loop2
- 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 a,$1f
- ld b,a
- ld a,e
- and a,$e0
- or b
- ld e,a
- dec c
- jr nz,.loop2
- 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, RedrawExposedScreenEdge, is used when walking to
-; improve efficiency.
-AutoBgMapTransfer:: ; 1d57 (0:1d57)
- ld a,[H_AUTOBGTRANSFERENABLED]
- and a
- ret z
- ld hl,[sp + 0]
- ld a,h
- ld [H_SPTEMP],a
- ld a,l
- ld [H_SPTEMP + 1],a ; save stack pinter
- ld a,[H_AUTOBGTRANSFERPORTION]
- and a
- jr z,.transferTopThird
- dec a
- jr z,.transferMiddleThird
-.transferBottomThird
- FuncCoord 0,12
- ld hl,Coord
- ld sp,hl
- ld a,[H_AUTOBGTRANSFERDEST + 1]
- ld h,a
- ld a,[H_AUTOBGTRANSFERDEST]
- ld l,a
- ld de,(12 * 32)
- add hl,de
- xor a ; TRANSFERTOP
- jr .doTransfer
-.transferTopThird
- FuncCoord 0,0
- ld hl,Coord
- ld sp,hl
- ld a,[H_AUTOBGTRANSFERDEST + 1]
- ld h,a
- ld a,[H_AUTOBGTRANSFERDEST]
- ld l,a
- ld a,TRANSFERMIDDLE
- jr .doTransfer
-.transferMiddleThird
- FuncCoord 0,6
- ld hl,Coord
- ld sp,hl
- ld a,[H_AUTOBGTRANSFERDEST + 1]
- ld h,a
- ld a,[H_AUTOBGTRANSFERDEST]
- ld l,a
- ld de,(6 * 32)
- add hl,de
- ld a,TRANSFERBOTTOM
-.doTransfer
- ld [H_AUTOBGTRANSFERPORTION],a ; store next portion
- ld b,6
-
-TransferBgRows:: ; 1d9e (0:1d9e)
-; unrolled loop and using pop for speed
-
- rept 20 / 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
-
-i ld a, 32 - (20 - 1)
- add l
- ld l, a
- jr nc, .ok
- inc h
-.ok
- dec b
- jr nz, TransferBgRows
-
- ld a, [H_SPTEMP]
- ld h, a
- ld a, [H_SPTEMP + 1]
- ld l, a
- ld sp, hl
- ret
-
-; Copies [H_VBCOPYBGNUMROWS] rows from H_VBCOPYBGSRC to H_VBCOPYBGDEST.
-; If H_VBCOPYBGSRC is XX00, the transfer is disabled.
-VBlankCopyBgMap:: ; 1de1 (0:1de1)
- ld a,[H_VBCOPYBGSRC] ; doubles as enabling byte
- and a
- ret z
- ld hl,[sp + 0]
- ld a,h
- ld [H_SPTEMP],a
- ld a,l
- ld [H_SPTEMP + 1],a ; save stack pointer
- ld a,[H_VBCOPYBGSRC]
- ld l,a
- ld a,[H_VBCOPYBGSRC + 1]
- ld h,a
- ld sp,hl
- ld a,[H_VBCOPYBGDEST]
- ld l,a
- ld a,[H_VBCOPYBGDEST + 1]
- ld h,a
- ld a,[H_VBCOPYBGNUMROWS]
- ld b,a
- xor a
- ld [H_VBCOPYBGSRC],a ; disable transfer so it doesn't continue next V-blank
- jr TransferBgRows
-
-
-VBlankCopyDouble::
-; Copy [H_VBCOPYDOUBLESIZE] 1bpp tiles
-; from H_VBCOPYDOUBLESRC to H_VBCOPYDOUBLEDEST.
-
-; While we're here, convert to 2bpp.
-; The process is straightforward:
-; copy each byte twice.
-
- ld a, [H_VBCOPYDOUBLESIZE]
- and a
- ret z
-
- ld hl, [sp + 0]
- ld a, h
- ld [H_SPTEMP], a
- ld a, l
- ld [H_SPTEMP + 1], a
-
- ld a, [H_VBCOPYDOUBLESRC]
- ld l, a
- ld a, [H_VBCOPYDOUBLESRC + 1]
- ld h, a
- ld sp, hl
-
- ld a, [H_VBCOPYDOUBLEDEST]
- ld l, a
- ld a, [H_VBCOPYDOUBLEDEST + 1]
- ld h, a
-
- ld a, [H_VBCOPYDOUBLESIZE]
- ld b, a
- xor a ; transferred
- ld [H_VBCOPYDOUBLESIZE], a
-
-.loop
- 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, .loop
-
- ld a, l
- ld [H_VBCOPYDOUBLEDEST], a
- ld a, h
- ld [H_VBCOPYDOUBLEDEST + 1], a
-
- ld hl, [sp + 0]
- ld a, l
- ld [H_VBCOPYDOUBLESRC], a
- ld a, h
- ld [H_VBCOPYDOUBLESRC + 1], a
-
- ld a, [H_SPTEMP]
- ld h, a
- ld a, [H_SPTEMP + 1]
- ld l, a
- ld sp, hl
-
- ret
-
-
-VBlankCopy::
-; Copy [H_VBCOPYSIZE] 2bpp tiles
-; from H_VBCOPYSRC to H_VBCOPYDEST.
-
-; Source and destination addresses
-; are updated, so transfer can
-; continue in subsequent calls.
-
- ld a, [H_VBCOPYSIZE]
- and a
- ret z
-
- ld hl, [sp + 0]
- ld a, h
- ld [H_SPTEMP], a
- ld a, l
- ld [H_SPTEMP + 1], a
-
- ld a, [H_VBCOPYSRC]
- ld l, a
- ld a, [H_VBCOPYSRC + 1]
- ld h, a
- ld sp, hl
-
- ld a, [H_VBCOPYDEST]
- ld l, a
- ld a, [H_VBCOPYDEST + 1]
- ld h, a
-
- ld a, [H_VBCOPYSIZE]
- ld b, a
- xor a ; transferred
- ld [H_VBCOPYSIZE], a
-
-.loop
- 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, .loop
-
- ld a, l
- ld [H_VBCOPYDEST], a
- ld a, h
- ld [H_VBCOPYDEST + 1], a
-
- ld hl, [sp + 0]
- ld a, l
- ld [H_VBCOPYSRC], a
- ld a, h
- ld [H_VBCOPYSRC + 1], a
-
- ld a, [H_SPTEMP]
- ld h, a
- ld a, [H_SPTEMP + 1]
- ld l, a
- ld sp, hl
-
- ret
-
-
-UpdateMovingBgTiles::
-; Animate water and flower
-; tiles in the overworld.
-
- ld a, [$ffd7]
- and a
- ret z
-
- ld a, [$ffd8]
- inc a
- ld [$ffd8], a
- cp $14
- ret c
- cp $15
- jr z, .flower
-
- ld hl, vTileset + $14 * $10
- ld c, $10
-
- ld a, [wd085]
- inc a
- and 7
- ld [wd085], a
-
- and 4
- jr nz, .left
-.right
- ld a, [hl]
- rrca
- ld [hli], a
- dec c
- jr nz, .right
- jr .done
-.left
- ld a, [hl]
- rlca
- ld [hli], a
- dec c
- jr nz, .left
-.done
- ld a, [$ffd7]
- rrca
- ret nc
- xor a
- ld [$ffd8], a
- ret
-
-.flower
- xor a
- ld [$ffd8], a
-
- ld a, [wd085]
- and 3
- cp 2
- ld hl, FlowerTile1
- jr c, .copy
- ld hl, FlowerTile2
- jr z, .copy
- ld hl, FlowerTile3
-.copy
- ld de, vTileset + $3 * $10
- ld c, $10
-.loop
- ld a, [hli]
- ld [de], a
- inc de
- dec c
- jr nz, .loop
- ret
-
-FlowerTile1: INCBIN "gfx/tilesets/flower/flower1.2bpp"
-FlowerTile2: INCBIN "gfx/tilesets/flower/flower2.2bpp"
-FlowerTile3: INCBIN "gfx/tilesets/flower/flower3.2bpp"
-
-
-SoftReset::
- call StopAllSounds
- call GBPalWhiteOut
- ld c, $20
- call DelayFrames
- ; fallthrough
-
-Init::
-; Program init.
-
-rLCDC_DEFAULT EQU %11100011
-; * LCD enabled
-; * Window tile map at $9C00
-; * Window display enabled
-; * BG and window tile data at $8800
-; * BG tile map at $9800
-; * 8x8 OBJ size
-; * OBJ display enabled
-; * BG display enabled
-
- di
-
- xor a
- ld [rIF], a
- ld [rIE], a
- ld [$ff43], a
- ld [$ff42], a
- ld [$ff01], a
- ld [$ff02], a
- ld [$ff4b], a
- ld [$ff4a], a
- ld [$ff06], a
- ld [$ff07], a
- ld [$ff47], a
- ld [$ff48], a
- ld [$ff49], a
-
- ld a, rLCDC_ENABLE_MASK
- ld [rLCDC], a
- call DisableLCD
-
- ld sp, wStack
-
- ld hl, $c000 ; start of WRAM
- ld bc, $2000 ; size of WRAM
-.loop
- ld [hl], 0
- inc hl
- dec bc
- ld a, b
- or c
- jr nz, .loop
-
- call ClearVram
-
- ld hl, $ff80
- ld bc, $ffff - $ff80
- call FillMemory
-
- call ClearSprites
-
- ld a, Bank(WriteDMACodeToHRAM)
- ld [H_LOADEDROMBANK], a
- ld [MBC3RomBank], a
- call WriteDMACodeToHRAM
-
- xor a
- ld [$ffd7], a
- ld [$ff41], a
- ld [$ffae], a
- ld [$ffaf], a
- ld [$ff0f], a
- ld a, 1 << VBLANK + 1 << TIMER + 1 << SERIAL
- ld [rIE], a
-
- ld a, 144 ; move the window off-screen
- ld [$ffb0], a
- ld [rWY], a
- ld a, 7
- ld [rWX], a
-
- ld a, $ff
- ld [$ffaa], a
-
- ld h, vBGMap0 / $100
- call ClearBgMap
- ld h, vBGMap1 / $100
- call ClearBgMap
-
- ld a, rLCDC_DEFAULT
- ld [rLCDC], a
- ld a, 16
- ld [hSoftReset], a
- call StopAllSounds
-
- ei
-
- ld a, $40 ; PREDEF_SGB_BORDER
- call Predef
-
- ld a, $1f
- ld [wc0ef], a
- ld [wc0f0], a
- ld a, $9c
- ld [$ffbd], a
- xor a
- ld [$ffbc], a
- dec a
- ld [wcfcb], a
-
- ld a, $32 ; PREDEF_INTRO
- call Predef
-
- call DisableLCD
- call ClearVram
- call GBPalNormal
- call ClearSprites
- ld a, rLCDC_DEFAULT
- ld [rLCDC], a
-
- jp SetDefaultNamesBeforeTitlescreen
-
-ClearVram:
- ld hl, $8000
- ld bc, $2000
- xor a
- jp FillMemory
-
-
-StopAllSounds::
- ld a, Bank(Func_9876)
- ld [wc0ef], a
- ld [wc0f0], a
- xor a
- ld [wMusicHeaderPointer], a
- ld [wc0ee], a
- ld [wcfca], a
- dec a
- jp PlaySound
-
-
-VBlank::
-
- push af
- push bc
- push de
- push hl
-
- ld a, [H_LOADEDROMBANK]
- ld [wd122], a
-
- ld a, [$ffae]
- ld [rSCX], a
- ld a, [$ffaf]
- ld [rSCY], a
-
- ld a, [wd0a0]
- and a
- jr nz, .ok
- ld a, [$ffb0]
- ld [rWY], a
-.ok
-
- call AutoBgMapTransfer
- call VBlankCopyBgMap
- call RedrawExposedScreenEdge
- call VBlankCopy
- call VBlankCopyDouble
- call UpdateMovingBgTiles
- call $ff80 ; hOAMDMA
- ld a, Bank(PrepareOAMData)
- ld [H_LOADEDROMBANK], a
- ld [MBC3RomBank], a
- call PrepareOAMData
-
- ; VBlank-sensitive operations end.
-
- call Random
-
- ld a, [H_VBLANKOCCURRED]
- and a
- jr z, .vblanked
- xor a
- ld [H_VBLANKOCCURRED], a
-.vblanked
-
- ld a, [H_FRAMECOUNTER]
- and a
- jr z, .decced
- dec a
- ld [H_FRAMECOUNTER], a
-.decced
-
- call Func_28cb
-
- ld a, [wc0ef] ; music ROM bank
- ld [H_LOADEDROMBANK], a
- ld [MBC3RomBank], a
-
- cp BANK(Func_9103)
- jr nz, .notbank2
-.bank2
- call Func_9103
- jr .afterMusic
-.notbank2
- cp 8
- jr nz, .bank1F
-.bank8
- call Func_2136e
- call Func_21879
- jr .afterMusic
-.bank1F
- call Func_7d177
-.afterMusic
-
- callba Func_18dee ; keep track of time played
-
- ld a, [$fff9]
- and a
- call z, ReadJoypad
-
- ld a, [wd122]
- ld [H_LOADEDROMBANK], a
- ld [MBC3RomBank], a
-
- pop hl
- pop de
- pop bc
- pop af
- reti
-
-
-DelayFrame::
-; Wait for the next vblank interrupt.
-; As a bonus, this saves battery.
-
-NOT_VBLANKED EQU 1
-
- ld a, NOT_VBLANKED
- ld [H_VBLANKOCCURRED], a
-.halt
- halt
- ld a, [H_VBLANKOCCURRED]
- and a
- jr nz, .halt
- ret
-
-
-; These routines manage gradual fading
-; (e.g., entering a doorway)
-LoadGBPal::
- ld a, [wd35d] ;tells if cur.map is dark (requires HM5_FLASH?)
- ld b, a
- ld hl, FadePal4
- ld a, l
- sub b
- ld l, a
- jr nc, .ok
- dec h
-.ok
- ld a, [hli]
- ld [rBGP], a
- ld a, [hli]
- ld [rOBP0], a
- ld a, [hli]
- ld [rOBP1], a
- ret
-
-GBFadeOut1::
- ld hl, FadePal1
- ld b, 4
- jr GBFadeOutCommon
-
-GBFadeOut2::
- ld hl, FadePal6
- ld b, 3
-
-GBFadeOutCommon::
- ld a, [hli]
- ld [rBGP], a
- ld a, [hli]
- ld [rOBP0], a
- ld a, [hli]
- ld [rOBP1], a
- ld c, 8
- call DelayFrames
- dec b
- jr nz, GBFadeOutCommon
- ret
-
-GBFadeIn1::
- ld hl, FadePal4 + 2
- ld b, 4
- jr GBFadeInCommon
-
-GBFadeIn2::
- ld hl, FadePal7 + 2
- ld b, 3
-
-GBFadeInCommon::
- ld a, [hld]
- ld [rOBP1], a
- ld a, [hld]
- ld [rOBP0], a
- ld a, [hld]
- ld [rBGP], a
- ld c, 8
- call DelayFrames
- dec b
- jr nz, GBFadeInCommon
- ret
-
-FadePal1:: db %11111111, %11111111, %11111111
-FadePal2:: db %11111110, %11111110, %11111000
-FadePal3:: db %11111001, %11100100, %11100100
-FadePal4:: db %11100100, %11010000, %11100000
-; rBGP rOBP0 rOBP1
-FadePal5:: db %11100100, %11010000, %11100000
-FadePal6:: db %10010000, %10000000, %10010000
-FadePal7:: db %01000000, %01000000, %01000000
-FadePal8:: db %00000000, %00000000, %00000000
-
-
Serial:: ; 2125 (0:2125)
push af
push bc
@@ -2248,194 +1454,15 @@
ld [$ff02], a
ret
+
; timer interrupt is apparently not invoked anyway
Timer:: ; 2306 (0:2306)
reti
-Func_2307:: ; 2307 (0:2307)
- call WaitForSoundToFinish
- xor a
- ld c, a
- ld d, a
- ld [wcfca], a
- jr asm_2324
-Func_2312:: ; 2312 (0:2312)
- ld c, $a
- ld d, $0
- ld a, [wd72e]
- bit 5, a
- jr z, asm_2324
- xor a
- ld [wcfca], a
- ld c, $8
- ld d, c
-asm_2324:: ; 2324 (0:2324)
- ld a, [wd700]
- and a
- jr z, .asm_2343
- cp $2
- jr z, .asm_2332
- ld a, MUSIC_BIKE_RIDING
- jr .asm_2334
-.asm_2332
- ld a, MUSIC_SURFING
-.asm_2334
- ld b, a
- ld a, d
- and a
- ld a, Bank(Func_7d8ea)
- jr nz, .asm_233e
- ld [wc0ef], a
-.asm_233e
- ld [wc0f0], a
- jr .asm_234c
-.asm_2343
- ld a, [wd35b]
- ld b, a
- call Func_2385
- jr c, .asm_2351
-.asm_234c
- ld a, [wcfca]
- cp b
- ret z
-.asm_2351
- ld a, c
- ld [wMusicHeaderPointer], a
- ld a, b
- ld [wcfca], a
- ld [wc0ee], a
- jp PlaySound
+INCLUDE "home/audio.asm"
-Func_235f:: ; 235f (0:235f)
- ld a, [wc0ef]
- ld b, a
- cp $2
- jr nz, .checkForBank08
-.bank02
- ld hl, Func_9103
- jr .asm_2378
-.checkForBank08
- cp $8
- jr nz, .bank1F
-.bank08
- ld hl, Func_21879
- jr .asm_2378
-.bank1F
- ld hl, Func_7d177
-.asm_2378
- ld c, $6
-.asm_237a
- push bc
- push hl
- call Bankswitch
- pop hl
- pop bc
- dec c
- jr nz, .asm_237a
- ret
-Func_2385:: ; 2385 (0:2385)
- ld a, [wd35c]
- ld e, a
- ld a, [wc0ef]
- cp e
- jr nz, .asm_2394
- ld [wc0f0], a
- and a
- ret
-.asm_2394
- ld a, c
- and a
- ld a, e
- jr nz, .asm_239c
- ld [wc0ef], a
-.asm_239c
- ld [wc0f0], a
- scf
- ret
-
-PlayMusic:: ; 23a1 (0:23a1)
- ld b, a
- ld [wc0ee], a
- xor a
- ld [wMusicHeaderPointer], a
- ld a, c
- ld [wc0ef], a
- ld [wc0f0], a
- ld a, b
-
-; plays music specified by a. If value is $ff, music is stopped
-PlaySound:: ; 23b1 (0:23b1)
- push hl
- push de
- push bc
- ld b, a
- ld a, [wc0ee]
- and a
- jr z, .asm_23c8
- xor a
- ld [wc02a], a
- ld [wc02b], a
- ld [wc02c], a
- ld [wc02d], a
-.asm_23c8
- ld a, [wMusicHeaderPointer]
- and a
- jr z, .asm_23e3
- ld a, [wc0ee]
- and a
- jr z, .asm_2425
- xor a
- ld [wc0ee], a
- ld a, [wcfca]
- cp $ff
- jr nz, .asm_2414
- xor a
- ld [wMusicHeaderPointer], a
-.asm_23e3
- xor a
- ld [wc0ee], a
- ld a, [H_LOADEDROMBANK]
- ld [$ffb9], a
- ld a, [wc0ef]
- ld [H_LOADEDROMBANK], a
- ld [$2000], a
- cp $2
- jr nz, .checkForBank08
-.bank02
- ld a, b
- call Func_9876
- jr .asm_240b
-.checkForBank08
- cp $8
- jr nz, .bank1F
-.bank08
- ld a, b
- call Func_22035
- jr .asm_240b
-.bank1F
- ld a, b
- call Func_7d8ea
-.asm_240b
- ld a, [$ffb9]
- ld [H_LOADEDROMBANK], a
- ld [$2000], a
- jr .asm_2425
-.asm_2414
- ld a, b
- ld [wcfca], a
- ld a, [wMusicHeaderPointer]
- ld [wcfc8], a
- ld [wcfc9], a
- ld a, b
- ld [wMusicHeaderPointer], a
-.asm_2425
- pop bc
- pop de
- pop hl
- ret
-
UpdateSprites:: ; 2429 (0:2429)
ld a, [wcfcb]
dec a
@@ -2486,598 +1513,10 @@
call Predef
jp TextScriptEnd
-; bankswitches and runs _UncompressSpriteData
-; bank is given in a, sprite input stream is pointed to in W_SPRITEINPUTPTR
-UncompressSpriteData:: ; 24fd (0:24fd)
- ld b, a
- ld a, [H_LOADEDROMBANK]
- push af
- ld a, b
- ld [H_LOADEDROMBANK], a
- ld [$2000], a
- ld a, $a
- ld [$0], a
- xor a
- ld [$4000], a
- call _UncompressSpriteData
- pop af
- ld [H_LOADEDROMBANK], a
- ld [$2000], a
- ret
-; initializes necessary data to load a sprite and runs UncompressSpriteDataLoop
-_UncompressSpriteData:: ; 251a (0:251a)
- ld hl, S_SPRITEBUFFER1
- ld c, (2*SPRITEBUFFERSIZE) % $100
- ld b, (2*SPRITEBUFFERSIZE) / $100
- xor a
- call FillMemory ; clear sprite buffer 1 and 2
- ld a, $1
- ld [W_SPRITEINPUTBITCOUNTER], a
- ld a, $3
- ld [W_SPRITEOUTPUTBITOFFSET], a
- xor a
- ld [W_SPRITECURPOSX], a
- ld [W_SPRITECURPOSY], a
- ld [W_SPRITELOADFLAGS], a ; wd0a8
- call ReadNextInputByte ; first byte of input determines sprite width (high nybble) and height (low nybble) in tiles (8x8 pixels)
- ld b, a
- and $f
- add a
- add a
- add a
- ld [W_SPRITEHEIGHT], a
- ld a, b
- swap a
- and $f
- add a
- add a
- add a
- ld [W_SPRITEWITDH], a
- call ReadNextInputBit
- ld [W_SPRITELOADFLAGS], a ; initialite bit1 to 0 and bit0 to the first input bit
- ; this will load two chunks of data to S_SPRITEBUFFER1 and S_SPRITEBUFFER2
- ; bit 0 decides in which one the first chunk is placed
- ; fall through
+INCLUDE "home/pic.asm"
-; uncompresses a chunk from the sprite input data stream (pointed to at wd0da) into S_SPRITEBUFFER1 or S_SPRITEBUFFER2
-; each chunk is a 1bpp sprite. A 2bpp sprite consist of two chunks which are merged afterwards
-; note that this is an endless loop which is terminated during a call to MoveToNextBufferPosition by manipulating the stack
-UncompressSpriteDataLoop:: ; 2556 (0:2556)
- ld hl, S_SPRITEBUFFER1
- ld a, [W_SPRITELOADFLAGS] ; wd0a8
- bit 0, a
- jr z, .useSpriteBuffer1 ; check which buffer to use
- ld hl, S_SPRITEBUFFER2
-.useSpriteBuffer1
- call StoreSpriteOutputPointer
- ld a, [W_SPRITELOADFLAGS] ; wd0a8
- bit 1, a
- jr z, .startDecompression ; check if last iteration
- call ReadNextInputBit ; if last chunk, read 1-2 bit unpacking mode
- and a
- jr z, .unpackingMode0 ; 0 -> mode 0
- call ReadNextInputBit ; 1 0 -> mode 1
- inc a ; 1 1 -> mode 2
-.unpackingMode0
- ld [W_SPRITEUNPACKMODE], a
-.startDecompression
- call ReadNextInputBit
- and a
- jr z, .readRLEncodedZeros ; if first bit is 0, the input starts with zeroes, otherwise with (non-zero) input
-.readNextInput
- call ReadNextInputBit
- ld c, a
- call ReadNextInputBit
- sla c
- or c ; read next two bits into c
- and a
- jr z, .readRLEncodedZeros ; 00 -> RLEncoded zeroes following
- call WriteSpriteBitsToBuffer ; otherwise write input to output and repeat
- call MoveToNextBufferPosition
- jr .readNextInput
-.readRLEncodedZeros
- ld c, $0 ; number of zeroes it length encoded, the number
-.countConsecutiveOnesLoop ; of consecutive ones determines the number of bits the number has
- call ReadNextInputBit
- and a
- jr z, .countConsecutiveOnesFinished
- inc c
- jr .countConsecutiveOnesLoop
-.countConsecutiveOnesFinished
- ld a, c
- add a
- ld hl, LengthEncodingOffsetList
- add l
- ld l, a
- jr nc, .noCarry
- inc h
-.noCarry
- ld a, [hli] ; read offset that is added to the number later on
- ld e, a ; adding an offset of 2^length - 1 makes every integer uniquely
- ld d, [hl] ; representable in the length encoding and saves bits
- push de
- inc c
- ld e, $0
- ld d, e
-.readNumberOfZerosLoop ; reads the next c+1 bits of input
- call ReadNextInputBit
- or e
- ld e, a
- dec c
- jr z, .readNumberOfZerosDone
- sla e
- rl d
- jr .readNumberOfZerosLoop
-.readNumberOfZerosDone
- pop hl ; add the offset
- add hl, de
- ld e, l
- ld d, h
-.writeZerosLoop
- ld b, e
- xor a ; write 00 to buffer
- call WriteSpriteBitsToBuffer
- ld e, b
- call MoveToNextBufferPosition
- dec de
- ld a, d
- and a
- jr nz, .continueLoop
- ld a, e
- and a
-.continueLoop
- jr nz, .writeZerosLoop
- jr .readNextInput
-; moves output pointer to next position
-; also cancels the calling function if the all output is done (by removing the return pointer from stack)
-; and calls postprocessing functions according to the unpack mode
-MoveToNextBufferPosition:: ; 25d8 (0:25d8)
- ld a, [W_SPRITEHEIGHT]
- ld b, a
- ld a, [W_SPRITECURPOSY]
- inc a
- cp b
- jr z, .curColumnDone
- ld [W_SPRITECURPOSY], a
- ld a, [W_SPRITEOUTPUTPTR]
- inc a
- ld [W_SPRITEOUTPUTPTR], a
- ret nz
- ld a, [W_SPRITEOUTPUTPTR+1]
- inc a
- ld [W_SPRITEOUTPUTPTR+1], a
- ret
-.curColumnDone
- xor a
- ld [W_SPRITECURPOSY], a
- ld a, [W_SPRITEOUTPUTBITOFFSET]
- and a
- jr z, .bitOffsetsDone
- dec a
- ld [W_SPRITEOUTPUTBITOFFSET], a
- ld hl, W_SPRITEOUTPUTPTRCACHED
- ld a, [hli]
- ld [W_SPRITEOUTPUTPTR], a
- ld a, [hl]
- ld [W_SPRITEOUTPUTPTR+1], a
- ret
-.bitOffsetsDone
- ld a, $3
- ld [W_SPRITEOUTPUTBITOFFSET], a
- ld a, [W_SPRITECURPOSX]
- add $8
- ld [W_SPRITECURPOSX], a
- ld b, a
- ld a, [W_SPRITEWITDH]
- cp b
- jr z, .allColumnsDone
- ld a, [W_SPRITEOUTPUTPTR]
- ld l, a
- ld a, [W_SPRITEOUTPUTPTR+1]
- ld h, a
- inc hl
- jp StoreSpriteOutputPointer
-.allColumnsDone
- pop hl
- xor a
- ld [W_SPRITECURPOSX], a
- ld a, [W_SPRITELOADFLAGS] ; wd0a8
- bit 1, a
- jr nz, .done ; test if there is one more sprite to go
- xor $1
- set 1, a
- ld [W_SPRITELOADFLAGS], a ; wd0a8
- jp UncompressSpriteDataLoop
-.done
- jp UnpackSprite
-
-; writes 2 bits (from a) to the output buffer (pointed to from W_SPRITEOUTPUTPTR)
-WriteSpriteBitsToBuffer:: ; 2649 (0:2649)
- ld e, a
- ld a, [W_SPRITEOUTPUTBITOFFSET]
- and a
- jr z, .offset0
- cp $2
- jr c, .offset1
- jr z, .offset2
- rrc e ; offset 3
- rrc e
- jr .offset0
-.offset1
- sla e
- sla e
- jr .offset0
-.offset2
- swap e
-.offset0
- ld a, [W_SPRITEOUTPUTPTR]
- ld l, a
- ld a, [W_SPRITEOUTPUTPTR+1]
- ld h, a
- ld a, [hl]
- or e
- ld [hl], a
- ret
-
-; reads next bit from input stream and returns it in a
-ReadNextInputBit:: ; 2670 (0:2670)
- ld a, [W_SPRITEINPUTBITCOUNTER]
- dec a
- jr nz, .curByteHasMoreBitsToRead
- call ReadNextInputByte
- ld [W_SPRITEINPUTCURBYTE], a
- ld a, $8
-.curByteHasMoreBitsToRead
- ld [W_SPRITEINPUTBITCOUNTER], a
- ld a, [W_SPRITEINPUTCURBYTE]
- rlca
- ld [W_SPRITEINPUTCURBYTE], a
- and $1
- ret
-
-; reads next byte from input stream and returns it in a
-ReadNextInputByte:: ; 268b (0:268b)
- ld a, [W_SPRITEINPUTPTR]
- ld l, a
- ld a, [W_SPRITEINPUTPTR+1]
- ld h, a
- ld a, [hli]
- ld b, a
- ld a, l
- ld [W_SPRITEINPUTPTR], a
- ld a, h
- ld [W_SPRITEINPUTPTR+1], a
- ld a, b
- ret
-
-; the nth item is 2^n - 1
-LengthEncodingOffsetList:: ; 269f (0:269f)
- dw %0000000000000001
- dw %0000000000000011
- dw %0000000000000111
- dw %0000000000001111
- dw %0000000000011111
- dw %0000000000111111
- dw %0000000001111111
- dw %0000000011111111
- dw %0000000111111111
- dw %0000001111111111
- dw %0000011111111111
- dw %0000111111111111
- dw %0001111111111111
- dw %0011111111111111
- dw %0111111111111111
- dw %1111111111111111
-
-; unpacks the sprite data depending on the unpack mode
-UnpackSprite:: ; 26bf (0:26bf)
- ld a, [W_SPRITEUNPACKMODE]
- cp $2
- jp z, UnpackSpriteMode2
- and a
- jp nz, XorSpriteChunks
- ld hl, S_SPRITEBUFFER1
- call SpriteDifferentialDecode
- ld hl, S_SPRITEBUFFER2
- ; fall through
-
-; decodes differential encoded sprite data
-; input bit value 0 preserves the current bit value and input bit value 1 toggles it (starting from initial value 0).
-SpriteDifferentialDecode:: ; 26d4 (0:26d4)
- xor a
- ld [W_SPRITECURPOSX], a
- ld [W_SPRITECURPOSY], a
- call StoreSpriteOutputPointer
- ld a, [W_SPRITEFLIPPED]
- and a
- jr z, .notFlipped
- ld hl, DecodeNybble0TableFlipped
- ld de, DecodeNybble1TableFlipped
- jr .storeDecodeTablesPointers
-.notFlipped
- ld hl, DecodeNybble0Table
- ld de, DecodeNybble1Table
-.storeDecodeTablesPointers
- ld a, l
- ld [W_SPRITEDECODETABLE0PTR], a
- ld a, h
- ld [W_SPRITEDECODETABLE0PTR+1], a
- ld a, e
- ld [W_SPRITEDECODETABLE1PTR], a
- ld a, d
- ld [W_SPRITEDECODETABLE1PTR+1], a
- ld e, $0 ; last decoded nybble, initialized to 0
-.decodeNextByteLoop
- ld a, [W_SPRITEOUTPUTPTR]
- ld l, a
- ld a, [W_SPRITEOUTPUTPTR+1]
- ld h, a
- ld a, [hl]
- ld b, a
- swap a
- and $f
- call DifferentialDecodeNybble ; decode high nybble
- swap a
- ld d, a
- ld a, b
- and $f
- call DifferentialDecodeNybble ; decode low nybble
- or d
- ld b, a
- ld a, [W_SPRITEOUTPUTPTR]
- ld l, a
- ld a, [W_SPRITEOUTPUTPTR+1]
- ld h, a
- ld a, b
- ld [hl], a ; write back decoded data
- ld a, [W_SPRITEHEIGHT]
- add l ; move on to next column
- jr nc, .noCarry
- inc h
-.noCarry
- ld [W_SPRITEOUTPUTPTR], a
- ld a, h
- ld [W_SPRITEOUTPUTPTR+1], a
- ld a, [W_SPRITECURPOSX]
- add $8
- ld [W_SPRITECURPOSX], a
- ld b, a
- ld a, [W_SPRITEWITDH]
- cp b
- jr nz, .decodeNextByteLoop ; test if current row is done
- xor a
- ld e, a
- ld [W_SPRITECURPOSX], a
- ld a, [W_SPRITECURPOSY] ; move on to next row
- inc a
- ld [W_SPRITECURPOSY], a
- ld b, a
- ld a, [W_SPRITEHEIGHT]
- cp b
- jr z, .done ; test if all rows finished
- ld a, [W_SPRITEOUTPUTPTRCACHED]
- ld l, a
- ld a, [W_SPRITEOUTPUTPTRCACHED+1]
- ld h, a
- inc hl
- call StoreSpriteOutputPointer
- jr .decodeNextByteLoop
-.done
- xor a
- ld [W_SPRITECURPOSY], a
- ret
-
-; decodes the nybble stored in a. Last decoded data is assumed to be in e (needed to determine if initial value is 0 or 1)
-DifferentialDecodeNybble:: ; 276d (0:276d)
- srl a ; c=a%2, a/=2
- ld c, $0
- jr nc, .evenNumber
- ld c, $1
-.evenNumber
- ld l, a
- ld a, [W_SPRITEFLIPPED]
- and a
- jr z, .notFlipped ; determine if initial value is 0 or one
- bit 3, e ; if flipped, consider MSB of last data
- jr .selectLookupTable
-.notFlipped
- bit 0, e ; else consider LSB
-.selectLookupTable
- ld e, l
- jr nz, .initialValue1 ; load the appropriate table
- ld a, [W_SPRITEDECODETABLE0PTR]
- ld l, a
- ld a, [W_SPRITEDECODETABLE0PTR+1]
- jr .tableLookup
-.initialValue1
- ld a, [W_SPRITEDECODETABLE1PTR]
- ld l, a
- ld a, [W_SPRITEDECODETABLE1PTR+1]
-.tableLookup
- ld h, a
- ld a, e
- add l
- ld l, a
- jr nc, .noCarry
- inc h
-.noCarry
- ld a, [hl]
- bit 0, c
- jr nz, .selectLowNybble
- swap a ; select high nybble
-.selectLowNybble
- and $f
- ld e, a ; update last decoded data
- ret
-
-DecodeNybble0Table:: ; 27a7 (0:27a7)
- dn $0, $1
- dn $3, $2
- dn $7, $6
- dn $4, $5
- dn $f, $e
- dn $c, $d
- dn $8, $9
- dn $b, $a
-DecodeNybble1Table:: ; 27af (0:27af)
- dn $f, $e
- dn $c, $d
- dn $8, $9
- dn $b, $a
- dn $0, $1
- dn $3, $2
- dn $7, $6
- dn $4, $5
-DecodeNybble0TableFlipped:: ; 27b7 (0:27b7)
- dn $0, $8
- dn $c, $4
- dn $e, $6
- dn $2, $a
- dn $f, $7
- dn $3, $b
- dn $1, $9
- dn $d, $5
-DecodeNybble1TableFlipped:: ; 27bf (0:27bf)
- dn $f, $7
- dn $3, $b
- dn $1, $9
- dn $d, $5
- dn $0, $8
- dn $c, $4
- dn $e, $6
- dn $2, $a
-
-; combines the two loaded chunks with xor (the chunk loaded second is the destination). The source chunk is differeintial decoded beforehand.
-XorSpriteChunks:: ; 27c7 (0:27c7)
- xor a
- ld [W_SPRITECURPOSX], a
- ld [W_SPRITECURPOSY], a
- call ResetSpriteBufferPointers
- ld a, [W_SPRITEOUTPUTPTR] ; points to buffer 1 or 2, depending on flags
- ld l, a
- ld a, [W_SPRITEOUTPUTPTR+1]
- ld h, a
- call SpriteDifferentialDecode ; decode buffer 1 or 2, depending on flags
- call ResetSpriteBufferPointers
- ld a, [W_SPRITEOUTPUTPTR] ; source buffer, points to buffer 1 or 2, depending on flags
- ld l, a
- ld a, [W_SPRITEOUTPUTPTR+1]
- ld h, a
- ld a, [W_SPRITEOUTPUTPTRCACHED] ; destination buffer, points to buffer 2 or 1, depending on flags
- ld e, a
- ld a, [W_SPRITEOUTPUTPTRCACHED+1]
- ld d, a
-.xorChunksLoop
- ld a, [W_SPRITEFLIPPED]
- and a
- jr z, .notFlipped
- push de
- ld a, [de]
- ld b, a
- swap a
- and $f
- call ReverseNybble ; if flipped reverse the nybbles in the destination buffer
- swap a
- ld c, a
- ld a, b
- and $f
- call ReverseNybble
- or c
- pop de
- ld [de], a
-.notFlipped
- ld a, [hli]
- ld b, a
- ld a, [de]
- xor b
- ld [de], a
- inc de
- ld a, [W_SPRITECURPOSY]
- inc a
- ld [W_SPRITECURPOSY], a ; go to next row
- ld b, a
- ld a, [W_SPRITEHEIGHT]
- cp b
- jr nz, .xorChunksLoop ; test if column finished
- xor a
- ld [W_SPRITECURPOSY], a
- ld a, [W_SPRITECURPOSX]
- add $8
- ld [W_SPRITECURPOSX], a ; go to next column
- ld b, a
- ld a, [W_SPRITEWITDH]
- cp b
- jr nz, .xorChunksLoop ; test if all columns finished
- xor a
- ld [W_SPRITECURPOSX], a
- ret
-
-; reverses the bits in the nybble given in register a
-ReverseNybble:: ; 2837 (0:2837)
- ld de, NybbleReverseTable
- add e
- ld e, a
- jr nc, .asm_283f
- inc d
-.asm_283f
- ld a, [de]
- ret
-
-; resets sprite buffer pointers to buffer 1 and 2, depending on W_SPRITELOADFLAGS
-ResetSpriteBufferPointers:: ; 2841 (0:2841)
- ld a, [W_SPRITELOADFLAGS] ; wd0a8
- bit 0, a
- jr nz, .buffer2Selected
- ld de, S_SPRITEBUFFER1
- ld hl, S_SPRITEBUFFER2
- jr .storeBufferPointers
-.buffer2Selected
- ld de, S_SPRITEBUFFER2
- ld hl, S_SPRITEBUFFER1
-.storeBufferPointers
- ld a, l
- ld [W_SPRITEOUTPUTPTR], a
- ld a, h
- ld [W_SPRITEOUTPUTPTR+1], a
- ld a, e
- ld [W_SPRITEOUTPUTPTRCACHED], a
- ld a, d
- ld [W_SPRITEOUTPUTPTRCACHED+1], a
- ret
-
-; maps each nybble to its reverse
-NybbleReverseTable:: ; 2867 (0:2867)
- db $0, $8, $4, $c, $2, $a, $6 ,$e, $1, $9, $5, $d, $3, $b, $7 ,$f
-
-; combines the two loaded chunks with xor (the chunk loaded second is the destination). Both chunks are differeintial decoded beforehand.
-UnpackSpriteMode2:: ; 2877 (0:2877)
- call ResetSpriteBufferPointers
- ld a, [W_SPRITEFLIPPED]
- push af
- xor a
- ld [W_SPRITEFLIPPED], a ; temporarily clear flipped flag for decoding the destination chunk
- ld a, [W_SPRITEOUTPUTPTRCACHED]
- ld l, a
- ld a, [W_SPRITEOUTPUTPTRCACHED+1]
- ld h, a
- call SpriteDifferentialDecode
- call ResetSpriteBufferPointers
- pop af
- ld [W_SPRITEFLIPPED], a
- jp XorSpriteChunks
-
-; stores hl into the output pointers
-StoreSpriteOutputPointer:: ; 2897 (0:2897)
- ld a, l
- ld [W_SPRITEOUTPUTPTR], a
- ld [W_SPRITEOUTPUTPTRCACHED], a
- ld a, h
- ld [W_SPRITEOUTPUTPTR+1], a
- ld [W_SPRITEOUTPUTPTRCACHED+1], a
- ret
-
ResetPlayerSpriteData:: ; 28a6 (0:28a6)
ld hl, wSpriteStateData1
call ResetPlayerSpriteData_ClearSpriteData
@@ -6721,56 +5160,7 @@
ret
-Predef::
-; Call predefined function a.
-; To preserve other registers, have the
-; destination call GetPredefRegisters.
-
- ; Save the predef id for GetPredefPointer.
- ld [wPredefID], a
-
- ; A hack for LoadDestinationWarpPosition.
- ; See Func_c754 (predef $19).
- ld a, [H_LOADEDROMBANK]
- ld [wPredefParentBank], a
-
- push af
- ld a, BANK(GetPredefPointer)
- ld [H_LOADEDROMBANK], a
- ld [$2000], a
-
- call GetPredefPointer
-
- ld a, [wPredefBank]
- ld [H_LOADEDROMBANK], a
- ld [$2000], a
-
- ld de, .done
- push de
- jp [hl]
-.done
-
- pop af
- ld [H_LOADEDROMBANK], a
- ld [$2000], a
- ret
-
-GetPredefRegisters::
-; Restore the contents of register pairs
-; when GetPredefPointer was called.
- ld a, [wPredefRegisters + 0]
- ld h, a
- ld a, [wPredefRegisters + 1]
- ld l, a
- ld a, [wPredefRegisters + 2]
- ld d, a
- ld a, [wPredefRegisters + 3]
- ld e, a
- ld a, [wPredefRegisters + 4]
- ld b, a
- ld a, [wPredefRegisters + 5]
- ld c, a
- ret
+INCLUDE "home/predef.asm"
Func_3ead:: ; 3ead (0:3ead)
--- /dev/null
+++ b/home/audio.asm
@@ -1,0 +1,183 @@
+Func_2307:: ; 2307 (0:2307)
+ call WaitForSoundToFinish
+ xor a
+ ld c, a
+ ld d, a
+ ld [wcfca], a
+ jr asm_2324
+
+Func_2312:: ; 2312 (0:2312)
+ ld c, $a
+ ld d, $0
+ ld a, [wd72e]
+ bit 5, a
+ jr z, asm_2324
+ xor a
+ ld [wcfca], a
+ ld c, $8
+ ld d, c
+asm_2324:: ; 2324 (0:2324)
+ ld a, [wd700]
+ and a
+ jr z, .asm_2343
+ cp $2
+ jr z, .asm_2332
+ ld a, MUSIC_BIKE_RIDING
+ jr .asm_2334
+.asm_2332
+ ld a, MUSIC_SURFING
+.asm_2334
+ ld b, a
+ ld a, d
+ and a
+ ld a, Bank(Func_7d8ea)
+ jr nz, .asm_233e
+ ld [wc0ef], a
+.asm_233e
+ ld [wc0f0], a
+ jr .asm_234c
+.asm_2343
+ ld a, [wd35b]
+ ld b, a
+ call Func_2385
+ jr c, .asm_2351
+.asm_234c
+ ld a, [wcfca]
+ cp b
+ ret z
+.asm_2351
+ ld a, c
+ ld [wMusicHeaderPointer], a
+ ld a, b
+ ld [wcfca], a
+ ld [wc0ee], a
+ jp PlaySound
+
+Func_235f:: ; 235f (0:235f)
+ ld a, [wc0ef]
+ ld b, a
+ cp $2
+ jr nz, .checkForBank08
+.bank02
+ ld hl, Func_9103
+ jr .asm_2378
+.checkForBank08
+ cp $8
+ jr nz, .bank1F
+.bank08
+ ld hl, Func_21879
+ jr .asm_2378
+.bank1F
+ ld hl, Func_7d177
+.asm_2378
+ ld c, $6
+.asm_237a
+ push bc
+ push hl
+ call Bankswitch
+ pop hl
+ pop bc
+ dec c
+ jr nz, .asm_237a
+ ret
+
+Func_2385:: ; 2385 (0:2385)
+ ld a, [wd35c]
+ ld e, a
+ ld a, [wc0ef]
+ cp e
+ jr nz, .asm_2394
+ ld [wc0f0], a
+ and a
+ ret
+.asm_2394
+ ld a, c
+ and a
+ ld a, e
+ jr nz, .asm_239c
+ ld [wc0ef], a
+.asm_239c
+ ld [wc0f0], a
+ scf
+ ret
+
+PlayMusic:: ; 23a1 (0:23a1)
+ ld b, a
+ ld [wc0ee], a
+ xor a
+ ld [wMusicHeaderPointer], a
+ ld a, c
+ ld [wc0ef], a
+ ld [wc0f0], a
+ ld a, b
+
+; plays music specified by a. If value is $ff, music is stopped
+PlaySound:: ; 23b1 (0:23b1)
+ push hl
+ push de
+ push bc
+ ld b, a
+ ld a, [wc0ee]
+ and a
+ jr z, .asm_23c8
+ xor a
+ ld [wc02a], a
+ ld [wc02b], a
+ ld [wc02c], a
+ ld [wc02d], a
+.asm_23c8
+ ld a, [wMusicHeaderPointer]
+ and a
+ jr z, .asm_23e3
+ ld a, [wc0ee]
+ and a
+ jr z, .asm_2425
+ xor a
+ ld [wc0ee], a
+ ld a, [wcfca]
+ cp $ff
+ jr nz, .asm_2414
+ xor a
+ ld [wMusicHeaderPointer], a
+.asm_23e3
+ xor a
+ ld [wc0ee], a
+ ld a, [H_LOADEDROMBANK]
+ ld [$ffb9], a
+ ld a, [wc0ef]
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+ cp $2
+ jr nz, .checkForBank08
+.bank02
+ ld a, b
+ call Func_9876
+ jr .asm_240b
+.checkForBank08
+ cp $8
+ jr nz, .bank1F
+.bank08
+ ld a, b
+ call Func_22035
+ jr .asm_240b
+.bank1F
+ ld a, b
+ call Func_7d8ea
+.asm_240b
+ ld a, [$ffb9]
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+ jr .asm_2425
+.asm_2414
+ ld a, b
+ ld [wcfca], a
+ ld a, [wMusicHeaderPointer]
+ ld [wcfc8], a
+ ld [wcfc9], a
+ ld a, b
+ ld [wMusicHeaderPointer], a
+.asm_2425
+ pop bc
+ pop de
+ pop hl
+ ret
--- /dev/null
+++ b/home/fade.asm
@@ -1,0 +1,73 @@
+; These routines manage gradual fading
+; (e.g., entering a doorway)
+LoadGBPal::
+ ld a, [wd35d] ;tells if cur.map is dark (requires HM5_FLASH?)
+ ld b, a
+ ld hl, FadePal4
+ ld a, l
+ sub b
+ ld l, a
+ jr nc, .ok
+ dec h
+.ok
+ ld a, [hli]
+ ld [rBGP], a
+ ld a, [hli]
+ ld [rOBP0], a
+ ld a, [hli]
+ ld [rOBP1], a
+ ret
+
+GBFadeOut1::
+ ld hl, FadePal1
+ ld b, 4
+ jr GBFadeOutCommon
+
+GBFadeOut2::
+ ld hl, FadePal6
+ ld b, 3
+
+GBFadeOutCommon::
+ ld a, [hli]
+ ld [rBGP], a
+ ld a, [hli]
+ ld [rOBP0], a
+ ld a, [hli]
+ ld [rOBP1], a
+ ld c, 8
+ call DelayFrames
+ dec b
+ jr nz, GBFadeOutCommon
+ ret
+
+GBFadeIn1::
+ ld hl, FadePal4 + 2
+ ld b, 4
+ jr GBFadeInCommon
+
+GBFadeIn2::
+ ld hl, FadePal7 + 2
+ ld b, 3
+
+GBFadeInCommon::
+ ld a, [hld]
+ ld [rOBP1], a
+ ld a, [hld]
+ ld [rOBP0], a
+ ld a, [hld]
+ ld [rBGP], a
+ ld c, 8
+ call DelayFrames
+ dec b
+ jr nz, GBFadeInCommon
+ ret
+
+FadePal1:: db %11111111, %11111111, %11111111
+FadePal2:: db %11111110, %11111110, %11111000
+FadePal3:: db %11111001, %11100100, %11100100
+FadePal4:: db %11100100, %11010000, %11100000
+; rBGP rOBP0 rOBP1
+FadePal5:: db %11100100, %11010000, %11100000
+FadePal6:: db %10010000, %10000000, %10010000
+FadePal7:: db %01000000, %01000000, %01000000
+FadePal8:: db %00000000, %00000000, %00000000
--- /dev/null
+++ b/home/init.asm
@@ -1,0 +1,139 @@
+SoftReset::
+ call StopAllSounds
+ call GBPalWhiteOut
+ ld c, $20
+ call DelayFrames
+ ; fallthrough
+
+Init::
+; Program init.
+
+rLCDC_DEFAULT EQU %11100011
+; * LCD enabled
+; * Window tile map at $9C00
+; * Window display enabled
+; * BG and window tile data at $8800
+; * BG tile map at $9800
+; * 8x8 OBJ size
+; * OBJ display enabled
+; * BG display enabled
+
+ di
+
+ xor a
+ ld [rIF], a
+ ld [rIE], a
+ ld [$ff43], a
+ ld [$ff42], a
+ ld [$ff01], a
+ ld [$ff02], a
+ ld [$ff4b], a
+ ld [$ff4a], a
+ ld [$ff06], a
+ ld [$ff07], a
+ ld [$ff47], a
+ ld [$ff48], a
+ ld [$ff49], a
+
+ ld a, rLCDC_ENABLE_MASK
+ ld [rLCDC], a
+ call DisableLCD
+
+ ld sp, wStack
+
+ ld hl, $c000 ; start of WRAM
+ ld bc, $2000 ; size of WRAM
+.loop
+ ld [hl], 0
+ inc hl
+ dec bc
+ ld a, b
+ or c
+ jr nz, .loop
+
+ call ClearVram
+
+ ld hl, $ff80
+ ld bc, $ffff - $ff80
+ call FillMemory
+
+ call ClearSprites
+
+ ld a, Bank(WriteDMACodeToHRAM)
+ ld [H_LOADEDROMBANK], a
+ ld [MBC3RomBank], a
+ call WriteDMACodeToHRAM
+
+ xor a
+ ld [$ffd7], a
+ ld [$ff41], a
+ ld [$ffae], a
+ ld [$ffaf], a
+ ld [$ff0f], a
+ ld a, 1 << VBLANK + 1 << TIMER + 1 << SERIAL
+ ld [rIE], a
+
+ ld a, 144 ; move the window off-screen
+ ld [$ffb0], a
+ ld [rWY], a
+ ld a, 7
+ ld [rWX], a
+
+ ld a, $ff
+ ld [$ffaa], a
+
+ ld h, vBGMap0 / $100
+ call ClearBgMap
+ ld h, vBGMap1 / $100
+ call ClearBgMap
+
+ ld a, rLCDC_DEFAULT
+ ld [rLCDC], a
+ ld a, 16
+ ld [hSoftReset], a
+ call StopAllSounds
+
+ ei
+
+ ld a, $40 ; PREDEF_SGB_BORDER
+ call Predef
+
+ ld a, $1f
+ ld [wc0ef], a
+ ld [wc0f0], a
+ ld a, $9c
+ ld [$ffbd], a
+ xor a
+ ld [$ffbc], a
+ dec a
+ ld [wcfcb], a
+
+ ld a, $32 ; PREDEF_INTRO
+ call Predef
+
+ call DisableLCD
+ call ClearVram
+ call GBPalNormal
+ call ClearSprites
+ ld a, rLCDC_DEFAULT
+ ld [rLCDC], a
+
+ jp SetDefaultNamesBeforeTitlescreen
+
+ClearVram:
+ ld hl, $8000
+ ld bc, $2000
+ xor a
+ jp FillMemory
+
+
+StopAllSounds::
+ ld a, Bank(Func_9876)
+ ld [wc0ef], a
+ ld [wc0f0], a
+ xor a
+ ld [wMusicHeaderPointer], a
+ ld [wc0ee], a
+ ld [wcfca], a
+ dec a
+ jp PlaySound
--- /dev/null
+++ b/home/pic.asm
@@ -1,0 +1,591 @@
+; bankswitches and runs _UncompressSpriteData
+; bank is given in a, sprite input stream is pointed to in W_SPRITEINPUTPTR
+UncompressSpriteData:: ; 24fd (0:24fd)
+ ld b, a
+ ld a, [H_LOADEDROMBANK]
+ push af
+ ld a, b
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+ ld a, $a
+ ld [$0], a
+ xor a
+ ld [$4000], a
+ call _UncompressSpriteData
+ pop af
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+ ret
+
+; initializes necessary data to load a sprite and runs UncompressSpriteDataLoop
+_UncompressSpriteData:: ; 251a (0:251a)
+ ld hl, S_SPRITEBUFFER1
+ ld c, (2*SPRITEBUFFERSIZE) % $100
+ ld b, (2*SPRITEBUFFERSIZE) / $100
+ xor a
+ call FillMemory ; clear sprite buffer 1 and 2
+ ld a, $1
+ ld [W_SPRITEINPUTBITCOUNTER], a
+ ld a, $3
+ ld [W_SPRITEOUTPUTBITOFFSET], a
+ xor a
+ ld [W_SPRITECURPOSX], a
+ ld [W_SPRITECURPOSY], a
+ ld [W_SPRITELOADFLAGS], a ; wd0a8
+ call ReadNextInputByte ; first byte of input determines sprite width (high nybble) and height (low nybble) in tiles (8x8 pixels)
+ ld b, a
+ and $f
+ add a
+ add a
+ add a
+ ld [W_SPRITEHEIGHT], a
+ ld a, b
+ swap a
+ and $f
+ add a
+ add a
+ add a
+ ld [W_SPRITEWITDH], a
+ call ReadNextInputBit
+ ld [W_SPRITELOADFLAGS], a ; initialite bit1 to 0 and bit0 to the first input bit
+ ; this will load two chunks of data to S_SPRITEBUFFER1 and S_SPRITEBUFFER2
+ ; bit 0 decides in which one the first chunk is placed
+ ; fall through
+
+; uncompresses a chunk from the sprite input data stream (pointed to at wd0da) into S_SPRITEBUFFER1 or S_SPRITEBUFFER2
+; each chunk is a 1bpp sprite. A 2bpp sprite consist of two chunks which are merged afterwards
+; note that this is an endless loop which is terminated during a call to MoveToNextBufferPosition by manipulating the stack
+UncompressSpriteDataLoop:: ; 2556 (0:2556)
+ ld hl, S_SPRITEBUFFER1
+ ld a, [W_SPRITELOADFLAGS] ; wd0a8
+ bit 0, a
+ jr z, .useSpriteBuffer1 ; check which buffer to use
+ ld hl, S_SPRITEBUFFER2
+.useSpriteBuffer1
+ call StoreSpriteOutputPointer
+ ld a, [W_SPRITELOADFLAGS] ; wd0a8
+ bit 1, a
+ jr z, .startDecompression ; check if last iteration
+ call ReadNextInputBit ; if last chunk, read 1-2 bit unpacking mode
+ and a
+ jr z, .unpackingMode0 ; 0 -> mode 0
+ call ReadNextInputBit ; 1 0 -> mode 1
+ inc a ; 1 1 -> mode 2
+.unpackingMode0
+ ld [W_SPRITEUNPACKMODE], a
+.startDecompression
+ call ReadNextInputBit
+ and a
+ jr z, .readRLEncodedZeros ; if first bit is 0, the input starts with zeroes, otherwise with (non-zero) input
+.readNextInput
+ call ReadNextInputBit
+ ld c, a
+ call ReadNextInputBit
+ sla c
+ or c ; read next two bits into c
+ and a
+ jr z, .readRLEncodedZeros ; 00 -> RLEncoded zeroes following
+ call WriteSpriteBitsToBuffer ; otherwise write input to output and repeat
+ call MoveToNextBufferPosition
+ jr .readNextInput
+.readRLEncodedZeros
+ ld c, $0 ; number of zeroes it length encoded, the number
+.countConsecutiveOnesLoop ; of consecutive ones determines the number of bits the number has
+ call ReadNextInputBit
+ and a
+ jr z, .countConsecutiveOnesFinished
+ inc c
+ jr .countConsecutiveOnesLoop
+.countConsecutiveOnesFinished
+ ld a, c
+ add a
+ ld hl, LengthEncodingOffsetList
+ add l
+ ld l, a
+ jr nc, .noCarry
+ inc h
+.noCarry
+ ld a, [hli] ; read offset that is added to the number later on
+ ld e, a ; adding an offset of 2^length - 1 makes every integer uniquely
+ ld d, [hl] ; representable in the length encoding and saves bits
+ push de
+ inc c
+ ld e, $0
+ ld d, e
+.readNumberOfZerosLoop ; reads the next c+1 bits of input
+ call ReadNextInputBit
+ or e
+ ld e, a
+ dec c
+ jr z, .readNumberOfZerosDone
+ sla e
+ rl d
+ jr .readNumberOfZerosLoop
+.readNumberOfZerosDone
+ pop hl ; add the offset
+ add hl, de
+ ld e, l
+ ld d, h
+.writeZerosLoop
+ ld b, e
+ xor a ; write 00 to buffer
+ call WriteSpriteBitsToBuffer
+ ld e, b
+ call MoveToNextBufferPosition
+ dec de
+ ld a, d
+ and a
+ jr nz, .continueLoop
+ ld a, e
+ and a
+.continueLoop
+ jr nz, .writeZerosLoop
+ jr .readNextInput
+
+; moves output pointer to next position
+; also cancels the calling function if the all output is done (by removing the return pointer from stack)
+; and calls postprocessing functions according to the unpack mode
+MoveToNextBufferPosition:: ; 25d8 (0:25d8)
+ ld a, [W_SPRITEHEIGHT]
+ ld b, a
+ ld a, [W_SPRITECURPOSY]
+ inc a
+ cp b
+ jr z, .curColumnDone
+ ld [W_SPRITECURPOSY], a
+ ld a, [W_SPRITEOUTPUTPTR]
+ inc a
+ ld [W_SPRITEOUTPUTPTR], a
+ ret nz
+ ld a, [W_SPRITEOUTPUTPTR+1]
+ inc a
+ ld [W_SPRITEOUTPUTPTR+1], a
+ ret
+.curColumnDone
+ xor a
+ ld [W_SPRITECURPOSY], a
+ ld a, [W_SPRITEOUTPUTBITOFFSET]
+ and a
+ jr z, .bitOffsetsDone
+ dec a
+ ld [W_SPRITEOUTPUTBITOFFSET], a
+ ld hl, W_SPRITEOUTPUTPTRCACHED
+ ld a, [hli]
+ ld [W_SPRITEOUTPUTPTR], a
+ ld a, [hl]
+ ld [W_SPRITEOUTPUTPTR+1], a
+ ret
+.bitOffsetsDone
+ ld a, $3
+ ld [W_SPRITEOUTPUTBITOFFSET], a
+ ld a, [W_SPRITECURPOSX]
+ add $8
+ ld [W_SPRITECURPOSX], a
+ ld b, a
+ ld a, [W_SPRITEWITDH]
+ cp b
+ jr z, .allColumnsDone
+ ld a, [W_SPRITEOUTPUTPTR]
+ ld l, a
+ ld a, [W_SPRITEOUTPUTPTR+1]
+ ld h, a
+ inc hl
+ jp StoreSpriteOutputPointer
+.allColumnsDone
+ pop hl
+ xor a
+ ld [W_SPRITECURPOSX], a
+ ld a, [W_SPRITELOADFLAGS] ; wd0a8
+ bit 1, a
+ jr nz, .done ; test if there is one more sprite to go
+ xor $1
+ set 1, a
+ ld [W_SPRITELOADFLAGS], a ; wd0a8
+ jp UncompressSpriteDataLoop
+.done
+ jp UnpackSprite
+
+; writes 2 bits (from a) to the output buffer (pointed to from W_SPRITEOUTPUTPTR)
+WriteSpriteBitsToBuffer:: ; 2649 (0:2649)
+ ld e, a
+ ld a, [W_SPRITEOUTPUTBITOFFSET]
+ and a
+ jr z, .offset0
+ cp $2
+ jr c, .offset1
+ jr z, .offset2
+ rrc e ; offset 3
+ rrc e
+ jr .offset0
+.offset1
+ sla e
+ sla e
+ jr .offset0
+.offset2
+ swap e
+.offset0
+ ld a, [W_SPRITEOUTPUTPTR]
+ ld l, a
+ ld a, [W_SPRITEOUTPUTPTR+1]
+ ld h, a
+ ld a, [hl]
+ or e
+ ld [hl], a
+ ret
+
+; reads next bit from input stream and returns it in a
+ReadNextInputBit:: ; 2670 (0:2670)
+ ld a, [W_SPRITEINPUTBITCOUNTER]
+ dec a
+ jr nz, .curByteHasMoreBitsToRead
+ call ReadNextInputByte
+ ld [W_SPRITEINPUTCURBYTE], a
+ ld a, $8
+.curByteHasMoreBitsToRead
+ ld [W_SPRITEINPUTBITCOUNTER], a
+ ld a, [W_SPRITEINPUTCURBYTE]
+ rlca
+ ld [W_SPRITEINPUTCURBYTE], a
+ and $1
+ ret
+
+; reads next byte from input stream and returns it in a
+ReadNextInputByte:: ; 268b (0:268b)
+ ld a, [W_SPRITEINPUTPTR]
+ ld l, a
+ ld a, [W_SPRITEINPUTPTR+1]
+ ld h, a
+ ld a, [hli]
+ ld b, a
+ ld a, l
+ ld [W_SPRITEINPUTPTR], a
+ ld a, h
+ ld [W_SPRITEINPUTPTR+1], a
+ ld a, b
+ ret
+
+; the nth item is 2^n - 1
+LengthEncodingOffsetList:: ; 269f (0:269f)
+ dw %0000000000000001
+ dw %0000000000000011
+ dw %0000000000000111
+ dw %0000000000001111
+ dw %0000000000011111
+ dw %0000000000111111
+ dw %0000000001111111
+ dw %0000000011111111
+ dw %0000000111111111
+ dw %0000001111111111
+ dw %0000011111111111
+ dw %0000111111111111
+ dw %0001111111111111
+ dw %0011111111111111
+ dw %0111111111111111
+ dw %1111111111111111
+
+; unpacks the sprite data depending on the unpack mode
+UnpackSprite:: ; 26bf (0:26bf)
+ ld a, [W_SPRITEUNPACKMODE]
+ cp $2
+ jp z, UnpackSpriteMode2
+ and a
+ jp nz, XorSpriteChunks
+ ld hl, S_SPRITEBUFFER1
+ call SpriteDifferentialDecode
+ ld hl, S_SPRITEBUFFER2
+ ; fall through
+
+; decodes differential encoded sprite data
+; input bit value 0 preserves the current bit value and input bit value 1 toggles it (starting from initial value 0).
+SpriteDifferentialDecode:: ; 26d4 (0:26d4)
+ xor a
+ ld [W_SPRITECURPOSX], a
+ ld [W_SPRITECURPOSY], a
+ call StoreSpriteOutputPointer
+ ld a, [W_SPRITEFLIPPED]
+ and a
+ jr z, .notFlipped
+ ld hl, DecodeNybble0TableFlipped
+ ld de, DecodeNybble1TableFlipped
+ jr .storeDecodeTablesPointers
+.notFlipped
+ ld hl, DecodeNybble0Table
+ ld de, DecodeNybble1Table
+.storeDecodeTablesPointers
+ ld a, l
+ ld [W_SPRITEDECODETABLE0PTR], a
+ ld a, h
+ ld [W_SPRITEDECODETABLE0PTR+1], a
+ ld a, e
+ ld [W_SPRITEDECODETABLE1PTR], a
+ ld a, d
+ ld [W_SPRITEDECODETABLE1PTR+1], a
+ ld e, $0 ; last decoded nybble, initialized to 0
+.decodeNextByteLoop
+ ld a, [W_SPRITEOUTPUTPTR]
+ ld l, a
+ ld a, [W_SPRITEOUTPUTPTR+1]
+ ld h, a
+ ld a, [hl]
+ ld b, a
+ swap a
+ and $f
+ call DifferentialDecodeNybble ; decode high nybble
+ swap a
+ ld d, a
+ ld a, b
+ and $f
+ call DifferentialDecodeNybble ; decode low nybble
+ or d
+ ld b, a
+ ld a, [W_SPRITEOUTPUTPTR]
+ ld l, a
+ ld a, [W_SPRITEOUTPUTPTR+1]
+ ld h, a
+ ld a, b
+ ld [hl], a ; write back decoded data
+ ld a, [W_SPRITEHEIGHT]
+ add l ; move on to next column
+ jr nc, .noCarry
+ inc h
+.noCarry
+ ld [W_SPRITEOUTPUTPTR], a
+ ld a, h
+ ld [W_SPRITEOUTPUTPTR+1], a
+ ld a, [W_SPRITECURPOSX]
+ add $8
+ ld [W_SPRITECURPOSX], a
+ ld b, a
+ ld a, [W_SPRITEWITDH]
+ cp b
+ jr nz, .decodeNextByteLoop ; test if current row is done
+ xor a
+ ld e, a
+ ld [W_SPRITECURPOSX], a
+ ld a, [W_SPRITECURPOSY] ; move on to next row
+ inc a
+ ld [W_SPRITECURPOSY], a
+ ld b, a
+ ld a, [W_SPRITEHEIGHT]
+ cp b
+ jr z, .done ; test if all rows finished
+ ld a, [W_SPRITEOUTPUTPTRCACHED]
+ ld l, a
+ ld a, [W_SPRITEOUTPUTPTRCACHED+1]
+ ld h, a
+ inc hl
+ call StoreSpriteOutputPointer
+ jr .decodeNextByteLoop
+.done
+ xor a
+ ld [W_SPRITECURPOSY], a
+ ret
+
+; decodes the nybble stored in a. Last decoded data is assumed to be in e (needed to determine if initial value is 0 or 1)
+DifferentialDecodeNybble:: ; 276d (0:276d)
+ srl a ; c=a%2, a/=2
+ ld c, $0
+ jr nc, .evenNumber
+ ld c, $1
+.evenNumber
+ ld l, a
+ ld a, [W_SPRITEFLIPPED]
+ and a
+ jr z, .notFlipped ; determine if initial value is 0 or one
+ bit 3, e ; if flipped, consider MSB of last data
+ jr .selectLookupTable
+.notFlipped
+ bit 0, e ; else consider LSB
+.selectLookupTable
+ ld e, l
+ jr nz, .initialValue1 ; load the appropriate table
+ ld a, [W_SPRITEDECODETABLE0PTR]
+ ld l, a
+ ld a, [W_SPRITEDECODETABLE0PTR+1]
+ jr .tableLookup
+.initialValue1
+ ld a, [W_SPRITEDECODETABLE1PTR]
+ ld l, a
+ ld a, [W_SPRITEDECODETABLE1PTR+1]
+.tableLookup
+ ld h, a
+ ld a, e
+ add l
+ ld l, a
+ jr nc, .noCarry
+ inc h
+.noCarry
+ ld a, [hl]
+ bit 0, c
+ jr nz, .selectLowNybble
+ swap a ; select high nybble
+.selectLowNybble
+ and $f
+ ld e, a ; update last decoded data
+ ret
+
+DecodeNybble0Table:: ; 27a7 (0:27a7)
+ dn $0, $1
+ dn $3, $2
+ dn $7, $6
+ dn $4, $5
+ dn $f, $e
+ dn $c, $d
+ dn $8, $9
+ dn $b, $a
+DecodeNybble1Table:: ; 27af (0:27af)
+ dn $f, $e
+ dn $c, $d
+ dn $8, $9
+ dn $b, $a
+ dn $0, $1
+ dn $3, $2
+ dn $7, $6
+ dn $4, $5
+DecodeNybble0TableFlipped:: ; 27b7 (0:27b7)
+ dn $0, $8
+ dn $c, $4
+ dn $e, $6
+ dn $2, $a
+ dn $f, $7
+ dn $3, $b
+ dn $1, $9
+ dn $d, $5
+DecodeNybble1TableFlipped:: ; 27bf (0:27bf)
+ dn $f, $7
+ dn $3, $b
+ dn $1, $9
+ dn $d, $5
+ dn $0, $8
+ dn $c, $4
+ dn $e, $6
+ dn $2, $a
+
+; combines the two loaded chunks with xor (the chunk loaded second is the destination). The source chunk is differeintial decoded beforehand.
+XorSpriteChunks:: ; 27c7 (0:27c7)
+ xor a
+ ld [W_SPRITECURPOSX], a
+ ld [W_SPRITECURPOSY], a
+ call ResetSpriteBufferPointers
+ ld a, [W_SPRITEOUTPUTPTR] ; points to buffer 1 or 2, depending on flags
+ ld l, a
+ ld a, [W_SPRITEOUTPUTPTR+1]
+ ld h, a
+ call SpriteDifferentialDecode ; decode buffer 1 or 2, depending on flags
+ call ResetSpriteBufferPointers
+ ld a, [W_SPRITEOUTPUTPTR] ; source buffer, points to buffer 1 or 2, depending on flags
+ ld l, a
+ ld a, [W_SPRITEOUTPUTPTR+1]
+ ld h, a
+ ld a, [W_SPRITEOUTPUTPTRCACHED] ; destination buffer, points to buffer 2 or 1, depending on flags
+ ld e, a
+ ld a, [W_SPRITEOUTPUTPTRCACHED+1]
+ ld d, a
+.xorChunksLoop
+ ld a, [W_SPRITEFLIPPED]
+ and a
+ jr z, .notFlipped
+ push de
+ ld a, [de]
+ ld b, a
+ swap a
+ and $f
+ call ReverseNybble ; if flipped reverse the nybbles in the destination buffer
+ swap a
+ ld c, a
+ ld a, b
+ and $f
+ call ReverseNybble
+ or c
+ pop de
+ ld [de], a
+.notFlipped
+ ld a, [hli]
+ ld b, a
+ ld a, [de]
+ xor b
+ ld [de], a
+ inc de
+ ld a, [W_SPRITECURPOSY]
+ inc a
+ ld [W_SPRITECURPOSY], a ; go to next row
+ ld b, a
+ ld a, [W_SPRITEHEIGHT]
+ cp b
+ jr nz, .xorChunksLoop ; test if column finished
+ xor a
+ ld [W_SPRITECURPOSY], a
+ ld a, [W_SPRITECURPOSX]
+ add $8
+ ld [W_SPRITECURPOSX], a ; go to next column
+ ld b, a
+ ld a, [W_SPRITEWITDH]
+ cp b
+ jr nz, .xorChunksLoop ; test if all columns finished
+ xor a
+ ld [W_SPRITECURPOSX], a
+ ret
+
+; reverses the bits in the nybble given in register a
+ReverseNybble:: ; 2837 (0:2837)
+ ld de, NybbleReverseTable
+ add e
+ ld e, a
+ jr nc, .asm_283f
+ inc d
+.asm_283f
+ ld a, [de]
+ ret
+
+; resets sprite buffer pointers to buffer 1 and 2, depending on W_SPRITELOADFLAGS
+ResetSpriteBufferPointers:: ; 2841 (0:2841)
+ ld a, [W_SPRITELOADFLAGS] ; wd0a8
+ bit 0, a
+ jr nz, .buffer2Selected
+ ld de, S_SPRITEBUFFER1
+ ld hl, S_SPRITEBUFFER2
+ jr .storeBufferPointers
+.buffer2Selected
+ ld de, S_SPRITEBUFFER2
+ ld hl, S_SPRITEBUFFER1
+.storeBufferPointers
+ ld a, l
+ ld [W_SPRITEOUTPUTPTR], a
+ ld a, h
+ ld [W_SPRITEOUTPUTPTR+1], a
+ ld a, e
+ ld [W_SPRITEOUTPUTPTRCACHED], a
+ ld a, d
+ ld [W_SPRITEOUTPUTPTRCACHED+1], a
+ ret
+
+; maps each nybble to its reverse
+NybbleReverseTable:: ; 2867 (0:2867)
+ db $0, $8, $4, $c, $2, $a, $6 ,$e, $1, $9, $5, $d, $3, $b, $7 ,$f
+
+; combines the two loaded chunks with xor (the chunk loaded second is the destination). Both chunks are differeintial decoded beforehand.
+UnpackSpriteMode2:: ; 2877 (0:2877)
+ call ResetSpriteBufferPointers
+ ld a, [W_SPRITEFLIPPED]
+ push af
+ xor a
+ ld [W_SPRITEFLIPPED], a ; temporarily clear flipped flag for decoding the destination chunk
+ ld a, [W_SPRITEOUTPUTPTRCACHED]
+ ld l, a
+ ld a, [W_SPRITEOUTPUTPTRCACHED+1]
+ ld h, a
+ call SpriteDifferentialDecode
+ call ResetSpriteBufferPointers
+ pop af
+ ld [W_SPRITEFLIPPED], a
+ jp XorSpriteChunks
+
+; stores hl into the output pointers
+StoreSpriteOutputPointer:: ; 2897 (0:2897)
+ ld a, l
+ ld [W_SPRITEOUTPUTPTR], a
+ ld [W_SPRITEOUTPUTPTRCACHED], a
+ ld a, h
+ ld [W_SPRITEOUTPUTPTR+1], a
+ ld [W_SPRITEOUTPUTPTRCACHED+1], a
+ ret
--- /dev/null
+++ b/home/predef.asm
@@ -1,0 +1,50 @@
+Predef::
+; Call predefined function a.
+; To preserve other registers, have the
+; destination call GetPredefRegisters.
+
+ ; Save the predef id for GetPredefPointer.
+ ld [wPredefID], a
+
+ ; A hack for LoadDestinationWarpPosition.
+ ; See Func_c754 (predef $19).
+ ld a, [H_LOADEDROMBANK]
+ ld [wPredefParentBank], a
+
+ push af
+ ld a, BANK(GetPredefPointer)
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+
+ call GetPredefPointer
+
+ ld a, [wPredefBank]
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+
+ ld de, .done
+ push de
+ jp [hl]
+.done
+
+ pop af
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+ ret
+
+GetPredefRegisters::
+; Restore the contents of register pairs
+; when GetPredefPointer was called.
+ ld a, [wPredefRegisters + 0]
+ ld h, a
+ ld a, [wPredefRegisters + 1]
+ ld l, a
+ ld a, [wPredefRegisters + 2]
+ ld d, a
+ ld a, [wPredefRegisters + 3]
+ ld e, a
+ ld a, [wPredefRegisters + 4]
+ ld b, a
+ ld a, [wPredefRegisters + 5]
+ ld c, a
+ ret
--- /dev/null
+++ b/home/vblank.asm
@@ -1,0 +1,105 @@
+VBlank::
+
+ push af
+ push bc
+ push de
+ push hl
+
+ ld a, [H_LOADEDROMBANK]
+ ld [wd122], a
+
+ ld a, [$ffae]
+ ld [rSCX], a
+ ld a, [$ffaf]
+ ld [rSCY], a
+
+ ld a, [wd0a0]
+ and a
+ jr nz, .ok
+ ld a, [$ffb0]
+ ld [rWY], a
+.ok
+
+ call AutoBgMapTransfer
+ call VBlankCopyBgMap
+ call RedrawExposedScreenEdge
+ call VBlankCopy
+ call VBlankCopyDouble
+ call UpdateMovingBgTiles
+ call $ff80 ; hOAMDMA
+ ld a, Bank(PrepareOAMData)
+ ld [H_LOADEDROMBANK], a
+ ld [MBC3RomBank], a
+ call PrepareOAMData
+
+ ; VBlank-sensitive operations end.
+
+ call Random
+
+ ld a, [H_VBLANKOCCURRED]
+ and a
+ jr z, .vblanked
+ xor a
+ ld [H_VBLANKOCCURRED], a
+.vblanked
+
+ ld a, [H_FRAMECOUNTER]
+ and a
+ jr z, .decced
+ dec a
+ ld [H_FRAMECOUNTER], a
+.decced
+
+ call Func_28cb
+
+ ld a, [wc0ef] ; music ROM bank
+ ld [H_LOADEDROMBANK], a
+ ld [MBC3RomBank], a
+
+ cp BANK(Func_9103)
+ jr nz, .notbank2
+.bank2
+ call Func_9103
+ jr .afterMusic
+.notbank2
+ cp 8
+ jr nz, .bank1F
+.bank8
+ call Func_2136e
+ call Func_21879
+ jr .afterMusic
+.bank1F
+ call Func_7d177
+.afterMusic
+
+ callba Func_18dee ; keep track of time played
+
+ ld a, [$fff9]
+ and a
+ call z, ReadJoypad
+
+ ld a, [wd122]
+ ld [H_LOADEDROMBANK], a
+ ld [MBC3RomBank], a
+
+ pop hl
+ pop de
+ pop bc
+ pop af
+ reti
+
+
+DelayFrame::
+; Wait for the next vblank interrupt.
+; As a bonus, this saves battery.
+
+NOT_VBLANKED EQU 1
+
+ ld a, NOT_VBLANKED
+ ld [H_VBLANKOCCURRED], a
+.halt
+ halt
+ ld a, [H_VBLANKOCCURRED]
+ and a
+ jr nz, .halt
+ ret
--- /dev/null
+++ b/home/vcopy.asm
@@ -1,0 +1,450 @@
+; this function seems to be used only once
+; it store the address of a row and column of the VRAM background map in hl
+; INPUT: h - row, l - column, b - high byte of background tile map address in VRAM
+GetRowColAddressBgMap:: ; 1cdd (0:1cdd)
+ xor a
+ srl h
+ rr a
+ srl h
+ rr a
+ srl h
+ rr a
+ or l
+ ld l,a
+ ld a,b
+ or h
+ ld h,a
+ ret
+
+; clears a VRAM background map with blank space tiles
+; INPUT: h - high byte of background tile map address in VRAM
+ClearBgMap:: ; 1cf0 (0:1cf0)
+ ld a," "
+ jr .next
+ ld a,l
+.next
+ ld de,$400 ; size of VRAM background map
+ ld l,e
+.loop
+ ld [hli],a
+ dec e
+ jr nz,.loop
+ dec d
+ jr nz,.loop
+ ret
+
+; When the player takes a step, a row or column of 2x2 tile blocks at the edge
+; of the screen toward which they moved is exposed and has to be redrawn.
+; This function does the redrawing.
+RedrawExposedScreenEdge:: ; 1d01 (0:1d01)
+ ld a,[H_SCREENEDGEREDRAW]
+ and a
+ ret z
+ ld b,a
+ xor a
+ ld [H_SCREENEDGEREDRAW],a
+ dec b
+ jr nz,.redrawRow
+.redrawColumn
+ ld hl,wScreenEdgeTiles
+ ld a,[H_SCREENEDGEREDRAWADDR]
+ ld e,a
+ ld a,[H_SCREENEDGEREDRAWADDR + 1]
+ ld d,a
+ ld c,18 ; screen height
+.loop1
+ ld a,[hli]
+ ld [de],a
+ inc de
+ ld a,[hli]
+ ld [de],a
+ ld a,31
+ 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 a,$03
+ or a,$98
+ ld d,a
+ dec c
+ jr nz,.loop1
+ xor a
+ ld [H_SCREENEDGEREDRAW],a
+ ret
+.redrawRow
+ ld hl,wScreenEdgeTiles
+ ld a,[H_SCREENEDGEREDRAWADDR]
+ ld e,a
+ ld a,[H_SCREENEDGEREDRAWADDR + 1]
+ ld d,a
+ push de
+ call .drawHalf ; draw upper half
+ pop de
+ ld a,32 ; width of VRAM background map
+ add e
+ ld e,a
+ ; draw lower half
+.drawHalf
+ ld c,10
+.loop2
+ 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 a,$1f
+ ld b,a
+ ld a,e
+ and a,$e0
+ or b
+ ld e,a
+ dec c
+ jr nz,.loop2
+ 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, RedrawExposedScreenEdge, is used when walking to
+; improve efficiency.
+AutoBgMapTransfer:: ; 1d57 (0:1d57)
+ ld a,[H_AUTOBGTRANSFERENABLED]
+ and a
+ ret z
+ ld hl,[sp + 0]
+ ld a,h
+ ld [H_SPTEMP],a
+ ld a,l
+ ld [H_SPTEMP + 1],a ; save stack pinter
+ ld a,[H_AUTOBGTRANSFERPORTION]
+ and a
+ jr z,.transferTopThird
+ dec a
+ jr z,.transferMiddleThird
+.transferBottomThird
+ FuncCoord 0,12
+ ld hl,Coord
+ ld sp,hl
+ ld a,[H_AUTOBGTRANSFERDEST + 1]
+ ld h,a
+ ld a,[H_AUTOBGTRANSFERDEST]
+ ld l,a
+ ld de,(12 * 32)
+ add hl,de
+ xor a ; TRANSFERTOP
+ jr .doTransfer
+.transferTopThird
+ FuncCoord 0,0
+ ld hl,Coord
+ ld sp,hl
+ ld a,[H_AUTOBGTRANSFERDEST + 1]
+ ld h,a
+ ld a,[H_AUTOBGTRANSFERDEST]
+ ld l,a
+ ld a,TRANSFERMIDDLE
+ jr .doTransfer
+.transferMiddleThird
+ FuncCoord 0,6
+ ld hl,Coord
+ ld sp,hl
+ ld a,[H_AUTOBGTRANSFERDEST + 1]
+ ld h,a
+ ld a,[H_AUTOBGTRANSFERDEST]
+ ld l,a
+ ld de,(6 * 32)
+ add hl,de
+ ld a,TRANSFERBOTTOM
+.doTransfer
+ ld [H_AUTOBGTRANSFERPORTION],a ; store next portion
+ ld b,6
+
+TransferBgRows:: ; 1d9e (0:1d9e)
+; unrolled loop and using pop for speed
+
+ rept 20 / 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
+
+i ld a, 32 - (20 - 1)
+ add l
+ ld l, a
+ jr nc, .ok
+ inc h
+.ok
+ dec b
+ jr nz, TransferBgRows
+
+ ld a, [H_SPTEMP]
+ ld h, a
+ ld a, [H_SPTEMP + 1]
+ ld l, a
+ ld sp, hl
+ ret
+
+; Copies [H_VBCOPYBGNUMROWS] rows from H_VBCOPYBGSRC to H_VBCOPYBGDEST.
+; If H_VBCOPYBGSRC is XX00, the transfer is disabled.
+VBlankCopyBgMap:: ; 1de1 (0:1de1)
+ ld a,[H_VBCOPYBGSRC] ; doubles as enabling byte
+ and a
+ ret z
+ ld hl,[sp + 0]
+ ld a,h
+ ld [H_SPTEMP],a
+ ld a,l
+ ld [H_SPTEMP + 1],a ; save stack pointer
+ ld a,[H_VBCOPYBGSRC]
+ ld l,a
+ ld a,[H_VBCOPYBGSRC + 1]
+ ld h,a
+ ld sp,hl
+ ld a,[H_VBCOPYBGDEST]
+ ld l,a
+ ld a,[H_VBCOPYBGDEST + 1]
+ ld h,a
+ ld a,[H_VBCOPYBGNUMROWS]
+ ld b,a
+ xor a
+ ld [H_VBCOPYBGSRC],a ; disable transfer so it doesn't continue next V-blank
+ jr TransferBgRows
+
+
+VBlankCopyDouble::
+; Copy [H_VBCOPYDOUBLESIZE] 1bpp tiles
+; from H_VBCOPYDOUBLESRC to H_VBCOPYDOUBLEDEST.
+
+; While we're here, convert to 2bpp.
+; The process is straightforward:
+; copy each byte twice.
+
+ ld a, [H_VBCOPYDOUBLESIZE]
+ and a
+ ret z
+
+ ld hl, [sp + 0]
+ ld a, h
+ ld [H_SPTEMP], a
+ ld a, l
+ ld [H_SPTEMP + 1], a
+
+ ld a, [H_VBCOPYDOUBLESRC]
+ ld l, a
+ ld a, [H_VBCOPYDOUBLESRC + 1]
+ ld h, a
+ ld sp, hl
+
+ ld a, [H_VBCOPYDOUBLEDEST]
+ ld l, a
+ ld a, [H_VBCOPYDOUBLEDEST + 1]
+ ld h, a
+
+ ld a, [H_VBCOPYDOUBLESIZE]
+ ld b, a
+ xor a ; transferred
+ ld [H_VBCOPYDOUBLESIZE], a
+
+.loop
+ 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, .loop
+
+ ld a, l
+ ld [H_VBCOPYDOUBLEDEST], a
+ ld a, h
+ ld [H_VBCOPYDOUBLEDEST + 1], a
+
+ ld hl, [sp + 0]
+ ld a, l
+ ld [H_VBCOPYDOUBLESRC], a
+ ld a, h
+ ld [H_VBCOPYDOUBLESRC + 1], a
+
+ ld a, [H_SPTEMP]
+ ld h, a
+ ld a, [H_SPTEMP + 1]
+ ld l, a
+ ld sp, hl
+
+ ret
+
+
+VBlankCopy::
+; Copy [H_VBCOPYSIZE] 2bpp tiles
+; from H_VBCOPYSRC to H_VBCOPYDEST.
+
+; Source and destination addresses
+; are updated, so transfer can
+; continue in subsequent calls.
+
+ ld a, [H_VBCOPYSIZE]
+ and a
+ ret z
+
+ ld hl, [sp + 0]
+ ld a, h
+ ld [H_SPTEMP], a
+ ld a, l
+ ld [H_SPTEMP + 1], a
+
+ ld a, [H_VBCOPYSRC]
+ ld l, a
+ ld a, [H_VBCOPYSRC + 1]
+ ld h, a
+ ld sp, hl
+
+ ld a, [H_VBCOPYDEST]
+ ld l, a
+ ld a, [H_VBCOPYDEST + 1]
+ ld h, a
+
+ ld a, [H_VBCOPYSIZE]
+ ld b, a
+ xor a ; transferred
+ ld [H_VBCOPYSIZE], a
+
+.loop
+ 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, .loop
+
+ ld a, l
+ ld [H_VBCOPYDEST], a
+ ld a, h
+ ld [H_VBCOPYDEST + 1], a
+
+ ld hl, [sp + 0]
+ ld a, l
+ ld [H_VBCOPYSRC], a
+ ld a, h
+ ld [H_VBCOPYSRC + 1], a
+
+ ld a, [H_SPTEMP]
+ ld h, a
+ ld a, [H_SPTEMP + 1]
+ ld l, a
+ ld sp, hl
+
+ ret
+
+
+UpdateMovingBgTiles::
+; Animate water and flower
+; tiles in the overworld.
+
+ ld a, [$ffd7]
+ and a
+ ret z
+
+ ld a, [$ffd8]
+ inc a
+ ld [$ffd8], a
+ cp $14
+ ret c
+ cp $15
+ jr z, .flower
+
+ ld hl, vTileset + $14 * $10
+ ld c, $10
+
+ ld a, [wd085]
+ inc a
+ and 7
+ ld [wd085], a
+
+ and 4
+ jr nz, .left
+.right
+ ld a, [hl]
+ rrca
+ ld [hli], a
+ dec c
+ jr nz, .right
+ jr .done
+.left
+ ld a, [hl]
+ rlca
+ ld [hli], a
+ dec c
+ jr nz, .left
+.done
+ ld a, [$ffd7]
+ rrca
+ ret nc
+ xor a
+ ld [$ffd8], a
+ ret
+
+.flower
+ xor a
+ ld [$ffd8], a
+
+ ld a, [wd085]
+ and 3
+ cp 2
+ ld hl, FlowerTile1
+ jr c, .copy
+ ld hl, FlowerTile2
+ jr z, .copy
+ ld hl, FlowerTile3
+.copy
+ ld de, vTileset + $3 * $10
+ ld c, $10
+.loop
+ ld a, [hli]
+ ld [de], a
+ inc de
+ dec c
+ jr nz, .loop
+ ret
+
+FlowerTile1: INCBIN "gfx/tilesets/flower/flower1.2bpp"
+FlowerTile2: INCBIN "gfx/tilesets/flower/flower2.2bpp"
+FlowerTile3: INCBIN "gfx/tilesets/flower/flower3.2bpp"