Okay, so we’ve got quite a few fancy tools to play with: FEditors, Nightmares, and the rest of our array of a toolbelt.
With a diverse cast of different programs that put an interface to ROM hacking, I’ve often found that the fundamentals are oft poorly understood by most newcomers to the hobby. The most basic of all tools: the hex editor. And that thought inspired me to write this. When you understand the fundamentals, the interfaces become much easier to navigate.
Check this out - I’m going to insert a map sprite into my FireShell port of Exalted Legacy for a demonstration. First, I need some free space, which I’ve got in the D00000-E00000 range, I’ve devoted the D60000 range to graphics, so continuing where I’d left off I’ll be inserting my map sprite at D65720.
All’s clear. So let’s open up the tool.
And insert the map sprite with “import a bitmap.”
Pick your file, uncheck the “import palette” and “abort if image bigger” boxes, and slap that OK button.
Bing bang boom, the witch is dead and we’re off to the land of Oz.
Which looks a little something like this. This is what GBA Graphics Editor just did.
This falls under what I’m calling “micro editing” (I’m writing this up in layman’s terms - don’t get too mad at me, technical people); it deals exclusively with arrays, pointers, and raw data. When I imported the image of @Agro’s sword armor standing map sprite, I created the
raw data for the image (formatted properly for the game’s engine) in my ROM.
Which I will then write a
pointer to in the Standing Map Sprite Editor.nmm.
Like so. Pretty simple operation, no? The Nightmare interface allows for a marked hex editing experience, rather than looking at the raw data. Most nightmare modules handle
structured arrays of data. I just edited the standing map sprite pointer in a structured array (in FireShell it’s been pre-expanded, so you just go to the next blank entry and add what you want).
See those highlighted words? It’s definition time, folks:
[quote]Raw Data: 10 00 03 00 3E 00 00 F0 01 F0 01 F0 01 F0 01 F0 01 00 1A 00 FF FF F0 14 80 1D 7F 00 1E F0 00 99 FC 00 8F 99 FC F0 98 00 99 CC 8F 98 99 75 AF 99 00 A9 C7 FF AA 7A 98 00 7F 00 77 98 F0 98 78 87 98 7F 00 FC 00 99 F8 8C 0F C9 F9 00 8C F8 77 87 77 F8 8C 88 00 7C 99 C9 CC 77 FF 99 99 00 79 F7 99 99 78 F8 F0 A8 00 79 14 00 9F 78 44 00 F0 00 57 45 00 00 41 31 00 DD 00 1F FF D0 FD 98 F9 DD FD 00 C9 FA D0 FD FF FF 98 99 00 F7 F9 91 89 FF 0F 11 F9 00 0F 00 2E 11 F8 00 32 2E 02 11 DD FF 32 2E D1 00 04 F3 3F DD DD F0 9F F0 01 F0 01 F0 01 F0 01 20 FB F8 10 DB F0 19 60 FB 10 DB C0 FB 75 FF AA 0B 5A C7 00 FF 20 FB 97 10 DB 90 FB 0B
It can be pretty much anything referenced by the game. From an imported map sprite to new music, new instrument samples, a new portrait or animation, new text, etc. and so on and so forth.
Pointers: Written in reverse byte order. Reference the Nightmare edit above: what the interface shows us as 0x8D65720 is, in raw data, actually 20 57 D6 08. When you point to expanded free space beyond offset 00FFFFFF, you’ll use 09 for pointers instead of 08. Pointers are what allow the game to actually find raw data.
Offset: Pointers refer to an offset in the ROM - we saw this in the hex editor above, which was at D65720. Sometimes, “offset” is erroneously used interchangeably with “pointer” and vice versa throughout the different tools. It’s just a location in the file.
Structured Arrays: To put it simple, arrays list data in an organized way to be read by the game. The character data array (modified by Character Editor.nmm) modifies the names, portraits, stats, growths, and many other attributes for each unit slot.
Pointer Arrays: A specific variant of an array that lists only pointers to raw data. The array at C9C9CC (the ever-vital event reference array - which contains the values for tilesets, map palettes, mid-chapter tile changes, tile configurations, and the events themselves) is simply a list of pointers to the data it sorts, in order to be referenced in other arrays.[/quote]
When you get into modifying the way the game handles raw data, arrays, and such, you’re getting into what I’m laymanly calling “macro editing” (because if this distinction works for economics, it’ll fucking work as a metaphor for this tutorial).
The majority of the community (including myself) mainly focuses on micro editing. For example, when using the Custom Animation Editor.nmm, you use the pointer address in the dropdown menu when specifying the class’s animation pointer in Class Editor.nmm. You aren’t, however, just limited to those dropdown entries - all those really do is write your
raw data for you. You could write an animation list at any free space and point to it all the same.
The last thing to know is how to tell where your data ends - when writing to free space it’s pretty simple.
Skip two lines for good measure. Just try to catch where it stops looking like data and goes back to looking like garbage 00s and FFs with those random others strewn about.
Our programs are numerous, and - let’s face it - a little shoddy at times. But hopefully this back-to-the-basics lesson helps strengthen your understanding of the fundamentals. All these interfaces really do is spit out: 2E 00 00 EA 24 FF AE 51 69 9A A2 21 3D 84 82 0A 84 E4 09 AD 11 24 8B 98 C0 81 7F 21 A3 52 BE 19 93 09 CE 20 10 46 4A 4A F8 27 31 EC 58 C7 E8 33 82 E3 CE BF 85 F4 DF 94 CE 4B 09 C1 94 56 8A C0 13 72 A7 FC 9F 84 4D 73 A3 CA 9A 61 58 97 A3 27 FC 03 98 76 23 1D C7 61 03 04 AE 56 BF 38 84 00 40 A7 0E FD FF 52 FE 03 6F 95 30 F1 97 FB C0 85 60 D6 80 25 A9 63 BE 03 01 4E 38 E2 F9 A2 34 FF BB 3E 03 44 78 00 90 CB 88 11 3A 94 65 C0 7C 63 87 F0 3C AF D6 25 E4 8B 38 0A AC 72 21 D4 F8 07 46 49 52 45 45 4D 42 4C 45 4D 45 00 41 45 37 45.
Be one with the hexadecimal vomit.