## 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 ``` 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*\ > MapEventStatus == 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 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_MAPSCRIPT CallScript 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 = 0 in 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() and r3_player_event = PLAYEREVENT_MAPSCRIPT / r3_player_event = PLAYEREVENT_ITEMBALL / *load trainer data* and r3_player_event = PLAYEREVENT_TALKTOTRAINER includes rock and boulder objects (PLAYEREVENT_MAPSCRIPT case)\ >>> $~~~~~~~~$*if bg event (signpost) in current coords and facing, and event's flag set if any*: CallScript( / HiddenItemScript) and r3_player_event = PLAYEREVENT_MAPSCRIPT\ >>> $~~~~~~~~$*if facing to collision event (use cut, whirlpool, waterfall, headbutt, surf)*: *call TryXOW, which returns with CallScript(AskXOW / CantXOW) and thus r3_player_event = PLAYEREVENT_MAPSCRIPT*\ >>> $~~~~$hJoyPressed[SELECT_F] == TRUE:\ >>> $~~~~~~~~$CallScript(SelectMenuScript) and r3_player_event = PLAYEREVENT_MAPSCRIPT\ >>> $~~~~$hJoyPressed[START_F] == TRUE:\ >>> $~~~~~~~~$CallScript(StartMenuScript) and r3_player_event = PLAYEREVENT_MAPSCRIPT\ >>> r3_player_event = r2_player_event in these instances is where PlayerMovement returned carry, so OWPlayerInput returns early >>> r3_player_event == 0: [j2] >> **[j1]**\ >> wScriptMode <= SCRIPT_READ\ >> wScriptRunning <= *loaded script from whatever jumped straight to [j1] OR r3_player_event* >>> DoPlayerEvent (wScriptRunning == TRUE and wScriptRunning != PLAYEREVENT_MAPSCRIPT): if there is a non-PLAYEREVENT_MAPSCRIPT script requested during this loop iteration, DoPlayerEvent pushes it to make it be executed by ScriptEvents. So the code up to [j2] below here **is actually executed by ScriptEvents and *NOT* right now**.\ >>> All scripts below finish with the *end* script unless otherwise stated (e.g. by the *endall* script) >>> wScriptRunning == PLAYEREVENT_SEENBYTRAINER:\ >>> $~~~~$SeenByTrainerScript + StartBattleWithMapTrainerScript >>> wScriptRunning == PLAYEREVENT_TALKTOTRAINER:\ >>> $~~~~$TalkToTrainerScript + StartBattleWithMapTrainerScript >>> wScriptRunning == PLAYEREVENT_ITEMBALL:\ >>> $~~~~$FindItemInBallScript >>> wScriptRunning == PLAYEREVENT_CONNECTION:\ >>> $~~~~$hMapEntryMethod <= MAPSETUP_CONNECTION\ >>> $~~~~$wMapStatus <= MAPSTATUS_ENTER\ >>> $~~~~$wScriptFlags[SCRIPT_RUNNING] = FALSE >>> wScriptRunning == PLAYEREVENT_WARP:\ >>> $~~~~$*play warp sound*\ >>> $~~~~$hMapEntryMethod <= MAPSETUP_DOOR\ >>> $~~~~$wMapStatus <= MAPSTATUS_ENTER\ >>> $~~~~$wScriptFlags[SCRIPT_RUNNING] = FALSE this write is exactly what the 'end' script also does >>> wScriptRunning == PLAYEREVENT_FALL:\ >>> $~~~~$hMapEntryMethod <= MAPSETUP_FALL\ >>> $~~~~$wMapStatus <= MAPSTATUS_ENTER\ >>> $~~~~$wScriptFlags[SCRIPT_RUNNING] = FALSE\ >>> $~~~~$*play fall sound 1*\ >>> $~~~~$*apply fall movement*\ >>> $~~~~$*play fall sound 2* >>> wScriptRunning == PLAYEREVENT_WHITEOUT:\ >>> $~~~~$OverworldWhiteoutScript + Script_Whiteout ends with hMapEntryMethod <= MAPSETUP_WARP + wMapStatus <= MAPSTATUS_ENTER + *endall* >>> wScriptRunning == PLAYEREVENT_HATCH:\ >>> $~~~~$OverworldHatchEgg >>> wScriptRunning == PLAYEREVENT_JOYCHANGEFACING:\ >>> $~~~~$wScriptDelay <= 3\ >>> $~~~~$wScriptMode <= SCRIPT_WAIT\ >>> $~~~~$wScriptFlags[SCRIPT_RUNNING] = FALSE\ >>> $~~~~$wScriptFlags2[4] == TRUE enable wild encounters >> **[j2]**\ >> wScriptFlags2 <= 0 >> ScriptEvents: executes scripts requested this loop by CallScript (PLAYEREVENT_MAPSCRIPT) >> wScriptFlags[SCRIPT_RUNNING] = TRUE\ >> while wScriptFlags[SCRIPT_RUNNING] == TRUE: breaks after *end* or similar script command >> $~~~~$wScriptMode == SCRIPT_OFF:\ >> $~~~~~~~~$wScriptFlags[SCRIPT_RUNNING] = FALSE >> $~~~~$wScriptMode == SCRIPT_READ:\ >> $~~~~~~~~$**(...)** >> $~~~~$wScriptMode == SCRIPT_WAIT_MOVEMENT:\ >> $~~~~~~~~$**(...)** >> $~~~~$wScriptMode == SCRIPT_WAIT:\ >> $~~~~~~~~$**(...)** > wMapStatus != MAPSTATUS_HANDLE: [j3] jump if any script during this iteration changed wMapStatus (some warp ocurred) > **HandleMapObjects**: >> **HandleNPCStep** **Includes player object!** At the beginning of each object, clears wPlayerStepVectorX, wPlayerStepVectorY, and wPlayerStepFlags, and sets wPlayerStepDirection to STANDING. HandleObjectStep is called for each visible object. This calls HandleStepType, which processes StepTypesJumptable by STEP_TYPE_. These functions manipulate wPlayerStepFlags among other things. >> _HandlePlayerStep (wPlayerStepFlags != 0): >>> wPlayerStepFlags(PLAYERSTEP_START_F) == TRUE:\ >>> $~~~~$wHandlePlayerStep <= 4\ >>> $~~~~$*Scroll map in the direction at wPlayerStepDirection*\ >>> $~~~~$wHandlePlayerStep <= wHandlePlayerStep - 1 >>> $~~~~$wPlayerBGMapOffsetX <= wPlayerBGMapOffsetX - wPlayerStepVectorX\ >>> $~~~~$wPlayerBGMapOffsetY <= wPlayerBGMapOffsetY - wPlayerStepVectorY\ >>> else wPlayerStepFlags(PLAYERSTEP_STOP_F) == TRUE:\ >>> $~~~~$*Increase or decrease wYCoord or wXCoord according to wPlayerStepDirection*\ >>> $~~~~$wHandlePlayerStep <= wHandlePlayerStep - 1\ >>> $~~~~$wHandlePlayerStep == 1: BufferScreen\ >>> $~~~~$wHandlePlayerStep == 0: GetMovementPermissions Update *wPlayerTile*, *wTilePermissions*, *wTileDown*, *wTileUp*, *wTileLeft*, and/or *wTileRight*\ >>> $~~~~$wPlayerBGMapOffsetX <= wPlayerBGMapOffsetX - wPlayerStepVectorX\ >>> $~~~~$wPlayerBGMapOffsetY <= wPlayerBGMapOffsetY - wPlayerStepVectorY\ >>> else wPlayerStepFlags(PLAYERSTEP_CONTINUE_F) == TRUE: same as PLAYERSTEP_STOP_F case except don't update *wYCoord* or *wXCoord*\ >>> $~~~~$wHandlePlayerStep <= wHandlePlayerStep - 1\ >>> $~~~~$wHandlePlayerStep == 1: BufferScreen\ >>> $~~~~$wHandlePlayerStep == 0: GetMovementPermissions Update wPlayerTile, wTilePermissions, wTileDown, wTileUp, wTileLeft, and/or wTileRight\ >>> $~~~~$wPlayerBGMapOffsetX <= wPlayerBGMapOffsetX - wPlayerStepVectorX\ >>> $~~~~$wPlayerBGMapOffsetY <= wPlayerBGMapOffsetY - wPlayerStepVectorY >> **CheckObjectEnteringVisibleRange** (wPlayerStepFlags[PLAYERSTEP_STOP_F] == TRUE) > DelayFrames(hOverworldDelay) > **HandleMapBackground** _UpdateSprites + ScrollScreen > CheckPlayerState:\ > wPlayerStepFlags[PLAYERSTEP_CONTINUE_F] == TRUE:\ > $~~~~$wMapEventStatus <= MAPEVENTS_ON\ > wPlayerStepFlags[PLAYERSTEP_STOP_F] == TRUE or wPlayerStepFlags[PLAYERSTEP_MIDAIR_F] == TRUE:\ > $~~~~$wMapEventStatus <= MAPEVENTS_OFF\ > else:\ > $~~~~$wScriptFlags2 <= \$ff\ > $~~~~$wMapEventStatus <= MAPEVENTS_ON > **[j3]** --- ***End of overworld loop. The remainder are intermediate functions*** --- Every script executed by ScriptEvents finishes with the some form of the **end** command. It returns (by updating wScriptPos and wScriptBank) to a parent script if any, and otherwise:\ wScriptRunning <= FALSE\ wScriptMode <= SCRIPT_OFF\ wScriptFlags[SCRIPT_RUNNING] = FALSE\ The **endall** command is like *end*, but also finishes parent scripts regardless. --- DoStep: wWalkingDirection == STANDING:\ $~~~~$wPlayerTurningDirection <= 0\ $~~~~$wMovementAnimation <= movement_step_sleep\ else:\ $~~~~$wMovementAnimation <= \ $~~~~$wPlayerTurningDirection <= \ | 1 << 7\ $~~~~$then always returns PLAYERMOVEMENT_FINISH but often is overwritten by caller ---