-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Custom Border Dimensions
Every map in the game is surrounded by a repeating group of metatiles called the border. In Emerald, these borders are always 2x2, while in FireRed/LeafGreen they can have different dimensions.
This tutorial will go over the steps to allow borders with different dimensions to be created in Emerald.
Note that Porymap version ≥ 4.0.0 supports this feature, so after these changes are made you will be able to edit the border dimensions in Porymap like you would for a pokefirered project.
First we will add 2 new fields to struct MapLayout
in include/global.fieldmap.h to hold the width and height of the border.
struct MapLayout
{
/*0x00*/ s32 width;
/*0x04*/ s32 height;
/*0x08*/ u16 *border;
/*0x0c*/ u16 *map;
/*0x10*/ struct Tileset *primaryTileset;
/*0x14*/ struct Tileset *secondaryTileset;
+ u8 borderWidth;
+ u8 borderHeight;
};
Next we need to use these new fields when we're trying to access border data. Depending on which repo you're using, find the definition of GetBorderBlockAt
in src/fieldmap.c, and replace it with the version below.
#define GetBorderBlockAt(x, y) ({ \
u16 block; \
s32 xprime; \
s32 yprime; \
\
const struct MapLayout *mapLayout = gMapHeader.mapLayout; \
\
xprime = x - MAP_OFFSET; \
xprime += 8 * mapLayout->borderWidth; \
xprime %= mapLayout->borderWidth; \
\
yprime = y - MAP_OFFSET; \
yprime += 8 * mapLayout->borderHeight; \
yprime %= mapLayout->borderHeight; \
\
block = mapLayout->border[xprime + yprime * mapLayout->borderWidth] | MAPGRID_COLLISION_MASK; \
})
static inline u16 GetBorderBlockAt(int x, int y)
{
u16 block;
s32 xPrime;
s32 yPrime;
const struct MapLayout *mapLayout = gMapHeader.mapLayout;
xPrime = x - MAP_OFFSET;
xPrime += 8 * mapLayout->borderWidth;
xPrime %= mapLayout->borderWidth;
yPrime = y - MAP_OFFSET;
yPrime += 8 * mapLayout->borderHeight;
yPrime %= mapLayout->borderHeight;
return (mapLayout->border[xPrime + yPrime * mapLayout->borderWidth] | MAPGRID_COLLISION_MASK);
}
Now we need to specify what the border dimensions are for each map layout. Because Emerald's are all 2x2 by default, this can be done quickly with a find and replace. In data/layouts/layouts.json, make the following substitution.
Find:
"primary_tileset"
Replace:
"border_width": 2,
"border_height": 2,
"primary_tileset"
The tool that converts layouts.json to data needs to know what to do with these fields. Update generate_layout_headers_text
in tools/mapjson/mapjson.cpp.
<< "\t.4byte " << json_to_string(layout, "secondary_tileset") << "\n";
- if (version == "firered") {
text << "\t.byte " << json_to_string(layout, "border_width") << "\n"
<< "\t.byte " << json_to_string(layout, "border_height") << "\n"
<< "\t.2byte 0\n";
- }
text << "\n";
Note the .2byte 0
is because structs are aligned to 4 byte boundaries. The new border width/height fields are 1 byte each, so we need an additional 2 bytes of padding. This may not be true if you've already made other changes to struct MapLayout
, or if you use different sizes for the new dimension fields.
-
Make sure to
make clean
and rebuild before attempting changes to ensure mapjson and all the map data gets rebuilt with the new map layout. -
Open your project with Porymap, and under the
Maps
tab inOptions -> Project Settings...
check theEnable Custom Border Size
option. Then selectOK
and reload your project. -
You should now be able to change the size of the border with the
Change Dimensions
button while on theMap
tab.