Fire Emblem: Shadow Dragon (FE11) documentation

Battle Animations

Based on the existing research from Blazer (mirrored on Laqieer’s GitHub), along with some hints from HeartHero’s “Accessible FE12 Hacking” post about battle animations, I have been able to piece a bit more together about how Battle Animations are structured in DSFE.

It’s not perfect or totally solved yet (I haven’t been able to figure out the correct palette data, or if there is a script format embedded inside of the animations), but I’ll try to document as far as I’ve been able to get for now.

First, a GIF export of the ARCHER_F dodge animation using the data extracted from the /data/b/ARCHER_F binary file:

frames_1

Details

What a weird format!!

As HeartHero mentions in their “Accessible FE12 hacking” post, each binary file in the /data/b directory represents an “archive” for that particular class’s animations. I use the term “archive” because the binary file appears to consist multiple files.

Each class has one “archive” for its unarmed animation, and one “archive” per weapon that class can wield. Example: LORD for the unarmed Lord class, and LORD_SW for the Lord class wielding a sword.

The first part of the binary file is a list of pairs containing the offsets to an animation (e.g. dodging, attacking, etc.), as well as that animation’s size within the binary. For example, I’ll use ARCHER_F. I assume that the blanks here could be filled by other animations, since ARCHER_F_BO has more entries filled out up front.

0x00000100 0x00002CF0 -> anim starts at 0x100, of size 0x2CF0
0x00000000 0x00000000
0x00000000 0x00000000
0x00000000 0x00000000
0x00002DF0 0x00004A5C -> anim starts at 0x2DF0, of size 0x4A5C
0x00000000 0x00000000

If we go to the location of that first animation, we can see data that looks like how other DSFE files are stored – it has a file “header”:

00 | word | pointer to end of animation
04 | word | pointer to this animation's "pointer table"
08 | word | number of entries in this animation's "pointer table"
0C-20 | word | blank?

We’ll use ARCHER_F’s first animation as an example:

@ 0x100 + 0x00, we have the offset to the end of the current animation. To calculate, add the base of the animation to the value at this offset to get the final offset of the animation. For ARCHER_F, it’s 0x2CF0 + 0x100 = 0x2DF0.
@ 0x100 + 0x04, we have the offset to this animation’s pointer table. To calculate it, we need to add two values: the base of this animation (0x100), and the space taken up by the “animation header” (0x20). For our example, ARCHER_F, it’s 0x2C58 + 0x100 + 0x20 = 0x2D78.
@ 0x100 + 0x08, we have the number of entries in the pointer table. For ARCHER_F, there are 0x1E (30) entries in the first animation’s pointer table.

We can go to 0x2D78 to look at the pointer table. Each pointer should be resolved relative to the start of its animation, with an additional 0x20 added to account for the “file header”. So for ARCHER_F’s first animation, when we see 0x14 in the pointer table, it really means 0x14 + 0x100 (start of the animation) + 0x20 (size of file header) = 0x134 in the binary file.


Picture: ARCHER_F’s pointer table (highlighted)

Below, I’ll show the values of the pointer table in the following format:

[pointer as shown in the table] => [actual location in the binary file]: [value at that location]
@ ARCHER_F's pointer table at 0x2D78. There are 0x1E (30) pointers in the table.
0x00000014 => 0x134: 0x1C
0x00000018 => 0x138: 0x13C (pointer to ?)
0x00000020 => 0x140: 0x1BC (pointer to first anim frame, compressed)
0x00000028 => 0x148: 0xEC (pointer to ?)
0x00000030 => 0x150: 0x4DE (pointer to second anim frame, compressed)
0x00000038 => 0x158: 0xF2 (pointer to ?)
0x00000040 => 0x160: 0x81B (pointer to third anim frame, compressed)
0x00000048
0x00000050
0x00000058
// (more)

The compression scheme of the frame data is the same as the “FEDS portrait compression”. Nintenlord’s decompression utilities can be used to decompress the individual frames. As I understand, it’s some sort of run-length encoding (RLE) used for the DSFE games.

There are still a lot of unknowns but hopefully this can be used as a building block for further research.

6 Likes