Skip to content

Custom Border Dimensions

GriffinR edited this page May 31, 2022 · 6 revisions

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.

1. Add dimension fields to MapLayout

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;
};

2. Use dimensions fields to read border data

Next we need to use these new fields when we're trying to access border data.

In src/fieldmap.c, find the definition of the macro GetBorderBlockAt 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; \
})

3. Add border dimension data

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"

4. Update the mapjson tool

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 " << layout["primary_tileset"].string_value() << "\n"
-             << "\t.4byte " << layout["secondary_tileset"].string_value() << "\n\n";
+             << "\t.4byte " << layout["secondary_tileset"].string_value() << "\n"
+             << "\t.byte " << layout["border_width"].int_value() << "\n"
+             << "\t.byte " << layout["border_height"].int_value() << "\n"
+             << "\t.2byte 0\n\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.

5. Rebuild and test in Porymap

  • 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.

  • If you've opened your project with Porymap before there will be a porymap.project.cfg file in your root folder. In that file, set use_custom_border_size to 1.

  • Open your project with Porymap and you should now be able to change the size of the border with the Change Dimensions button while on the Map tab.

Clone this wiki locally