summaryrefslogtreecommitdiff
path: root/home.asm
diff options
context:
space:
mode:
Diffstat (limited to 'home.asm')
-rw-r--r--home.asm5173
1 files changed, 151 insertions, 5022 deletions
diff --git a/home.asm b/home.asm
index b13714fe..e3d4309b 100644
--- a/home.asm
+++ b/home.asm
@@ -124,2468 +124,11 @@ Start::
jp Init
-ReadJoypad::
-; Poll joypad input.
-; Unlike the hardware register, button
-; presses are indicated by a set bit.
-
- ld a, 1 << 5 ; select direction keys
- ld c, 0
-
- ld [rJOYP], a
- rept 6
- ld a, [rJOYP]
- endr
- cpl
- and %1111
- swap a
- ld b, a
-
- ld a, 1 << 4 ; select button keys
- ld [rJOYP], a
- rept 10
- ld a, [rJOYP]
- endr
- cpl
- and %1111
- or b
-
- ld [hJoyInput], a
-
- ld a, 1 << 4 + 1 << 5 ; deselect keys
- ld [rJOYP], a
- ret
-
-Joypad::
-; Update the joypad state variables:
-; [hJoyReleased] keys released since last time
-; [hJoyPressed] keys pressed since last time
-; [hJoyHeld] currently pressed keys
- homecall _Joypad
- ret
-
+INCLUDE "home/joypad.asm"
INCLUDE "data/map_header_pointers.asm"
-HandleMidJump::
-; Handle the player jumping down
-; a ledge in the overworld.
- ld b, BANK(_HandleMidJump)
- ld hl, _HandleMidJump
- jp Bankswitch
-
-EnterMap::
-; Load a new map.
- ld a, $ff
- ld [wJoyIgnore], a
- call LoadMapData
- callba Func_c335 ; initialize map variables
- ld hl, wd72c
- bit 0, [hl]
- jr z, .doNotCountSteps
- ld a, 3
- ld [wd13c], a ; some kind of step counter (counts up to 3 steps?)
-.doNotCountSteps
- ld hl, wd72e
- bit 5, [hl] ; did a battle happen immediately before this?
- res 5, [hl] ; unset the "battle just happened" flag
- call z, Func_12e7
- call nz, MapEntryAfterBattle
- ld hl, wd732
- ld a, [hl]
- and 1 << 4 | 1 << 3
- jr z, .didNotFlyOrTeleportIn
- res 3, [hl]
- callba Func_70510 ; display fly/teleport in graphical effect
- call UpdateSprites
-.didNotFlyOrTeleportIn
- callba CheckForceBikeOrSurf ; handle currents in SF islands and forced bike riding in cycling road
- ld hl, wd72d
- res 5, [hl]
- call UpdateSprites
- ld hl, wd126
- set 5, [hl]
- set 6, [hl]
- xor a
- ld [wJoyIgnore], a
-
-OverworldLoop::
- call DelayFrame
-OverworldLoopLessDelay::
- call DelayFrame
- call LoadGBPal
- ld a,[wd736]
- bit 6,a ; jumping down a ledge?
- call nz, HandleMidJump
- ld a,[wWalkCounter]
- and a
- jp nz,.moveAhead ; if the player sprite has not yet completed the walking animation
- call JoypadOverworld ; get joypad state (which is possibly simulated)
- callba SafariZoneCheck
- ld a,[wda46]
- and a
- jp nz,WarpFound2
- ld hl,wd72d
- bit 3,[hl]
- res 3,[hl]
- jp nz,WarpFound2
- ld a,[wd732]
- and a,$18
- jp nz,HandleFlyOrTeleportAway
- ld a,[W_CUROPPONENT]
- and a
- jp nz,.newBattle
- ld a,[wd730]
- bit 7,a ; are we simulating button presses?
- jr z,.notSimulating
- ld a,[hJoyHeld]
- jr .checkIfStartIsPressed
-.notSimulating
- ld a,[hJoyPressed]
-.checkIfStartIsPressed
- bit 3,a ; start button
- jr z,.startButtonNotPressed
-; if START is pressed
- xor a
- ld [$ff8c],a ; the $2920 ID for the start menu is 0
- jp .displayDialogue
-.startButtonNotPressed
- bit 0,a ; A button
- jp z,.checkIfDownButtonIsPressed
-; if A is pressed
- ld a,[wd730]
- bit 2,a
- jp nz,.noDirectionButtonsPressed
- call Func_30fd
- jr nz,.checkForOpponent
- call Func_3eb5 ; check for hidden items, PC's, etc.
- ld a,[$ffeb]
- and a
- jp z,OverworldLoop
- call IsSpriteOrSignInFrontOfPlayer ; check for sign or sprite in front of the player
- ld a,[$ff8c] ; $2920 ID for NPC/sign text, if any
- and a
- jp z,OverworldLoop
-.displayDialogue
- ld a,$35
- call Predef ; check what is in front of the player
- call UpdateSprites ; move sprites
- ld a,[wFlags_0xcd60]
- bit 2,a
- jr nz,.checkForOpponent
- bit 0,a
- jr nz,.checkForOpponent
- FuncCoord 8, 9
- ld a,[Coord]
- ld [wcf0e],a
- call DisplayTextID ; display either the start menu or the NPC/sign text
- ld a,[wcc47]
- and a
- jr z,.checkForOpponent
- dec a
- ld a,$00
- ld [wcc47],a
- jr z,.changeMap
- ld a,$52
- call Predef
- ld a,[W_CURMAP]
- ld [wd71a],a
- call Func_62ce
- ld a,[W_CURMAP]
- call SwitchToMapRomBank ; switch to the ROM bank of the current map
- ld hl,W_CURMAPTILESET
- set 7,[hl]
-.changeMap
- jp EnterMap
-.checkForOpponent
- ld a,[W_CUROPPONENT]
- and a
- jp nz,.newBattle
- jp OverworldLoop
-.noDirectionButtonsPressed
- ld hl,wFlags_0xcd60
- res 2,[hl]
- call UpdateSprites ; move sprites
- ld a,$01
- ld [wcc4b],a
- ld a,[wd528] ; the direction that was pressed last time
- and a
- jp z,OverworldLoop
-; if a direction was pressed last time
- ld [wd529],a ; save the last direction
- xor a
- ld [wd528],a ; zero the direction
- jp OverworldLoop
-.checkIfDownButtonIsPressed
- ld a,[hJoyHeld] ; current joypad state
- bit 7,a ; down button
- jr z,.checkIfUpButtonIsPressed
- ld a,$01
- ld [wSpriteStateData1 + 3],a
- ld a,$04
- jr .handleDirectionButtonPress
-.checkIfUpButtonIsPressed
- bit 6,a ; up button
- jr z,.checkIfLeftButtonIsPressed
- ld a,$ff
- ld [wSpriteStateData1 + 3],a
- ld a,$08
- jr .handleDirectionButtonPress
-.checkIfLeftButtonIsPressed
- bit 5,a ; left button
- jr z,.checkIfRightButtonIsPressed
- ld a,$ff
- ld [wSpriteStateData1 + 5],a
- ld a,$02
- jr .handleDirectionButtonPress
-.checkIfRightButtonIsPressed
- bit 4,a ; right button
- jr z,.noDirectionButtonsPressed
- ld a,$01
- ld [wSpriteStateData1 + 5],a
-.handleDirectionButtonPress
- ld [wd52a],a ; new direction
- ld a,[wd730]
- bit 7,a ; are we simulating button presses?
- jr nz,.noDirectionChange ; ignore direction changes if we are
- ld a,[wcc4b]
- and a
- jr z,.noDirectionChange
- ld a,[wd52a] ; new direction
- ld b,a
- ld a,[wd529] ; old direction
- cp b
- jr z,.noDirectionChange
-; the code below is strange
-; it computes whether or not the player did a 180 degree turn, but then overwrites the result
-; also, it does a seemingly pointless loop afterwards
- swap a ; put old direction in upper half
- or b ; put new direction in lower half
- cp a,$48 ; change dir from down to up
- jr nz,.notDownToUp
- ld a,$02
- ld [wd528],a
- jr .oddLoop
-.notDownToUp
- cp a,$84 ; change dir from up to down
- jr nz,.notUpToDown
- ld a,$01
- ld [wd528],a
- jr .oddLoop
-.notUpToDown
- cp a,$12 ; change dir from right to left
- jr nz,.notRightToLeft
- ld a,$04
- ld [wd528],a
- jr .oddLoop
-.notRightToLeft
- cp a,$21 ; change dir from left to right
- jr nz,.oddLoop
- ld a,$08
- ld [wd528],a
-.oddLoop
- ld hl,wFlags_0xcd60
- set 2,[hl]
- ld hl,wcc4b
- dec [hl]
- jr nz,.oddLoop
- ld a,[wd52a]
- ld [wd528],a
- call NewBattle
- jp c,.battleOccurred
- jp OverworldLoop
-.noDirectionChange
- ld a,[wd52a] ; current direction
- ld [wd528],a ; save direction
- call UpdateSprites ; move sprites
- ld a,[wd700]
- cp a,$02 ; surfing
- jr z,.surfing
-; not surfing
- call CollisionCheckOnLand
- jr nc,.noCollision
- push hl
- ld hl,wd736
- bit 2,[hl]
- pop hl
- jp z,OverworldLoop
- push hl
- call ExtraWarpCheck ; sets carry if there is a potential to warp
- pop hl
- jp c,CheckWarpsCollision
- jp OverworldLoop
-.surfing
- call CollisionCheckOnWater
- jp c,OverworldLoop
-.noCollision
- ld a,$08
- ld [wWalkCounter],a
- jr .moveAhead2
-.moveAhead
- ld a,[wd736]
- bit 7,a
- jr z,.noSpinning
- callba LoadSpinnerArrowTiles ; spin while moving
-.noSpinning
- call UpdateSprites ; move sprites
-.moveAhead2
- ld hl,wFlags_0xcd60
- res 2,[hl]
- ld a,[wd700]
- dec a ; riding a bike?
- jr nz,.normalPlayerSpriteAdvancement
- ld a,[wd736]
- bit 6,a ; jumping a ledge?
- jr nz,.normalPlayerSpriteAdvancement
- call BikeSpeedup ; if riding a bike and not jumping a ledge
-.normalPlayerSpriteAdvancement
- call AdvancePlayerSprite
- ld a,[wWalkCounter]
- and a
- jp nz,CheckMapConnections ; it seems like this check will never succeed (the other place where CheckMapConnections is run works)
-; walking animation finished
- ld a,[wd730]
- bit 7,a
- jr nz,.doneStepCounting ; if button presses are being simulated, don't count steps
-; step counting
- ld hl,wd13b ; step counter
- dec [hl]
- ld a,[wd72c]
- bit 0,a
- jr z,.doneStepCounting
- ld hl,wd13c
- dec [hl]
- jr nz,.doneStepCounting
- ld hl,wd72c
- res 0,[hl]
-.doneStepCounting
- ld a,[wd790]
- bit 7,a ; in the safari zone?
- jr z,.notSafariZone
- callba SafariZoneCheckSteps
- ld a,[wda46]
- and a
- jp nz,WarpFound2
-.notSafariZone
- ld a,[W_ISINBATTLE]
- and a
- jp nz,CheckWarpsNoCollision
- ld a,$13
- call Predef ; decrement HP of poisoned pokemon
- ld a,[wd12d]
- and a
- jp nz,HandleBlackOut ; if all pokemon fainted
-.newBattle
- call NewBattle
- ld hl,wd736
- res 2,[hl]
- jp nc,CheckWarpsNoCollision ; check for warps if there was no battle
-.battleOccurred
- ld hl,wd72d
- res 6,[hl]
- ld hl,W_FLAGS_D733
- res 3,[hl]
- ld hl,wd126
- set 5,[hl]
- set 6,[hl]
- xor a
- ld [hJoyHeld],a ; clear joypad state
- ld a,[W_CURMAP]
- cp a,CINNABAR_GYM
- jr nz,.notCinnabarGym
- ld hl,wd79b
- set 7,[hl]
-.notCinnabarGym
- ld hl,wd72e
- set 5,[hl]
- ld a,[W_CURMAP]
- cp a,OAKS_LAB
- jp z,.noFaintCheck
- callab AnyPlayerPokemonAliveCheck ; check if all the player's pokemon fainted
- ld a,d
- and a
- jr z,.allPokemonFainted
-.noFaintCheck
- ld c,$0a
- call DelayFrames
- jp EnterMap
-.allPokemonFainted
- ld a,$ff
- ld [W_ISINBATTLE],a
- call RunMapScript
- jp HandleBlackOut
-
-; function to determine if there will be a battle and execute it (either a trainer battle or wild battle)
-; sets carry if a battle occurred and unsets carry if not
-NewBattle:: ; 0683 (0:0683)
- ld a,[wd72d]
- bit 4,a
- jr nz,.noBattle
- call Func_30fd
- jr nz,.noBattle
- ld a,[wd72e]
- bit 4,a
- jr nz,.noBattle
- ld b, BANK(InitBattle)
- ld hl, InitBattle
- jp Bankswitch ; determines if a battle will occur and runs the battle if so
-.noBattle
- and a
- ret
-
-; function to make bikes twice as fast as walking
-BikeSpeedup:: ; 06a0 (0:06a0)
- ld a,[wcc57]
- and a
- ret nz
- ld a,[W_CURMAP]
- cp a,ROUTE_17 ; Cycling Road
- jr nz,.goFaster
- ld a,[hJoyHeld] ; current joypad state
- and a,%01110000 ; bit mask for up, left, right buttons
- ret nz
-.goFaster
- jp AdvancePlayerSprite
-
-; check if the player has stepped onto a warp after having not collided
-CheckWarpsNoCollision:: ; 06b4 (0:06b4)
- ld a,[wd3ae] ; number of warps
- and a
- jp z,CheckMapConnections
- ld a,[wd3ae] ; number of warps
- ld b,$00
- ld c,a
- ld a,[W_YCOORD]
- ld d,a
- ld a,[W_XCOORD]
- ld e,a
- ld hl,wd3af ; start of warp entries
-CheckWarpsNoCollisionLoop:: ; 06cc (0:06cc)
- ld a,[hli] ; check if the warp's Y position matches
- cp d
- jr nz,CheckWarpsNoCollisionRetry1
- ld a,[hli] ; check if the warp's X position matches
- cp e
- jr nz,CheckWarpsNoCollisionRetry2
-; if a match was found
- push hl
- push bc
- ld hl,wd736
- set 2,[hl]
- callba Func_c49d ; check if the player sprite is standing on a "door" tile
- pop bc
- pop hl
- jr c,WarpFound1 ; if it is, go to 0735
- push hl
- push bc
- call ExtraWarpCheck ; sets carry if the warp is confirmed
- pop bc
- pop hl
- jr nc,CheckWarpsNoCollisionRetry2
-; if the extra check passed
- ld a,[W_FLAGS_D733]
- bit 2,a
- jr nz,WarpFound1
- push de
- push bc
- call Joypad
- pop bc
- pop de
- ld a,[hJoyHeld] ; current joypad state
- and a,%11110000 ; bit mask for directional buttons
- jr z,CheckWarpsNoCollisionRetry2 ; if directional buttons aren't being pressed, do not pass through the warp
- jr WarpFound1
-
-; check if the player has stepped onto a warp after having collided
-CheckWarpsCollision:: ; 0706 (0:0706)
- ld a,[wd3ae] ; number of warps
- ld c,a
- ld hl,wd3af ; start of warp entries
-.loop
- ld a,[hli] ; Y coordinate of warp
- ld b,a
- ld a,[W_YCOORD]
- cp b
- jr nz,.retry1
- ld a,[hli] ; X coordinate of warp
- ld b,a
- ld a,[W_XCOORD]
- cp b
- jr nz,.retry2
- ld a,[hli]
- ld [wd42f],a ; save target warp ID
- ld a,[hl]
- ld [$ff8b],a ; save target map
- jr WarpFound2
-.retry1
- inc hl
-.retry2
- inc hl
- inc hl
- dec c
- jr nz,.loop
- jp OverworldLoop
-
-CheckWarpsNoCollisionRetry1:: ; 072f (0:072f)
- inc hl
-CheckWarpsNoCollisionRetry2:: ; 0730 (0:0730)
- inc hl
- inc hl
- jp ContinueCheckWarpsNoCollisionLoop
-
-WarpFound1:: ; 0735 (0:0735)
- ld a,[hli]
- ld [wd42f],a ; save target warp ID
- ld a,[hli]
- ld [$ff8b],a ; save target map
-
-WarpFound2:: ; 073c (0:073c)
- ld a,[wd3ae] ; number of warps
- sub c
- ld [wd73b],a ; save ID of used warp
- ld a,[W_CURMAP]
- ld [wd73c],a
- call CheckIfInOutsideMap
- jr nz,.indoorMaps
-; this is for handling "outside" maps that can't have the 0xFF destination map
- ld a,[W_CURMAP]
- ld [wLastMap],a
- ld a,[W_CURMAPWIDTH]
- ld [wd366],a
- ld a,[$ff8b] ; destination map number
- ld [W_CURMAP],a ; change current map to destination map
- cp a,ROCK_TUNNEL_1
- jr nz,.notRockTunnel
- ld a,$06
- ld [wd35d],a
- call GBFadeIn1
-.notRockTunnel
- call PlayMapChangeSound
- jr .done
-; for maps that can have the 0xFF destination map, which means to return to the outside map; not all these maps are necessarily indoors, though
-.indoorMaps
- ld a,[$ff8b] ; destination map
- cp a,$ff
- jr z,.goBackOutside
-; if not going back to the previous map
- ld [W_CURMAP],a ; current map number
- callba Func_70787 ; check if the warp was a Silph Co. teleporter
- ld a,[wcd5b]
- dec a
- jr nz,.notTeleporter
-; if it's a Silph Co. teleporter
- ld hl,wd732
- set 3,[hl]
- call DoFlyOrTeleportAwayGraphics
- jr .skipMapChangeSound
-.notTeleporter
- call PlayMapChangeSound
-.skipMapChangeSound
- ld hl,wd736
- res 0,[hl]
- res 1,[hl]
- jr .done
-.goBackOutside
- ld a,[wLastMap]
- ld [W_CURMAP],a
- call PlayMapChangeSound
- xor a
- ld [wd35d],a
-.done
- ld hl,wd736
- set 0,[hl]
- call Func_12da
- jp EnterMap
-
-ContinueCheckWarpsNoCollisionLoop:: ; 07b5 (0:07b5)
- inc b ; increment warp number
- dec c ; decrement number of warps
- jp nz,CheckWarpsNoCollisionLoop
-
-; if no matching warp was found
-CheckMapConnections:: ; 07ba (0:07ba)
-.checkWestMap
- ld a,[W_XCOORD]
- cp a,$ff
- jr nz,.checkEastMap
- ld a,[W_MAPCONN3PTR]
- ld [W_CURMAP],a
- ld a,[wd38f] ; new X coordinate upon entering west map
- ld [W_XCOORD],a
- ld a,[W_YCOORD]
- ld c,a
- ld a,[wd38e] ; Y adjustment upon entering west map
- add c
- ld c,a
- ld [W_YCOORD],a
- ld a,[wd390] ; pointer to upper left corner of map without adjustment for Y position
- ld l,a
- ld a,[wd391]
- ld h,a
- srl c
- jr z,.savePointer1
-.pointerAdjustmentLoop1
- ld a,[wd38d] ; width of connected map
- add a,$06
- ld e,a
- ld d,$00
- ld b,$00
- add hl,de
- dec c
- jr nz,.pointerAdjustmentLoop1
-.savePointer1
- ld a,l
- ld [wd35f],a ; pointer to upper left corner of current tile block map section
- ld a,h
- ld [wd360],a
- jp .loadNewMap
-.checkEastMap
- ld b,a
- ld a,[wd525] ; map width
- cp b
- jr nz,.checkNorthMap
- ld a,[W_MAPCONN4PTR]
- ld [W_CURMAP],a
- ld a,[wd39a] ; new X coordinate upon entering east map
- ld [W_XCOORD],a
- ld a,[W_YCOORD]
- ld c,a
- ld a,[wd399] ; Y adjustment upon entering east map
- add c
- ld c,a
- ld [W_YCOORD],a
- ld a,[wd39b] ; pointer to upper left corner of map without adjustment for Y position
- ld l,a
- ld a,[wd39c]
- ld h,a
- srl c
- jr z,.savePointer2
-.pointerAdjustmentLoop2
- ld a,[wd398]
- add a,$06
- ld e,a
- ld d,$00
- ld b,$00
- add hl,de
- dec c
- jr nz,.pointerAdjustmentLoop2
-.savePointer2
- ld a,l
- ld [wd35f],a ; pointer to upper left corner of current tile block map section
- ld a,h
- ld [wd360],a
- jp .loadNewMap
-.checkNorthMap
- ld a,[W_YCOORD]
- cp a,$ff
- jr nz,.checkSouthMap
- ld a,[W_MAPCONN1PTR]
- ld [W_CURMAP],a
- ld a,[wd378] ; new Y coordinate upon entering north map
- ld [W_YCOORD],a
- ld a,[W_XCOORD]
- ld c,a
- ld a,[wd379] ; X adjustment upon entering north map
- add c
- ld c,a
- ld [W_XCOORD],a
- ld a,[wd37a] ; pointer to upper left corner of map without adjustment for X position
- ld l,a
- ld a,[wd37b]
- ld h,a
- ld b,$00
- srl c
- add hl,bc
- ld a,l
- ld [wd35f],a ; pointer to upper left corner of current tile block map section
- ld a,h
- ld [wd360],a
- jp .loadNewMap
-.checkSouthMap
- ld b,a
- ld a,[wd524]
- cp b
- jr nz,.didNotEnterConnectedMap
- ld a,[W_MAPCONN2PTR]
- ld [W_CURMAP],a
- ld a,[wd383] ; new Y coordinate upon entering south map
- ld [W_YCOORD],a
- ld a,[W_XCOORD]
- ld c,a
- ld a,[wd384] ; X adjustment upon entering south map
- add c
- ld c,a
- ld [W_XCOORD],a
- ld a,[wd385] ; pointer to upper left corner of map without adjustment for X position
- ld l,a
- ld a,[wd386]
- ld h,a
- ld b,$00
- srl c
- add hl,bc
- ld a,l
- ld [wd35f],a ; pointer to upper left corner of current tile block map section
- ld a,h
- ld [wd360],a
-.loadNewMap ; load the connected map that was entered
- call LoadMapHeader
- call Func_2312 ; music
- ld b,$09
- call GoPAL_SET
-; Since the sprite set shouldn't change, this will just update VRAM slots at
-; $C2XE without loading any tile patterns.
- callba InitMapSprites
- call LoadTileBlockMap
- jp OverworldLoopLessDelay
-.didNotEnterConnectedMap
- jp OverworldLoop
-
-; function to play a sound when changing maps
-PlayMapChangeSound:: ; 08c9 (0:08c9)
- FuncCoord 8, 8
- ld a,[Coord] ; upper left tile of the 4x4 square the player's sprite is standing on
- cp a,$0b ; door tile in tileset 0
- jr nz,.didNotGoThroughDoor
- ld a,(SFX_02_57 - SFX_Headers_02) / 3
- jr .playSound
-.didNotGoThroughDoor
- ld a,(SFX_02_5c - SFX_Headers_02) / 3
-.playSound
- call PlaySound
- ld a,[wd35d]
- and a
- ret nz
- jp GBFadeIn1
-
-CheckIfInOutsideMap:: ; 08e1 (0:08e1)
-; If the player is in an outside map (a town or route), set the z flag
- ld a, [W_CURMAPTILESET]
- and a ; most towns/routes have tileset 0 (OVERWORLD)
- ret z
- cp PLATEAU ; Route 23 / Indigo Plateau
- ret
-
-; this function is an extra check that sometimes has to pass in order to warp, beyond just standing on a warp
-; the "sometimes" qualification is necessary because of CheckWarpsNoCollision's behavior
-; depending on the map, either "function 1" or "function 2" is used for the check
-; "function 1" passes when the player is at the edge of the map and is facing towards the outside of the map
-; "function 2" passes when the the tile in front of the player is among a certain set
-; sets carry if the check passes, otherwise clears carry
-ExtraWarpCheck:: ; 08e9 (0:08e9)
- ld a, [W_CURMAP]
- cp SS_ANNE_3
- jr z, .useFunction1
- cp ROCKET_HIDEOUT_1
- jr z, .useFunction2
- cp ROCKET_HIDEOUT_2
- jr z, .useFunction2
- cp ROCKET_HIDEOUT_4
- jr z, .useFunction2
- cp ROCK_TUNNEL_1
- jr z, .useFunction2
- ld a, [W_CURMAPTILESET]
- and a ; outside tileset (OVERWORLD)
- jr z, .useFunction2
- cp SHIP ; S.S. Anne tileset
- jr z, .useFunction2
- cp SHIP_PORT ; Vermilion Port tileset
- jr z, .useFunction2
- cp PLATEAU ; Indigo Plateau tileset
- jr z, .useFunction2
-.useFunction1
- ld hl, Func_c3ff
- jr .doBankswitch
-.useFunction2
- ld hl, Func_c44e
-.doBankswitch
- ld b, BANK(Func_c44e)
- jp Bankswitch
-
-MapEntryAfterBattle:: ; 091f (0:091f)
- callba Func_c35f ; function that appears to disable warp testing after collisions if the player is standing on a warp
- ld a,[wd35d]
- and a
- jp z,GBFadeIn2
- jp LoadGBPal
-
-HandleBlackOut::
-; For when all the player's pokemon faint.
-; Does not print the "blacked out" message.
-
- call GBFadeIn1
- ld a, $08
- call StopMusic
- ld hl, wd72e
- res 5, [hl]
- ld a, Bank(Func_40b0) ; also Bank(Func_62ce) and Bank(Func_5d5f)
- ld [H_LOADEDROMBANK], a
- ld [MBC3RomBank], a
- call Func_40b0
- call Func_62ce
- call Func_2312
- jp Func_5d5f
-
-StopMusic::
- ld [wMusicHeaderPointer], a
- ld a, $ff
- ld [wc0ee], a
- call PlaySound
-.wait
- ld a, [wMusicHeaderPointer]
- and a
- jr nz, .wait
- jp StopAllSounds
-
-HandleFlyOrTeleportAway::
- call UpdateSprites
- call Delay3
- xor a
- ld [wcf0b], a
- ld [wd700], a
- ld [W_ISINBATTLE], a
- ld [wd35d], a
- ld hl, wd732
- set 2, [hl]
- res 5, [hl]
- call DoFlyOrTeleportAwayGraphics
- ld a, Bank(Func_62ce)
- ld [H_LOADEDROMBANK], a
- ld [$2000], a
- call Func_62ce
- jp Func_5d5f
-
-DoFlyOrTeleportAwayGraphics::
- ld b, BANK(_DoFlyOrTeleportAwayGraphics)
- ld hl, _DoFlyOrTeleportAwayGraphics
- jp Bankswitch
-
-LoadPlayerSpriteGraphics::
-; Load sprite graphics based on whether the player is standing, biking, or surfing.
-
- ; 0: standing
- ; 1: biking
- ; 2: surfing
-
- ld a, [wd700]
- dec a
- jr z, .ridingBike
-
- ld a, [$ffd7]
- and a
- jr nz, .determineGraphics
- jr .startWalking
-
-.ridingBike
- ; If the bike can't be used,
- ; start walking instead.
- call IsBikeRidingAllowed
- jr c, .determineGraphics
-
-.startWalking
- xor a
- ld [wd700], a
- ld [wd11a], a
- jp LoadWalkingPlayerSpriteGraphics
-
-.determineGraphics
- ld a, [wd700]
- and a
- jp z, LoadWalkingPlayerSpriteGraphics
- dec a
- jp z, LoadBikePlayerSpriteGraphics
- dec a
- jp z, LoadSurfingPlayerSpriteGraphics
- jp LoadWalkingPlayerSpriteGraphics
-
-IsBikeRidingAllowed::
-; The bike can be used on Route 23 and Indigo Plateau,
-; or maps with tilesets in BikeRidingTilesets.
-; Return carry if biking is allowed.
-
- ld a, [W_CURMAP]
- cp ROUTE_23
- jr z, .allowed
- cp INDIGO_PLATEAU
- jr z, .allowed
-
- ld a, [W_CURMAPTILESET]
- ld b, a
- ld hl, BikeRidingTilesets
-.loop
- ld a, [hli]
- cp b
- jr z, .allowed
- inc a
- jr nz, .loop
- and a
- ret
-
-.allowed
- scf
- ret
-
-INCLUDE "data/bike_riding_tilesets.asm"
-
-; load the tile pattern data of the current tileset into VRAM
-LoadTilesetTilePatternData:: ; 09e8 (0:09e8)
- ld a,[W_TILESETGFXPTR]
- ld l,a
- ld a,[W_TILESETGFXPTR + 1]
- ld h,a
- ld de,vTileset
- ld bc,$600
- ld a,[W_TILESETBANK]
- jp FarCopyData2
-
-; this loads the current maps complete tile map (which references blocks, not individual tiles) to C6E8
-; it can also load partial tile maps of connected maps into a border of length 3 around the current map
-LoadTileBlockMap:: ; 09fc (0:09fc)
-; fill C6E8-CBFB with the background tile
- ld hl,wOverworldMap
- ld a,[wd3ad] ; background tile number
- ld d,a
- ld bc,$0514
-.backgroundTileLoop
- ld a,d
- ld [hli],a
- dec bc
- ld a,c
- or b
- jr nz,.backgroundTileLoop
-; load tile map of current map (made of tile block IDs)
-; a 3-byte border at the edges of the map is kept so that there is space for map connections
- ld hl,wOverworldMap
- ld a,[W_CURMAPWIDTH]
- ld [$ff8c],a
- add a,$06 ; border (east and west)
- ld [$ff8b],a ; map width + border
- ld b,$00
- ld c,a
-; make space for north border (next 3 lines)
- add hl,bc
- add hl,bc
- add hl,bc
- ld c,$03
- add hl,bc ; this puts us past the (west) border
- ld a,[W_MAPDATAPTR] ; tile map pointer
- ld e,a
- ld a,[W_MAPDATAPTR + 1]
- ld d,a ; de = tile map pointer
- ld a,[W_CURMAPHEIGHT]
- ld b,a
-.rowLoop ; copy one row each iteration
- push hl
- ld a,[$ff8c] ; map width (without border)
- ld c,a
-.rowInnerLoop
- ld a,[de]
- inc de
- ld [hli],a
- dec c
- jr nz,.rowInnerLoop
-; add the map width plus the border to the base address of the current row to get the next row's address
- pop hl
- ld a,[$ff8b] ; map width + border
- add l
- ld l,a
- jr nc,.noCarry
- inc h
-.noCarry
- dec b
- jr nz,.rowLoop
-.northConnection
- ld a,[W_MAPCONN1PTR]
- cp a,$ff
- jr z,.southConnection
- call SwitchToMapRomBank
- ld a,[wd372]
- ld l,a
- ld a,[wd373]
- ld h,a
- ld a,[wd374]
- ld e,a
- ld a,[wd375]
- ld d,a
- ld a,[wd376]
- ld [$ff8b],a
- ld a,[wd377]
- ld [$ff8c],a
- call LoadNorthSouthConnectionsTileMap
-.southConnection
- ld a,[W_MAPCONN2PTR]
- cp a,$ff
- jr z,.westConnection
- call SwitchToMapRomBank
- ld a,[wd37d]
- ld l,a
- ld a,[wd37e]
- ld h,a
- ld a,[wd37f]
- ld e,a
- ld a,[wd380]
- ld d,a
- ld a,[wd381]
- ld [$ff8b],a
- ld a,[wd382]
- ld [$ff8c],a
- call LoadNorthSouthConnectionsTileMap
-.westConnection
- ld a,[W_MAPCONN3PTR]
- cp a,$ff
- jr z,.eastConnection
- call SwitchToMapRomBank
- ld a,[wd388]
- ld l,a
- ld a,[wd389]
- ld h,a
- ld a,[wd38a]
- ld e,a
- ld a,[wd38b]
- ld d,a
- ld a,[wd38c]
- ld b,a
- ld a,[wd38d]
- ld [$ff8b],a
- call LoadEastWestConnectionsTileMap
-.eastConnection
- ld a,[W_MAPCONN4PTR]
- cp a,$ff
- jr z,.done
- call SwitchToMapRomBank
- ld a,[wd393]
- ld l,a
- ld a,[wd394]
- ld h,a
- ld a,[wd395]
- ld e,a
- ld a,[wd396]
- ld d,a
- ld a,[wd397]
- ld b,a
- ld a,[wd398]
- ld [$ff8b],a
- call LoadEastWestConnectionsTileMap
-.done
- ret
-
-LoadNorthSouthConnectionsTileMap:: ; 0ade (0:0ade)
- ld c,$03
-.loop
- push de
- push hl
- ld a,[$ff8b] ; width of connection
- ld b,a
-.innerLoop
- ld a,[hli]
- ld [de],a
- inc de
- dec b
- jr nz,.innerLoop
- pop hl
- pop de
- ld a,[$ff8c] ; width of connected map
- add l
- ld l,a
- jr nc,.noCarry1
- inc h
-.noCarry1
- ld a,[W_CURMAPWIDTH]
- add a,$06
- add e
- ld e,a
- jr nc,.noCarry2
- inc d
-.noCarry2
- dec c
- jr nz,.loop
- ret
-
-LoadEastWestConnectionsTileMap:: ; 0b02 (0:0b02)
- push hl
- push de
- ld c,$03
-.innerLoop
- ld a,[hli]
- ld [de],a
- inc de
- dec c
- jr nz,.innerLoop
- pop de
- pop hl
- ld a,[$ff8b] ; width of connected map
- add l
- ld l,a
- jr nc,.noCarry1
- inc h
-.noCarry1
- ld a,[W_CURMAPWIDTH]
- add a,$06
- add e
- ld e,a
- jr nc,.noCarry2
- inc d
-.noCarry2
- dec b
- jr nz,LoadEastWestConnectionsTileMap
- ret
-
-; function to check if there is a sign or sprite in front of the player
-; if so, it is stored in [$FF8C]
-; if not, [$FF8C] is set to 0
-IsSpriteOrSignInFrontOfPlayer:: ; 0b23 (0:0b23)
- xor a
- ld [$ff8c],a
- ld a,[wd4b0] ; number of signs in the map
- and a
- jr z,.extendRangeOverCounter
-; if there are signs
- ld a,$35
- call Predef ; get the coordinates in front of the player in de
- ld hl,wd4b1 ; start of sign coordinates
- ld a,[wd4b0] ; number of signs in the map
- ld b,a
- ld c,$00
-.signLoop
- inc c
- ld a,[hli] ; sign Y
- cp d
- jr z,.yCoordMatched
- inc hl
- jr .retry
-.yCoordMatched
- ld a,[hli] ; sign X
- cp e
- jr nz,.retry
-.xCoordMatched
-; found sign
- push hl
- push bc
- ld hl,wd4d1 ; start of sign text ID's
- ld b,$00
- dec c
- add hl,bc
- ld a,[hl]
- ld [$ff8c],a ; store sign text ID
- pop bc
- pop hl
- ret
-.retry
- dec b
- jr nz,.signLoop
-; check if the player is front of a counter in a pokemon center, pokemart, etc. and if so, extend the range at which he can talk to the NPC
-.extendRangeOverCounter
- ld a,$35
- call Predef ; get the tile in front of the player in c
- ld hl,W_TILESETTALKINGOVERTILES ; list of tiles that extend talking range (counter tiles)
- ld b,$03
- ld d,$20 ; talking range in pixels (long range)
-.counterTilesLoop
- ld a,[hli]
- cp c
- jr z,IsSpriteInFrontOfPlayer2 ; jumps if the tile in front of the player is a counter tile
- dec b
- jr nz,.counterTilesLoop
-
-; part of the above function, but sometimes its called on its own, when signs are irrelevant
-; the caller must zero [$FF8C]
-IsSpriteInFrontOfPlayer:: ; 0b6b (0:0b6b)
- ld d,$10 ; talking range in pixels (normal range)
-IsSpriteInFrontOfPlayer2:: ; 0b6d (0:0b6d)
- ld bc,$3c40 ; Y and X position of player sprite
- ld a,[wSpriteStateData1 + 9] ; direction the player is facing
-.checkIfPlayerFacingUp
- cp a,$04
- jr nz,.checkIfPlayerFacingDown
-; facing up
- ld a,b
- sub d
- ld b,a
- ld a,$08
- jr .doneCheckingDirection
-.checkIfPlayerFacingDown
- cp a,$00
- jr nz,.checkIfPlayerFacingRight
-; facing down
- ld a,b
- add d
- ld b,a
- ld a,$04
- jr .doneCheckingDirection
-.checkIfPlayerFacingRight
- cp a,$0c
- jr nz,.playerFacingLeft
-; facing right
- ld a,c
- add d
- ld c,a
- ld a,$01
- jr .doneCheckingDirection
-.playerFacingLeft
-; facing left
- ld a,c
- sub d
- ld c,a
- ld a,$02
-.doneCheckingDirection
- ld [wd52a],a
- ld a,[W_NUMSPRITES] ; number of sprites
- and a
- ret z
-; if there are sprites
- ld hl,wSpriteStateData1 + $10
- ld d,a
- ld e,$01
-.spriteLoop
- push hl
- ld a,[hli] ; image (0 if no sprite)
- and a
- jr z,.nextSprite
- inc l
- ld a,[hli] ; sprite visibility
- inc a
- jr z,.nextSprite
- inc l
- ld a,[hli] ; Y location
- cp b
- jr nz,.nextSprite
- inc l
- ld a,[hl] ; X location
- cp c
- jr z,.foundSpriteInFrontOfPlayer
-.nextSprite
- pop hl
- ld a,l
- add a,$10
- ld l,a
- inc e
- dec d
- jr nz,.spriteLoop
- ret
-.foundSpriteInFrontOfPlayer
- pop hl
- ld a,l
- and a,$f0
- inc a
- ld l,a
- set 7,[hl]
- ld a,e
- ld [$ff8c],a ; store sprite ID
- ret
-
-; function to check if the player will jump down a ledge and check if the tile ahead is passable (when not surfing)
-; sets the carry flag if there is a collision, and unsets it if there isn't a collision
-CollisionCheckOnLand:: ; 0bd1 (0:0bd1)
- ld a,[wd736]
- bit 6,a ; is the player jumping?
- jr nz,.noCollision
-; if not jumping a ledge
- ld a,[wcd38]
- and a
- jr nz,.noCollision
- ld a,[wd52a] ; the direction that the player is trying to go in
- ld d,a
- ld a,[wSpriteStateData1 + 12] ; the player sprite's collision data (bit field) (set in the sprite movement code)
- and d ; check if a sprite is in the direction the player is trying to go
- jr nz,.collision
- xor a
- ld [$ff8c],a
- call IsSpriteInFrontOfPlayer ; check for sprite collisions again? when does the above check fail to detect a sprite collision?
- ld a,[$ff8c]
- and a ; was there a sprite collision?
- jr nz,.collision
-; if no sprite collision
- ld hl,TilePairCollisionsLand
- call CheckForJumpingAndTilePairCollisions
- jr c,.collision
- call CheckTilePassable
- jr nc,.noCollision
-.collision
- ld a,[wc02a]
- cp a,(SFX_02_5b - SFX_Headers_02) / 3 ; check if collision sound is already playing
- jr z,.setCarry
- ld a,(SFX_02_5b - SFX_Headers_02) / 3
- call PlaySound ; play collision sound (if it's not already playing)
-.setCarry
- scf
- ret
-.noCollision
- and a
- ret
-
-; function that checks if the tile in front of the player is passable
-; clears carry if it is, sets carry if not
-CheckTilePassable:: ; 0c10 (0:0c10)
- ld a,$35
- call Predef ; get tile in front of player
- ld a,[wcfc6] ; tile in front of player
- ld c,a
- ld hl,W_TILESETCOLLISIONPTR ; pointer to list of passable tiles
- ld a,[hli]
- ld h,[hl]
- ld l,a ; hl now points to passable tiles
-.loop
- ld a,[hli]
- cp a,$ff
- jr z,.tileNotPassable
- cp c
- ret z
- jr .loop
-.tileNotPassable
- scf
- ret
-
-; check if the player is going to jump down a small ledge
-; and check for collisions that only occur between certain pairs of tiles
-; Input: hl - address of directional collision data
-; sets carry if there is a collision and unsets carry if not
-CheckForJumpingAndTilePairCollisions:: ; 0c2a (0:0c2a)
- push hl
- ld a,$35
- call Predef ; get the tile in front of the player
- push de
- push bc
- callba HandleLedges ; check if the player is trying to jump a ledge
- pop bc
- pop de
- pop hl
- and a
- ld a,[wd736]
- bit 6,a ; is the player jumping?
- ret nz
-; if not jumping
-
-Func_c44:: ; 0c44 (0:0c44)
- FuncCoord 8, 9
- ld a,[Coord] ; tile the player is on
- ld [wcf0e],a
-
-CheckForTilePairCollisions:: ; 0c4a (0:0c4a)
- ld a,[wcfc6] ; tile in front of the player
- ld c,a
-.tilePairCollisionLoop
- ld a,[W_CURMAPTILESET] ; tileset number
- ld b,a
- ld a,[hli]
- cp a,$ff
- jr z,.noMatch
- cp b
- jr z,.tilesetMatches
- inc hl
-.retry
- inc hl
- jr .tilePairCollisionLoop
-.tilesetMatches
- ld a,[wcf0e] ; tile the player is on
- ld b,a
- ld a,[hl]
- cp b
- jr z,.currentTileMatchesFirstInPair
- inc hl
- ld a,[hl]
- cp b
- jr z,.currentTileMatchesSecondInPair
- jr .retry
-.currentTileMatchesFirstInPair
- inc hl
- ld a,[hl]
- cp c
- jr z,.foundMatch
- jr .tilePairCollisionLoop
-.currentTileMatchesSecondInPair
- dec hl
- ld a,[hli]
- cp c
- inc hl
- jr nz,.tilePairCollisionLoop
-.foundMatch
- scf
- ret
-.noMatch
- and a
- ret
-
-; FORMAT: tileset number, tile 1, tile 2
-; terminated by 0xFF
-; these entries indicate that the player may not cross between tile 1 and tile 2
-; it's mainly used to simulate differences in elevation
-
-TilePairCollisionsLand:: ; 0c7e (0:0c7e)
- db CAVERN, $20, $05
- db CAVERN, $41, $05
- db FOREST, $30, $2E
- db CAVERN, $2A, $05
- db CAVERN, $05, $21
- db FOREST, $52, $2E
- db FOREST, $55, $2E
- db FOREST, $56, $2E
- db FOREST, $20, $2E
- db FOREST, $5E, $2E
- db FOREST, $5F, $2E
- db $FF
-
-TilePairCollisionsWater:: ; 0ca0 (0:0ca0)
- db FOREST, $14, $2E
- db FOREST, $48, $2E
- db CAVERN, $14, $05
- db $FF
-
-; this builds a tile map from the tile block map based on the current X/Y coordinates of the player's character
-LoadCurrentMapView:: ; 0caa (0:0caa)
- ld a,[H_LOADEDROMBANK]
- push af
- ld a,[W_TILESETBANK] ; tile data ROM bank
- ld [H_LOADEDROMBANK],a
- ld [$2000],a ; switch to ROM bank that contains tile data
- ld a,[wd35f] ; address of upper left corner of current map view
- ld e,a
- ld a,[wd360]
- ld d,a
- ld hl,wTileMapBackup
- ld b,$05
-.rowLoop ; each loop iteration fills in one row of tile blocks
- push hl
- push de
- ld c,$06
-.rowInnerLoop ; loop to draw each tile block of the current row
- push bc
- push de
- push hl
- ld a,[de]
- ld c,a ; tile block number
- call DrawTileBlock
- pop hl
- pop de
- pop bc
- inc hl
- inc hl
- inc hl
- inc hl
- inc de
- dec c
- jr nz,.rowInnerLoop
-; update tile block map pointer to next row's address
- pop de
- ld a,[W_CURMAPWIDTH]
- add a,$06
- add e
- ld e,a
- jr nc,.noCarry
- inc d
-.noCarry
-; update tile map pointer to next row's address
- pop hl
- ld a,$60
- add l
- ld l,a
- jr nc,.noCarry2
- inc h
-.noCarry2
- dec b
- jr nz,.rowLoop
- ld hl,wTileMapBackup
- ld bc,$0000
-.adjustForYCoordWithinTileBlock
- ld a,[W_YBLOCKCOORD]
- and a
- jr z,.adjustForXCoordWithinTileBlock
- ld bc,$0030
- add hl,bc
-.adjustForXCoordWithinTileBlock
- ld a,[W_XBLOCKCOORD]
- and a
- jr z,.copyToVisibleAreaBuffer
- ld bc,$0002
- add hl,bc
-.copyToVisibleAreaBuffer
- ld de,wTileMap ; base address for the tiles that are directly transfered to VRAM during V-blank
- ld b,$12
-.rowLoop2
- ld c,$14
-.rowInnerLoop2
- ld a,[hli]
- ld [de],a
- inc de
- dec c
- jr nz,.rowInnerLoop2
- ld a,$04
- add l
- ld l,a
- jr nc,.noCarry3
- inc h
-.noCarry3
- dec b
- jr nz,.rowLoop2
- pop af
- ld [H_LOADEDROMBANK],a
- ld [$2000],a ; restore previous ROM bank
- ret
-
-AdvancePlayerSprite:: ; 0d27 (0:0d27)
- ld a,[wSpriteStateData1 + 3] ; delta Y
- ld b,a
- ld a,[wSpriteStateData1 + 5] ; delta X
- ld c,a
- ld hl,wWalkCounter ; walking animation counter
- dec [hl]
- jr nz,.afterUpdateMapCoords
-; if it's the end of the animation, update the player's map coordinates
- ld a,[W_YCOORD]
- add b
- ld [W_YCOORD],a
- ld a,[W_XCOORD]
- add c
- ld [W_XCOORD],a
-.afterUpdateMapCoords
- ld a,[wWalkCounter] ; walking animation counter
- cp a,$07
- jp nz,.scrollBackgroundAndSprites
-; if this is the first iteration of the animation
- ld a,c
- cp a,$01
- jr nz,.checkIfMovingWest
-; moving east
- ld a,[wd526]
- ld e,a
- and a,$e0
- ld d,a
- ld a,e
- add a,$02
- and a,$1f
- or d
- ld [wd526],a
- jr .adjustXCoordWithinBlock
-.checkIfMovingWest
- cp a,$ff
- jr nz,.checkIfMovingSouth
-; moving west
- ld a,[wd526]
- ld e,a
- and a,$e0
- ld d,a
- ld a,e
- sub a,$02
- and a,$1f
- or d
- ld [wd526],a
- jr .adjustXCoordWithinBlock
-.checkIfMovingSouth
- ld a,b
- cp a,$01
- jr nz,.checkIfMovingNorth
-; moving south
- ld a,[wd526]
- add a,$40
- ld [wd526],a
- jr nc,.adjustXCoordWithinBlock
- ld a,[wd527]
- inc a
- and a,$03
- or a,$98
- ld [wd527],a
- jr .adjustXCoordWithinBlock
-.checkIfMovingNorth
- cp a,$ff
- jr nz,.adjustXCoordWithinBlock
-; moving north
- ld a,[wd526]
- sub a,$40
- ld [wd526],a
- jr nc,.adjustXCoordWithinBlock
- ld a,[wd527]
- dec a
- and a,$03
- or a,$98
- ld [wd527],a
-.adjustXCoordWithinBlock
- ld a,c
- and a
- jr z,.pointlessJump ; mistake?
-.pointlessJump
- ld hl,W_XBLOCKCOORD
- ld a,[hl]
- add c
- ld [hl],a
- cp a,$02
- jr nz,.checkForMoveToWestBlock
-; moved into the tile block to the east
- xor a
- ld [hl],a
- ld hl,wd4e3
- inc [hl]
- ld de,wd35f
- call MoveTileBlockMapPointerEast
- jr .updateMapView
-.checkForMoveToWestBlock
- cp a,$ff
- jr nz,.adjustYCoordWithinBlock
-; moved into the tile block to the west
- ld a,$01
- ld [hl],a
- ld hl,wd4e3
- dec [hl]
- ld de,wd35f
- call MoveTileBlockMapPointerWest
- jr .updateMapView
-.adjustYCoordWithinBlock
- ld hl,W_YBLOCKCOORD
- ld a,[hl]
- add b
- ld [hl],a
- cp a,$02
- jr nz,.checkForMoveToNorthBlock
-; moved into the tile block to the south
- xor a
- ld [hl],a
- ld hl,wd4e2
- inc [hl]
- ld de,wd35f
- ld a,[W_CURMAPWIDTH]
- call MoveTileBlockMapPointerSouth
- jr .updateMapView
-.checkForMoveToNorthBlock
- cp a,$ff
- jr nz,.updateMapView
-; moved into the tile block to the north
- ld a,$01
- ld [hl],a
- ld hl,wd4e2
- dec [hl]
- ld de,wd35f
- ld a,[W_CURMAPWIDTH]
- call MoveTileBlockMapPointerNorth
-.updateMapView
- call LoadCurrentMapView
- ld a,[wSpriteStateData1 + 3] ; delta Y
- cp a,$01
- jr nz,.checkIfMovingNorth2
-; if moving south
- call ScheduleSouthRowRedraw
- jr .scrollBackgroundAndSprites
-.checkIfMovingNorth2
- cp a,$ff
- jr nz,.checkIfMovingEast2
-; if moving north
- call ScheduleNorthRowRedraw
- jr .scrollBackgroundAndSprites
-.checkIfMovingEast2
- ld a,[wSpriteStateData1 + 5] ; delta X
- cp a,$01
- jr nz,.checkIfMovingWest2
-; if moving east
- call ScheduleEastColumnRedraw
- jr .scrollBackgroundAndSprites
-.checkIfMovingWest2
- cp a,$ff
- jr nz,.scrollBackgroundAndSprites
-; if moving west
- call ScheduleWestColumnRedraw
-.scrollBackgroundAndSprites
- ld a,[wSpriteStateData1 + 3] ; delta Y
- ld b,a
- ld a,[wSpriteStateData1 + 5] ; delta X
- ld c,a
- sla b
- sla c
- ld a,[$ffaf]
- add b
- ld [$ffaf],a ; update background scroll Y
- ld a,[$ffae]
- add c
- ld [$ffae],a ; update background scroll X
-; shift all the sprites in the direction opposite of the player's motion
-; so that the player appears to move relative to them
- ld hl,wSpriteStateData1 + $14
- ld a,[W_NUMSPRITES] ; number of sprites
- and a ; are there any sprites?
- jr z,.done
- ld e,a
-.spriteShiftLoop
- ld a,[hl]
- sub b
- ld [hli],a
- inc l
- ld a,[hl]
- sub c
- ld [hl],a
- ld a,$0e
- add l
- ld l,a
- dec e
- jr nz,.spriteShiftLoop
-.done
- ret
-
-; the following four functions are used to move the pointer to the upper left
-; corner of the tile block map in the direction of motion
-
-MoveTileBlockMapPointerEast:: ; 0e65 (0:0e65)
- ld a,[de]
- add a,$01
- ld [de],a
- ret nc
- inc de
- ld a,[de]
- inc a
- ld [de],a
- ret
-
-MoveTileBlockMapPointerWest:: ; 0e6f (0:0e6f)
- ld a,[de]
- sub a,$01
- ld [de],a
- ret nc
- inc de
- ld a,[de]
- dec a
- ld [de],a
- ret
-
-MoveTileBlockMapPointerSouth:: ; 0e79 (0:0e79)
- add a,$06
- ld b,a
- ld a,[de]
- add b
- ld [de],a
- ret nc
- inc de
- ld a,[de]
- inc a
- ld [de],a
- ret
-
-MoveTileBlockMapPointerNorth:: ; 0e85 (0:0e85)
- add a,$06
- ld b,a
- ld a,[de]
- sub b
- ld [de],a
- ret nc
- inc de
- ld a,[de]
- dec a
- ld [de],a
- ret
-
-; the following 6 functions are used to tell the V-blank handler to redraw
-; the portion of the map that was newly exposed due to the player's movement
-
-ScheduleNorthRowRedraw:: ; 0e91 (0:0e91)
- FuncCoord 0, 0
- ld hl,Coord
- call ScheduleRowRedrawHelper
- ld a,[wd526]
- ld [H_SCREENEDGEREDRAWADDR],a
- ld a,[wd527]
- ld [H_SCREENEDGEREDRAWADDR + 1],a
- ld a,REDRAWROW
- ld [H_SCREENEDGEREDRAW],a
- ret
-
-ScheduleRowRedrawHelper:: ; 0ea6 (0:0ea6)
- ld de,wScreenEdgeTiles
- ld c,$28
-.loop
- ld a,[hli]
- ld [de],a
- inc de
- dec c
- jr nz,.loop
- ret
-
-ScheduleSouthRowRedraw:: ; 0eb2 (0:0eb2)
- FuncCoord 0,16
- ld hl,Coord
- call ScheduleRowRedrawHelper
- ld a,[wd526]
- ld l,a
- ld a,[wd527]
- ld h,a
- ld bc,$0200
- add hl,bc
- ld a,h
- and a,$03
- or a,$98
- ld [H_SCREENEDGEREDRAWADDR + 1],a
- ld a,l
- ld [H_SCREENEDGEREDRAWADDR],a
- ld a,REDRAWROW
- ld [H_SCREENEDGEREDRAW],a
- ret
-
-ScheduleEastColumnRedraw:: ; 0ed3 (0:0ed3)
- FuncCoord 18,0
- ld hl,Coord
- call ScheduleColumnRedrawHelper
- ld a,[wd526]
- ld c,a
- and a,$e0
- ld b,a
- ld a,c
- add a,18
- and a,$1f
- or b
- ld [H_SCREENEDGEREDRAWADDR],a
- ld a,[wd527]
- ld [H_SCREENEDGEREDRAWADDR + 1],a
- ld a,REDRAWCOL
- ld [H_SCREENEDGEREDRAW],a
- ret
-
-ScheduleColumnRedrawHelper:: ; 0ef2 (0:0ef2)
- ld de,wScreenEdgeTiles
- ld c,$12
-.loop
- ld a,[hli]
- ld [de],a
- inc de
- ld a,[hl]
- ld [de],a
- inc de
- ld a,19
- add l
- ld l,a
- jr nc,.noCarry
- inc h
-.noCarry
- dec c
- jr nz,.loop
- ret
-
-ScheduleWestColumnRedraw:: ; 0f08 (0:0f08)
- FuncCoord 0,0
- ld hl,Coord
- call ScheduleColumnRedrawHelper
- ld a,[wd526]
- ld [H_SCREENEDGEREDRAWADDR],a
- ld a,[wd527]
- ld [H_SCREENEDGEREDRAWADDR + 1],a
- ld a,REDRAWCOL
- ld [H_SCREENEDGEREDRAW],a
- ret
-
-; function to write the tiles that make up a tile block to memory
-; Input: c = tile block ID, hl = destination address
-DrawTileBlock:: ; 0f1d (0:0f1d)
- push hl
- ld a,[W_TILESETBLOCKSPTR] ; pointer to tiles
- ld l,a
- ld a,[W_TILESETBLOCKSPTR + 1]
- ld h,a
- ld a,c
- swap a
- ld b,a
- and a,$f0
- ld c,a
- ld a,b
- and a,$0f
- ld b,a ; bc = tile block ID * 0x10
- add hl,bc
- ld d,h
- ld e,l ; de = address of the tile block's tiles
- pop hl
- ld c,$04 ; 4 loop iterations
-.loop ; each loop iteration, write 4 tile numbers
- push bc
- ld a,[de]
- ld [hli],a
- inc de
- ld a,[de]
- ld [hli],a
- inc de
- ld a,[de]
- ld [hli],a
- inc de
- ld a,[de]
- ld [hl],a
- inc de
- ld bc,$0015
- add hl,bc
- pop bc
- dec c
- jr nz,.loop
- ret
-
-; function to update joypad state and simulate button presses
-JoypadOverworld:: ; 0f4d (0:0f4d)
- xor a
- ld [wSpriteStateData1 + 3],a
- ld [wSpriteStateData1 + 5],a
- call RunMapScript
- call Joypad
- ld a,[W_FLAGS_D733]
- bit 3,a ; check if a trainer wants a challenge
- jr nz,.notForcedDownwards
- ld a,[W_CURMAP]
- cp a,ROUTE_17 ; Cycling Road
- jr nz,.notForcedDownwards
- ld a,[hJoyHeld] ; current joypad state
- and a,%11110011 ; bit mask for all directions and A/B
- jr nz,.notForcedDownwards
- ld a,%10000000 ; down pressed
- ld [hJoyHeld],a ; on the cycling road, if there isn't a trainer and the player isn't pressing buttons, simulate a down press
-.notForcedDownwards
- ld a,[wd730]
- bit 7,a
- ret z
-; if simulating button presses
- ld a,[hJoyHeld] ; current joypad state
- ld b,a
- ld a,[wcd3b] ; bit mask for button presses that override simulated ones
- and b
- ret nz ; return if the simulated button presses are overridden
- ld hl,wcd38 ; index of current simulated button press
- dec [hl]
- ld a,[hl]
- cp a,$ff
- jr z,.doneSimulating ; if the end of the simulated button presses has been reached
- ld hl,wccd3 ; base address of simulated button presses
-; add offset to base address
- add l
- ld l,a
- jr nc,.noCarry
- inc h
-.noCarry
- ld a,[hl]
- ld [hJoyHeld],a ; store simulated button press in joypad state
- and a
- ret nz
- ld [hJoyPressed],a
- ld [hJoyReleased],a
- ret
-; if done simulating button presses
-.doneSimulating
- xor a
- ld [wcd3a],a
- ld [wcd38],a
- ld [wccd3],a
- ld [wJoyIgnore],a
- ld [hJoyHeld],a
- ld hl,wd736
- ld a,[hl]
- and a,$f8
- ld [hl],a
- ld hl,wd730
- res 7,[hl]
- ret
-
-; function to check the tile ahead to determine if the character should get on land or keep surfing
-; sets carry if there is a collision and clears carry otherwise
-; It seems that this function has a bug in it, but due to luck, it doesn't
-; show up. After detecting a sprite collision, it jumps to the code that
-; checks if the next tile is passable instead of just directly jumping to the
-; "collision detected" code. However, it doesn't store the next tile in c,
-; so the old value of c is used. 2429 is always called before this function,
-; and 2429 always sets c to 0xF0. There is no 0xF0 background tile, so it
-; is considered impassable and it is detected as a collision.
-CollisionCheckOnWater:: ; 0fb7 (0:0fb7)
- ld a,[wd730]
- bit 7,a
- jp nz,.noCollision ; return and clear carry if button presses are being simulated
- ld a,[wd52a] ; the direction that the player is trying to go in
- ld d,a
- ld a,[wSpriteStateData1 + 12] ; the player sprite's collision data (bit field) (set in the sprite movement code)
- and d ; check if a sprite is in the direction the player is trying to go
- jr nz,.checkIfNextTileIsPassable ; bug?
- ld hl,TilePairCollisionsWater
- call CheckForJumpingAndTilePairCollisions
- jr c,.collision
- ld a,$35
- call Predef ; get tile in front of player (puts it in c and [wcfc6])
- ld a,[wcfc6] ; tile in front of player
- cp a,$14 ; water tile
- jr z,.noCollision ; keep surfing if it's a water tile
- cp a,$32 ; either the left tile of the S.S. Anne boarding platform or the tile on eastern coastlines (depending on the current tileset)
- jr z,.checkIfVermilionDockTileset
- cp a,$48 ; tile on right on coast lines in Safari Zone
- jr z,.noCollision ; keep surfing
-; check if the [land] tile in front of the player is passable
-.checkIfNextTileIsPassable
- ld hl,W_TILESETCOLLISIONPTR ; pointer to list of passable tiles
- ld a,[hli]
- ld h,[hl]
- ld l,a
-.loop
- ld a,[hli]
- cp a,$ff
- jr z,.collision
- cp c
- jr z,.stopSurfing ; stop surfing if the tile is passable
- jr .loop
-.collision
- ld a,[wc02a]
- cp a,(SFX_02_5b - SFX_Headers_02) / 3 ; check if collision sound is already playing
- jr z,.setCarry
- ld a,(SFX_02_5b - SFX_Headers_02) / 3
- call PlaySound ; play collision sound (if it's not already playing)
-.setCarry
- scf
- jr .done
-.noCollision
- and a
-.done
- ret
-.stopSurfing
- xor a
- ld [wd700],a
- call LoadPlayerSpriteGraphics
- call Func_2307
- jr .noCollision
-.checkIfVermilionDockTileset
- ld a, [W_CURMAPTILESET] ; tileset
- cp SHIP_PORT ; Vermilion Dock tileset
- jr nz, .noCollision ; keep surfing if it's not the boarding platform tile
- jr .stopSurfing ; if it is the boarding platform tile, stop surfing
-
-; function to run the current map's script
-RunMapScript:: ; 101b (0:101b)
- push hl
- push de
- push bc
- callba Func_f225 ; check if the player is pushing a boulder
- ld a,[wFlags_0xcd60]
- bit 1,a ; is the player pushing a boulder?
- jr z,.afterBoulderEffect
- callba Func_f2b5 ; displays dust effect when pushing a boulder
-.afterBoulderEffect
- pop bc
- pop de
- pop hl
- call Func_310e
- ld a,[W_CURMAP] ; current map number
- call SwitchToMapRomBank ; change to the ROM bank the map's data is in
- ld hl,W_MAPSCRIPTPTR
- ld a,[hli]
- ld h,[hl]
- ld l,a
- ld de,.return
- push de
- jp [hl] ; jump to script
-.return
- ret
-
-LoadWalkingPlayerSpriteGraphics:: ; 104d (0:104d)
- ld de,RedSprite ; $4180
- ld hl,vNPCSprites
- jr LoadPlayerSpriteGraphicsCommon
-
-LoadSurfingPlayerSpriteGraphics:: ; 1055 (0:1055)
- ld de,SeelSprite
- ld hl,vNPCSprites
- jr LoadPlayerSpriteGraphicsCommon
-
-LoadBikePlayerSpriteGraphics:: ; 105d (0:105d)
- ld de,RedCyclingSprite
- ld hl,vNPCSprites
-
-LoadPlayerSpriteGraphicsCommon:: ; 1063 (0:1063)
- push de
- push hl
- ld bc,(BANK(RedSprite) << 8) + $0c
- call CopyVideoData
- pop hl
- pop de
- ld a,$c0
- add e
- ld e,a
- jr nc,.noCarry
- inc d
-.noCarry
- set 3,h
- ld bc,$050c
- jp CopyVideoData
-
-; function to load data from the map header
-LoadMapHeader:: ; 107c (0:107c)
- callba Func_f113
- ld a,[W_CURMAPTILESET]
- ld [wd119],a
- ld a,[W_CURMAP]
- call SwitchToMapRomBank
- ld a,[W_CURMAPTILESET]
- ld b,a
- res 7,a
- ld [W_CURMAPTILESET],a
- ld [$ff8b],a
- bit 7,b
- ret nz
- ld hl,MapHeaderPointers
- ld a,[W_CURMAP]
- sla a
- jr nc,.noCarry1
- inc h
-.noCarry1
- add l
- ld l,a
- jr nc,.noCarry2
- inc h
-.noCarry2
- ld a,[hli]
- ld h,[hl]
- ld l,a ; hl = base of map header
-; copy the first 10 bytes (the fixed area) of the map data to D367-D370
- ld de,W_CURMAPTILESET
- ld c,$0a
-.copyFixedHeaderLoop
- ld a,[hli]
- ld [de],a
- inc de
- dec c
- jr nz,.copyFixedHeaderLoop
-; initialize all the connected maps to disabled at first, before loading the actual values
- ld a,$ff
- ld [W_MAPCONN1PTR],a
- ld [W_MAPCONN2PTR],a
- ld [W_MAPCONN3PTR],a
- ld [W_MAPCONN4PTR],a
-; copy connection data (if any) to WRAM
- ld a,[W_MAPCONNECTIONS]
- ld b,a
-.checkNorth
- bit 3,b
- jr z,.checkSouth
- ld de,W_MAPCONN1PTR
- call CopyMapConnectionHeader
-.checkSouth
- bit 2,b
- jr z,.checkWest
- ld de,W_MAPCONN2PTR
- call CopyMapConnectionHeader
-.checkWest
- bit 1,b
- jr z,.checkEast
- ld de,W_MAPCONN3PTR
- call CopyMapConnectionHeader
-.checkEast
- bit 0,b
- jr z,.getObjectDataPointer
- ld de,W_MAPCONN4PTR
- call CopyMapConnectionHeader
-.getObjectDataPointer
- ld a,[hli]
- ld [wd3a9],a
- ld a,[hli]
- ld [wd3aa],a
- push hl
- ld a,[wd3a9]
- ld l,a
- ld a,[wd3aa]
- ld h,a ; hl = base of object data
- ld de,wd3ad ; background tile ID
- ld a,[hli]
- ld [de],a ; save background tile ID
-.loadWarpData
- ld a,[hli] ; number of warps
- ld [wd3ae],a ; save the number of warps
- and a ; are there any warps?
- jr z,.loadSignData ; if not, skip this
- ld c,a
- ld de,wd3af ; base address of warps
-.warpLoop ; one warp per loop iteration
- ld b,$04
-.warpInnerLoop
- ld a,[hli]
- ld [de],a
- inc de
- dec b
- jr nz,.warpInnerLoop
- dec c
- jr nz,.warpLoop
-.loadSignData
- ld a,[hli] ; number of signs
- ld [wd4b0],a ; save the number of signs
- and a ; are there any signs?
- jr z,.loadSpriteData ; if not, skip this
- ld c,a
- ld de,wd4d1 ; base address of sign text IDs
- ld a,d
- ld [$ff95],a
- ld a,e
- ld [$ff96],a
- ld de,wd4b1 ; base address of sign coordinates
-.signLoop
- ld a,[hli]
- ld [de],a
- inc de
- ld a,[hli]
- ld [de],a
- inc de
- push de
- ld a,[$ff95]
- ld d,a
- ld a,[$ff96]
- ld e,a
- ld a,[hli]
- ld [de],a
- inc de
- ld a,d
- ld [$ff95],a
- ld a,e
- ld [$ff96],a
- pop de
- dec c
- jr nz,.signLoop
-.loadSpriteData
- ld a,[wd72e]
- bit 5,a ; did a battle happen immediately before this?
- jp nz,.finishUp ; if so, skip this because battles don't destroy this data
- ld a,[hli]
- ld [W_NUMSPRITES],a ; save the number of sprites
- push hl
-; zero C110-C1FF and C210-C2FF
- ld hl,wSpriteStateData1 + $10
- ld de,wSpriteStateData2 + $10
- xor a
- ld b,$f0
-.zeroSpriteDataLoop
- ld [hli],a
- ld [de],a
- inc e
- dec b
- jr nz,.zeroSpriteDataLoop
-; initialize all C100-C1FF sprite entries to disabled (other than player's)
- ld hl,wSpriteStateData1 + $12
- ld de,$0010
- ld c,$0f
-.disableSpriteEntriesLoop
- ld [hl],$ff
- add hl,de
- dec c
- jr nz,.disableSpriteEntriesLoop
- pop hl
- ld de,wSpriteStateData1 + $10
- ld a,[W_NUMSPRITES] ; number of sprites
- and a ; are there any sprites?
- jp z,.finishUp ; if there are no sprites, skip the rest
- ld b,a
- ld c,$00
-.loadSpriteLoop
- ld a,[hli]
- ld [de],a ; store picture ID at C1X0
- inc d
- ld a,$04
- add e
- ld e,a
- ld a,[hli]
- ld [de],a ; store Y position at C2X4
- inc e
- ld a,[hli]
- ld [de],a ; store X position at C2X5
- inc e
- ld a,[hli]
- ld [de],a ; store movement byte 1 at C2X6
- ld a,[hli]
- ld [$ff8d],a ; save movement byte 2
- ld a,[hli]
- ld [$ff8e],a ; save text ID and flags byte
- push bc
- push hl
- ld b,$00
- ld hl,W_MAPSPRITEDATA
- add hl,bc
- ld a,[$ff8d]
- ld [hli],a ; store movement byte 2 in byte 0 of sprite entry
- ld a,[$ff8e]
- ld [hl],a ; this appears pointless, since the value is overwritten immediately after
- ld a,[$ff8e]
- ld [$ff8d],a
- and a,$3f
- ld [hl],a ; store text ID in byte 1 of sprite entry
- pop hl
- ld a,[$ff8d]
- bit 6,a
- jr nz,.trainerSprite
- bit 7,a
- jr nz,.itemBallSprite
- jr .regularSprite
-.trainerSprite
- ld a,[hli]
- ld [$ff8d],a ; save trainer class
- ld a,[hli]
- ld [$ff8e],a ; save trainer number (within class)
- push hl
- ld hl,W_MAPSPRITEEXTRADATA
- add hl,bc
- ld a,[$ff8d]
- ld [hli],a ; store trainer class in byte 0 of the entry
- ld a,[$ff8e]
- ld [hl],a ; store trainer number in byte 1 of the entry
- pop hl
- jr .nextSprite
-.itemBallSprite
- ld a,[hli]
- ld [$ff8d],a ; save item number
- push hl
- ld hl,W_MAPSPRITEEXTRADATA
- add hl,bc
- ld a,[$ff8d]
- ld [hli],a ; store item number in byte 0 of the entry
- xor a
- ld [hl],a ; zero byte 1, since it is not used
- pop hl
- jr .nextSprite
-.regularSprite
- push hl
- ld hl,W_MAPSPRITEEXTRADATA
- add hl,bc
-; zero both bytes, since regular sprites don't use this extra space
- xor a
- ld [hli],a
- ld [hl],a
- pop hl
-.nextSprite
- pop bc
- dec d
- ld a,$0a
- add e
- ld e,a
- inc c
- inc c
- dec b
- jp nz,.loadSpriteLoop
-.finishUp
- ld a,$19
- call Predef ; load tileset data
- callab LoadWildData ; load wild pokemon data
- pop hl ; restore hl from before going to the warp/sign/sprite data (this value was saved for seemingly no purpose)
- ld a,[W_CURMAPHEIGHT] ; map height in 4x4 tile blocks
- add a ; double it
- ld [wd524],a ; store map height in 2x2 tile blocks
- ld a,[W_CURMAPWIDTH] ; map width in 4x4 tile blocks
- add a ; double it
- ld [wd525],a ; map width in 2x2 tile blocks
- ld a,[W_CURMAP]
- ld c,a
- ld b,$00
- ld a,[H_LOADEDROMBANK]
- push af
- ld a, BANK(MapSongBanks)
- ld [H_LOADEDROMBANK],a
- ld [$2000],a
- ld hl, MapSongBanks
- add hl,bc
- add hl,bc
- ld a,[hli]
- ld [wd35b],a ; music 1
- ld a,[hl]
- ld [wd35c],a ; music 2
- pop af
- ld [H_LOADEDROMBANK],a
- ld [$2000],a
- ret
-
-; function to copy map connection data from ROM to WRAM
-; Input: hl = source, de = destination
-CopyMapConnectionHeader:: ; 1238 (0:1238)
- ld c,$0b
-.loop
- ld a,[hli]
- ld [de],a
- inc de
- dec c
- jr nz,.loop
- ret
-
-; function to load map data
-LoadMapData:: ; 1241 (0:1241)
- ld a,[H_LOADEDROMBANK]
- push af
- call DisableLCD
- ld a,$98
- ld [wd527],a
- xor a
- ld [wd526],a
- ld [$ffaf],a
- ld [$ffae],a
- ld [wWalkCounter],a
- ld [wd119],a
- ld [wd11a],a
- ld [W_SPRITESETID],a
- call LoadTextBoxTilePatterns
- call LoadMapHeader
- callba InitMapSprites ; load tile pattern data for sprites
- call LoadTileBlockMap
- call LoadTilesetTilePatternData
- call LoadCurrentMapView
-; copy current map view to VRAM
- ld hl,wTileMap
- ld de,vBGMap0
- ld b,18
-.vramCopyLoop
- ld c,20
-.vramCopyInnerLoop
- ld a,[hli]
- ld [de],a
- inc e
- dec c
- jr nz,.vramCopyInnerLoop
- ld a,32 - 20
- add e
- ld e,a
- jr nc,.noCarry
- inc d
-.noCarry
- dec b
- jr nz,.vramCopyLoop
- ld a,$01
- ld [wcfcb],a
- call EnableLCD
- ld b,$09
- call GoPAL_SET
- call LoadPlayerSpriteGraphics
- ld a,[wd732]
- and a,$18 ; did the player fly or teleport in?
- jr nz,.restoreRomBank
- ld a,[W_FLAGS_D733]
- bit 1,a
- jr nz,.restoreRomBank
- call Func_235f ; music related
- call Func_2312 ; music related
-.restoreRomBank
- pop af
- ld [H_LOADEDROMBANK],a
- ld [$2000],a
- ret
-
-; function to switch to the ROM bank that a map is stored in
-; Input: a = map number
-SwitchToMapRomBank:: ; 12bc (0:12bc)
- push hl
- push bc
- ld c,a
- ld b,$00
- ld a,Bank(MapHeaderBanks)
- call BankswitchHome ; switch to ROM bank 3
- ld hl,MapHeaderBanks
- add hl,bc
- ld a,[hl]
- ld [$ffe8],a ; save map ROM bank
- call BankswitchBack
- ld a,[$ffe8]
- ld [H_LOADEDROMBANK],a
- ld [$2000],a ; switch to map ROM bank
- pop bc
- pop hl
- ret
-
-Func_12da:: ; 12da (0:12da)
- ld a, $1e
- ld [wd13a], a
- ld hl, wd730
- ld a, [hl]
- or $26
- ld [hl], a
- ret
-
-Func_12e7:: ; 12e7 (0:12e7)
- ld hl, wd728
- res 0, [hl]
- ret
-
-ForceBikeOrSurf:: ; 12ed (0:12ed)
- ld b, BANK(RedSprite)
- ld hl, LoadPlayerSpriteGraphics
- call Bankswitch
- jp Func_2307 ; update map/player state?
+INCLUDE "home/overworld.asm"
; this is used to check if the player wants to interrupt the opening sequence at several points
; XXX is this used anywhere else?
@@ -3365,75 +908,33 @@ InterlaceMergeSpriteBuffers:: ; 16ea (0:16ea)
ld b, a
jp CopyVideoData
-Underground_Coll:: ; 172f (0:172f)
- INCBIN "gfx/tilesets/underground.tilecoll"
-Overworld_Coll:: ; 1735 (0:1735)
- INCBIN "gfx/tilesets/overworld.tilecoll"
-RedsHouse1_Coll::
-RedsHouse2_Coll:: ; 1749 (0:1749)
- INCBIN "gfx/tilesets/reds_house.tilecoll"
-Mart_Coll
-Pokecenter_Coll:: ; 1753 (0:1753)
- INCBIN "gfx/tilesets/pokecenter.tilecoll"
-Dojo_Coll::
-Gym_Coll:: ; 1759 (0:1759)
- INCBIN "gfx/tilesets/gym.tilecoll"
-Forest_Coll:: ; 1765 (0:1765)
- INCBIN "gfx/tilesets/forest.tilecoll"
-House_Coll:: ; 1775 (0:1775)
- INCBIN "gfx/tilesets/house.tilecoll"
-ForestGate_Coll::
-Museum_Coll::
-Gate_Coll:: ; 177f (0:177f)
- INCBIN "gfx/tilesets/gate.tilecoll"
-Ship_Coll:: ; 178a (0:178a)
- INCBIN "gfx/tilesets/ship.tilecoll"
-ShipPort_Coll:: ; 1795 (0:1795)
- INCBIN "gfx/tilesets/ship_port.tilecoll"
-Cemetery_Coll:: ; 179a (0:179a)
- INCBIN "gfx/tilesets/cemetery.tilecoll"
-Interior_Coll:: ; 17a2 (0:17a2)
- INCBIN "gfx/tilesets/interior.tilecoll"
-Cavern_Coll:: ; 17ac (0:17ac)
- INCBIN "gfx/tilesets/cavern.tilecoll"
-Lobby_Coll:: ; 17b8 (0:17b8)
- INCBIN "gfx/tilesets/lobby.tilecoll"
-Mansion_Coll:: ; 17c0 (0:17c0)
- INCBIN "gfx/tilesets/mansion.tilecoll"
-Lab_Coll:: ; 17ca (0:17ca)
- INCBIN "gfx/tilesets/lab.tilecoll"
-Club_Coll:: ; 17d1 (0:17d1)
- INCBIN "gfx/tilesets/club.tilecoll"
-Facility_Coll:: ; 17dd (0:17dd)
- INCBIN "gfx/tilesets/facility.tilecoll"
-Plateau_Coll:: ; 17f0 (0:17f0)
- INCBIN "gfx/tilesets/plateau.tilecoll"
-
-; does the same thing as FarCopyData at 009D
-; only difference is that it uses [$ff8b] instead of [wHPBarMaxHP] for a temp value
-; copy bc bytes of data from a:hl to de
-FarCopyData2:: ; 17f7 (0:17f7)
+
+INCLUDE "data/collision.asm"
+
+
+FarCopyData2::
+; Identical to FarCopyData, but uses $ff8b
+; as temp space instead of wBuffer.
ld [$ff8b],a
ld a,[H_LOADEDROMBANK]
push af
ld a,[$ff8b]
ld [H_LOADEDROMBANK],a
- ld [$2000],a
+ ld [MBC3RomBank],a
call CopyData
pop af
ld [H_LOADEDROMBANK],a
- ld [$2000],a
+ ld [MBC3RomBank],a
ret
-; does a far copy but the source is de and the destination is hl
-; copy bc bytes of data from a:de to hl
-FarCopyData3:: ; 180d (0:180d)
+FarCopyData3::
+; Copy bc bytes from a:de to hl.
ld [$ff8b],a
ld a,[H_LOADEDROMBANK]
push af
ld a,[$ff8b]
ld [H_LOADEDROMBANK],a
- ld [$2000],a
+ ld [MBC3RomBank],a
push hl
push de
push de
@@ -3445,18 +946,18 @@ FarCopyData3:: ; 180d (0:180d)
pop hl
pop af
ld [H_LOADEDROMBANK],a
- ld [$2000],a
+ ld [MBC3RomBank],a
ret
-; copies each source byte to the destination twice (next to each other)
-; copy bc source bytes from a:hl to de
-FarCopyDataDouble:: ; 182b (0:182b)
+FarCopyDataDouble::
+; Expand bc bytes of 1bpp image data
+; from a:hl to 2bpp data at de.
ld [$ff8b],a
ld a,[H_LOADEDROMBANK]
push af
ld a,[$ff8b]
ld [H_LOADEDROMBANK],a
- ld [$2000],a
+ ld [MBC3RomBank],a
.loop
ld a,[hli]
ld [de],a
@@ -3469,1740 +970,184 @@ FarCopyDataDouble:: ; 182b (0:182b)
jr nz,.loop
pop af
ld [H_LOADEDROMBANK],a
- ld [$2000],a
+ ld [MBC3RomBank],a
ret
-; copy (c * 16) bytes from b:de to hl during V-blank
-; transfers up to 128 bytes per V-blank
-CopyVideoData:: ; 1848 (0:1848)
- ld a,[H_AUTOBGTRANSFERENABLED] ; save auto-transfer enabled flag
- push af
- xor a
- ld [H_AUTOBGTRANSFERENABLED],a ; disable auto-transfer while copying
- ld a,[H_LOADEDROMBANK]
- ld [$ff8b],a
- ld a,b
- ld [H_LOADEDROMBANK],a
- ld [$2000],a
- ld a,e
- ld [H_VBCOPYSRC],a
- ld a,d
- ld [H_VBCOPYSRC + 1],a
- ld a,l
- ld [H_VBCOPYDEST],a
- ld a,h
- ld [H_VBCOPYDEST + 1],a
-.loop
- ld a,c
- cp a,8 ; are there more than 128 bytes left to copy?
- jr nc,.copyMaxSize ; only copy up to 128 bytes at a time
-.copyRemainder
- ld [H_VBCOPYSIZE],a
- call DelayFrame ; wait for V-blank handler to perform the copy
- ld a,[$ff8b]
- ld [H_LOADEDROMBANK],a
- ld [$2000],a
- pop af
- ld [H_AUTOBGTRANSFERENABLED],a ; restore original auto-transfer enabled flag
- ret
-.copyMaxSize
- ld a,8 ; 128 bytes
- ld [H_VBCOPYSIZE],a
- call DelayFrame ; wait for V-blank handler to perform the copy
- ld a,c
- sub a,8
- ld c,a
- jr .loop
+CopyVideoData::
+; Wait for the next VBlank, then copy c 2bpp
+; tiles from b:de to hl, 8 tiles at a time.
+; This takes c/8 frames.
-; copy (c * 8) source bytes from b:de to hl during V-blank
-; copies each source byte to the destination twice (next to each other)
-; transfers up to 64 source bytes per V-blank
-CopyVideoDataDouble:: ; 1886 (0:1886)
- ld a,[H_AUTOBGTRANSFERENABLED] ; save auto-transfer enabled flag
+ ld a, [H_AUTOBGTRANSFERENABLED]
push af
- xor a
- ld [H_AUTOBGTRANSFERENABLED],a ; disable auto-transfer while copying
- ld a,[H_LOADEDROMBANK]
- ld [$ff8b],a
- ld a,b
- ld [H_LOADEDROMBANK],a
- ld [$2000],a
- ld a,e
- ld [H_VBCOPYDOUBLESRC],a
- ld a,d
- ld [H_VBCOPYDOUBLESRC + 1],a
- ld a,l
- ld [H_VBCOPYDOUBLEDEST],a
- ld a,h
- ld [H_VBCOPYDOUBLEDEST + 1],a
-.loop
- ld a,c
- cp a,8 ; are there more than 64 source bytes left to copy?
- jr nc,.copyMaxSize ; only copy up to 64 source bytes at a time
-.copyRemainder
- ld [H_VBCOPYDOUBLESIZE],a
- call DelayFrame ; wait for V-blank handler to perform the copy
- ld a,[$ff8b]
- ld [H_LOADEDROMBANK],a
- ld [$2000],a
- pop af
- ld [H_AUTOBGTRANSFERENABLED],a ; restore original auto-transfer enabled flag
- ret
-.copyMaxSize
- ld a,8 ; 64 source bytes
- ld [H_VBCOPYDOUBLESIZE],a
- call DelayFrame ; wait for V-blank handler to perform the copy
- ld a,c
- sub a,8
- ld c,a
- jr .loop
+ xor a ; disable auto-transfer while copying
+ ld [H_AUTOBGTRANSFERENABLED], a
-; clears an area of the screen
-; INPUT:
-; hl = address of upper left corner of the area
-; b = height
-; c = width
-ClearScreenArea:: ; 18c4 (0:18c4)
- ld a,$7F ; blank tile
- ld de,20 ; screen width
-.loop
- push hl
- push bc
-.innerLoop
- ld [hli],a
- dec c
- jr nz,.innerLoop
- pop bc
- pop hl
- add hl,de
- dec b
- jr nz,.loop
- ret
+ ld a, [H_LOADEDROMBANK]
+ ld [$ff8b], a
-; copies the screen tile buffer from WRAM to VRAM
-; copying is done in 3 chunks of 6 rows each
-; b: high byte of VRAM destination address ($98 or $9c for window tile map 0 or 1 resp.)
-CopyScreenTileBufferToVRAM:: ; 18d6 (0:18d6)
- ld c, $6
- ld hl, $0000
- ld de, wTileMap
- call InitScreenTileBufferTransferParameters
- call DelayFrame
- ld hl, $600
- ld de, wTileMap + 20 * 6
- call InitScreenTileBufferTransferParameters
- call DelayFrame
- ld hl, $c00
- ld de, wTileMap + 20 * 12
- call InitScreenTileBufferTransferParameters
- jp DelayFrame
+ ld a, b
+ ld [H_LOADEDROMBANK], a
+ ld [MBC3RomBank], a
-InitScreenTileBufferTransferParameters:: ; 18fc (0:18fc)
+ ld a, e
+ ld [H_VBCOPYSRC], a
ld a, d
- ld [H_VBCOPYBGSRC+1], a
- call GetRowColAddressBgMap
+ ld [H_VBCOPYSRC + 1], a
+
ld a, l
- ld [H_VBCOPYBGDEST], a ; $ffc3
+ ld [H_VBCOPYDEST], a
ld a, h
- ld [H_VBCOPYBGDEST+1], a
- ld a, c
- ld [H_VBCOPYBGNUMROWS], a ; $ffc5
- ld a, e
- ld [H_VBCOPYBGSRC], a ; $ffc1
- ret
-
-ClearScreen:: ; 190f (0:190f)
-; clears all tiles in the tilemap,
-; then wait three frames
- ld bc,$0168 ; tilemap size
- inc b
- ld hl,wTileMap ; TILEMAP_START
- ld a,$7F ; $7F is blank tile
-.loop
- ld [hli],a
- dec c
- jr nz,.loop
- dec b
- jr nz,.loop
- jp Delay3
-
-TextBoxBorder:: ; 1922 (0:1922)
-; draw a text box
-; upper-left corner at coordinates hl
-; height b
-; width c
-
- ; first row
- push hl
- ld a,"┌"
- ld [hli],a
- inc a ; horizontal border ─
- call NPlaceChar
- inc a ; upper-right border ┐
- ld [hl],a
-
- ; middle rows
- pop hl
- ld de,20
- add hl,de ; skip the top row
-
-.PlaceRow
- push hl
- ld a,"│"
- ld [hli],a
- ld a," "
- call NPlaceChar
- ld [hl],"│"
-
- pop hl
- ld de,20
- add hl,de ; move to next row
- dec b
- jr nz,.PlaceRow
+ ld [H_VBCOPYDEST + 1], a
- ; bottom row
- ld a,"└"
- ld [hli],a
- ld a,"─"
- call NPlaceChar
- ld [hl],"┘"
- ret
-;
-NPlaceChar:: ; 194f (0:194f)
-; place a row of width c of identical characters
- ld d,c
.loop
- ld [hli],a
- dec d
- jr nz,.loop
- ret
-
-PlaceString:: ; 1955 (0:1955)
- push hl
-PlaceNextChar:: ; 1956 (0:1956)
- ld a,[de]
-
- cp "@"
- jr nz,.PlaceText
- ld b,h
- ld c,l
- pop hl
- ret
-
-.PlaceText
- cp $4E
- jr nz,.next
- ld bc,$0028
- ld a,[$FFF6]
- bit 2,a
- jr z,.next2
- ld bc,$14
-.next2
- pop hl
- add hl,bc
- push hl
- jp Next19E8
-
-.next
- cp $4F
- jr nz,.next3
- pop hl
- FuncCoord 1, 16
- ld hl,Coord
- push hl
- jp Next19E8
-
-.next3 ; Check against a dictionary
- and a
- jp z,Char00
- cp $4C
- jp z,Char4C
- cp $4B
- jp z,Char4B
- cp $51
- jp z,Char51
- cp $49
- jp z,Char49
- cp $52
- jp z,Char52
- cp $53
- jp z,Char53
- cp $54
- jp z,Char54
- cp $5B
- jp z,Char5B
- cp $5E
- jp z,Char5E
- cp $5C
- jp z,Char5C
- cp $5D
- jp z,Char5D
- cp $55
- jp z,Char55
- cp $56
- jp z,Char56
- cp $57
- jp z,Char57
- cp $58
- jp z,Char58
- cp $4A
- jp z,Char4A
- cp $5F
- jp z,Char5F
- cp $59
- jp z,Char59
- cp $5A
- jp z,Char5A
- ld [hli],a
- call PrintLetterDelay
-Next19E8:: ; 19e8 (0:19e8)
- inc de
- jp PlaceNextChar
-
-Char00:: ; 19ec (0:19ec)
- ld b,h
- ld c,l
- pop hl
- ld de,Char00Text
- dec de
- ret
-
-Char00Text:: ; 0x19f4 “%d ERROR.”
- TX_FAR _Char00Text
- db "@"
-
-Char52:: ; 0x19f9 player’s name
- push de
- ld de,W_PLAYERNAME
- jr FinishDTE
-
-Char53:: ; 19ff (0:19ff) ; rival’s name
- push de
- ld de,W_RIVALNAME
- jr FinishDTE
-
-Char5D:: ; 1a05 (0:1a05) ; TRAINER
- push de
- ld de,Char5DText
- jr FinishDTE
-
-Char5C:: ; 1a0b (0:1a0b) ; TM
- push de
- ld de,Char5CText
- jr FinishDTE
-
-Char5B:: ; 1a11 (0:1a11) ; PC
- push de
- ld de,Char5BText
- jr FinishDTE
-
-Char5E:: ; 1a17 (0:1a17) ; ROCKET
- push de
- ld de,Char5EText
- jr FinishDTE
-
-Char54:: ; 1a1d (0:1a1d) ; POKé
- push de
- ld de,Char54Text
- jr FinishDTE
-
-Char56:: ; 1a23 (0:1a23) ; ……
- push de
- ld de,Char56Text
- jr FinishDTE
-
-Char4A:: ; 1a29 (0:1a29) ; PKMN
- push de
- ld de,Char4AText
- jr FinishDTE
-
-Char59:: ; 1a2f (0:1a2f)
-; depending on whose turn it is, print
-; enemy active monster’s name, prefixed with “Enemy ”
-; or
-; player active monster’s name
-; (like Char5A but flipped)
- ld a,[H_WHOSETURN]
- xor 1
- jr MonsterNameCharsCommon
-
-Char5A:: ; 1a35 (0:1a35)
-; depending on whose turn it is, print
-; player active monster’s name
-; or
-; enemy active monster’s name, prefixed with “Enemy ”
- ld a,[H_WHOSETURN]
-MonsterNameCharsCommon:: ; 1a37 (0:1a37)
- push de
- and a
- jr nz,.Enemy
- ld de,W_PLAYERMONNAME ; player active monster name
- jr FinishDTE
-
-.Enemy ; 1A40
- ; print “Enemy ”
- ld de,Char5AText
- call PlaceString
-
- ld h,b
- ld l,c
- ld de,W_ENEMYMONNAME ; enemy active monster name
-
-FinishDTE:: ; 1a4b (0:1a4b)
- call PlaceString
- ld h,b
- ld l,c
- pop de
- inc de
- jp PlaceNextChar
-
-Char5CText:: ; 1a55 (0:1a55)
- db "TM@"
-Char5DText:: ; 1a58 (0:1a58)
- db "TRAINER@"
-Char5BText:: ; 1a60 (0:1a60)
- db "PC@"
-Char5EText:: ; 1a63 (0:1a63)
- db "ROCKET@"
-Char54Text:: ; 1a6a (0:1a6a)
- db "POKé@"
-Char56Text:: ; 1a6f (0:1a6f)
- db "……@"
-Char5AText:: ; 1a72 (0:1a72)
- db "Enemy @"
-Char4AText:: ; 1a79 (0:1a79)
- db $E1,$E2,"@" ; PKMN
-
-Char55:: ; 1a7c (0:1a7c)
- push de
- ld b,h
- ld c,l
- ld hl,Char55Text
- call TextCommandProcessor
- ld h,b
- ld l,c
- pop de
- inc de
- jp PlaceNextChar
-
-Char55Text:: ; 1a8c (0:1a8c)
-; equivalent to Char4B
- TX_FAR _Char55Text
- db "@"
+ ld a, c
+ cp 8
+ jr nc, .keepgoing
-Char5F:: ; 1a91 (0:1a91)
-; ends a Pokédex entry
- ld [hl],"."
- pop hl
+.done
+ ld [H_VBCOPYSIZE], a
+ call DelayFrame
+ ld a, [$ff8b]
+ ld [H_LOADEDROMBANK], a
+ ld [MBC3RomBank], a
+ pop af
+ ld [H_AUTOBGTRANSFERENABLED], a
ret
-Char58:: ; 1a95 (0:1a95)
- ld a,[W_ISLINKBATTLE]
- cp 4
- jp z,Next1AA2
- ld a,$EE
- FuncCoord 18, 16
- ld [Coord],a
-Next1AA2:: ; 1aa2 (0:1aa2)
- call ProtectedDelay3
- call ManualTextScroll
- ld a,$7F
- FuncCoord 18, 16
- ld [Coord],a
-Char57:: ; 1aad (0:1aad)
- pop hl
- ld de,Char58Text
- dec de
- ret
+.keepgoing
+ ld a, 8
+ ld [H_VBCOPYSIZE], a
+ call DelayFrame
+ ld a, c
+ sub 8
+ ld c, a
+ jr .loop
-Char58Text:: ; 1ab3 (0:1ab3)
- db "@"
+CopyVideoDataDouble::
+; Wait for the next VBlank, then copy c 1bpp
+; tiles from b:de to hl, 8 tiles at a time.
+; This takes c/8 frames.
+ ld a, [H_AUTOBGTRANSFERENABLED]
+ push af
+ xor a ; disable auto-transfer while copying
+ ld [H_AUTOBGTRANSFERENABLED], a
+ ld a, [H_LOADEDROMBANK]
+ ld [$ff8b], a
-Char51:: ; 1ab4 (0:1ab4)
- push de
- ld a,$EE
- FuncCoord 18, 16
- ld [Coord],a
- call ProtectedDelay3
- call ManualTextScroll
- FuncCoord 1, 13
- ld hl,Coord
- ld bc,$0412
- call ClearScreenArea
- ld c,$14
- call DelayFrames
- pop de
- FuncCoord 1, 14
- ld hl,Coord
- jp Next19E8
+ ld a, b
+ ld [H_LOADEDROMBANK], a
+ ld [MBC3RomBank], a
-Char49:: ; 1ad5 (0:1ad5)
- push de
- ld a,$EE
- FuncCoord 18, 16
- ld [Coord],a
- call ProtectedDelay3
- call ManualTextScroll
- FuncCoord 1, 10
- ld hl,Coord
- ld bc,$0712
- call ClearScreenArea
- ld c,$14
- call DelayFrames
- pop de
- pop hl
- FuncCoord 1, 11
- ld hl,Coord
- push hl
- jp Next19E8
+ ld a, e
+ ld [H_VBCOPYDOUBLESRC], a
+ ld a, d
+ ld [H_VBCOPYDOUBLESRC + 1], a
-Char4B:: ; 1af8 (0:1af8)
- ld a,$EE
- FuncCoord 18, 16
- ld [Coord],a
- call ProtectedDelay3
- push de
- call ManualTextScroll
- pop de
- ld a,$7F
- FuncCoord 18, 16
- ld [Coord],a
- ;fall through
-Char4C:: ; 1b0a (0:1b0a)
- push de
- call Next1B18
- call Next1B18
- FuncCoord 1, 16
- ld hl,Coord
- pop de
- jp Next19E8
+ ld a, l
+ ld [H_VBCOPYDOUBLEDEST], a
+ ld a, h
+ ld [H_VBCOPYDOUBLEDEST + 1], a
-Next1B18:: ; 1b18 (0:1b18)
- FuncCoord 0, 14
- ld hl,Coord
- FuncCoord 0, 13
- ld de,Coord
- ld b,$3C
-.next
- ld a,[hli]
- ld [de],a
- inc de
- dec b
- jr nz,.next
- FuncCoord 1, 16
- ld hl,Coord
- ld a,$7F
- ld b,$12
-.next2
- ld [hli],a
- dec b
- jr nz,.next2
+.loop
+ ld a, c
+ cp 8
+ jr nc, .keepgoing
- ; wait five frames
- ld b,5
-.WaitFrame
+.done
+ ld [H_VBCOPYDOUBLESIZE], a
call DelayFrame
- dec b
- jr nz,.WaitFrame
-
- ret
-
-ProtectedDelay3:: ; 1b3a (0:1b3a)
- push bc
- call Delay3
- pop bc
- ret
-
-TextCommandProcessor:: ; 1b40 (0:1b40)
- ld a,[wd358]
- push af
- set 1,a
- ld e,a
- ld a,[$fff4]
- xor e
- ld [wd358],a
- ld a,c
- ld [wcc3a],a
- ld a,b
- ld [wcc3b],a
-
-NextTextCommand:: ; 1b55 (0:1b55)
- ld a,[hli]
- cp a, "@" ; terminator
- jr nz,.doTextCommand
+ ld a, [$ff8b]
+ ld [H_LOADEDROMBANK], a
+ ld [MBC3RomBank], a
pop af
- ld [wd358],a
+ ld [H_AUTOBGTRANSFERENABLED], a
ret
-.doTextCommand
- push hl
- cp a,$17
- jp z,TextCommand17
- cp a,$0e
- jp nc,TextCommand0B ; if a != 0x17 and a >= 0xE, go to command 0xB
-; if a < 0xE, use a jump table
- ld hl,TextCommandJumpTable
- push bc
- add a
- ld b,$00
- ld c,a
- add hl,bc
- pop bc
- ld a,[hli]
- ld h,[hl]
- ld l,a
- jp [hl]
-
-; draw box
-; 04AAAABBCC
-; AAAA = address of upper left corner
-; BB = height
-; CC = width
-TextCommand04:: ; 1b78 (0:1b78)
- pop hl
- ld a,[hli]
- ld e,a
- ld a,[hli]
- ld d,a
- ld a,[hli]
- ld b,a
- ld a,[hli]
- ld c,a
- push hl
- ld h,d
- ld l,e
- call TextBoxBorder
- pop hl
- jr NextTextCommand
-
-; place string inline
-; 00{string}
-TextCommand00:: ; 1b8a (0:1b8a)
- pop hl
- ld d,h
- ld e,l
- ld h,b
- ld l,c
- call PlaceString
- ld h,d
- ld l,e
- inc hl
- jr NextTextCommand
-
-; place string from RAM
-; 01AAAA
-; AAAA = address of string
-TextCommand01:: ; 1b97 (0:1b97)
- pop hl
- ld a,[hli]
- ld e,a
- ld a,[hli]
- ld d,a
- push hl
- ld h,b
- ld l,c
- call PlaceString
- pop hl
- jr NextTextCommand
-
-; print BCD number
-; 02AAAABB
-; AAAA = address of BCD number
-; BB
-; bits 0-4 = length in bytes
-; bits 5-7 = unknown flags
-TextCommand02:: ; 1ba5 (0:1ba5)
- pop hl
- ld a,[hli]
- ld e,a
- ld a,[hli]
- ld d,a
- ld a,[hli]
- push hl
- ld h,b
- ld l,c
- ld c,a
- call PrintBCDNumber
- ld b,h
- ld c,l
- pop hl
- jr NextTextCommand
-
-; repoint destination address
-; 03AAAA
-; AAAA = new destination address
-TextCommand03:: ; 1bb7 (0:1bb7)
- pop hl
- ld a,[hli]
- ld [wcc3a],a
- ld c,a
- ld a,[hli]
- ld [wcc3b],a
- ld b,a
- jp NextTextCommand
-
-; repoint destination to second line of dialogue text box
-; 05
-; (no arguments)
-TextCommand05:: ; 1bc5 (0:1bc5)
- pop hl
- FuncCoord 1, 16
- ld bc,Coord ; address of second line of dialogue text box
- jp NextTextCommand
-
-; blink arrow and wait for A or B to be pressed
-; 06
-; (no arguments)
-TextCommand06:: ; 1bcc (0:1bcc)
- ld a,[W_ISLINKBATTLE]
- cp a,$04
- jp z,TextCommand0D
- ld a,$ee ; down arrow
- FuncCoord 18, 16
- ld [Coord],a ; place down arrow in lower right corner of dialogue text box
- push bc
- call ManualTextScroll ; blink arrow and wait for A or B to be pressed
- pop bc
- ld a," "
- FuncCoord 18, 16
- ld [Coord],a ; overwrite down arrow with blank space
- pop hl
- jp NextTextCommand
-
-; scroll text up one line
-; 07
-; (no arguments)
-TextCommand07:: ; 1be7 (0:1be7)
- ld a," "
- FuncCoord 18, 16
- ld [Coord],a ; place blank space in lower right corner of dialogue text box
- call Next1B18 ; scroll up text
- call Next1B18
- pop hl
- FuncCoord 1, 16
- ld bc,Coord ; address of second line of dialogue text box
- jp NextTextCommand
-
-; execute asm inline
-; 08{code}
-TextCommand08:: ; 1bf9 (0:1bf9)
- pop hl
- ld de,NextTextCommand
- push de ; return address
- jp [hl]
-
-; print decimal number (converted from binary number)
-; 09AAAABB
-; AAAA = address of number
-; BB
-; bits 0-3 = how many digits to display
-; bits 4-7 = how long the number is in bytes
-TextCommand09:: ; 1bff (0:1bff)
- pop hl
- ld a,[hli]
- ld e,a
- ld a,[hli]
- ld d,a
- ld a,[hli]
- push hl
- ld h,b
- ld l,c
- ld b,a
- and a,$0f
- ld c,a
- ld a,b
- and a,$f0
- swap a
- set 6,a
- ld b,a
- call PrintNumber
- ld b,h
- ld c,l
- pop hl
- jp NextTextCommand
-
-; wait half a second if the user doesn't hold A or B
-; 0A
-; (no arguments)
-TextCommand0A:: ; 1c1d (0:1c1d)
- push bc
- call Joypad
- ld a,[hJoyHeld]
- and a,%00000011 ; A and B buttons
- jr nz,.skipDelay
- ld c,30
- call DelayFrames
-.skipDelay
- pop bc
- pop hl
- jp NextTextCommand
-; plays sounds
-; this actually handles various command ID's, not just 0B
-; (no arguments)
-TextCommand0B:: ; 1c31 (0:1c31)
- pop hl
- push bc
- dec hl
- ld a,[hli]
- ld b,a ; b = command number that got us here
- push hl
- ld hl,TextCommandSounds
-.loop
- ld a,[hli]
- cp b
- jr z,.matchFound
- inc hl
+.keepgoing
+ ld a, 8
+ ld [H_VBCOPYDOUBLESIZE], a
+ call DelayFrame
+ ld a, c
+ sub 8
+ ld c, a
jr .loop
-.matchFound
- cp a,$14
- jr z,.pokemonCry
- cp a,$15
- jr z,.pokemonCry
- cp a,$16
- jr z,.pokemonCry
- ld a,[hl]
- call PlaySound
- call WaitForSoundToFinish
- pop hl
- pop bc
- jp NextTextCommand
-.pokemonCry
- push de
- ld a,[hl]
- call PlayCry
- pop de
- pop hl
- pop bc
- jp NextTextCommand
-
-; format: text command ID, sound ID or cry ID
-TextCommandSounds:: ; 1c64 (0:1c64)
- db $0B,(SFX_02_3a - SFX_Headers_02) / 3
- db $12,(SFX_02_46 - SFX_Headers_02) / 3
- db $0E,(SFX_02_41 - SFX_Headers_02) / 3
- db $0F,(SFX_02_3a - SFX_Headers_02) / 3
- db $10,(SFX_02_3b - SFX_Headers_02) / 3
- db $11,(SFX_02_42 - SFX_Headers_02) / 3
- db $13,(SFX_02_44 - SFX_Headers_02) / 3
- db $14,NIDORINA ; used in OakSpeech
- db $15,PIDGEOT ; used in SaffronCityText12
- db $16,DEWGONG ; unused?
-
-; draw ellipses
-; 0CAA
-; AA = number of ellipses to draw
-TextCommand0C:: ; 1c78 (0:1c78)
- pop hl
- ld a,[hli]
- ld d,a
- push hl
- ld h,b
- ld l,c
-.loop
- ld a,$75 ; ellipsis
- ld [hli],a
- push de
- call Joypad
- pop de
- ld a,[hJoyHeld] ; joypad state
- and a,%00000011 ; is A or B button pressed?
- jr nz,.skipDelay ; if so, skip the delay
- ld c,10
- call DelayFrames
-.skipDelay
- dec d
- jr nz,.loop
- ld b,h
- ld c,l
- pop hl
- jp NextTextCommand
-; wait for A or B to be pressed
-; 0D
-; (no arguments)
-TextCommand0D:: ; 1c9a (0:1c9a)
+ClearScreenArea::
+; Clear tilemap area cxb at hl.
+ ld a, $7f ; blank tile
+ ld de, 20 ; screen width
+.y
+ push hl
push bc
- call ManualTextScroll ; wait for A or B to be pressed
+.x
+ ld [hli], a
+ dec c
+ jr nz, .x
pop bc
pop hl
- jp NextTextCommand
-
-; process text commands in another ROM bank
-; 17AAAABB
-; AAAA = address of text commands
-; BB = bank
-TextCommand17:: ; 1ca3 (0:1ca3)
- pop hl
- ld a,[H_LOADEDROMBANK]
- push af
- ld a,[hli]
- ld e,a
- ld a,[hli]
- ld d,a
- ld a,[hli]
- ld [H_LOADEDROMBANK],a
- ld [$2000],a
- push hl
- ld l,e
- ld h,d
- call TextCommandProcessor
- pop hl
- pop af
- ld [H_LOADEDROMBANK],a
- ld [$2000],a
- jp NextTextCommand
-
-TextCommandJumpTable:: ; 1cc1 (0:1cc1)
- dw TextCommand00
- dw TextCommand01
- dw TextCommand02
- dw TextCommand03
- dw TextCommand04
- dw TextCommand05
- dw TextCommand06
- dw TextCommand07
- dw TextCommand08
- dw TextCommand09
- dw TextCommand0A
- dw TextCommand0B
- dw TextCommand0C
- dw TextCommand0D
-
-; 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
-
-; unrolled loop and using pop for speed
-TransferBgRows:: ; 1d9e (0:1d9e)
- pop de
- ld [hl],e
- inc l
- ld [hl],d
- inc l
- pop de
- ld [hl],e
- inc l
- ld [hl],d
- inc l
- pop de
- ld [hl],e
- inc l
- ld [hl],d
- inc l
- pop de
- ld [hl],e
- inc l
- ld [hl],d
- inc l
- pop de
- ld [hl],e
- inc l
- ld [hl],d
- inc l
- pop de
- ld [hl],e
- inc l
- ld [hl],d
- inc l
- pop de
- ld [hl],e
- inc l
- ld [hl],d
- inc l
- pop de
- ld [hl],e
- inc l
- ld [hl],d
- inc l
- pop de
- ld [hl],e
- inc l
- ld [hl],d
- inc l
- pop de
- ld [hl],e
- inc l
- ld [hl],d
- ld a,13
- add l
- ld l,a
- jr nc,.noCarry
- inc h
-.noCarry
+ add hl, de
dec b
- jr nz,TransferBgRows
- ld a,[H_SPTEMP]
- ld h,a
- ld a,[H_SPTEMP + 1]
- ld l,a
- ld sp,hl ; restore stack pointer
+ jr nz, .y
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
+CopyScreenTileBufferToVRAM::
+; Copy wTileMap to the BG Map starting at b * $100.
+; This is done in thirds of 6 rows, so it takes 3 frames.
- 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 c, 6
- 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
+ ld hl, $600 * 0
+ ld de, wTileMap + 20 * 6 * 0
+ call .setup
+ call DelayFrame
- 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 hl, $600 * 1
+ ld de, wTileMap + 20 * 6 * 1
+ call .setup
+ call DelayFrame
- ld a, l
- ld [H_VBCOPYDOUBLEDEST], a
- ld a, h
- ld [H_VBCOPYDOUBLEDEST + 1], a
+ ld hl, $600 * 2
+ ld de, wTileMap + 20 * 6 * 2
+ call .setup
+ jp DelayFrame
- ld hl, [sp + 0]
+.setup
+ ld a, d
+ ld [H_VBCOPYBGSRC+1], a
+ call GetRowColAddressBgMap
ld a, l
- ld [H_VBCOPYDOUBLESRC], a
+ ld [H_VBCOPYBGDEST], 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
-
+ ld [H_VBCOPYBGDEST+1], a
+ ld a, c
+ ld [H_VBCOPYBGNUMROWS], a
+ ld a, e
+ ld [H_VBCOPYBGSRC], a
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
-
+ClearScreen::
+; Clear wTileMap, then wait
+; for the bg map to update.
+ ld bc, 20 * 18
+ inc b
+ ld hl, wTileMap
+ ld a, $7f
.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 20
- ret c
- cp 21
- 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, wc000 ; 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
- ; XXX this is a hack--rgbasm adds
- ; a nop after halts by default.
- db $76 ; halt
-
- ld a, [H_VBLANKOCCURRED]
- and a
- jr nz, .halt
- ret
-
-
-; These routines manage gradual fading
-; (e.g., entering a doorway)
-LoadGBPal:: ; 20ba (0:20ba)
- ld a,[wd35d] ;tells if cur.map is dark (requires HM5_FLASH?)
- ld b,a
- ld hl,GBPalTable_00 ;16
- ld a,l
- sub b
- ld l,a
- jr nc,.jr0
- dec h
-.jr0
- ld a,[hli]
- ld [rBGP],a
- ld a,[hli]
- ld [rOBP0],a
- ld a,[hli]
- ld [rOBP1],a
- ret
-
-GBFadeOut1:: ; 20d1 (0:20d1)
- ld hl,IncGradGBPalTable_01 ;0d
- ld b,$04
- jr GBFadeOutCommon
-
-GBFadeOut2:: ; 20d8 (0:20d8)
- ld hl,IncGradGBPalTable_02 ;1c
- ld b,$03
-
-GBFadeOutCommon:: ; 20dd (0:20dd)
- 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
+ jr nz, .loop
+ jp Delay3
-GBFadeIn1:: ; 20ef (0:20ef)
- ld hl,DecGradGBPalTable_01 ;18
- ld b,$04
- jr GBFadeInCommon
-GBFadeIn2:: ; 20f6 (0:20f6)
- ld hl,DecGradGBPalTable_02 ;21
- ld b,$03
+INCLUDE "home/text.asm"
+INCLUDE "home/vcopy.asm"
+INCLUDE "home/init.asm"
+INCLUDE "home/vblank.asm"
+INCLUDE "home/fade.asm"
-GBFadeInCommon:: ; 20fb (0:20fb)
- 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
-
-IncGradGBPalTable_01:: ; 210d (0:210d)
- db %11111111 ;BG Pal
- db %11111111 ;OBJ Pal 1
- db %11111111 ;OBJ Pal 2
- ;and so on...
- db %11111110
- db %11111110
- db %11111000
-
- db %11111001
- db %11100100
- db %11100100
-GBPalTable_00:: ; 2116 (0:2116)
- db %11100100
- db %11010000
-DecGradGBPalTable_01:: ; 2118 (0:2118)
- db %11100000
- ;19
- db %11100100
- db %11010000
- db %11100000
-IncGradGBPalTable_02:: ; 211c (0:211c)
- db %10010000
- db %10000000
- db %10010000
-
- db %01000000
- db %01000000
-DecGradGBPalTable_02:: ; 2121 (0:2121)
- db %01000000
-
- db %00000000
- db %00000000
- db %00000000
Serial:: ; 2125 (0:2125)
push af
@@ -5509,193 +1454,14 @@ Func_22fa:: ; 22fa (0:22fa)
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
-
-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
+INCLUDE "home/audio.asm"
-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]
@@ -5747,597 +1513,9 @@ Predef5CText:: ; 24f4 (0:24f4)
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
-
-; 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
+INCLUDE "home/pic.asm"
-; 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
@@ -9982,56 +5160,7 @@ Random::
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)