Fire EmBot: Already made?

I have a better way… (and I’ll explain why it’s better):

– FE Map Changes –

Think about some of the levels from FE7… like when you get Matthew… that map changes a lot. And if you pull the map from ROM then you are only getting the map, pre-level-start, which doesn’t include changes (you’ll read “roof” for the tile codes of the castle, etc.). Thus… we have a problem. Solution? Read from RAM.

– Reading from RAM –

The biggest issue is that things move around. So as any experienced hacker would know, you use pointers instead… pointers do just that… point to where other things are. That way, pointers can be static (relatively speaking), but actual data can be allocated where available in RAM (in the case of BizHawk, this is “EWRAM”, or External Working RAM). @Vesly linked to a VERY useful document (the dropbox one) that I had to parse through, but it IS accurate, for FE7 at a minimum (that’s all I’m working with). For map data, there is one byte at 0202E3D8 (width) and one at 0202E3DA (height). Now, you may say, as I did “but I can only enter 6 chars in BizHawk RAM Search”… yup. That’s because the offset for EWRAM is always +0x02000000. So you can search for “02E3D8” instead, in EWRAM in BizHawk and find the width.

– Where Map info is actually stored –

Okay, so now that you know HOW to read EWRAM, you need to know where to look. So:

  • 02E3E0 is the “pointer to the terrain table”… it is a pointer TO “row pointers”… might sound confusing but hear me out lol.
  • If you read 4 bytes, starting at 02E3E0, you’ll get another address… this is the pointer to Row 0 (0, 0) = Top Left… 4 bytes after that is the pointer to Row 1. Four after that is Row 2, etc., etc. (Thus, you can see how 02E3E0 points to a list of pointers).
  • FINALLY, after following the double pointer jumps, you get to a list whose length is the width of the map (for each row). So for the first level, you can read 15 individual bytes… each byte is a terrain ID (identical to those in the “Tile Names” editor of FEBuilder).

Thus, in summary… follow the first pointer, from @Vesly’s doc to a list of pointers… follow each pointer to each row, and then read one byte X number of times, where X is the width, and that’ll build the actual terrain of the map.