From e7c63e6a27d8552f0a2bddff8d168b0dc9472c3e Mon Sep 17 00:00:00 2001 From: Josh <32826900+ShinyDragonHunter@users.noreply.github.com> Date: Tue, 25 May 2021 22:25:13 +0100 Subject: [PATCH] Created Adding Multi-region Support (markdown) --- Adding-Multi-region-Support.md | 305 +++++++++++++++++++++++++++++++++ 1 file changed, 305 insertions(+) create mode 100644 Adding-Multi-region-Support.md diff --git a/Adding-Multi-region-Support.md b/Adding-Multi-region-Support.md new file mode 100644 index 0000000..2f185f2 --- /dev/null +++ b/Adding-Multi-region-Support.md @@ -0,0 +1,305 @@ +When making a hack, you may want the player to visit more than one region and with how Pokémon Emerald is set up, there is no way of identifying the region. + +This tutorial will walk you through how to add the support for multiple regions through the available mapsection IDs. How to do this is simple. + +Firstly, we need to open **[src/overworld.c](https://github.com/pret/pokeemerald/blob/master/src/overworld.c)** as there are two functions we need to change. + +Find `LoadCurrentMapData` and make the following change: +```diff +static void LoadCurrentMapData(void) +{ + sLastMapSectionId = gMapHeader.regionMapSectionId; + gMapHeader = *Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum); + gSaveBlock1Ptr->mapLayoutId = gMapHeader.mapLayoutId; + gMapHeader.mapLayout = GetMapLayout(); ++ gMapHeader.region = sMapsecToRegion[gMapHeader.regionMapSectionId]; +} +``` +This function handles the loading of the data for the currently loaded map +Right below that function, there is `LoadSaveblockMapHeader`, which handles loading the respective map data on save resume. We need to make the following change: +```diff +static void LoadSaveblockMapHeader(void) +{ + gMapHeader = *Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum); + gMapHeader.mapLayout = GetMapLayout(); ++ gMapHeader.region = sMapsecToRegion[gMapHeader.regionMapSectionId]; +} +``` +If you notice, we've add `gMapHeader.region` which loads data in `sMapsecToRegion` which we will be covering. + +Next, we need to open **[include/global.fieldmap.h](https://github.com/pret/pokeemerald/blob/master/include/global.fieldmap.h)** and find the struct `MapHeader` which should look like this: +```c +struct MapHeader +{ + /* 0x00 */ const struct MapLayout *mapLayout; + /* 0x04 */ const struct MapEvents *events; + /* 0x08 */ const u8 *mapScripts; + /* 0x0C */ const struct MapConnections *connections; + /* 0x10 */ u16 music; + /* 0x12 */ u16 mapLayoutId; + /* 0x14 */ u8 regionMapSectionId; + /* 0x15 */ u8 cave; + /* 0x16 */ u8 weather; + /* 0x17 */ u8 mapType; + /* 0x18 */ u8 filler_18[2]; + /* 0x1A */ u8 flags; + /* 0x1B */ u8 battleType; +}; +``` +`u8 filler_18[2]` is our point of interest here as it's simply used for padding the struct by two bytes. We will be using one of those bytes for our own `region` byte, like so: +```diff +struct MapHeader +{ + /* 0x00 */ const struct MapLayout *mapLayout; + /* 0x04 */ const struct MapEvents *events; + /* 0x08 */ const u8 *mapScripts; + /* 0x0C */ const struct MapConnections *connections; + /* 0x10 */ u16 music; + /* 0x12 */ u16 mapLayoutId; + /* 0x14 */ u8 regionMapSectionId; + /* 0x15 */ u8 cave; + /* 0x16 */ u8 weather; + /* 0x17 */ u8 mapType; +- /* 0x18 */ u8 filler_18[2]; ++ /* 0x18 */ u8 filler_18; ++ /* 0x19 */ u8 region; + /* 0x1A */ u8 flags; + /* 0x1B */ u8 battleType; +}; +``` +Now, we are going to be adding a new array that will be used for our new region field. +For the sake of this tutorial, we will be using Hoenn, Kanto and the Sevii Islands. +Open **[include/overworld.h](https://github.com/pret/pokeemerald/blob/master/include/overworld.h)** and add the following: +```diff ++enum { ++ REGION_HOENN, ++ REGION_KANTO, ++ REGION_SEVII ++}; +``` +These are IDs for the different regions with `REGION_HOENN` being 0, `REGION_KANTO` being 1 and `REGION_SEVII` being 2. +We are now going to add the array. +I prefer to put this into its own file, but you need to have the following somewhere in **[src/overworld.c](https://github.com/pret/pokeemerald/blob/master/src/overworld.c)**: +```diff ++static const u8 sMapsecToRegion[] = { ++ [MAPSEC_LITTLEROOT_TOWN] = REGION_HOENN, ++ [MAPSEC_OLDALE_TOWN] = REGION_HOENN, ++ [MAPSEC_DEWFORD_TOWN] = REGION_HOENN, ++ [MAPSEC_LAVARIDGE_TOWN] = REGION_HOENN, ++ [MAPSEC_FALLARBOR_TOWN] = REGION_HOENN, ++ [MAPSEC_VERDANTURF_TOWN] = REGION_HOENN, ++ [MAPSEC_PACIFIDLOG_TOWN] = REGION_HOENN, ++ [MAPSEC_PETALBURG_CITY] = REGION_HOENN, ++ [MAPSEC_SLATEPORT_CITY] = REGION_HOENN, ++ [MAPSEC_MAUVILLE_CITY] = REGION_HOENN, ++ [MAPSEC_RUSTBORO_CITY] = REGION_HOENN, ++ [MAPSEC_FORTREE_CITY] = REGION_HOENN, ++ [MAPSEC_LILYCOVE_CITY] = REGION_HOENN, ++ [MAPSEC_MOSSDEEP_CITY] = REGION_HOENN, ++ [MAPSEC_SOOTOPOLIS_CITY] = REGION_HOENN, ++ [MAPSEC_EVER_GRANDE_CITY] = REGION_HOENN, ++ [MAPSEC_ROUTE_101] = REGION_HOENN, ++ [MAPSEC_ROUTE_102] = REGION_HOENN, ++ [MAPSEC_ROUTE_103] = REGION_HOENN, ++ [MAPSEC_ROUTE_104] = REGION_HOENN, ++ [MAPSEC_ROUTE_105] = REGION_HOENN, ++ [MAPSEC_ROUTE_106] = REGION_HOENN, ++ [MAPSEC_ROUTE_107] = REGION_HOENN, ++ [MAPSEC_ROUTE_108] = REGION_HOENN, ++ [MAPSEC_ROUTE_109] = REGION_HOENN, ++ [MAPSEC_ROUTE_110] = REGION_HOENN, ++ [MAPSEC_ROUTE_111] = REGION_HOENN, ++ [MAPSEC_ROUTE_112] = REGION_HOENN, ++ [MAPSEC_ROUTE_113] = REGION_HOENN, ++ [MAPSEC_ROUTE_114] = REGION_HOENN, ++ [MAPSEC_ROUTE_115] = REGION_HOENN, ++ [MAPSEC_ROUTE_116] = REGION_HOENN, ++ [MAPSEC_ROUTE_117] = REGION_HOENN, ++ [MAPSEC_ROUTE_118] = REGION_HOENN, ++ [MAPSEC_ROUTE_119] = REGION_HOENN, ++ [MAPSEC_ROUTE_120] = REGION_HOENN, ++ [MAPSEC_ROUTE_121] = REGION_HOENN, ++ [MAPSEC_ROUTE_122] = REGION_HOENN, ++ [MAPSEC_ROUTE_123] = REGION_HOENN, ++ [MAPSEC_ROUTE_124] = REGION_HOENN, ++ [MAPSEC_ROUTE_125] = REGION_HOENN, ++ [MAPSEC_ROUTE_126] = REGION_HOENN, ++ [MAPSEC_ROUTE_127] = REGION_HOENN, ++ [MAPSEC_ROUTE_128] = REGION_HOENN, ++ [MAPSEC_ROUTE_129] = REGION_HOENN, ++ [MAPSEC_ROUTE_130] = REGION_HOENN, ++ [MAPSEC_ROUTE_131] = REGION_HOENN, ++ [MAPSEC_ROUTE_132] = REGION_HOENN, ++ [MAPSEC_ROUTE_133] = REGION_HOENN, ++ [MAPSEC_ROUTE_134] = REGION_HOENN, ++ [MAPSEC_UNDERWATER_124] = REGION_HOENN, ++ [MAPSEC_UNDERWATER_126] = REGION_HOENN, ++ [MAPSEC_UNDERWATER_127] = REGION_HOENN, ++ [MAPSEC_UNDERWATER_128] = REGION_HOENN, ++ [MAPSEC_UNDERWATER_SOOTOPOLIS] = REGION_HOENN, ++ [MAPSEC_GRANITE_CAVE] = REGION_HOENN, ++ [MAPSEC_MT_CHIMNEY] = REGION_HOENN, ++ [MAPSEC_SAFARI_ZONE] = REGION_HOENN, ++ [MAPSEC_BATTLE_FRONTIER] = REGION_HOENN, ++ [MAPSEC_PETALBURG_WOODS] = REGION_HOENN, ++ [MAPSEC_RUSTURF_TUNNEL] = REGION_HOENN, ++ [MAPSEC_ABANDONED_SHIP] = REGION_HOENN, ++ [MAPSEC_NEW_MAUVILLE] = REGION_HOENN, ++ [MAPSEC_METEOR_FALLS] = REGION_HOENN, ++ [MAPSEC_METEOR_FALLS2] = REGION_HOENN, ++ [MAPSEC_MT_PYRE] = REGION_HOENN, ++ [MAPSEC_AQUA_HIDEOUT_OLD] = REGION_HOENN, ++ [MAPSEC_SHOAL_CAVE] = REGION_HOENN, ++ [MAPSEC_SEAFLOOR_CAVERN] = REGION_HOENN, ++ [MAPSEC_UNDERWATER_SEAFLOOR_CAVERN] = REGION_HOENN, ++ [MAPSEC_VICTORY_ROAD] = REGION_HOENN, ++ [MAPSEC_MIRAGE_ISLAND] = REGION_HOENN, ++ [MAPSEC_CAVE_OF_ORIGIN] = REGION_HOENN, ++ [MAPSEC_SOUTHERN_ISLAND] = REGION_HOENN, ++ [MAPSEC_FIERY_PATH] = REGION_HOENN, ++ [MAPSEC_FIERY_PATH2] = REGION_HOENN, ++ [MAPSEC_JAGGED_PASS] = REGION_HOENN, ++ [MAPSEC_JAGGED_PASS2] = REGION_HOENN, ++ [MAPSEC_SEALED_CHAMBER] = REGION_HOENN, ++ [MAPSEC_UNDERWATER_SEALED_CHAMBER] = REGION_HOENN, ++ [MAPSEC_SCORCHED_SLAB] = REGION_HOENN, ++ [MAPSEC_ISLAND_CAVE] = REGION_HOENN, ++ [MAPSEC_DESERT_RUINS] = REGION_HOENN, ++ [MAPSEC_ANCIENT_TOMB] = REGION_HOENN, ++ [MAPSEC_INSIDE_OF_TRUCK] = REGION_HOENN, ++ [MAPSEC_SKY_PILLAR] = REGION_HOENN, ++ [MAPSEC_SECRET_BASE] = REGION_HOENN, ++ [MAPSEC_DYNAMIC] = REGION_HOENN, ++ [MAPSEC_PALLET_TOWN] = REGION_KANTO, ++ [MAPSEC_VIRIDIAN_CITY] = REGION_KANTO, ++ [MAPSEC_PEWTER_CITY] = REGION_KANTO, ++ [MAPSEC_CERULEAN_CITY] = REGION_KANTO, ++ [MAPSEC_LAVENDER_TOWN] = REGION_KANTO, ++ [MAPSEC_VERMILION_CITY] = REGION_KANTO, ++ [MAPSEC_CELADON_CITY] = REGION_KANTO, ++ [MAPSEC_FUCHSIA_CITY] = REGION_KANTO, ++ [MAPSEC_CINNABAR_ISLAND] = REGION_KANTO, ++ [MAPSEC_INDIGO_PLATEAU] = REGION_KANTO, ++ [MAPSEC_SAFFRON_CITY] = REGION_KANTO, ++ [MAPSEC_ROUTE_4_FLYDUP] = REGION_KANTO, ++ [MAPSEC_ROUTE_10_FLYDUP] = REGION_KANTO, ++ [MAPSEC_ROUTE_1] = REGION_KANTO, ++ [MAPSEC_ROUTE_2] = REGION_KANTO, ++ [MAPSEC_ROUTE_3] = REGION_KANTO, ++ [MAPSEC_ROUTE_4] = REGION_KANTO, ++ [MAPSEC_ROUTE_5] = REGION_KANTO, ++ [MAPSEC_ROUTE_6] = REGION_KANTO, ++ [MAPSEC_ROUTE_7] = REGION_KANTO, ++ [MAPSEC_ROUTE_8] = REGION_KANTO, ++ [MAPSEC_ROUTE_9] = REGION_KANTO, ++ [MAPSEC_ROUTE_10] = REGION_KANTO, ++ [MAPSEC_ROUTE_11] = REGION_KANTO, ++ [MAPSEC_ROUTE_12] = REGION_KANTO, ++ [MAPSEC_ROUTE_13] = REGION_KANTO, ++ [MAPSEC_ROUTE_14] = REGION_KANTO, ++ [MAPSEC_ROUTE_15] = REGION_KANTO, ++ [MAPSEC_ROUTE_16] = REGION_KANTO, ++ [MAPSEC_ROUTE_17] = REGION_KANTO, ++ [MAPSEC_ROUTE_18] = REGION_KANTO, ++ [MAPSEC_ROUTE_19] = REGION_KANTO, ++ [MAPSEC_ROUTE_20] = REGION_KANTO, ++ [MAPSEC_ROUTE_21] = REGION_KANTO, ++ [MAPSEC_ROUTE_22] = REGION_KANTO, ++ [MAPSEC_ROUTE_23] = REGION_KANTO, ++ [MAPSEC_ROUTE_24] = REGION_KANTO, ++ [MAPSEC_ROUTE_25] = REGION_KANTO, ++ [MAPSEC_VIRIDIAN_FOREST] = REGION_KANTO, ++ [MAPSEC_MT_MOON] = REGION_KANTO, ++ [MAPSEC_S_S_ANNE] = REGION_KANTO, ++ [MAPSEC_UNDERGROUND_PATH] = REGION_KANTO, ++ [MAPSEC_UNDERGROUND_PATH_2] = REGION_KANTO, ++ [MAPSEC_DIGLETTS_CAVE] = REGION_KANTO, ++ [MAPSEC_KANTO_VICTORY_ROAD] = REGION_KANTO, ++ [MAPSEC_ROCKET_HIDEOUT] = REGION_KANTO, ++ [MAPSEC_SILPH_CO] = REGION_KANTO, ++ [MAPSEC_POKEMON_MANSION] = REGION_KANTO, ++ [MAPSEC_KANTO_SAFARI_ZONE] = REGION_KANTO, ++ [MAPSEC_POKEMON_LEAGUE] = REGION_KANTO, ++ [MAPSEC_ROCK_TUNNEL] = REGION_KANTO, ++ [MAPSEC_SEAFOAM_ISLANDS] = REGION_KANTO, ++ [MAPSEC_POKEMON_TOWER] = REGION_KANTO, ++ [MAPSEC_CERULEAN_CAVE] = REGION_KANTO, ++ [MAPSEC_POWER_PLANT] = REGION_KANTO, ++ [MAPSEC_ONE_ISLAND] = REGION_SEVII, ++ [MAPSEC_TWO_ISLAND] = REGION_SEVII, ++ [MAPSEC_THREE_ISLAND] = REGION_SEVII, ++ [MAPSEC_FOUR_ISLAND] = REGION_SEVII, ++ [MAPSEC_FIVE_ISLAND] = REGION_SEVII, ++ [MAPSEC_SEVEN_ISLAND] = REGION_SEVII, ++ [MAPSEC_SIX_ISLAND] = REGION_SEVII, ++ [MAPSEC_KINDLE_ROAD] = REGION_SEVII, ++ [MAPSEC_TREASURE_BEACH] = REGION_SEVII, ++ [MAPSEC_CAPE_BRINK] = REGION_SEVII, ++ [MAPSEC_BOND_BRIDGE] = REGION_SEVII, ++ [MAPSEC_THREE_ISLE_PORT] = REGION_SEVII, ++ [MAPSEC_SEVII_ISLE_6] = REGION_SEVII, ++ [MAPSEC_SEVII_ISLE_7] = REGION_SEVII, ++ [MAPSEC_SEVII_ISLE_8] = REGION_SEVII, ++ [MAPSEC_SEVII_ISLE_9] = REGION_SEVII, ++ [MAPSEC_RESORT_GORGEOUS] = REGION_SEVII, ++ [MAPSEC_WATER_LABYRINTH] = REGION_SEVII, ++ [MAPSEC_FIVE_ISLE_MEADOW] = REGION_SEVII, ++ [MAPSEC_MEMORIAL_PILLAR] = REGION_SEVII, ++ [MAPSEC_OUTCAST_ISLAND] = REGION_SEVII, ++ [MAPSEC_GREEN_PATH] = REGION_SEVII, ++ [MAPSEC_WATER_PATH] = REGION_SEVII, ++ [MAPSEC_RUIN_VALLEY] = REGION_SEVII, ++ [MAPSEC_TRAINER_TOWER] = REGION_SEVII, ++ [MAPSEC_CANYON_ENTRANCE] = REGION_SEVII, ++ [MAPSEC_SEVAULT_CANYON] = REGION_SEVII, ++ [MAPSEC_TANOBY_RUINS] = REGION_SEVII, ++ [MAPSEC_SEVII_ISLE_22] = REGION_SEVII, ++ [MAPSEC_SEVII_ISLE_23] = REGION_SEVII, ++ [MAPSEC_SEVII_ISLE_24] = REGION_SEVII, ++ [MAPSEC_NAVEL_ROCK_FRLG] = REGION_SEVII, ++ [MAPSEC_MT_EMBER] = REGION_SEVII, ++ [MAPSEC_BERRY_FOREST] = REGION_SEVII, ++ [MAPSEC_ICEFALL_CAVE] = REGION_SEVII, ++ [MAPSEC_ROCKET_WAREHOUSE] = REGION_SEVII, ++ [MAPSEC_TRAINER_TOWER_2] = REGION_SEVII, ++ [MAPSEC_DOTTED_HOLE] = REGION_SEVII, ++ [MAPSEC_LOST_CAVE] = REGION_SEVII, ++ [MAPSEC_PATTERN_BUSH] = REGION_SEVII, ++ [MAPSEC_ALTERING_CAVE_FRLG] = REGION_SEVII, ++ [MAPSEC_TANOBY_CHAMBERS] = REGION_SEVII, ++ [MAPSEC_THREE_ISLE_PATH] = REGION_SEVII, ++ [MAPSEC_TANOBY_KEY] = REGION_SEVII, ++ [MAPSEC_BIRTH_ISLAND_FRLG] = REGION_SEVII, ++ [MAPSEC_MONEAN_CHAMBER] = REGION_SEVII, ++ [MAPSEC_LIPTOO_CHAMBER] = REGION_SEVII, ++ [MAPSEC_WEEPTH_CHAMBER] = REGION_SEVII, ++ [MAPSEC_DILFORD_CHAMBER] = REGION_SEVII, ++ [MAPSEC_SCUFIB_CHAMBER] = REGION_SEVII, ++ [MAPSEC_RIXY_CHAMBER] = REGION_SEVII, ++ [MAPSEC_VIAPOIS_CHAMBER] = REGION_SEVII, ++ [MAPSEC_EMBER_SPA] = REGION_SEVII, ++ [MAPSEC_SPECIAL_AREA] = REGION_KANTO, ++ [MAPSEC_AQUA_HIDEOUT] = REGION_HOENN, ++ [MAPSEC_MAGMA_HIDEOUT] = REGION_HOENN, ++ [MAPSEC_MIRAGE_TOWER] = REGION_HOENN, ++ [MAPSEC_BIRTH_ISLAND] = REGION_SEVII, ++ [MAPSEC_FARAWAY_ISLAND] = REGION_HOENN, ++ [MAPSEC_ARTISAN_CAVE] = REGION_HOENN, ++ [MAPSEC_MARINE_CAVE] = REGION_HOENN, ++ [MAPSEC_UNDERWATER_MARINE_CAVE] = REGION_HOENN, ++ [MAPSEC_TERRA_CAVE] = REGION_HOENN, ++ [MAPSEC_UNDERWATER_105] = REGION_HOENN, ++ [MAPSEC_UNDERWATER_125] = REGION_HOENN, ++ [MAPSEC_UNDERWATER_129] = REGION_HOENN, ++ [MAPSEC_DESERT_UNDERPASS] = REGION_HOENN, ++ [MAPSEC_ALTERING_CAVE] = REGION_HOENN, ++ [MAPSEC_NAVEL_ROCK] = REGION_SEVII, ++ [MAPSEC_TRAINER_HILL] = REGION_HOENN ++}; +``` +Don't forget to declare it somewhere in **[src/overworld.c](https://github.com/pret/pokeemerald/blob/master/src/overworld.c)** like so: +```diff ++static const u8 sMapsecToRegion[]; +``` +If I explained this correctly and didn't miss anything out, you should be able to compile the changes using `make` and the game will now use the region field for the current map the player is on. +With this, you can do things like add battle music that changes depending on the region the player is in. I will update this tutorial at some point with how you can do this. \ No newline at end of file