## Functions
#### Apply VRAM/OAM
- **SafeUpdateSprites**: Set BG map mode to 0 (disabled) and disable OAM update + UpdateSprites + enable OAM update + DelayFrame + restore original state of BG map mode and OAM update
- **UpdateSprites**: Compute state of overworld sprites to wShadowOAM. Disable OAM update while editing wShadowOAM, and restore its original state when finished
- **ApplyPals**: Copy wBGPals1 into wBGPals2 and wOBPals1 into wOBPals2. Does not request pal update during vblank by itself
- **ApplyAttrmap**: Set BG map mode to 2 (pals) and delay 4 frames, and finally restore original state BG map mode. If LCD disabled instead copy all pals at once immediately
- **ApplyTilemap**: Set BG map mode to 1 (tiles) and delay 4 frames. If wSpriteUpdatesEnabled is non-0, instead call CopyTilemapAtOnce to do it all in one frame. This delays the next vblank to LY ~$7f
#### Load font
- **LoadFont_NoOAMUpdate**: LoadFrame + Hide Window + LoadStandardFont with OAM update disabled
- **LoadOverworldFont_NoOAMUpdate**: LoadOverworldFontAndFrame + hide Window with OAM update disabled
#### Textboxes
- **Textbox1bpp**: TextboxBorder + TextboxAttributes1bpp
- **Textbox2bpp**: _OverworldTextbox + TextboxAttributes2bpp
- **SpeechTextbox1bpp**: Textbox1bpp with speech location and dimensions
- **SpeechTextbox2bpp**: Textbox2bpp with speech location and dimensions
- **ClearTextbox**: Clear the inside of a speech textbox (fill with " ")
- **PrintTextboxText**: Print text in speech textbox coordinates with letter delay
- **PrintText1bpp**, **FarPrintText1bpp**: SpeechTextbox1bpp + UpdateSprites + ApplyTilemap + ClearTextbox + PrintTextboxText
- **PrintText2bpp**: SpeechTextbox2bpp + UpdateSprites + ApplyTilemap + ClearTextbox + PrintTextboxText
- **MapTextbox**: ClearTextbox + redraw tile behind cursor + SafeUpdateSprites + disable OAM update + ApplyTilemap + PrintTextboxText + enable OAM update
- **MenuBox**: Calls Textbox1bpp or Textbox2bpp, depending on the value of wText2bpp, with menu location and dimensions.
#### Overworld map scrolling
- **LoadScreenTilemap**: From the metatile-based 24x20 map in wSurroundingTiles, load the corresponding 20x18 tiles to wTilemap. Later, BackupBGMap* from ScrollMap* copies new row/column from wTilemap to wBGMapBuffer. _ScrollBGMapPalettes populates wBGMapPalBuffer based on the tiles at wBGMapBuffer. These are read during vblank by UpdateBGMapBuffer.
- **LoadScreenAttrmapPals**: Load wAttrmap palette numbers based on the tileset palettes of the current map. Called only by LoadScreenTilemapAndAttrmapPals.
- **LoadScreenTilemapAndAttrmapPals**: LoadScreenTilemap + LoadScreenAttrmapPals. Often used to reload screen after closing a text box.
#### Overworld map anchoring
- **ReanchorBGMap_NoOAMUpdate**: LoadScreenTilemapAndAttrmapPals + HDMATransferTilemapAndAttrmap_OpenAndCloseMenu, then fill BG map with all black while Window is displayed, finally anchor map and objects. Shall by followed by CopyTilemapAtOnce or by a HDMATransferTilemapAndAttrmap_* to redraw the screen.
- **OpenText1bpp**, **OpenText2bpp**: ClearMenuAndWindowData + ReanchorBGMap_NoOAMUpdate + SpeechTextbox1bpp + HDMATransferTilemapAndAttrmap_OpenAndCloseMenu + hide Window
- **OpenText1bpp**: Loads 1bpp font (LoadFont_NoOAMUpdate)
- **OpenText2bpp**: Doesn't load 2bpp font
- **RefreshScreen**: Same as OpenText functions but doesn't call any SpeechTextbox
#### VRAM transfer
- **Request1bpp**, **Request2bpp**: Copy 1bpp or 2bpp tiles at a rate of TILES_PER_CYCLE (8) per frame during vblank. Wait until complete
- **Copy1bpp**, **Copy2bpp**: Copy 1bpp or 2bpp tiles immediately
- **Get1bpp**, **Get2bpp**: Call Copy1bpp or Copy2bpp if LCD disabled. Request1bpp or Request2bpp otherwise
- **HDMATransfer1bpp**: Copy 1bpp tiles via HDMA. Maximum 16 tiles per frame
- **HDMATransfer2bpp**: Copy 2bpp tiles via HDMA. No hardcoded limit. Timing considers 1 tile per hblank
- **Get1bppViaHDMA**, **Get2bppViaHDMA**: Call Copy1bpp or Copy2bpp if LCD disabled. HDMATransfer1bpp or HDMATransfer2bpp otherwise
- **HDMATransferTilemapAndAttrmap_OpenAndCloseMenu**, **HDMATransferTilemapAndAttrmap_OverworldEffect**: Similar, but with slightly different scanline timing. So they're essentially like RefreshScreen minus the anchoring part.
#### HUD
- **EnableWindowHUD**: Configure LCD interrupt in LYC=LY mode with corresponding LYC.
- **DisableWindowHUD**: Configure LCD interrupt in hblank mode
- **LoadHUD**: Load the HUD at wWhichHUD to the top of wTilemap and wAttrmap
- **LoadWindowHUD**: Like LoadHUD, but for HUDs that require a Window overlay. Only does anything if hWindowHUDLY is non-0
- **ConstructOverworldHUDTilemap**: Draw the overworld HUD's tilemap into wOverworldHUDTiles
- **TransferOverworldHUDToBGMap**: Transfer overworld HUD to vBGMap1/vBGMap3 during v/hblank(s). Tilemap is read from wOverworldHUDTiles, attrmap is all PAL_BG_TEXT | PRIORITY.
- **RefreshOverworldHUD**: ConstructOverworldHUDTilemap + TransferOverworldHUDToBGMap
## Scripts
- **refreshscreen**: RefreshScreen
- **reloadmappart**: LoadScreenTilemapAndAttrmapPals + GetMovementPermissions + HDMATransferTilemapAndAttrmap_OverworldEffect + UpdateSprites. Similar to refreshscreen, but does not reanchor. On the other hand, it refreshes movement permissions. Often used after a block change or field move, which can affect collisions.
## Overworld loop (pokecrystal)
```
Primary functions are denoted in red and using indentation
*[j]* means jumping ahead
*r_* means break/return from current function with a return value
Horizontal line means end of loop
Bold denotes not documented yet
This denotes a comment
```
wMapStatus == MAPSTATUS_START:\
$~~~~$wScriptRunning <= 0\
$~~~~$wMapStatus ~ wMapStatusEnd <= 0
wMapStatus == MAPSTATUS_START or wMapStatus == MAPSTATUS_ENTER:\
$~~~~$**RunMapSetupScript**\
$~~~~$hMapEntryMethod == MAPSETUP_CONNECTION:\
$~~~~~~~~$wScriptFlags2 <= \$ff\
$~~~~$hMapEntryMethod <= 0\
$~~~~$wMapStatus <= MAPSTATUS_HANDLE
---
wMapStatus == MAPSTATUS_DONE:\
$~~~~$*Exit overworld loop*
---
wMapStatus == MAPSTATUS_HANDLE: the remainder of the code goes at this level
> hOverworldDelay <= 2 2 is *MaxOverworldDelay*\
> wMapEventStatus == MAPEVENTS_ON:\
>$~~~~$*Get joypad* update hJoyDown, hJoyReleased, hJoyPressed\
>$~~~~$*Refresh pals*
> HandleCmdQueue runs cmds queued by callbacks of type MAPCALLBACK_CMDQUEUE that execute the writecmdqueue script. Used only for stone tables, where any boulder from that table that is on a pit tile is made to disappear.
> MapEvents (wMapEventStatus == MAPEVENTS_ON):
>> PlayerEvents (wScriptRunning == FALSE):wScriptRunning check not to interrupt a running script command with wait/delay mode like applymovement and deactivatefacing
>>> CheckTrainerBattle:\
>>> *if seen by trainer (if any visible sprite is a trainer not yet beaten facing the player within line of sight)*:\
>>>$~~~~$*update wSeenTrainerDistance, wSeenTrainerDirection, wSeenTrainerBank, hLastTalked*\
>>>$~~~~$*load trainer data to wTempTrainer ~ wTempTrainerEnd*\
>>>$~~~~$[j1(PLAYEREVENT_SEENBYTRAINER)]
>>> CheckTileEvent:\
>>> *if warp, coord event, step event, or wild encounter*:\
>>> $~~~~$[j1(PLAYEREVENT_CONNECTION / PLAYEREVENT_FALL / PLAYEREVENT_WARP / PLAYEREVENT_MAPSCRIPT / PLAYEREVENT_HATCH)]step events include: special phone call, repel, poison, happiness, egg, daycare, bike\
>>> $~~~~$*may also* CallScript( / Script_ReceivePhoneCall / RepelWoreOffScript / Script_MonFaintedToPoison / WildBattleScript / BugCatchingContestBattleScript)
>>> **RunMemScript**:\
>>> *if any script at wMapReentryScript*: [j1]used for phone scripts
>>> **RunSceneScript**:\
>>> *if scene event (wCurMapSceneScriptCount)*: [j1(PLAYEREVENT_MAPSCRIPT)]
>>> **CheckTimeEvents**:\
>>> *if any time event*: [j1]used for bug contest, daily events
>>> OWPlayerInput:
>>>> PlayerMovement:
>>>>> DoPlayerMovement:
>>>>> wCurInput <= hJoyDown if BIKEFLAGS_DOWNHILL_F and hJoyDown & D_PAD == 0, instead load D_DOWN \
>>>>> wMovementAnimation <= movement_step_sleep\
>>>>> wWalkingIntoEdgeWarp <= FALSE
>>>>> Tile collision checks below consist on reading the current tile *wPlayerTile* and comparing it to a *COLL_* constant or a range of *COLL_* constants.\
>>>>> Tile permission checks below consist on reading the permissions of the tile that the player is walking into: *wTilePermissions* (applies only to *COLL_WALL*s) and *wWalkingTile* (*LAND_TILE*, *WATER_TILE*, or *WALL_TILE* for the tile in the walking direction; *WALL_TILE* permission is not the same as a *COLL_WALL* collision).\
>>>>> wPlayerState == PLAYER_NORMAL or wPlayerState = PLAYER_BIKE:\
>>>>> $~~~~$*if on ice tile and wPlayerTurningDirection != 0: wCurInput <= current direction button*\
>>>>> $~~~~$*update wWalkingDirection, wFacingDirection, wWalkingX, wWalkingY, wWalkingTile, based on wCurInput direction*\
>>>>> $~~~~$*if whirlpool tile: r1_player_movement = PLAYERMOVEMENT_FORCE_TURN*\
>>>>> $~~~~$*if waterfall tile: wWalkingDirection <= direction, DoStep(STEP_WALK), r1_player_movement = PLAYERMOVEMENT_CONTINUE*\
>>>>> $~~~~$*if door/staircase/cave warp tile (non ladder/carpet): wWalkingDirection <= DOWN, DoStep(STEP_WALK), r1_player_movement = PLAYERMOVEMENT_CONTINUE*\
>>>>> $~~~~$*if directions at wWalkingDirection and wPlayerDirection are not the same (turning): DoStep(STEP_TURN), r1_player_movement = PLAYERMOVEMENT_TURN*\
>>>>> $~~~~$*if no bump (land tile permissions or NPC): DoStep(STEP_WALK / STEP_BIKE / STEP_ICE)*\
>>>>> $~~~~~~~~$*if not leaving water: r1_player_movement = PLAYERMOVEMENT_FINISH*\
>>>>> $~~~~~~~~$*if leaving water: wPlayerState <= PLAYER_NORMAL, reload music and sprites, and r1_player_movement = PLAYERMOVEMENT_EXIT_WATER*\
>>>>> $~~~~$*if ledge tile: play sfx, DoStep(STEP_LEDGE), and r1_player_movement = PLAYERMOVEMENT_JUMP*\
>>>>> $~~~~$*if carpet warp tile matching wWalkingDirection: wWalkingIntoEdgeWarp <= TRUE*\
>>>>> $~~~~~~~~$*if directions at wWalkingDirection and wPlayerDirection are the same: load warp data, wPlayerTurningDirection <= 0, wMovementAnimation <= movement_step_sleep, and r1_player_movement = PLAYERMOVEMENT_WARP*\
>>>>> $~~~~$wWalkingDirection == STANDING: wPlayerTurningDirection <= 0, wMovementAnimation <= movement_step_sleep\
>>>>> $~~~~$wWalkingDirection != STANDING: if wWalkingIntoEdgeWarp == FALSE, *play bump sound*, wPlayerTurningDirection <= 0, wMovementAnimation <= movement_step_bump
>>>>> wPlayerState == PLAYER_SURF:\
>>>>> $~~~~$*if on ice tile and wPlayerTurningDirection != 0: wCurInput <= current direction button*\
>>>>> $~~~~$*update wWalkingDirection, wFacingDirection: wWalkingX, wWalkingY, wWalkingTile, based on wCurInput direction*\
>>>>> $~~~~$*if whirlpool tile: r1_player_movement = PLAYERMOVEMENT_FORCE_TURN*\
>>>>> $~~~~$*if waterfall tile: wWalkingDirection <= direction, DoStep(STEP_WALK), r1_player_movement = PLAYERMOVEMENT_CONTINUE*\
>>>>> $~~~~$*if door/staircase/cave warp tile (non ladder/carpet): wWalkingDirection <= DOWN, DoStep(STEP_WALK), r1_player_movement = PLAYERMOVEMENT_CONTINUE*\
>>>>> $~~~~$*if directions at wWalkingDirection and wPlayerDirection are not the same (turning): DoStep(STEP_TURN), r1_player_movement = PLAYERMOVEMENT_TURN*\
>>>>> $~~~~$*if no bump (water tile permissions or NPC): DoStep(STEP_WALK / STEP_BIKE / STEP_ICE)*\
>>>>> $~~~~~~~~$*if not leaving water: r1_player_movement = PLAYERMOVEMENT_FINISH*\
>>>>> $~~~~~~~~$*if leaving water: wPlayerState <= PLAYER_NORMAL, reload music and sprites, and r1_player_movement = PLAYERMOVEMENT_EXIT_WATER*\
>>>>> $~~~~$wWalkingDirection == STANDING: wPlayerTurningDirection <= 0, wMovementAnimation <= movement_step_sleep\
>>>>> $~~~~$wWalkingDirection != STANDING: if wWalkingIntoEdgeWarp == FALSE, *play bump sound*, wPlayerTurningDirection <= 0, wMovementAnimation <= movement_step_bump
>>>>> wPlayerNextMovement <= wMovementAnimation\
>>>>> r1_player_movement = PLAYERMOVEMENT_NORMAL
>>>> r1_player_movement == PLAYERMOVEMENT_NORMAL or r1_player_movement == PLAYERMOVEMENT_JUMP or r1_player_movement == PLAYERMOVEMENT_FINISH: r2_player_event = 0\
>>>> r1_player_movement == PLAYERMOVEMENT_WARP: r2_player_event = PLAYEREVENT_WARP\
>>>> r1_player_movement == PLAYERMOVEMENT_TURN: r2_player_event = PLAYEREVENT_JOYCHANGEFACING\
>>>> r1_player_movement == PLAYERMOVEMENT_FORCE_TURN: CallScript(Script_ForcedMovement), r2_player_event = PLAYEREVENT_MAPSCRIPTCallScript returns PLAYEREVENT_MAPSCRIPT always\
>>>> r1_player_movement == PLAYERMOVEMENT_CONTINUE or r1_player_movement == PLAYERMOVEMENT_EXIT_WATER: r2_player_event = -1
>>> r2_player_event == -1: r3_player_event = 0in this case, apart from r2_player_event = -1, PlayerMovement has also returned nc\
>>> r2_player_event == 0: in this case, apart from r2_player_event = 0, PlayerMovement has also returned nc\
>>> $~~~~$*if on ice tile and wPlayerTurningDirection != 0*: [j2]\
>>> $~~~~$if A_BUTTON in hJoyPressed:\
>>> $~~~~~~~~$*if facing to object event*: CallScript(