Tile Configurations

So from what I’ve seen, not many people know much about tile configurations and how they work. Let’s change that!

If you have any knowledge whatsoever about tile configurations and how they work, please share it here on this topic.

From what I’ve seen, it is possible that each configuration acts as a table for each individual tile in its set. Also, not all of the tile configurations are the same size. Leading to the notion that the size is dependent on how many tiles in a set are used in game and how many remain blank.

I thought I read something about that a long time ago in I think it was Hextator’s doc but I can’t seem to find it and where’s the fun in that anyway so I looked on my own.

“Tile Config” is compressed (probably lzss but it shouldn’t matter), and when decompressed it has two fixed size parts: the first 0x2000 bytes define how each tile looks (bg tile bases), while the second 0x400 assigns terrain indices to each tile.

(This means that the size should be a fixed 0x2400? Maybe some tile sets don’t use the full 0x400 terrain bytes when they don’t need to? I decompressed tile config in chapter data slot 3 and got a 0x2400 byte file so idk)

appearance

the 0x2000 bytes are an array of 0x400 (1024, one per possible raw tile index, in order) 8 byte entries that are layed out the following way:

  +0 | short (2byte) | tile base for top left corner of tile
  +2 | short (2byte) | tile base for top right corner of tile
  +4 | short (2byte) | tile base for bottom left corner of tile
  +6 | short (2byte) | tile base for bottom right corner of tile

“tile base” is the term I use to refer to the base value that will be eventually modified to be output to a bg map (see gbatek for details about that), where the tile number is as with obj1 gfx mapped at tile 0 and obj2 gfx mapped at tile 0x200, palette as with map palette mapped at 0.

This structure is standard enough that you can just put the tile config pointer in the GBAGE Tile Control window with the corresponding obj gfx and palette and you’ll get something correct.

The function that does the “transformation” (reading from the tile config and putting to a bg map) is at FE8U:8019B18.

terrain

This one’s easier. the 0x400 bytes is a 0x400 entry array of bytes, with each entry being which terrain this tile is assigned to.

The function that updates the terrain map from tile config is at FE8U:8019A64. At FE8U:859A9D0 is a pointer to the second part of the decompressed tile config, where the terrain lookup is located.


Raw tile indices are kinda weird because they have a “step” of 4 (the first tile index is 0, the second is 4, the third is 8, etc). The arrays are indexed by floor(<raw tile index> / 4) (Well, the terrain array is, the “appearance” array will result in weird tile mixes graphics for raw tiles non divisible by 4).

Tile Config is decompressed at FE8U:80198D8 to FE8U:2030B8C and should stay there for as long as the game is running.

2 Likes

How were you able to decompress the configuration?

I found a note I left when I was making FEBuilderGBA.
The way to decide whether the tile is Plain, River or Woods is as follows.

For example, if the chipset is 0x208
What the terrain is,
1 * 2 bytes from chipset_config[(0x208 >> 2) + 0x2000].

//The calculation formulas obtained when decomposing the disassembler are as follows.
//chipset_config[ ((0x208 >> 3)*2) + 0x2000 ]
//
//Also, chipset_config is compressed with lz77, please decompress beforehand.
//

struct terrain
{
    u8 terrain_data1;
    u8 terrain_data2;
}; //sizeof() == 2

terrain_data expresses the terrain as one byte like a meadow or a treasure box.
Which one of the two data is referred to is determined by the 0x4th bit of the map chip.

if ( 0x208 & 0x4 ) terrain_data2
else               terrain_data1

terrain_data is the terrain ID used in the movement cost table and terrain name table.
terrain name table is SJIS C language string in FE8J. (null termination.).
However, in FE8U, it is a text ID.(ushort[])

I used this tool because I had that on hand but anything that can decompress standard gba lz77 data should work.

With FEBuilderGBA, you can compress and decompress lz77 from MENU -> Tool->LZ77 Tool.

Just a Summary of How Map Data and Tileset Data Work (Programmatically)

Okay… I’m new to FE/GBA hacking/editing, but I’m working on a project for Uni, and needed a programmatic way to figure out the terrain on each map. It took me a while to get it, and I really wouldn’t be posting this and bumping a 7yr old thread unless I thought it was REALLY necessary (I feel like this thread could be worded a lot better lol). Here’s how to pull map data for FE7 (the prologue is my current example):

– THE MAP ITSELF (Use FEBuilder) - Map data (tile-ID-wise) is stored at 0x36AF00 –

  • This data is 0x12C (300 bytes) long, and LZ77 GBA-style compressed
  • After pulling and decompressing the data, the first two bytes are the width and height (“0F 0A” for the Prologue, which is (15 x 10))
  • After this, every 2 bytes is little-Endian formatted tile IDs (“0A B0 (first tile) 0A B4 (second tile) 0C 9C (third tile), etc.”)
  • These tile IDs MATCH the ingrained tile IDs in FEBuilder, if you open Tileset Palette and click on the tiles
  • (It’s the ‘No.’, or the ‘Tile Base’, in @StanH’s words)

– APPEARANCE AND TERRAIN - Map data (terrain-ID-wise) is stored (for the Prologue) at 0x35EE10 –

  • This data is 0x2400 (9216 bytes) long, and LZ77 GBA-style compressed

  • After pulling and decompressing the data, the first 0x2000 bytes are the

  • “Upper left, Upper Right, Bottom Left, Bottom Right” little-Endian-formatted addresses (Each tile uses 8 bytes)

  • After this, the last 0x400 bytes are the TERRAIN IDs that the tiles belong to, IN ORDER, one byte per tile

  • Thus, tile 1 belongs to terrain 0x00, tile 2 to 0x20, tile 0x3 to 0x13, etc.

  • Thus, you can figure out the hex address to the terrain ID for a tile by taking the (tile ID / 4), and adding + 0x2000

    • Tile 0x0AB0 / 4 = 0x2AC (which also happens to be the GID, if you download the map as a .tmx in FEBuilder)
    • 0x2000 + 0x2AC = 0x22AC
    • The byte at 0x22AC = 0x11 (which is the Mtn terrain ID, which IS the correct ID for Tile 1 (0x0AB0) of the Prologue)

Hope this helps someone else out! Like I said, I’m new, and it took about 3 days to put all this together, but it’s (relatively) easy if you use FEBuilder and look at the data side-by-side, in HxD.

Edits:

– Some other useful information –

  • Remember that not all maps are the same size, so make sure your script doesn’t ONLY decode +0x300 bytes from the given map data address (it’ll throw errors anyway, because of how LZ77 compression blocks work)
  • Tileset data IS always the same… every tileset is 0x2400 bytes.
  • Tilesets are just a way to simultaneously map terrain data and graphical data to a massive png of 1024 tiles. Lots of tilesets are reused (terrain-data-wise), and it’s just the graphical palette that changes.
1 Like