ref: 7c34b9d74b12d9d70cbf8cb2eb71feaef6e55756
parent: 9ebed58a93e79bf3511e340bfb33890fada43a85
author: YamaArashi <devnull@localhost>
date: Sun Jan 22 10:03:57 EST 2012
disasm of 39e-12da hg-commit-id: fccdbeaf9091
--- a/common.asm
+++ b/common.asm
@@ -364,7 +364,2417 @@
dw Bruno_h
dw Agatha_h ;247
-INCBIN "baserom.gbc",$39E,$1627 - $39E
+; this function calls a function that takes necessary actions
+; at the beginning of each overworld loop iteration as the player jumps
+; down a ledge
+; it also ends the jump when it's completed
+HandleMidJump: ; 39E
+ ld b,$1c
+ ld hl,$487e
+ jp Bankswitch
+
+; this is jumped to immediately after loading a save / starting a new game / loading a new map
+EnterMap: ; 3A6
+ ld a,$ff
+ ld [$cd6b],a
+ call LoadMapData ; load map data
+ ld b,$03
+ ld hl,$4335
+ call Bankswitch ; initialize some variables
+ ld hl,$d72c
+ bit 0,[hl]
+ jr z,.doNotCountSteps\@
+ ld a,$03
+ ld [$d13c],a ; some kind of step counter (counts up to 3 steps?)
+.doNotCountSteps\@
+ ld hl,$d72e
+ bit 5,[hl] ; did a battle happen immediately before this?
+ res 5,[hl] ; unset the "battle just happened" flag
+ call z,$12e7
+ call nz,MapEntryAfterBattle
+ ld hl,$d732
+ ld a,[hl]
+ and a,$18
+ jr z,.didNotFlyOrTeleportIn\@
+ res 3,[hl]
+ ld b,$1c
+ ld hl,$4510
+ call Bankswitch ; display fly/teleport in graphical effect
+ call $2429 ; move sprites
+.didNotFlyOrTeleportIn\@
+ ld b,$03
+ ld hl,$438b
+ call Bankswitch ; handle currents in SF islands and forced bike riding in cycling road
+ ld hl,$d72d
+ res 5,[hl]
+ call $2429 ; move sprites
+ ld hl,$d126
+ set 5,[hl]
+ set 6,[hl]
+ xor a
+ ld [$cd6b],a
+
+OverworldLoop: ; 3FF
+ call DelayFrame
+OverworldLoopLessDelay:
+ call DelayFrame
+ call LoadGBPal
+ ld a,[$d736]
+ bit 6,a ; jumping down a ledge?
+ call nz,$039e
+ ld a,[$cfc5] ; walking animation counter
+ and a
+ jp nz,.moveAhead\@ ; if the player sprite has not yet completed the walking animation
+ call GetJoypadStateOverworld ; get joypad state (which is possibly simulated)
+ ld b,$07
+ ld hl,$6988
+ call Bankswitch
+ ld a,[$da46]
+ and a
+ jp nz,WarpFound2
+ ld hl,$d72d
+ bit 3,[hl]
+ res 3,[hl]
+ jp nz,WarpFound2
+ ld a,[$d732]
+ and a,$18
+ jp nz,HandleFlyOrTeleportAway
+ ld a,[W_CUROPPONENT]
+ and a
+ jp nz,.newBattle\@
+ ld a,[$d730]
+ bit 7,a ; are we simulating button presses?
+ jr z,.notSimulating\@
+ ld a,[$ffb4]
+ jr .checkIfStartIsPressed\@
+.notSimulating\@
+ ld a,[$ffb3]
+.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,[$d730]
+ bit 2,a
+ jp nz,.noDirectionButtonsPressed\@
+ call $30fd
+ jr nz,.checkForOpponent\@
+ call $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 $2429 ; move sprites
+ ld a,[$cd60]
+ bit 2,a
+ jr nz,.checkForOpponent\@
+ bit 0,a
+ jr nz,.checkForOpponent\@
+ ld a,[$c45c]
+ ld [$cf0e],a
+ call $2920 ; display either the start menu or the NPC/sign text
+ ld a,[$cc47]
+ and a
+ jr z,.checkForOpponent\@
+ dec a
+ ld a,$00
+ ld [$cc47],a
+ jr z,.changeMap\@
+ ld a,$52
+ call Predef
+ ld a,[W_CURMAP]
+ ld [$d71a],a
+ call $62ce
+ ld a,[W_CURMAP]
+ call SwitchToMapRomBank ; switch to the ROM bank of the current map
+ ld hl,$d367
+ set 7,[hl]
+.changeMap\@
+ jp EnterMap
+.checkForOpponent\@
+ ld a,[W_CUROPPONENT]
+ and a
+ jp nz,.newBattle\@
+ jp OverworldLoop
+.noDirectionButtonsPressed\@
+ ld hl,$cd60
+ res 2,[hl]
+ call $2429 ; move sprites
+ ld a,$01
+ ld [$cc4b],a
+ ld a,[$d528] ; the direction that was pressed last time
+ and a
+ jp z,OverworldLoop
+; if a direction was pressed last time
+ ld [$d529],a ; save the last direction
+ xor a
+ ld [$d528],a ; zero the direction
+ jp OverworldLoop
+.checkIfDownButtonIsPressed\@
+ ld a,[$ffb4] ; current joypad state
+ bit 7,a ; down button
+ jr z,.checkIfUpButtonIsPressed\@
+ ld a,$01
+ ld [$c103],a
+ ld a,$04
+ jr .handleDirectionButtonPress\@
+.checkIfUpButtonIsPressed\@
+ bit 6,a ; up button
+ jr z,.checkIfLeftButtonIsPressed\@
+ ld a,$ff
+ ld [$c103],a
+ ld a,$08
+ jr .handleDirectionButtonPress\@
+.checkIfLeftButtonIsPressed\@
+ bit 5,a ; left button
+ jr z,.checkIfRightButtonIsPressed\@
+ ld a,$ff
+ ld [$c105],a
+ ld a,$02
+ jr .handleDirectionButtonPress\@
+.checkIfRightButtonIsPressed\@
+ bit 4,a ; right button
+ jr z,.noDirectionButtonsPressed\@
+ ld a,$01
+ ld [$c105],a
+.handleDirectionButtonPress\@
+ ld [$d52a],a ; new direction
+ ld a,[$d730]
+ bit 7,a ; are we simulating button presses?
+ jr nz,.noDirectionChange\@ ; ignore direction changes if we are
+ ld a,[$cc4b]
+ and a
+ jr z,.noDirectionChange\@
+ ld a,[$d52a] ; new direction
+ ld b,a
+ ld a,[$d529] ; 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 [$d528],a
+ jr .oddLoop\@
+.notDownToUp\@
+ cp a,$84 ; change dir from up to down
+ jr nz,.notUpToDown\@
+ ld a,$01
+ ld [$d528],a
+ jr .oddLoop\@
+.notUpToDown\@
+ cp a,$12 ; change dir from right to left
+ jr nz,.notRightToLeft\@
+ ld a,$04
+ ld [$d528],a
+ jr .oddLoop\@
+.notRightToLeft\@
+ cp a,$21 ; change dir from left to right
+ jr nz,.oddLoop\@
+ ld a,$08
+ ld [$d528],a
+.oddLoop\@
+ ld hl,$cd60
+ set 2,[hl]
+ ld hl,$cc4b
+ dec [hl]
+ jr nz,.oddLoop\@
+ ld a,[$d52a]
+ ld [$d528],a
+ call $0683
+ jp c,$0637
+ jp OverworldLoop
+.noDirectionChange\@
+ ld a,[$d52a] ; current direction
+ ld [$d528],a ; save direction
+ call $2429 ; move sprites
+ ld a,[$d700]
+ cp a,$02 ; surfing
+ jr z,.surfing\@
+; not surfing
+ call CollisionCheckOnLand
+ jr nc,.noCollision\@
+ push hl
+ ld hl,$d736
+ 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 [$cfc5],a ; walking animation counter
+ jr .moveAhead2\@
+.moveAhead\@
+ ld a,[$d736]
+ bit 7,a
+ jr z,.noSpinning\@
+ ld b,$11
+ ld hl,$4fd7
+ call Bankswitch ; spin while moving
+.noSpinning\@
+ call $2429 ; move sprites
+.moveAhead2\@
+ ld hl,$cd60
+ res 2,[hl]
+ ld a,[$d700]
+ dec a ; riding a bike?
+ jr nz,.normalPlayerSpriteAdvancement\@
+ ld a,[$d736]
+ 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,[$cfc5] ; walking animation counter
+ 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,[$d730]
+ bit 7,a
+ jr nz,.doneStepCounting\@ ; if button presses are being simulated, don't count steps
+; step counting
+ ld hl,$d13b ; step counter
+ dec [hl]
+ ld a,[$d72c]
+ bit 0,a
+ jr z,.doneStepCounting\@
+ ld hl,$d13c
+ dec [hl]
+ jr nz,.doneStepCounting\@
+ ld hl,$d72c
+ res 0,[hl]
+.doneStepCounting\@
+ ld a,[$d790]
+ bit 7,a ; in the safari zone?
+ jr z,.notSafariZone\@
+ ld b,$07
+ ld hl,$6997
+ call Bankswitch
+ ld a,[$da46]
+ 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,[$d12d]
+ and a
+ jp nz,HandleBlackOut ; if all pokemon fainted
+.newBattle\@
+ call NewBattle
+ ld hl,$d736
+ res 2,[hl]
+ jp nc,CheckWarpsNoCollision ; check for warps if there was no battle
+; if a battle occurred
+ ld hl,$d72d
+ res 6,[hl]
+ ld hl,$d733
+ res 3,[hl]
+ ld hl,$d126
+ set 5,[hl]
+ set 6,[hl]
+ xor a
+ ld [$ffb4],a ; clear joypad state
+ ld a,[W_CURMAP]
+ cp a,CINNABAR_GYM
+ jr nz,.notCinnabarGyn\@
+ ld hl,$d79b
+ set 7,[hl]
+.notCinnabarGyn\@
+ ld hl,$d72e
+ set 5,[hl]
+ ld a,[W_CURMAP]
+ cp a,OAKS_LAB
+ jp z,.noFaintCheck\@
+ ld hl,$4a83
+ ld b,$0f
+ call Bankswitch ; 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 [$d057],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: ; 683
+ ld a,[$d72d]
+ bit 4,a
+ jr nz,.noBattle\@
+ call $30fd
+ jr nz,.noBattle\@
+ ld a,[$d72e]
+ bit 4,a
+ jr nz,.noBattle\@
+ ld b,$0f
+ ld hl,$6f12
+ jp Bankswitch ; determines if a battle will occurr and runs the battle if so
+.noBattle\@
+ and a
+ ret
+
+; function to make bikes twice as fast as walking
+BikeSpeedup: ; 6A0
+ ld a,[$cc57]
+ and a
+ ret nz
+ ld a,[W_CURMAP]
+ cp a,ROUTE_17 ; Cycling Road
+ jr nz,.goFaster\@
+ ld a,[$ffb4] ; 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: ; 6B4
+ ld a,[$d3ae] ; number of warps
+ and a
+ jp z,CheckMapConnections
+ ld a,[$d3ae] ; 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,$d3af ; start of warp entries
+CheckWarpsNoCollisionLoop: ; 6CC
+ 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,$d736
+ set 2,[hl]
+ ld b,$03
+ ld hl,$449d
+ call Bankswitch ; 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,[$d733]
+ bit 2,a
+ jr nz,WarpFound1
+ push de
+ push bc
+ call $019a ; update joypad state
+ pop bc
+ pop de
+ ld a,[$ffb4] ; 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: ; 706
+ ld a,[$d3ae] ; number of warps
+ ld c,a
+ ld hl,$d3af ; 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 [$d42f],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: ; 72F
+ inc hl
+CheckWarpsNoCollisionRetry2: ; 730
+ inc hl
+ inc hl
+ jp ContinueCheckWarpsNoCollisionLoop
+
+WarpFound1: ; 735
+ ld a,[hli]
+ ld [$d42f],a ; save target warp ID
+ ld a,[hli]
+ ld [$ff8b],a ; save target map
+
+WarpFound2: ; 73C
+ ld a,[$d3ae] ; number of warps
+ sub c
+ ld [$d73b],a ; save ID of used warp
+ ld a,[W_CURMAP]
+ ld [$d73c],a
+ call CheckIfInOutsideMap ; check if the tileset number is 0 or the map is Route 12
+ jr nz,.indoorMaps\@
+; this is for handling "outside" maps that can't have the 0xFF destination map
+ ld a,[W_CURMAP]
+ ld [$d365],a ; save current map as previous map
+ ld a,[W_CURMAPWIDTH]
+ ld [$d366],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 [$d35d],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
+ ld b,$1c
+ ld hl,$4787
+ call Bankswitch ; check if the warp was a Silph Co. teleporter
+ ld a,[$cd5b]
+ dec a
+ jr nz,.notTeleporter\@
+; if it's a Silph Co. teleporter
+ ld hl,$d732
+ set 3,[hl]
+ call DoFlyOrTeleportAwayGraphics
+ jr .skipMapChangeSound\@
+.notTeleporter\@
+ call PlayMapChangeSound
+.skipMapChangeSound\@
+ ld hl,$d736
+ res 0,[hl]
+ res 1,[hl]
+ jr .done\@
+.goBackOutside\@
+ ld a,[$d365] ; previous map
+ ld [W_CURMAP],a
+ call PlayMapChangeSound
+ xor a
+ ld [$d35d],a
+.done\@
+ ld hl,$d736
+ set 0,[hl]
+ call $12da
+ jp EnterMap
+
+ContinueCheckWarpsNoCollisionLoop: ; 7B5
+ inc b ; increment warp number
+ dec c ; decrement number of warps
+ jp nz,CheckWarpsNoCollisionLoop
+
+; if no matching warp was found
+CheckMapConnections: ; 7BA
+.checkWestMap\@
+ ld a,[W_XCOORD]
+ cp a,$ff
+ jr nz,.checkEastMap\@
+ ld a,[$d387]
+ ld [W_CURMAP],a
+ ld a,[$d38f] ; new X coordinate upon entering west map
+ ld [W_XCOORD],a
+ ld a,[W_YCOORD]
+ ld c,a
+ ld a,[$d38e] ; Y adjustment upon entering west map
+ add c
+ ld c,a
+ ld [W_YCOORD],a
+ ld a,[$d390] ; pointer to upper left corner of map without adjustment for Y position
+ ld l,a
+ ld a,[$d391]
+ ld h,a
+ srl c
+ jr z,.savePointer1\@
+.pointerAdjustmentLoop1\@
+ ld a,[$d38d] ; 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 [$d35f],a ; pointer to upper left corner of current tile block map section
+ ld a,h
+ ld [$d360],a
+ jp .loadNewMap\@
+.checkEastMap\@
+ ld b,a
+ ld a,[$d525] ; map width
+ cp b
+ jr nz,.checkNorthMap\@
+ ld a,[$d392]
+ ld [W_CURMAP],a
+ ld a,[$d39a] ; new X coordinate upon entering east map
+ ld [W_XCOORD],a
+ ld a,[W_YCOORD]
+ ld c,a
+ ld a,[$d399] ; Y adjustment upon entering east map
+ add c
+ ld c,a
+ ld [W_YCOORD],a
+ ld a,[$d39b] ; pointer to upper left corner of map without adjustment for Y position
+ ld l,a
+ ld a,[$d39c]
+ ld h,a
+ srl c
+ jr z,.savePointer2\@
+.pointerAdjustmentLoop2\@
+ ld a,[$d398]
+ 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 [$d35f],a ; pointer to upper left corner of current tile block map section
+ ld a,h
+ ld [$d360],a
+ jp .loadNewMap\@
+.checkNorthMap\@
+ ld a,[W_YCOORD]
+ cp a,$ff
+ jr nz,.checkSouthMap\@
+ ld a,[$d371]
+ ld [W_CURMAP],a
+ ld a,[$d378] ; new Y coordinate upon entering north map
+ ld [W_YCOORD],a
+ ld a,[W_XCOORD]
+ ld c,a
+ ld a,[$d379] ; X adjustment upon entering north map
+ add c
+ ld c,a
+ ld [W_XCOORD],a
+ ld a,[$d37a] ; pointer to upper left corner of map without adjustment for X position
+ ld l,a
+ ld a,[$d37b]
+ ld h,a
+ ld b,$00
+ srl c
+ add hl,bc
+ ld a,l
+ ld [$d35f],a ; pointer to upper left corner of current tile block map section
+ ld a,h
+ ld [$d360],a
+ jp .loadNewMap\@
+.checkSouthMap\@
+ ld b,a
+ ld a,[$d524]
+ cp b
+ jr nz,.didNotEnterConnectedMap\@
+ ld a,[$d37c]
+ ld [W_CURMAP],a
+ ld a,[$d383] ; new Y coordinate upon entering south map
+ ld [W_YCOORD],a
+ ld a,[W_XCOORD]
+ ld c,a
+ ld a,[$d384] ; X adjustment upon entering south map
+ add c
+ ld c,a
+ ld [W_XCOORD],a
+ ld a,[$d385] ; pointer to upper left corner of map without adjustment for X position
+ ld l,a
+ ld a,[$d386]
+ ld h,a
+ ld b,$00
+ srl c
+ add hl,bc
+ ld a,l
+ ld [$d35f],a ; pointer to upper left corner of current tile block map section
+ ld a,h
+ ld [$d360],a
+.loadNewMap\@ ; load the connected map that was entered
+ call LoadMapHeader
+ call $2312 ; music
+ ld b,$09
+ call $3def ; SGB palette
+ ld b,$05
+ ld hl,$785b ; load tile pattern data for sprites
+ call Bankswitch
+ call LoadTileBlockMap
+ jp OverworldLoopLessDelay
+.didNotEnterConnectedMap\@
+ jp OverworldLoop
+
+; function to play a sound when changing maps
+PlayMapChangeSound:
+ ld a,[$c448] ; 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,$ad
+ jr .playSound\@
+.didNotGoThroughDoor\@
+ ld a,$b5
+.playSound\@
+ call $23b1
+ ld a,[$d35d]
+ and a
+ ret nz
+ jp GBFadeIn1
+
+; function to set the Z flag if the tileset number is 0 or the map is Route 12
+; strangely, Route 12 has tileset 0, so the check is redundant
+CheckIfInOutsideMap: ; 8E1
+ ld a,[W_CURMAPTILESET]
+ and a
+ ret z
+ cp a,ROUTE_12
+ 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: ; 8E9
+ ld a,[W_CURMAP]
+ cp a,SS_ANNE_3
+ jr z,.useFunction1\@
+ cp a,ROCKET_HIDEOUT_1
+ jr z,.useFunction2\@
+ cp a,ROCKET_HIDEOUT_2
+ jr z,.useFunction2\@
+ cp a,ROCKET_HIDEOUT_4
+ jr z,.useFunction2\@
+ cp a,ROCK_TUNNEL_1
+ jr z,.useFunction2\@
+ ld a,[W_CURMAPTILESET]
+ and a ; outside tileset
+ jr z,.useFunction2\@
+ cp a,$0d ; S.S. Anne tileset
+ jr z,.useFunction2\@
+ cp a,$0e ; Vermilion Port tileset
+ jr z,.useFunction2\@
+ cp a,$17 ; Indigo Plateau tileset
+ jr z,.useFunction2\@
+.useFunction1\@
+ ld hl,$43ff
+ jr .doBankswitch\@
+.useFunction2\@
+ ld hl,$444e
+.doBankswitch\@
+ ld b,$03
+ jp Bankswitch
+
+MapEntryAfterBattle: ; 91F
+ ld b,$03
+ ld hl,$435f
+ call Bankswitch ; function that appears to disable warp testing after collisions if the player is standing on a warp
+ ld a,[$d35d]
+ and a
+ jp z,GBFadeIn2
+ jp LoadGBPal
+
+; for when all the player's pokemon faint
+; other code prints the "you blacked out" message before this is called
+HandleBlackOut: ; 931
+ call GBFadeIn1
+ ld a,$08
+ call StopMusic
+ ld hl,$d72e
+ res 5,[hl]
+ ld a,$01
+ ld [$ffb8],a
+ ld [$2000],a
+ call $40b0
+ call $62ce
+ call $2312
+ jp $5d5f
+
+StopMusic: ; 951
+ ld [$cfc7],a
+ ld a,$ff
+ ld [$c0ee],a
+ call $23b1
+.waitLoop\@
+ ld a,[$cfc7]
+ and a
+ jr nz,.waitLoop\@
+ jp $200e
+
+HandleFlyOrTeleportAway: ; 965
+ call $2429 ; move sprites
+ call $3dd7
+ xor a
+ ld [$cf0b],a
+ ld [$d700],a
+ ld [$d057],a
+ ld [$d35d],a
+ ld hl,$d732
+ set 2,[hl]
+ res 5,[hl]
+ call DoFlyOrTeleportAwayGraphics
+ ld a,$01
+ ld [$ffb8],a
+ ld [$2000],a
+ call $62ce
+ jp $5d5f
+
+; function that calls a function to do fly away or teleport away graphics
+DoFlyOrTeleportAwayGraphics: ; 98F
+ ld b,$1c
+ ld hl,$45ba
+ jp Bankswitch
+
+; load sprite graphics based on whether the player is standing, biking, or surfing
+LoadPlayerSpriteGraphics: ; 997
+ ld a,[$d700]
+ dec a
+ jr z,.ridingBike\@
+ ld a,[$ffd7]
+ and a
+ jr nz,.determineGraphics\@
+ jr .startWalking\@
+.ridingBike\@
+ call IsBikeRidingAllowed
+ jr c,.determineGraphics\@ ; don't start walking if bike riding is allowed
+.startWalking\@
+ xor a
+ ld [$d700],a
+ ld [$d11a],a
+ jp LoadWalkingPlayerSpriteGraphics
+.determineGraphics\@
+ ld a,[$d700]
+ and a
+ jp z,LoadWalkingPlayerSpriteGraphics
+ dec a
+ jp z,LoadBikePlayerSpriteGraphics
+ dec a
+ jp z,LoadSurfingPlayerSpriteGraphics
+ jp LoadWalkingPlayerSpriteGraphics
+
+; function to check if bike riding is allowed on the current map
+; sets carry if bike is allowed, clears carry otherwise
+IsBikeRidingAllowed:
+ ld a,[W_CURMAP]
+ cp a,ROUTE_23
+ jr z,.allowed\@
+ cp a,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
+
+BikeRidingTilesets:
+db $00, $03, $0B, $0E, $11, $FF
+
+; load the tile pattern data of the current tileset into VRAM
+LoadTilesetTilePatternData: ; 9E8
+ ld a,[$d52e]
+ ld l,a
+ ld a,[$d52f]
+ ld h,a
+ ld de,$9000
+ ld bc,$0600
+ ld a,[$d52b]
+ jp $17f7
+
+; 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: ; 9FC
+; fill C6E8-CBFB with the background tile
+ ld hl,$c6e8
+ ld a,[$d3ad] ; 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,$c6e8
+ 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,[$d36a] ; tile map pointer
+ ld e,a
+ ld a,[$d36b]
+ 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,[$d371]
+ cp a,$ff
+ jr z,.southConnection\@
+ call SwitchToMapRomBank
+ ld a,[$d372]
+ ld l,a
+ ld a,[$d373]
+ ld h,a
+ ld a,[$d374]
+ ld e,a
+ ld a,[$d375]
+ ld d,a
+ ld a,[$d376]
+ ld [$ff8b],a
+ ld a,[$d377]
+ ld [$ff8c],a
+ call LoadNorthSouthConnectionsTileMap
+.southConnection\@
+ ld a,[$d37c]
+ cp a,$ff
+ jr z,.westConnection\@
+ call SwitchToMapRomBank
+ ld a,[$d37d]
+ ld l,a
+ ld a,[$d37e]
+ ld h,a
+ ld a,[$d37f]
+ ld e,a
+ ld a,[$d380]
+ ld d,a
+ ld a,[$d381]
+ ld [$ff8b],a
+ ld a,[$d382]
+ ld [$ff8c],a
+ call LoadNorthSouthConnectionsTileMap
+.westConnection\@
+ ld a,[$d387]
+ cp a,$ff
+ jr z,.eastConnection\@
+ call SwitchToMapRomBank
+ ld a,[$d388]
+ ld l,a
+ ld a,[$d389]
+ ld h,a
+ ld a,[$d38a]
+ ld e,a
+ ld a,[$d38b]
+ ld d,a
+ ld a,[$d38c]
+ ld b,a
+ ld a,[$d38d]
+ ld [$ff8b],a
+ call LoadEastWestConnectionsTileMap
+.eastConnection\@
+ ld a,[$d392]
+ cp a,$ff
+ jr z,.done\@
+ call SwitchToMapRomBank
+ ld a,[$d393]
+ ld l,a
+ ld a,[$d394]
+ ld h,a
+ ld a,[$d395]
+ ld e,a
+ ld a,[$d396]
+ ld d,a
+ ld a,[$d397]
+ ld b,a
+ ld a,[$d398]
+ ld [$ff8b],a
+ call LoadEastWestConnectionsTileMap
+.done\@
+ ret
+
+LoadNorthSouthConnectionsTileMap: ; ADE
+ 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: ; B02
+ 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: ; B23
+ xor a
+ ld [$ff8c],a
+ ld a,[$d4b0] ; 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,$d4b1 ; start of sign coordinates
+ ld a,[$d4b0] ; 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,$d4d1 ; 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,$d532 ; 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: ; B6B
+ ld d,$10 ; talking range in pixels (normal range)
+IsSpriteInFrontOfPlayer2: ; B6D
+ ld bc,$3c40 ; Y and X position of player sprite
+ ld a,[$c109] ; 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 [$d52a],a
+ ld a,[$d4e1] ; number of sprites
+ and a
+ ret z
+; if there are sprites
+ ld hl,$c110
+ 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: ; BD1
+ ld a,[$d736]
+ bit 6,a ; is the player jumping?
+ jr nz,.noCollision\@
+; if not jumping a ledge
+ ld a,[$cd38]
+ and a
+ jr nz,.noCollision\@
+ ld a,[$d52a] ; the direction that the player is trying to go in
+ ld d,a
+ ld a,[$c10c] ; 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,[$c02a]
+ cp a,$b4 ; check if collision sound is already playing
+ jr z,.setCarry\@
+ ld a,$b4
+ call $23b1 ; 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: ; C10
+ ld a,$35
+ call Predef ; get tile in front of player
+ ld a,[$cfc6] ; tile in front of player
+ ld c,a
+ ld hl,$d530 ; 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: ; C2A
+ push hl
+ ld a,$35
+ call Predef ; get the tile in front of the player
+ push de
+ push bc
+ ld b,$06
+ ld hl,$6672
+ call Bankswitch ; check if the player is trying to jump a ledge
+ pop bc
+ pop de
+ pop hl
+ and a
+ ld a,[$d736]
+ bit 6,a ; is the player jumping?
+ ret nz
+; if not jumping
+ ld a,[$c45c] ; tile the player is on
+ ld [$cf0e],a
+ ld a,[$cfc6] ; 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,[$cf0e] ; 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: ; C7E
+db $11, $20, $05;
+db $11, $41, $05;
+db $03, $30, $2E;
+db $11, $2A, $05;
+db $11, $05, $21;
+db $03, $52, $2E;
+db $03, $55, $2E;
+db $03, $56, $2E;
+db $03, $20, $2E;
+db $03, $5E, $2E;
+db $03, $5F, $2E;
+db $FF;
+
+TilePairCollisionsWater: ; CA0
+db $03, $14, $2E;
+db $03, $48, $2E;
+db $11, $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: ; CAA
+ ld a,[$ffb8]
+ push af
+ ld a,[$d52b] ; tile data ROM bank
+ ld [$ffb8],a
+ ld [$2000],a ; switch to ROM bank that contains tile data
+ ld a,[$d35f] ; address of upper left corner of current map view
+ ld e,a
+ ld a,[$d360]
+ ld d,a
+ ld hl,$c508
+ 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,$c508
+ 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,$c3a0 ; 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 [$ffb8],a
+ ld [$2000],a ; restore previous ROM bank
+ ret
+
+AdvancePlayerSprite: ; D27
+ ld a,[$c103] ; delta Y
+ ld b,a
+ ld a,[$c105] ; delta X
+ ld c,a
+ ld hl,$cfc5 ; 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,[$cfc5] ; 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,[$d526]
+ ld e,a
+ and a,$e0
+ ld d,a
+ ld a,e
+ add a,$02
+ and a,$1f
+ or d
+ ld [$d526],a
+ jr .adjustXCoordWithinBlock\@
+.checkIfMovingWest\@
+ cp a,$ff
+ jr nz,.checkIfMovingSouth\@
+; moving west
+ ld a,[$d526]
+ ld e,a
+ and a,$e0
+ ld d,a
+ ld a,e
+ sub a,$02
+ and a,$1f
+ or d
+ ld [$d526],a
+ jr .adjustXCoordWithinBlock\@
+.checkIfMovingSouth\@
+ ld a,b
+ cp a,$01
+ jr nz,.checkIfMovingNorth\@
+; moving south
+ ld a,[$d526]
+ add a,$40
+ ld [$d526],a
+ jr nc,.adjustXCoordWithinBlock\@
+ ld a,[$d527]
+ inc a
+ and a,$03
+ or a,$98
+ ld [$d527],a
+ jr .adjustXCoordWithinBlock\@
+.checkIfMovingNorth\@
+ cp a,$ff
+ jr nz,.adjustXCoordWithinBlock\@
+; moving north
+ ld a,[$d526]
+ sub a,$40
+ ld [$d526],a
+ jr nc,.adjustXCoordWithinBlock\@
+ ld a,[$d527]
+ dec a
+ and a,$03
+ or a,$98
+ ld [$d527],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,$d4e3
+ inc [hl]
+ ld de,$d35f
+ 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,$d4e3
+ dec [hl]
+ ld de,$d35f
+ 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,$d4e2
+ inc [hl]
+ ld de,$d35f
+ 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,$d4e2
+ dec [hl]
+ ld de,$d35f
+ ld a,[W_CURMAPWIDTH]
+ call MoveTileBlockMapPointerNorth
+.updateMapView\@
+ call LoadCurrentMapView
+ ld a,[$c103] ; 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,[$c105] ; 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,[$c103] ; delta Y
+ ld b,a
+ ld a,[$c105] ; 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,$c114
+ ld a,[$d4e1] ; 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: ; E65
+ ld a,[de]
+ add a,$01
+ ld [de],a
+ ret nc
+ inc de
+ ld a,[de]
+ inc a
+ ld [de],a
+ ret
+
+MoveTileBlockMapPointerWest: ; E6F
+ ld a,[de]
+ sub a,$01
+ ld [de],a
+ ret nc
+ inc de
+ ld a,[de]
+ dec a
+ ld [de],a
+ ret
+
+MoveTileBlockMapPointerSouth: ; E79
+ 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: ; E85
+ 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: ; E91
+ ld hl,$c3a0
+ call ScheduleRowRedrawHelper
+ ld a,[$d526]
+ ld [$ffd1],a
+ ld a,[$d527]
+ ld [$ffd2],a
+ ld a,$02
+ ld [$ffd0],a
+ ret
+
+ScheduleRowRedrawHelper: ; EA6
+ ld de,$cbfc
+ ld c,$28
+.loop\@
+ ld a,[hli]
+ ld [de],a
+ inc de
+ dec c
+ jr nz,.loop\@
+ ret
+
+ScheduleSouthRowRedraw: ; EB2
+ ld hl,$c4e0
+ call $0ea6
+ ld a,[$d526]
+ ld l,a
+ ld a,[$d527]
+ ld h,a
+ ld bc,$0200
+ add hl,bc
+ ld a,h
+ and a,$03
+ or a,$98
+ ld [$ffd2],a
+ ld a,l
+ ld [$ffd1],a
+ ld a,$02
+ ld [$ffd0],a
+ ret
+
+ScheduleEastColumnRedraw: ; ED3
+ ld hl,$c3b2
+ call ScheduleColumnRedrawHelper
+ ld a,[$d526]
+ ld c,a
+ and a,$e0
+ ld b,a
+ ld a,c
+ add a,$12
+ and a,$1f
+ or b
+ ld [$ffd1],a
+ ld a,[$d527]
+ ld [$ffd2],a
+ ld a,$01
+ ld [$ffd0],a
+ ret
+
+ScheduleColumnRedrawHelper: ; EF2
+ ld de,$cbfc
+ ld c,$12
+.loop\@
+ ld a,[hli]
+ ld [de],a
+ inc de
+ ld a,[hl]
+ ld [de],a
+ inc de
+ ld a,$13
+ add l
+ ld l,a
+ jr nc,.noCarry\@
+ inc h
+.noCarry\@
+ dec c
+ jr nz,.loop\@
+ ret
+
+ScheduleWestColumnRedraw: ; F08
+ ld hl,$c3a0
+ call ScheduleColumnRedrawHelper
+ ld a,[$d526]
+ ld [$ffd1],a
+ ld a,[$d527]
+ ld [$ffd2],a
+ ld a,$01
+ ld [$ffd0],a
+ ret
+
+; function to write the tiles that make up a tile block to memory
+; Input: c = tile block ID, hl = destination address
+DrawTileBlock: ; F1D
+ push hl
+ ld a,[$d52c] ; pointer to tiles
+ ld l,a
+ ld a,[$d52d]
+ 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
+GetJoypadStateOverworld: ; F4D
+ xor a
+ ld [$c103],a
+ ld [$c105],a
+ call RunMapScript
+ call $019a ; update joypad state
+ ld a,[$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,[$ffb4] ; current joypad state
+ and a,%11110011 ; bit mask for all directions and A/B
+ jr nz,.notForcedDownwards\@
+ ld a,%10000000 ; down pressed
+ ld [$ffb4],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,[$d730]
+ bit 7,a
+ ret z
+; if simulating button presses
+ ld a,[$ffb4] ; current joypad state
+ ld b,a
+ ld a,[$cd3b] ; bit mask for button presses that override simulated ones
+ and b
+ ret nz ; return if the simulated button presses are overridden
+ ld hl,$cd38 ; 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,$ccd3 ; 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 [$ffb4],a ; store simulated button press in joypad state
+ and a
+ ret nz
+ ld [$ffb3],a
+ ld [$ffb2],a
+ ret
+; if done simulating button presses
+.doneSimulating\@
+ xor a
+ ld [$cd3a],a
+ ld [$cd38],a
+ ld [$ccd3],a
+ ld [$cd6b],a
+ ld [$ffb4],a
+ ld hl,$d736
+ ld a,[hl]
+ and a,$f8
+ ld [hl],a
+ ld hl,$d730
+ 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: ; FB7
+ ld a,[$d730]
+ bit 7,a
+ jp nz,.noCollision\@ ; return and clear carry if button presses are being simulated
+ ld a,[$d52a] ; the direction that the player is trying to go in
+ ld d,a
+ ld a,[$c10c] ; 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 [$CFC6])
+ ld a,[$cfc6] ; 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,$d530 ; 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,[$c02a]
+ cp a,$b4 ; check if collision sound is already playing
+ jr z,.setCarry\@
+ ld a,$b4
+ call $23b1 ; play collision sound (if it's not already playing)
+.setCarry\@
+ scf
+ jr .done\@
+.noCollision\@
+ and a
+.done\@
+ ret
+.stopSurfing\@
+ xor a
+ ld [$d700],a
+ call LoadPlayerSpriteGraphics
+ call $2307
+ jr .noCollision\@
+.checkIfVermilionDockTileset\@
+ ld a,[W_CURMAPTILESET] ; tileset
+ cp a,$0e ; 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
+ push hl
+ push de
+ push bc
+ ld b,$03
+ ld hl,$7225
+ call Bankswitch ; check if the player is pushing a boulder
+ ld a,[$cd60]
+ bit 1,a ; is the player pushing a boulder?
+ jr z,.afterBoulderEffect\@
+ ld b,$03
+ ld hl,$72b5
+ call Bankswitch ; displays dust effect when pushing a boulder
+.afterBoulderEffect\@
+ pop bc
+ pop de
+ pop hl
+ call $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:
+ ld de,$4180
+ ld hl,$8000
+ jr LoadPlayerSpriteGraphicsCommon
+
+LoadSurfingPlayerSpriteGraphics:
+ ld de,$76c0
+ ld hl,$8000
+ jr LoadPlayerSpriteGraphicsCommon
+
+LoadBikePlayerSpriteGraphics:
+ ld de,$4000
+ ld hl,$8000
+
+LoadPlayerSpriteGraphicsCommon:
+ push de
+ push hl
+ ld bc,$050c
+ call $1848
+ 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 $1848
+
+; function to load data from the map header
+LoadMapHeader: ; 107C
+ ld b,$03
+ ld hl,$7113
+ call Bankswitch
+ ld a,[W_CURMAPTILESET]
+ ld [$d119],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,$d367
+ 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 [$d371],a
+ ld [$d37c],a
+ ld [$d387],a
+ ld [$d392],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 [$d3a9],a
+ ld a,[hli]
+ ld [$d3aa],a
+ push hl
+ ld a,[$d3a9]
+ ld l,a
+ ld a,[$d3aa]
+ ld h,a ; hl = base of object data
+ ld de,$d3ad ; background tile ID
+ ld a,[hli]
+ ld [de],a ; save background tile ID
+.loadWarpData\@
+ ld a,[hli] ; number of warps
+ ld [$d3ae],a ; save the number of warps
+ and a ; are there any warps?
+ jr z,.loadSignData\@ ; if not, skip this
+ ld c,a
+ ld de,$d3af ; 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 [$d4b0],a ; save the number of signs
+ and a ; are there any signs?
+ jr z,.loadSpriteData\@ ; if not, skip this
+ ld c,a
+ ld de,$d4d1 ; base address of sign text IDs
+ ld a,d
+ ld [$ff95],a
+ ld a,e
+ ld [$ff96],a
+ ld de,$d4b1 ; 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,[$d72e]
+ 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 [$d4e1],a ; save the number of sprites
+ push hl
+; zero C110-C1FF and C210-C2FF
+ ld hl,$c110
+ ld de,$c210
+ 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,$c112
+ ld de,$0010
+ ld c,$0f
+.disableSpriteEntriesLoop\@
+ ld [hl],$ff
+ add hl,de
+ dec c
+ jr nz,.disableSpriteEntriesLoop\@
+ pop hl
+ ld de,$c110
+ ld a,[$d4e1] ; 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,$d4e4 ; base address of sprite entries
+ 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,$d504 ; base address of extra sprite info entries
+ 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,$d504 ; base address of extra sprite info
+ 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,$d504 ; base address of extra sprite info
+ 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
+ ld hl,$4eb8
+ ld b,$03
+ call Bankswitch ; 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 [$d524],a ; store map height in 2x2 tile blocks
+ ld a,[W_CURMAPWIDTH] ; map width in 4x4 tile blocks
+ add a ; double it
+ ld [$d525],a ; map width in 2x2 tile blocks
+ ld a,[W_CURMAP]
+ ld c,a
+ ld b,$00
+ ld a,[$ffb8]
+ push af
+ ld a,$03
+ ld [$ffb8],a
+ ld [$2000],a
+ ld hl,$404d
+ add hl,bc
+ add hl,bc
+ ld a,[hli]
+ ld [$d35b],a ; music 1
+ ld a,[hl]
+ ld [$d35c],a ; music 2
+ pop af
+ ld [$ffb8],a
+ ld [$2000],a
+ ret
+
+; function to copy map connection data from ROM to WRAM
+; Input: hl = source, de = destination
+CopyMapConnectionHeader: ; 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
+ ld a,[$ffb8]
+ push af
+ call DisableLCD
+ ld a,$98
+ ld [$d527],a
+ xor a
+ ld [$d526],a
+ ld [$ffaf],a
+ ld [$ffae],a
+ ld [$cfc5],a
+ ld [$d119],a
+ ld [$d11a],a
+ ld [$d3a8],a
+ call $36a0 ; transfer tile pattern data for text windows into VRAM
+ call LoadMapHeader
+ ld b,$05
+ ld hl,$785b
+ call Bankswitch ; load tile pattern data for sprites
+ call LoadTileBlockMap
+ call LoadTilesetTilePatternData
+ call LoadCurrentMapView
+; copy current map view to VRAM
+ ld hl,$c3a0
+ ld de,$9800
+ ld b,$12
+.vramCopyLoop\@
+ ld c,$14
+.vramCopyInnerLoop\@
+ ld a,[hli]
+ ld [de],a
+ inc e
+ dec c
+ jr nz,.vramCopyInnerLoop\@
+ ld a,$0c
+ add e
+ ld e,a
+ jr nc,.noCarry\@
+ inc d
+.noCarry\@
+ dec b
+ jr nz,.vramCopyLoop\@
+ ld a,$01
+ ld [$cfcb],a
+ call EnableLCD
+ ld b,$09
+ call $3def ; handle SGB palette
+ call LoadPlayerSpriteGraphics
+ ld a,[$d732]
+ and a,$18 ; did the player fly or teleport in?
+ jr nz,.restoreRomBank\@
+ ld a,[$d733]
+ bit 1,a
+ jr nz,.restoreRomBank\@
+ call $235f ; music related
+ call $2312 ; music related
+.restoreRomBank\@
+ pop af
+ ld [$ffb8],a
+ ld [$2000],a
+ ret
+
+; function to switch to the ROM bank that a map is stored in
+; Input: a = map number
+SwitchToMapRomBank: ; 12BC
+ push hl
+ push bc
+ ld c,a
+ ld b,$00
+ ld a,$03
+ 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 [$ffb8],a
+ ld [$2000],a ; switch to map ROM bank
+ pop bc
+ pop hl
+ ret
+
+INCBIN "baserom.gbc",$12DA,$1627 - $12DA
;XXX what does this do
;XXX what points to this