shithub: pokered

Download patch

ref: 93b1361dffaff4fae83f4f283fa7a39ab414d73d
parent: 188ac8a9b4816dd98df0108314e58885c3b07452
author: yenatch <yenatch@gmail.com>
date: Fri May 30 14:30:25 EDT 2014

Split out joypad and overworld code from home.asm.

diff: cannot open b/home//null: file does not exist: 'b/home//null'
--- a/home.asm
+++ b/home.asm
@@ -124,2468 +124,11 @@
 	jp Init
 
 
-ReadJoypad::
-; Poll joypad input.
-; Unlike the hardware register, button
-; presses are indicated by a set bit.
+INCLUDE "home/joypad.asm"
 
-	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 "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?
--- /dev/null
+++ b/home/joypad.asm
@@ -1,0 +1,39 @@
+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
--- /dev/null
+++ b/home/overworld.asm
@@ -1,0 +1,2419 @@
+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?