Every textual character in FF1 GBA (and in FF2, I assume) is encoded in the ROM in 2 bytes, and not one, as is common in many ROMs. The table below should help you decode the text in the ROM. This is not exhaustive; just my observations as I worked on my mod.
Textual encoding in hex
|A =||8260||a =||8281||J =||8269||j =||828a||S =||8272||s =||8293|
|B =||8261||b =||8282||K =||826a||k =||828b||T =||8273||t =||8294|
|C =||8262||c =||8283||L =||826b||l =||828c||U =||8274||u =||8295|
|D =||8263||d =||8284||M =||826c||m =||828d||V =||8275||v =||8296|
|E =||8264||e =||8285||N =||826d||n =||828e||W =||8276||w =||8297|
|F =||8265||f =||8286||O =||826e||o =||828f||X =||8277||x =||8298|
|G =||8266||g =||8287||P =||826f||p =||8290||Y =||8278||y =||8299|
|H =||8267||h =||8288||Q =||8270||q =||8291||Z =||8279||z =||829a|
|I =||8268||i =||8289||R =||8271||r =||8292|
|0 =||824f||1 =||8250||2 =||8251||3 =||8252||4 =||8253||5 =||8254|
|6 =||8255||7 =||8256||8 =||8257||9 =||8258|
Final Fantasy 1 Item Symbols
|Gloves||874c||White Magic||874d||Black Magic||874e||Potion||874f||Bag||8750||Tent||8751|
Final Fantasy 2 Item Symbols
|Gloves||8312||Book||8313||Trash||8314||Fist||8315||White Magic||8316||Black Magic||8317|
A simple 00 can end a string.
What this means
The name of the weapon “Rapier” is encoded in the ROM as shown below. You can fire up your hex editor, and search for the hex string below (without spaces) to find in in the ROM. For convenience, you can copy the string from the page here: 8740827182818290828982858292.
String locations and pointers that I have identified
First of all, what is a pointer?
Simply put, it “points” to a particular place in the GBA ROM. Most of these pointers are 4 bytes in length, stored in Little Endian format. The last byte generally is 08… since the ROM is stored in GBA memory starting at location 0×08000000 when it is loaded into an emulator. For instance, if you searched for the string above, you found it at location 0×19a687. Following the rule above, the pointer would point to this place in the ROM by making that pointer 0×0819a687. However, since it would be stored 4 byte Little Endian format, that pointer would look like 87a61908 in the ROM itself. Are you following me? Good job!
String pointer locations in the ROM
Armed with this information, the string pointers at these locations will point you elsewhere in the ROM to find the actual strings that you may want to edit. Each actual string is of variable length, and each are terminated by a 00. If you need more space, you could actually edit the pointer to point to another location in the ROM (be careful that you don’t overwrite actual code) and write your string there (obviously, terminating it with a 00). There appears to be extra room for your own strings beginning at ROM location 0xee1000 and all the way through the end of the file, at 0xffffff.
In almost every case, pointers in the ROM either directly precede or procede the data to which the point. But as I’ve pointed out, they don’t necessarily have to.
If I don’t provide an ending for the lists below, it was because I was too lazy to find its end. You can always email me with that info if you find it yourself. And lastly, as you’ll see below, some information is in the ROM in multiple locations. For instance, to properly change a Class Name, you’ll have to edit it in three separate locations.
|Class Names:||0×1da85c — 0×1da937||0×1e08a4 — 0×1e097f||0×1e13b4 — 0×1e148f|
|Pointers to Class Names:||0×1da938 — 0×1da967||0×1e0980 — 0×1e09af||0×1e1390 — 0×1e13bf|
|Item Names:||0×19a261 — 0×19a659|
|Weapon Names:||0×19a65a — 0×19ac05|
|Armor Names:||0×19ac06 — 0×19b319|
|Quest Item Descriptions:||0×19ac1a — 0×19bc9e|
|Item Descriptions:||0×19bc9f — 0×19c40c|
|Weapon Descriptions:||0×19c40d — 0×19d454|
|Armor Descriptions:||0×19d455 — ??|
|Spell Names:||0×1a8668 — ??||0×1a021d — ??|
|Spell Descriptions:||0×1a0787 — 0×1a164e|
|Monster Attacks:||0×1a05bb — 0×1a0786|
|Monster Names:||0×2257ac — ??|
|Pointers to Dialogue:||0×210370 — 0×21177f|
|Monster Attacks:||0×1a05bb — 0×1a0786||0×211780 — 0×212b7f|