Fire EmBot: Already made?

Hi everyone! I want to create a bot capable of playing FE7 automatically like a person would: reading the information from the screen and introducing the inputs on the emulator to beat every level.

I searched the internet and looked at some topics on the blog, but I couldn’t find anything related, so the first question i have is there already a topic or project like this that I can consult?

If the answer is “no” then I have some ideas on how to get started, and the main problem I want to tackle is how to get the map information. I thought on two alternatives: accessing the in-play map file each turn to read the terrain cost, accessibility, player/enemy positioning, events (like “seize” options, buy from stores, etc.) of each file if possible; or gathering the same information via screenshots (which I think will be way more difficult). I have no idea about reading game files or how can I extract the mentioned information, so I’d be very grateful if you could point me to some topic I can consult for documentation on file manipulation.

Also, if you have any suggestion on how can I gather the map information on each turn, that would be super useful to me. Thanks to everyone in advance!

The closest thing to that that I know is this AFK Romhack AI v2.1 - seize, villages, and more
But it’s essentially just giving control of the blue units to the AI while making that AI slightly smarter than red/green units and adding things like visiting villages.

If you open a game in FEbuilder’s debugger by pressing F5, you can see a lot of RAM data that is documented there which you can make your program read during play.

2 Likes

I want to try to run the bot’s script outside the game itself, but I’ll definitely look at the AFK Romhack you linked when I reach that stage of development.

As for the RAM data of FEbuilder, I think I found an interesting MapID value but still don’t know how to use it or how can I read the map information using an external script.

I’d also recommend checking out @StanH’s GBA Fire Emblem for Screen Readers (GitHub). It’s not for the same purpose as what you’re describing, but it demonstrates a method for reading various information from the game’s memory using Lua.

It’s currently hard-coded to support FE8U, but you can reference various community resources such as FEBuilder, the decompilations of the GBAFE games, and other documentation threads to locate important addresses for the other games/versions.

Good luck! This seems like a cool project!

3 Likes

I believe the procs lua script StanH made also writes to ram whenever the game reaches a certain line of code as a bugfix, so lua scripts could also write to ram as player inputs or to tell the game what to do. Vba-rr supports lua scripting iirc.

Fe8u has far more documentation than fe7, so be prepared to do a lot of digging in no$gba yourself if you must make this for fe7 and not fe8. Good luck

2 Likes

This is truly an interesting idea. Technically speaking, as long as you can dump the entire ROM file and also instantly refresh the data in IWRAM and EWRAM, you can obtain the complete information at any given moment. The subsequent work involves analyzing the data, making decisions, and guiding button inputs. Theoretically, if these tasks are handed over to a modern CPU, I believe it wouldn’t even cause any lag.

1 Like

Thank you all for your suggestions! :blush:

Since I have no idea of Lua, this is the approach I’m taking :point_up:.

So far I’ve discovered a few things:

  1. The ROM stores a pointer list to every level map at address 0xC9C9C8. Browsing through this list, we can see a pointer to each map (and other things I haven’t looked into yet) in a format like 0x8######. I’ve got this information by looking at FEBuilder, as you can see on the box next to the “Pointer” button on Advanced Editors → MAP PLIST Editor (I couldn’t upload an image, sorry :sweat_smile:).

  2. It seems that 0x08000000 is a common ROM base for GBA games, so substracting this base to the map pointers mentioned before gives us the map tileset information! For example, the first map for Lyn’s story is pointed at 0x0836AF00, therefore, the information of this map is located at 0x36AF00, which we can verify by looking at the map editor.

  3. Reading the information on that memory direction I’d found out that the 6th and 7th bytes on the returning string gives us information about the size of the map! In this case the string goes 0F 0A, which is equivalent to a 15x10 map. Once again, this can be seen on the map editor, and I’ve tested this for other maps as well and it seems to be correct!

This three conclusions are probably right for the other GBA games as well, but I haven’t tried it.

I’ve yet to figure out a way to read the properties of every individual tile & then try to read the IWRAM and EWRAM information at any given time to see the position of every unit (I have no idea how to do the latter hahaha).

Thanks again for all your comments!

Your first point is referring to the PTABLE, which is an indexed table of various things retaining to map data. Each entry in the PTABLE can be a pointer to one of the following:

  • Tileset Object
  • Tileset Palette
  • Tileset Config
  • Tileset Tile Animations 1 (Actual animation)
  • Tileset Tile Animations 2 (Palette shifting used in ch18)
  • Map Data
  • Tile Changes
  • Event Data

It’s probably useful to know that most of the time, only the application of the config to the object matters for tilesets, and hence then the map data/tile changes and events
So around 25-30% of the PTABLE is useless for a bot.

You can grab info about specific tiles by using the relevant maps.

############
MAPS:
Map size: 202D200 (FE6) 202E3D8 (FE7) 202E4D4 (FE8) 202E4D0 (FE8J): Has length and height as halfwords. Note: These are 1-aligned, not 0-aligned.

There's a table of pointers immediately afterwards:

FE6		FE7		FE8		Description
202D204 202E3DC	202E4D8	Unit map (allegiance byte)
202D208 202E3E0	202E4DC	Terrain map (tile id)
202D20C 202E3E4	202E4E0	Movement map (movement cost to move to a specific tile when selecting a character; 0xFF else)
202D210 202E3E8	202E4E4	Range map (nonzero if square can be reached/targeted)
202D214 202E3EC	202E4E8	Fog (nonzero if square can be seen)
202D218 202E3F0	202E4EC	Unknown (code at 18592 in FE8 suggests this is a bitfield, which isn't spectacularly helpful)
202D21C 202E3F4	202E4F0	Backup movement map (seems to be used when exiting the moveable tile zone and entering on another tile to calculate the new path, also used for enemy movement?) (also filled in with squares covered by magic seals prior to displaying red squares when selecting a unit in FE7) (AI stores potential target (str + weapon might)/2 for calcs)
202D220 202E3F8	202E4F4	Middle of the unit map? Seems unused
202D224 202E3FC	202E4F8	Middle of the unit map? Seems unused

Quote from Teq Doq
https://www.dropbox.com/scl/fo/otz4z799wu08jb5or937h/ANJpaKaLANAJnCs1SK9j8F4/Tequila/Teq%20Doq?e=1&preview=Better+Notes.txt&rlkey=1yywzhb79g9qiax0rdpawj925&dl=0

More recent documentation for the same thing:
https://github.com/FireEmblemUniverse/fireemblem8u/blob/1193deefdd322c261df42d561e21002957ccc08d/include/bmmap.h#L31

Addresses of decomp names for things:
https://fireemblemuniverse.github.io/fireemblem8u/symbols.txt

2 Likes

There’s a post about tilemaps (terrain data and colors) and spritemaps (the actual layout of the map, and which tiles are used), and how to read those programmatically, here: Tile Configurations - #7 by x8Reaper. I did this for FE7, for a project I’m currently working on.

I think this is exactly what I need. Thank you!

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.

Awesome!
Is this planned for FE6, FE7 and FE8? I would like to see a new bot being able to play all these games. According to the messages of the other users there is already a bot but maybe someone can improve it?