diff --git a/README.md b/README.md index 21ed74c8f..fe6764c03 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,42 @@ -# Pokémon Crystal [![Build Status][ci-badge]][ci] +# pokecrystal-board -This is a disassembly of Pokémon Crystal. +pokecrystal-board is a board game engine for the GBC based on [pokecrystal](https://github.com/pret/pokecrystal). -It builds the following ROMs: +In pokecrystal-board **you will find**: +- Content with new built-in features + - Overworld board game engine: menus, movement, events, turn lifecycle, etc. + - Level selection menu ("world map") + - Game progression logic + - Other supporting features +- Empty canvas with pokecrystal-board placeholder content, or with no content + - Actual levels and maps, and their design + - Board space effects + - Many GFX and SFX elements + - Layout of transition screens and menus + - ... +- Empty canvas with pokecrystal placeholder content + - The complete battle engine + - Pokemon data and storage + - Item data and storage + - ... -- Pokemon - Crystal Version (UE) (V1.0) [C][!].gbc `sha1: f4cd194bdee0d04ca4eac29e09b8e4e9d818c133` -- Pokemon - Crystal Version (UE) (V1.1) [C][!].gbc `sha1: f2f52230b536214ef7c9924f483392993e226cfb` -- Pokemon - Crystal Version (A) [C][!].gbc `sha1: a0fc810f1d4e124434f7be2c989ab5b5892ddf36` -- CRYSTAL_ps3_010328d.bin `sha1: c60d57a24bbe8ecf7cba54ab3f90669f97bd330d` -- CRYSTAL_ps3_us_revise_010710d.bin `sha1: 391ae86b1d5a26db712ffe6c28bbf2a1f804c3c4` -- CGBBYTE1.784.patch `sha1: a25517f60ca0e887d39ec698aa56a0040532a4b3` +In pokecrystal-board **you will *not* find**: +- A ready-to-play game +- An engine that requires less ASM knowledge to use than the pokecrystal disassembly +- Guaranteed compatibility with extensions to pokecrystal developed by the community +- Definitive GFX and SFX assets for the pokecrystal-board features -To set up the repository, see [INSTALL.md](INSTALL.md). +**How can you use and what can you do with pokecrystal-board**: +- Use it as the base engine to develop your own game +- Develop new features or expand existing features for the purpose of your own game +- Develop new features or expand existing features to be incorporated into pokecrystal-board +- Design assets to be incorporated in place of the placeholder GFX/SFX in pokecrystal-board (see issue #9) +- Request or show your interest in specific features to be added to pokecrystal-board (open an issue for this) +Compared to pokecrystal and the Pokemon Crystal ROM, the ROM built by pokecrystal-board uses a MBC5 chip and requires 64 KB of RAM (8 banks of 8KB each). -## See also +pokecrystal-board requires RGBDS 0.7.0 to build. It has two build targets: *crystal*, and *crystal_debug*. The former builds a ROM with the *_DEBUG* symbol undefined, and the latter builds a ROM with the *_DEBUG* symbol defined. *crystal_debug* is meant to include additional content and configurations to facilitate testing during development, while *crystal* builds the ROM meant to be hypothetically released to the public. Other than that, refer to the [install docs from pokecrystal](INSTALL.md) for detailed instructions on how to setup and build pokecrystal-board. -- [**FAQ**](FAQ.md) -- [**Documentation**][docs] -- [**Wiki**][wiki] (includes [tutorials][tutorials]) -- [**Symbols**][symbols] +If you have specific questions about the usage of pokecrystal-board or how to contribute to it, feel free to open an issue or to contact me on Discord. But please, do not do this for questions that are rather in the domain of pokecrystal. -You can find us on [Discord (pret, #pokecrystal)](https://discord.gg/d5dubZ3). - -For other pret projects, see [pret.github.io](https://pret.github.io/). - -[docs]: https://pret.github.io/pokecrystal/ -[wiki]: https://github.com/pret/pokecrystal/wiki -[tutorials]: https://github.com/pret/pokecrystal/wiki/Tutorials -[symbols]: https://github.com/pret/pokecrystal/tree/symbols -[ci]: https://github.com/pret/pokecrystal/actions -[ci-badge]: https://github.com/pret/pokecrystal/actions/workflows/main.yml/badge.svg +If you are interested on developing on top of pokecrystal-board, [docs/usage/index.md](docs/usage/index.md) details the different features. For generic changes made in pokecrystal-board (adaptations, cleaning up, etc.) refer to issues #1, #2, #7, #8. You can also navigate issues tagged with a "Feature" label to see commits pertaining specific features. Additionally, a rough list of new RAM addresses can be found in [docs/develop/ram_addresses.md](docs/develop/ram_addresses.md). \ No newline at end of file diff --git a/docs/develop/index.md b/docs/develop/index.md deleted file mode 100755 index 606706e6d..000000000 --- a/docs/develop/index.md +++ /dev/null @@ -1,161 +0,0 @@ -## 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 - -- **LoadOverworldTilemap**: 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. -- **LoadOverworldAttrmapPals**: Load wAttrmap palette numbers based on the tileset palettes of the current map. Called only by LoadOverworldTilemapAndAttrmapPals. -- **LoadOverworldTilemapAndAttrmapPals**: LoadOverworldTilemap + LoadOverworldAttrmapPals. Often used to reload screen after closing a text box. - -#### Overworld map anchoring - -- **ReanchorBGMap_NoOAMUpdate**: LoadOverworldTilemapAndAttrmapPals + HDMATransferTilemapAndAttrmap_Menu, 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_Menu + 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_Menu**, **HDMATransferTilemapAndAttrmap_Overworld**: 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 - -- **reanchormap**: RefreshScreen -- **refreshmap**: LoadOverworldTilemapAndAttrmapPals + GetMovementPermissions + HDMATransferTilemapAndAttrmap_Overworld + UpdateSprites. Similar to reanchormap, 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. - -## Changes - -### RAM addresses - -- **hCurBoardEvent**: holds a *BOARDEVENT_* value. - -- **wTurnData** ~ **wTurnDataEnd**: not preserved on save, and cleared at the beginning of BoardMenuScript (i.e. on turn begin). It's part of *wMapStatus* ~ *wMapStatusEnd*, so it's also cleared by *StartMap*. Includes: - - **wDieRoll** - - **wSpacesLeft** - -- Addresses within *wCurMapData* ~ *wCurMapDataEnd*: preserved on save. Initialized when entering a level (in StartMap), and updated accordingly throughout the level. Includes: - - **wCurTurn** - - **wCurSpace** - - **wCurLevelCoins** - - **wCurLevelExp** - - **wCurSpaceStruct**: - - **wCurSpaceXCoord** - - **wCurSpaceYCoord** - - **wCurSpaceEffect** for non-branch spaces, or **wCurSpaceBranchStructPtr** (two bytes) for branch spaces - - **wCurSpaceNextSpace** for non-branch spaces - -- Addresses within *wPlayerData* ~ *wPlayerDataEnd*: preserved on save. Includes: - - **wUnlockedLevels**: flag array that tracks progression regarding which levels have been unlocked. - - **wClearedLevelsStage**: flag array that tracks progression regarding which levels have been cleared. Each level can have up to four clearable endings (N). - - **wUnlockedTechniques**: flag array that tracks progression regarding which techniques have been unlocked. - - **wCurLevel**: initialized in LevelSelectionMenu (where it is also used), and stays static during the level. - - **wDefaultLevelSelectionMenuLandmark**: used to know in which landmark to place the player when entering level selection menu. - - **wCurOverworldMiscPal** - - **wLevelSelectionMenuEntryEventQueue**: which events have to be triggered the next time the player enters the level selection menu. - -- These addresses share memory region with string buffers from *wStringBuffer3* onwards. They are placed in memory in the following order. - - **wTempSpaceStruct**: Temporary scope. Same structure as *wCurSpaceStruct* - - **wTempSpaceBranchStruct**: Temporary scope. The structure is four bytes for next space for each direction (R/L/U/D; -1 if unavailable direction) followed by four bytes for required techniques for each direction (R/L/U/D) - - **wViewMapModeRange**, **wViewMapModeDisplacementY**, **wViewMapModeDisplacementX**: Temporary scope during a Vew Map mode session. - - **wBeforeViewMapYCoord**, **wBeforeViewMapXCoord**, **wBeforeViewMapMapGroup**, **wBeforeViewMapMapNumber**, **wBeforeViewMapDirection**: Temporary scope during a Vew Map mode session. Used to preserve player state before entering View Map mode. - -- Additional addresses for View Map mode, that share memory region with *wCurBattleMon* and *wCurMoveNum*, which are not used outside of battle: - - **wPlayerMockYCoord**, **wPlayerMockXCoord**: Used to handle the player mock sprite through map connections during View Map mode. - -- Addresses for talker events: - - *wSeenTrainer** addresses have been repurposed as **wSeenTrainerOrTalker*** - - **wSeenTrainerOrTalkerIsTalker**: added right before *wSeenTrainerOrTalker**. - - **wTempTalker** ~ **wTempTalkerEnd**: allocated to the same address space as *wTempTrainer*. Same scope as *wTempTrainer*, but for talker events. - -- Address spaces for backing up the map state (disabled spaces and map objects). Located outside of WRAM banks 0 and 1. - - **wDisabledSpacesBackups**: preserved on save to **sDisabledSpacesBackups**. - - **wMapObjectsBackups**: preserved on save to **sMapObjectsBackups**. - -- **wLevelSelectionMenu\*** addresses, union under the *"Miscellaneous WRAM 1"* section. Temporary scope during level selection menu, except for *wLevelSelectionMenuEntryEventQueue*. - -- Other WRAM 0 addresses (not preserved on save): - - **wText2bpp** - - **wWhichHUD** - - **wExitOverworldReason** - -### Overworld workflow - -1) ``OverworldLoop`` is called from ``GameMenu_World`` with either ``hMapEntryMethod`` = ``MAPSETUP_ENTERLEVEL`` or ``hMapEntryMethod`` = ``MAPSETUP_CONTINUE``. -2) ``StartMap`` resets ``wCurTurn`` and ``wCurSpace`` if ``MAPSETUP_ENTERLEVEL``. ``StartMap`` sets ``hCurBoardEvent`` to ``BOARDEVENT_DISPLAY_MENU``. ``wEnabledPlayerEvents`` is cleared. ``wMapStatus`` is set to ``MAPSTATUS_HANDLE`` causing ``HandleMap`` to be called. -3) ``MapEvents`` (from ``HandleMap``) calls ``PlayerEvents``. ``CheckBoardEvent`` queues ``BoardMenuScript`` which is executed by ``ScriptEvents``. -4) ``BoardMenuScript.Upkeep`` saves the game, clears ``wTurnData[]``, increases ``wCurTurn``, and loads current space to ``wCurSpaceStruct[]``. - - If player exits, the ``exitoverworld`` script sets ``wMapStatus`` to ``MAPSTATUS_DONE``. This causes ``OverworldLoop`` to return back to the game menu. **Exit this workflow**. -5) Player rolls die and the animation plays. After the animation, ``wDisplaySecondarySprites.SECONDARYSPRITES_SPACES_LEFT_F`` is set and ``hCurBoardEvent`` is set to ``BOARDEVENT_HANDLE_BOARD``. At the end of this ``HandleMap`` iteration, ``CheckPlayerState`` sets ``wMapEventStatus`` to ``MAPEVENTS_ON`` (``wEnabledPlayerEvents`` is not touched so it remains cleared). -6) In the next ``HandleMap`` iteration, ``CheckBoardEvent`` from ``PlayerEvents`` jumps to ``.board`` and then to ``.no_space_effect`` due to ``wEnabledPlayerEvents[4]`` not being set. -7) Execution continues in ``PlayerEvents``; ``OWPlayerInput`` is eventually called, and thus ``DoPlayerMovement``. Here, ``StepTowardsNextSpace`` computes based on ``wCurSpaceNextSpace`` what direction key to write to ``wCurInput``, causing the player to begin a movement in that direction. -8) The player may need to turn to a different direction through the ``ChangeDirectionScript`` (when ``DoPlayerMovement`` returns with ``PLAYERMOVEMENT_TURN``). Otherwise or after that, ``CheckPlayerState`` sets ``wMapEventStatus`` to ``MAPEVENTS_OFF``, -9) When the step finishes (i.e. ``PLAYERSTEP_STOP_F`` becomes set) in some ``HandleMap`` iteration, ``CheckPlayerState`` sets ``wEnabledPlayerEvents`` to $ff and ``wMapEventStatus`` to ``MAPEVENTS_ON``. -10) In the next ``HandleMap`` iteration, ``CheckBoardEvent.board`` is called with ``wEnabledPlayerEvents[4]`` set. - - If ``wCurSpaceNextSpace`` matches ``NEXT_SPACE_IS_ANCHOR_POINT``: If player is at a tile with an anchor event, ``wCurSpaceNextSpace`` is updated with the next space byte of salid anchor event. ``wEnabledPlayerEvents[4]`` is reset. **Go back to 7**. - - If player is not above a tile (``wPlayerTileCollision``) with a space collision: ``wEnabledPlayerEvents[4]`` is reset. **Go back to 7**. - - If player is above a tile, the corresponding space script is queued to be executed by ``ScriptEvents`` in the current ``HandleMap`` iteration. ``wEnabledPlayerEvents[4]`` is reset. **Continue to 11**. -11) The space script loads the value of ``wCurSpaceNextSpace`` into ``wCurSpace``, and loads the new space data to ``wCurSpaceStruct[]``. Unless the space is a Branch Space or a Union Space, ``wSpacesLeft`` is decreased. - - If the space is a Branch Space, the branch data is loaded to ``wTempSpaceBranchStruct``. Then the player is prompted to choose a valid direction. ``wCurSpaceNextSpace`` is populated with the next space that corresponds to the chosen direction. **Go back to 6**. - - If the space is an End Space, a fading out animation plays and then the ``exitoverworld`` script sets ``wMapStatus`` to ``MAPSTATUS_DONE``. This causes ``OverworldLoop`` to return back to the game menu. **Exit this workflow**. -12) If ``wSpacesLeft`` is non-0, **go back to 6**. -13) The script code specific to the space type of the landed-on space is executed. - - If player whites out in battle, ``Script_BattleWhiteout`` executes ``exitoverworld``. **Exit this workflow**. -14) The landed-on space is disabled by executing a block change that converts it into a Grey Space. ``hCurBoardEvent`` is set to ``BOARDEVENT_END_TURN``. ``CheckBoardEvent`` does nothing in this state. In the first subsequent ``HandleMap`` iteration where no other kind of event triggers causing ``PlayerEvents`` to return early, ``hCurBoardEvent`` is set to ``BOARDEVENT_DISPLAY_MENU``. -15) **Go back to 3** - -### View Map mode workflow - -1) Pressing SELECT in the board menu triggers View Map mode. ``hCurBoardEvent`` is set to ``BOARDEVENT_VIEW_MAP_MODE``, player state (coordinates as well as current map in order to support connected maps) is backed up, ``wPlayerFlags[INVISIBLE_F]`` is set, and a static mockup of the player object is loaded to the last ``wMapObject`` and, in the background, to the first ``wObjectStruct`` is available. -2) The board event handler in ``CheckBoardEvent`` listens for the B button being pressed (except when a DPAD key is simultaneously held). When B is pressed, a script (a single ``reloadmapafterviewmapmode``) to exit from View Map mode is queued to be executed by ``ScriptEvents``. Otherwise, ``DoPlayerMovement.ViewMapMode`` handles movement input in this mode. -3) When requested exit of View Map mode via B button, ``reloadmapafterviewmapmode`` sets ``hMapEntryMethod`` to ``MAPSETUP_EXITVIEWMAP``, ``hMapEntryMethod`` to ``SPAWN_FROM_RAM`` (required by the map setup command ``EnterMapSpawnPoint`` to restore the backed up player state), loads ``MAPSTATUS_ENTER`` tp ``wMapStatus``, and resets ``wPlayerFlags[INVISIBLE_F]`` (the mocked player object naturally disappears when the map reloads). -4) Then: - a) If View Map mode was entered from the board menu, ``BOARDEVENT_REDISPLAY_MENU`` is loaded. It is the same as ``BOARDEVENT_DISPLAY_MENU`` but skips ``BoardMenuScript.Upkeep``. - b) If View Map mode was entered from the branch menu, instead ``BOARDEVENT_RESUME_BRANCH`` is loaded, using ``wPlayerSpriteSetupFlags[PLAYERSPRITESETUP_CUSTOM_FACING_F]`` to maintain the facing direction according to the direction (``SPRITEMOVEDATA_*``) of the mocked player object. ``BOARDEVENT_RESUME_BRANCH`` makes sure to shortcut the branch space script by calling ``BranchSpaceScript_PromptPlayer`` directly and avoiding the recomputation of the branch struct that would cause corruption. ``BOARDEVENT_HANDLE_BOARD`` is loaded immediately by ``BOARDEVENT_RESUME_BRANCH``. - -- In View Map mode, regular collisions except for ``COLL_OUT_OF_BOUNDS`` are ignored whereas going off-limits (i.e. outside of the map limits in a direction where there is no connected map) or off-range is accounted for. -- Events other than warpless connections are ignored in View Map mode (as well as button actions, like while in ``BOARDEVENT_HANDLE_BOARD``). -- ``wTileDown``, ``wTileUp``, etc., otherwise unused, are borrowed by in order to signal valid directions to ``InitSecondarySprites`` (e.g. ``wTileDown=COLL_OUT_OF_BOUNDS`` means that DOWN direction is not valid). -- In View Map mode, the overworld delay is 1 rather than 2. -- ``UpdatePlayerCoords`` tracks the displacement during View Map mode in the X and Y axes in order to monitor the allowed range. \ No newline at end of file diff --git a/docs/develop/notes.md b/docs/develop/notes.md new file mode 100755 index 000000000..b9361f70d --- /dev/null +++ b/docs/develop/notes.md @@ -0,0 +1,66 @@ +## 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 + +- **LoadOverworldTilemap**: 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. +- **LoadOverworldAttrmapPals**: Load wAttrmap palette numbers based on the tileset palettes of the current map. Called only by LoadOverworldTilemapAndAttrmapPals. +- **LoadOverworldTilemapAndAttrmapPals**: LoadOverworldTilemap + LoadOverworldAttrmapPals. Often used to reload screen after closing a text box. + +#### Overworld map anchoring + +- **ReanchorBGMap_NoOAMUpdate**: LoadOverworldTilemapAndAttrmapPals + HDMATransferTilemapAndAttrmap_Menu, 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_Menu + 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_Menu**, **HDMATransferTilemapAndAttrmap_Overworld**: 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 + +- **reanchormap**: RefreshScreen +- **refreshmap**: LoadOverworldTilemapAndAttrmapPals + GetMovementPermissions + HDMATransferTilemapAndAttrmap_Overworld + UpdateSprites. Similar to reanchormap, 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. \ No newline at end of file diff --git a/docs/overworld_loop.md b/docs/develop/overworld_loop.md similarity index 100% rename from docs/overworld_loop.md rename to docs/develop/overworld_loop.md diff --git a/docs/develop/ram_addresses.md b/docs/develop/ram_addresses.md new file mode 100755 index 000000000..4f3894dbb --- /dev/null +++ b/docs/develop/ram_addresses.md @@ -0,0 +1,52 @@ +# RAM addresses + +- **hCurBoardEvent**: holds a *BOARDEVENT_* value. + +- **wTurnData** ~ **wTurnDataEnd**: not preserved on save, and cleared at the beginning of BoardMenuScript (i.e. on turn begin). It's part of *wMapStatus* ~ *wMapStatusEnd*, so it's also cleared by *StartMap*. Includes: + - **wDieRoll** + - **wSpacesLeft** + +- Addresses within *wCurMapData* ~ *wCurMapDataEnd*: preserved on save. Initialized when entering a level (in StartMap), and updated accordingly throughout the level. Includes: + - **wCurTurn** + - **wCurSpace** + - **wCurLevelCoins** + - **wCurLevelExp** + - **wCurSpaceStruct**: + - **wCurSpaceXCoord** + - **wCurSpaceYCoord** + - **wCurSpaceEffect** for non-branch spaces, or **wCurSpaceBranchStructPtr** (two bytes) for branch spaces + - **wCurSpaceNextSpace** for non-branch spaces + +- Addresses within *wPlayerData* ~ *wPlayerDataEnd*: preserved on save. Includes: + - **wUnlockedLevels**: flag array that tracks progression regarding which levels have been unlocked. + - **wClearedLevelsStage**: flag array that tracks progression regarding which levels have been cleared. Each level can have up to four clearable endings (N). + - **wUnlockedTechniques**: flag array that tracks progression regarding which techniques have been unlocked. + - **wCurLevel**: initialized in LevelSelectionMenu (where it is also used), and stays static during the level. + - **wDefaultLevelSelectionMenuLandmark**: used to know in which landmark to place the player when entering level selection menu. + - **wCurOverworldMiscPal** + - **wLevelSelectionMenuEntryEventQueue**: which events have to be triggered the next time the player enters the level selection menu. + +- These addresses share memory region with string buffers from *wStringBuffer3* onwards. They are placed in memory in the following order. + - **wTempSpaceStruct**: Temporary scope. Same structure as *wCurSpaceStruct* + - **wTempSpaceBranchStruct**: Temporary scope. The structure is four bytes for next space for each direction (R/L/U/D; -1 if unavailable direction) followed by four bytes for required techniques for each direction (R/L/U/D) + - **wViewMapModeRange**, **wViewMapModeDisplacementY**, **wViewMapModeDisplacementX**: Temporary scope during a Vew Map mode session. + - **wBeforeViewMapYCoord**, **wBeforeViewMapXCoord**, **wBeforeViewMapMapGroup**, **wBeforeViewMapMapNumber**, **wBeforeViewMapDirection**: Temporary scope during a Vew Map mode session. Used to preserve player state before entering View Map mode. + +- Additional addresses for View Map mode, that share memory region with *wCurBattleMon* and *wCurMoveNum*, which are not used outside of battle: + - **wPlayerMockYCoord**, **wPlayerMockXCoord**: Used to handle the player mock sprite through map connections during View Map mode. + +- Addresses for talker events: + - *wSeenTrainer** addresses have been repurposed as **wSeenTrainerOrTalker*** + - **wSeenTrainerOrTalkerIsTalker**: added right before *wSeenTrainerOrTalker**. + - **wTempTalker** ~ **wTempTalkerEnd**: allocated to the same address space as *wTempTrainer*. Same scope as *wTempTrainer*, but for talker events. + +- Address spaces for backing up the map state (disabled spaces and map objects). Located outside of WRAM banks 0 and 1. + - **wDisabledSpacesBackups**: preserved on save to **sDisabledSpacesBackups**. + - **wMapObjectsBackups**: preserved on save to **sMapObjectsBackups**. + +- **wLevelSelectionMenu\*** addresses, union under the *"Miscellaneous WRAM 1"* section. Temporary scope during level selection menu, except for *wLevelSelectionMenuEntryEventQueue*. + +- Other WRAM 0 addresses (not preserved on save): + - **wText2bpp** + - **wWhichHUD** + - **wExitOverworldReason** \ No newline at end of file diff --git a/docs/develop/workflows.md b/docs/develop/workflows.md new file mode 100755 index 000000000..854dab206 --- /dev/null +++ b/docs/develop/workflows.md @@ -0,0 +1,39 @@ +# Overworld workflow + +1) ``OverworldLoop`` is called from ``GameMenu_World`` with either ``hMapEntryMethod`` = ``MAPSETUP_ENTERLEVEL`` or ``hMapEntryMethod`` = ``MAPSETUP_CONTINUE``. +2) ``StartMap`` resets ``wCurTurn`` and ``wCurSpace`` if ``MAPSETUP_ENTERLEVEL``. ``StartMap`` sets ``hCurBoardEvent`` to ``BOARDEVENT_DISPLAY_MENU``. ``wEnabledPlayerEvents`` is cleared. ``wMapStatus`` is set to ``MAPSTATUS_HANDLE`` causing ``HandleMap`` to be called. +3) ``MapEvents`` (from ``HandleMap``) calls ``PlayerEvents``. ``CheckBoardEvent`` queues ``BoardMenuScript`` which is executed by ``ScriptEvents``. +4) ``BoardMenuScript.Upkeep`` saves the game, clears ``wTurnData[]``, increases ``wCurTurn``, and loads current space to ``wCurSpaceStruct[]``. + - If player exits, the ``exitoverworld`` script sets ``wMapStatus`` to ``MAPSTATUS_DONE``. This causes ``OverworldLoop`` to return back to the game menu. **Exit this workflow**. +5) Player rolls die and the animation plays. After the animation, ``wDisplaySecondarySprites.SECONDARYSPRITES_SPACES_LEFT_F`` is set and ``hCurBoardEvent`` is set to ``BOARDEVENT_HANDLE_BOARD``. At the end of this ``HandleMap`` iteration, ``CheckPlayerState`` sets ``wMapEventStatus`` to ``MAPEVENTS_ON`` (``wEnabledPlayerEvents`` is not touched so it remains cleared). +6) In the next ``HandleMap`` iteration, ``CheckBoardEvent`` from ``PlayerEvents`` jumps to ``.board`` and then to ``.no_space_effect`` due to ``wEnabledPlayerEvents[4]`` not being set. +7) Execution continues in ``PlayerEvents``; ``OWPlayerInput`` is eventually called, and thus ``DoPlayerMovement``. Here, ``StepTowardsNextSpace`` computes based on ``wCurSpaceNextSpace`` what direction key to write to ``wCurInput``, causing the player to begin a movement in that direction. +8) The player may need to turn to a different direction through the ``ChangeDirectionScript`` (when ``DoPlayerMovement`` returns with ``PLAYERMOVEMENT_TURN``). Otherwise or after that, ``CheckPlayerState`` sets ``wMapEventStatus`` to ``MAPEVENTS_OFF``, +9) When the step finishes (i.e. ``PLAYERSTEP_STOP_F`` becomes set) in some ``HandleMap`` iteration, ``CheckPlayerState`` sets ``wEnabledPlayerEvents`` to $ff and ``wMapEventStatus`` to ``MAPEVENTS_ON``. +10) In the next ``HandleMap`` iteration, ``CheckBoardEvent.board`` is called with ``wEnabledPlayerEvents[4]`` set. + - If ``wCurSpaceNextSpace`` matches ``NEXT_SPACE_IS_ANCHOR_POINT``: If player is at a tile with an anchor event, ``wCurSpaceNextSpace`` is updated with the next space byte of salid anchor event. ``wEnabledPlayerEvents[4]`` is reset. **Go back to 7**. + - If player is not above a tile (``wPlayerTileCollision``) with a space collision: ``wEnabledPlayerEvents[4]`` is reset. **Go back to 7**. + - If player is above a tile, the corresponding space script is queued to be executed by ``ScriptEvents`` in the current ``HandleMap`` iteration. ``wEnabledPlayerEvents[4]`` is reset. **Continue to 11**. +11) The space script loads the value of ``wCurSpaceNextSpace`` into ``wCurSpace``, and loads the new space data to ``wCurSpaceStruct[]``. Unless the space is a Branch Space or a Union Space, ``wSpacesLeft`` is decreased. + - If the space is a Branch Space, the branch data is loaded to ``wTempSpaceBranchStruct``. Then the player is prompted to choose a valid direction. ``wCurSpaceNextSpace`` is populated with the next space that corresponds to the chosen direction. **Go back to 6**. + - If the space is an End Space, a fading out animation plays and then the ``exitoverworld`` script sets ``wMapStatus`` to ``MAPSTATUS_DONE``. This causes ``OverworldLoop`` to return back to the game menu. **Exit this workflow**. +12) If ``wSpacesLeft`` is non-0, **go back to 6**. +13) The script code specific to the space type of the landed-on space is executed. + - If player whites out in battle, ``Script_BattleWhiteout`` executes ``exitoverworld``. **Exit this workflow**. +14) The landed-on space is disabled by executing a block change that converts it into a Grey Space. ``hCurBoardEvent`` is set to ``BOARDEVENT_END_TURN``. ``CheckBoardEvent`` does nothing in this state. In the first subsequent ``HandleMap`` iteration where no other kind of event triggers causing ``PlayerEvents`` to return early, ``hCurBoardEvent`` is set to ``BOARDEVENT_DISPLAY_MENU``. +15) **Go back to 3** + +# View Map mode workflow + +1) Pressing SELECT in the board menu triggers View Map mode. ``hCurBoardEvent`` is set to ``BOARDEVENT_VIEW_MAP_MODE``, player state (coordinates as well as current map in order to support connected maps) is backed up, ``wPlayerFlags[INVISIBLE_F]`` is set, and a static mockup of the player object is loaded to the last ``wMapObject`` and, in the background, to the first ``wObjectStruct`` is available. +2) The board event handler in ``CheckBoardEvent`` listens for the B button being pressed (except when a DPAD key is simultaneously held). When B is pressed, a script (a single ``reloadmapafterviewmapmode``) to exit from View Map mode is queued to be executed by ``ScriptEvents``. Otherwise, ``DoPlayerMovement.ViewMapMode`` handles movement input in this mode. +3) When requested exit of View Map mode via B button, ``reloadmapafterviewmapmode`` sets ``hMapEntryMethod`` to ``MAPSETUP_EXITVIEWMAP``, ``hMapEntryMethod`` to ``SPAWN_FROM_RAM`` (required by the map setup command ``EnterMapSpawnPoint`` to restore the backed up player state), loads ``MAPSTATUS_ENTER`` tp ``wMapStatus``, and resets ``wPlayerFlags[INVISIBLE_F]`` (the mocked player object naturally disappears when the map reloads). +4) Then: + a) If View Map mode was entered from the board menu, ``BOARDEVENT_REDISPLAY_MENU`` is loaded. It is the same as ``BOARDEVENT_DISPLAY_MENU`` but skips ``BoardMenuScript.Upkeep``. + b) If View Map mode was entered from the branch menu, instead ``BOARDEVENT_RESUME_BRANCH`` is loaded, using ``wPlayerSpriteSetupFlags[PLAYERSPRITESETUP_CUSTOM_FACING_F]`` to maintain the facing direction according to the direction (``SPRITEMOVEDATA_*``) of the mocked player object. ``BOARDEVENT_RESUME_BRANCH`` makes sure to shortcut the branch space script by calling ``BranchSpaceScript_PromptPlayer`` directly and avoiding the recomputation of the branch struct that would cause corruption. ``BOARDEVENT_HANDLE_BOARD`` is loaded immediately by ``BOARDEVENT_RESUME_BRANCH``. + +- In View Map mode, regular collisions except for ``COLL_OUT_OF_BOUNDS`` are ignored whereas going off-limits (i.e. outside of the map limits in a direction where there is no connected map) or off-range is accounted for. +- Events other than warpless connections are ignored in View Map mode (as well as button actions, like while in ``BOARDEVENT_HANDLE_BOARD``). +- ``wTileDown``, ``wTileUp``, etc., otherwise unused, are borrowed by in order to signal valid directions to ``InitSecondarySprites`` (e.g. ``wTileDown=COLL_OUT_OF_BOUNDS`` means that DOWN direction is not valid). +- In View Map mode, the overworld delay is 1 rather than 2. +- ``UpdatePlayerCoords`` tracks the displacement during View Map mode in the X and Y axes in order to monitor the allowed range. \ No newline at end of file diff --git a/docs/usage/index.md b/docs/usage/index.md index acb33d22d..758e80ed5 100755 --- a/docs/usage/index.md +++ b/docs/usage/index.md @@ -1,47 +1,4 @@ -# pokecrystal-board - -pokecrystal-board is a board game engine for the GBC based on [pokecrystal](https://github.com/pret/pokecrystal). - -In pokecrystal-board **you will find**: -- Content with new built-in features - - Overworld board game engine: menus, movement, events, turn lifecycle, etc. - - Level selection menu ("world map") - - Game progression logic - - Other supporting features -- Empty canvas with pokecrystal-board placeholder content, or with no content - - Actual levels and maps, and their design - - Board space effects - - Many GFX and SFX elements - - Layout of transition screens and menus - - ... -- Empty canvas with pokecrystal placeholder content - - The complete battle engine - - Pokemon data and storage - - Item data and storage - - ... - -In pokecrystal-board **you will *not* find**: -- A ready-to-play game -- An engine that requires less ASM knowledge to use than the pokecrystal disassembly -- Guaranteed compatibility with extensions to pokecrystal developed by the community -- Definitive GFX and SFX assets for the pokecrystal-board features - -**How can you use and what can you do with pokecrystal-board**: -- Use it as the base engine to develop your own game -- Develop new features or expand existing features for the purpose of your own game -- Develop new features or expand existing features to be incorporated into pokecrystal-board -- Design assets to be incorporated in place of the placeholder GFX/SFX in pokecrystal-board (see issue #9) -- Request or show your interest in specific features to be added to pokecrystal-board (open an issue for this) - -Compared to pokecrystal and the Pokemon Crystal ROM, the ROM built by pokecrystal-board uses a MBC5 chip and requires 64 KB of RAM (8 banks of 8KB each). - -pokecrystal-board requires RGBDS 0.7.0 to build. It has two build targets: *crystal*, and *crystal_debug*. The former builds a ROM with the *_DEBUG* symbol undefined, and the latter builds a ROM with the *_DEBUG* symbol defined. *crystal_debug* is meant to include additional content and configurations to facilitate testing during development, while *crystal* builds the ROM meant to be hypothetically released to the public. Other than that, refer to the [install docs from pokecrystal](INSTALL.md) for detailed instructions on how to setup and build pokecrystal-board. - -If you have specific questions about the usage of pokecrystal-board or how to contribute to it, feel free to open an issue or to contact me on Discord. But please, do not do this for questions that are rather in the domain of pokecrystal. - -If you are interested on developing on top of pokecrystal-board, the rest of this document details the different features. For generic changes made in pokecrystal-board (adaptations, cleaning up, etc.) refer to issues #1, #2, #7, #8. You can also navigate issues tagged with a "Feature" label to see commits pertaining specific features. Additionally, a rough list of new RAM addresses can be found in [docs/develop/index.md](docs/develop/index.md). - -## Level selection menu +# Level selection menu The level selection menu is essentially a world map that the player navigates to select a level to play. The player can move through landmarks that correspond to unlocked levels in the level selection menu. The level seleciton menu can have multiple map pages each with their own landmarks. When the player moves from a landmark in one page to a landmark in another page, the new page is loaded during the transition. @@ -63,13 +20,13 @@ The data is located in [data/levels/level_selection_menu.asm](data/levels/level_ - *LevelSelectionMenu_PageGrid*: layout of all pages in the big picture. Each byte entry is the page number, or -1 for no page. - *LandmarkToLevelTable*: denotes the mapping between landmarks and levels. -## Overworld +# Overworld The overworld uses a turn-based system. Each level is composed of one or more maps, and the maps are designed with spaces in them, which are meant for the player to move through them. Each turn the player rolls a die and advances spaces accordingly. Events may occur as appropriate while the player is advancing and/or when it lands in a space. -In addition to what is covered in this section, you can find more low level stuff about the pokecrystal-board overworld engine in the rough workflows described here: [docs/develop/index.md](docs/develop/index.md). The core of the overworld engine is in [engine/overworld/events.asm](engine/overworld/events.asm) and, in a way, the main logic occurs in *PlayerEvents*. New board logic in this context is in *CheckBoardEvent* and the state is defined by *BOARDEVENT_* constants. Again, for in-depth details refer to the aforementioned workflows or to the code itself. +In addition to what is covered in this section, you can find more low level stuff about the pokecrystal-board overworld engine in the rough workflows described here: [docs/develop/workflows.md](docs/develop/workflows.md). The core of the overworld engine is in [engine/overworld/events.asm](engine/overworld/events.asm) and, in a way, the main logic occurs in *PlayerEvents*. New board logic in this context is in *CheckBoardEvent* and the state is defined by *BOARDEVENT_* constants. Again, for in-depth details refer to the aforementioned workflows or to the code itself. -### Board menu +## Board menu The board menu is shown to the player at the beginning of each turn. In allows for several choices. The only ones that are specific to the pokecrystal-board engine are "roll die", "view map", and "exit level". The other three choices point to the party menu, bag menu, and pokegear, and are placeholders from pokecrystal. The board menu can be navigated horizontally. All menu options are accessed by selecting the corresponding icon of the menu, except for "view map" which is accessible via the Select button. All menu options except for "roll die" and "exit level" eventually return back to the board menu. @@ -77,7 +34,7 @@ TODO: add image The implementation is located in [engine/board/menu.asm](engine/board/menu.asm). Icon tiles are drawn over the background of the textbox as if they were font characters. The current menu item is highlighted with a colored overlay using objects. This file includes also the animation logic for rolling a die when the "roll die" option is selected. These animations leverage the overworld sprite animation engine from pokecrystal. Finally, [gfx/board](gfx/board) contains GFX assets. -### Board spaces +## Board spaces The spaces of each map are defined in the map file (in the [maps](maps) directory) under *\*_MapSpaces*. The definition of each space uses the *space* macro. An example: @@ -98,11 +55,11 @@ Board space effects are triggered from *PlayerEvents.CheckBoardEvent* during *BO When a player lands on a space, it turns into a "grey space" with no effect should the player land on it in a later turn. -#### Regular spaces +### Regular spaces Regular space scripts have a check for whether the player has finished the movement according to the die roll and thus landed on the space. The actual effect is only executed when it is determined that the player has landed on the space. -#### Branch space +### Branch space A branch space triggers even if the player has not completed the movement. A branch space additionally does not count as an actual space in the movement (so it can't be landed on either). In a branch space, the player is prompted to choose a direction to continue the movement. Some of these directions can be made locked until the player has unlocked a specific technique (Cut, Surf, etc.). Directions that can be followed are represented in the game with a colored arrow, whereas directions that are locked due to techniques are represented with a grey arrow. @@ -124,13 +81,13 @@ In a branch space, the last two bytes of the *space* macro are repurposed as a p Each *branchdir* entry includes: direction, next space id, techniques required. The order of entries is irrelevant, but do not put the same direction more than once in the same branch struct (all but the last entry using that direction will be ignored). -#### End space +### End space Landing on an end space means that the player has cleared the level. Like the branch space, the end space effect triggers even if the player has not completed the movement. It transitions the player to a post-level screen (and then back to the level selection menu.) The space-specific argument in the *space* entry of an end space indicates the stage of the level to be cleared by reaching this end space. An *ES\** constant from [constants/space_constants.asm](constants/space_constants.asm) is used for this. -### Board movement +## Board movement The player moves in the board according to the next space id value of the last space passed through. Given ``SpaceA[NextSpaceId] = SpaceB``, if the movement to follow between SpaceA and SpaceB is linear (all steps in the same direction), the movement is automatic. On the other hand, for non-linear transitions between spaces (e.g. to make a turn or to avoid an obstacle), something called anchor events have to be used. @@ -160,7 +117,7 @@ Note that if the next space id value of the last landed space or anchor event is This simple board movement logic is located in [engine/board/movement.asm](engine/board/movement.asm) and is part of *DoPlayerMovement* in [engine/overworld/player_movement.asm](engine/overworld/player_movement.asm). -#### Warp events and connections +### Warp events and connections The player can traverse warps as part of a movement between two spaces, or cross the connection between two maps. The way you define map connections and warps in maps of pokecrystal-board is the same as in pokecrystal, and the underlying engine behind warps and connections is also the same. @@ -182,7 +139,7 @@ Note that origin map and destination map could be the same map in the specific c While the above example showcases a regular space, this same logic can be extrapolated to branch spaces using the *branchdir* macro explained beforehand. -#### Technique events +### Technique events Technique events in pokecrystal-board represent the equivalent of hidden machines in Pokemon Crystal. A technique like Cut, Surf, Rock Smash, etc. can be unlocked through game progression (how exactly is unspecified), enabling what you can imagine i.e. cutting trees, surfing over water, smashing rocks, etc. Technique constants are defined in [constants/technique_constants.asm](constants/technique_constants.asm). @@ -190,38 +147,38 @@ The main difference in pokecrystal-board is that techniques are executed in the Techniques are implemented in different manners. Cut and Rock Smash use objects entirely and are implemented through *CheckFacingTileEvent* in *PlayerEvents*, queuing the corresponding script. Surf (start/stop surfing) and Waterfall are also implemented in *CheckFacingTileEvent* alongside specific collision values carried over from pokecrystal. Flash is instead implemented as a map setup command. -### Object events +## Object events -#### Trainer events +### Trainer events -#### Talker events +### Talker events -### View map mode +## View map mode -### Map state preservation +## Map state preservation -## Game navigation and progression +# Game navigation and progression -## Other features +# Other features -### Window HUD +## Window HUD -### Overworld textbox +## Overworld textbox -### RGB palette fading +## RGB palette fading -### Tilesets +## Tilesets -### OAM management +## OAM management -## Design aspects +# Design aspects This section covers miscellaneous design aspects not yet fully covered in other sections. -### Levels +## Levels -### Game currency +## Game currency -### Time counting +## Time counting -### Game autosaving \ No newline at end of file +## Game autosaving \ No newline at end of file