Seen August 19th, 2019
Posted November 21st, 2018
9 posts
5.3 Years
I've been teaching myself the different data formats for the Fire Red ROM using Google and some of the already established modding programs available. I'm developing a program to act as a PokeDex to accompany a personal ROM mod. It loads the actual data off the ROM and uses it to display relevant stats and info;

I'm modifying all the base stats and movesets for this ROM mod, so something like this program that I don't ever need to update was useful for me. Having to update a spreadsheet for each change can be tiresome. While I could view the data in various modding programs, it wasn't convenient or consolidated as different programs are needed for each. This tool just displays information and doesn't have the capacity for modifying the ROM.

Right now I'm cheating for the pokemon sprites by using downloaded images stored alongside the program. While this is fine for 251 images, it's both unwieldy and sloppy to do it for all the items as well. It'd also be a nuisance getting images for each item, and I'd rather load it from the ROM so that it would display any custom sprites. I'm trying to look into how the sprites are stored as data, but am only coming across tutorials for replacing them with established software. Does anyone have access to information regarding the sprite format in the ROM file and how to assemble it using the accompanying palette? I can find the offsets that link to them, but wouldn't know where to start with the data.

Also any type of document outlining the actual ROM format would be a huge help as I have no idea why any of this data is where it is, and don't know how I could have found it without existing tools. I've just been digging around with a hex editor and making changes to find where the data begins.

I apologize in advance for having this be an introduction. I don't like to ask for so much without having anything to offer, but when I get a bit more added I'll happily upload the program. Again, it's only a guide tool as it can't make any edits, but it should work for any Fire Red ROM so long as you haven't moved any tables or added data anywhere.

Edit: So I'm pretty sure I've found the sprite's data and built a basic tool to try to draw it in grayscale to test. But these sprites are compressed via LZ77. Looking into decompression algorithms now.

Edit 2:

So to anyone who finds this topic in the future and needs assistance.

The offsets for Sprites and Palettes are loaded as a straight list. Don't remember the offset right now but I'll update when I get it.

The offsets are 3 byte little-endian integers. You can read them as int32 and subtract 0x08000000 from them. It's sprite-offset, palette-offset, repeat.

The actual sprites and palette are compressed as LZ77 data. First byte is 0x10, the next 3 bytes is the length of the decompressed data. As you go along flags may be stored which leads to data earlier in the string you copy again. I recommend the source code for DsDecmp for this section. Lots of bitshifting and bit logic operations.

Once you've uncompressed the data, look into the palette. There should be 16 colors stored as 16 bit integers. It's actually a 15bit RGB value;

red = (gba_color & 31) << 3
green = ((gba_color >> 5) & 31) << 3
blue = ((gba_color >> 10) & 31) << 3

The bytes are read little-endian, so A5DD is actually DDA5 when compiling the math.

The sprite are split bytes representing which pixel in the palette to use. The first half of the byte, or the first 4 bits, is the second pixel. The second half of the byte, or the last 4 bits, is the first pixel. As such, the length of uncompressed sprite data should equal (length*width/2) of the sprite. Item sprites are 24x24.

To clarify the split bytes, reading

would actually be

Color 4, Color 0, Color 4, Color 4, Color 4, Color 10, Color 10, Color 0, Color 0, Color 1, Color 1, Color 1,

The sprites begin in the top left corner, write 8 pixels, and then move down one pixel to repeat. After writing 8 pixels across and 8 rows down, the sprite picks up from the top and draws another 8x8 square to the right of the first. Starts at the top row at (8,0) and draws 8 pixels, moves down a row. After repeating this to the images width, it moves down 8 rows and draws the next line of 8x8 squares until it reaches the end of the data. In effect, the image is split into 8x8 sub-images that each get drawn making up the larger sprite. While I can't confirm this, the LZ77 compression may find more string lengths to compress when the data is organized by section as opposed to just by rows.

While you'll have to find the offsets and the method for decompressing LZ77 data, this should give anyone the help they need to write up their code.