Skip to content

Tutorial: Export and Modify Compressed Graphics

Shadow edited this page Sep 22, 2015 · 19 revisions

Export and Modify Compressed Graphics

While CoilSnake is known to decompile and extract most of the graphics found in the EarthBound ROM, there are still some things that CoilSnake itself does not allow to edit (yet).

These graphics that are known as "compressed graphics", since this data is not viewable in any Tile editor just by opening the ROM with it. To be able to edit any compressed graphics, we'll need three things:

*I recommend that you put all of the files (inhal.exe, exhal.exe, EarthBound ROM (.smc file) and HxD into the same folder for convenience and to avoid issues with file paths in CMD.



1. Knowing your graphics offset in the ROM.

First of all, we need to know what graphics you are looking for and were to find them. Let's say that you want to edit the Cast Sequence text as an example, since those are handled as compressed graphics, you'll need to use this guide for it.

Search in the EarthBound ROM Map website for the word "Cast", you'll find a match here:

  • 21DA35-21E6E6 (000cb2) = Character Names for Cast Sequence

This means that the EarthBound ROM has the data regarding the Cast sequence text between addresses 0x21DA35 and 0x21E6E6. The one that we must focus on is where the data starts, which is 0x21DA35.


2. Decompressing the compressed graphics from the ROM

Now let's open up a CMD (Windows Command Prompt) to be able to run EXHAL (.exe). These are the commands we are going to use:

  • To use exhal (the decompressor):

exhal.exe romfile.smc (offset in 0x000000 format) outfile.smc

  • To insert compressed data into a ROM:

inhal.exe infile.smc romfile.smc (offset in 0x000000 format)

Let's focus on exhal and follow the example of the Cast text. So we got 0x21DA35 as the offset, and our EB ROM is called EarthBound.smc, we should end up with a command in CMD like this one:

  • To use exhal (the decompressor):

exhal.exe EarthBound.smc 0x21DA35 CastText.smc

The "CastText.smc" file can be named anyway you like, just remember to add the .smc at the end of it.

After you press Enter, you will see that a file named "CastText.smc" has been created in the same folder as the rest of your other files. This is the file that we are going to use with Tile Molester.


3. Open up the compressed graphics to edit them.

This step depends solely on you and what you want to achieve. All you need to do is grab your newly created .smc file (props to EXHAL) and open it up with Tile Molester.

If you see some garbled data or something similar, you must change the view of the file. Go to View -> Codec -> 2bpp planar. The file should be readable now.

If you are still struggling, mess around with the width and height indexes inside Tile Molester to accommodate the graphics.

Once you are done editing them, save the file and be ready to compress it back into the ROM.


4. Compress the graphics back into the ROM.

Now all we gotta do is put the graphics back into the ROM. Open up CMD again and let's run the following command:

  • To insert compressed data into a ROM:

inhal.exe infile.smc romfile.smc (offset in 0x000000 format)

Example:

  • To insert compressed data into a ROM:

inhal.exe CastText.smc EarthBound.smc 0x21DA35

That's it! Your edited compressed graphics, have now been put back into the game! Now open up your ROM with an emulator and test the graphics in-game!

But... whooops... The colours are messed up! That happens when you get a little edit-happy and the compressed graphics have now surpassed the original size, resulting in the compressed graphics now going into the next data bank due to insufficient space.

Don't worry, though! CoilSnake and CCScript are here to help us out!



How to avoid a data bank corruption if the compressed graphics size surpasses the original size after the edit.

This might not always occur, but if you are going to add some additional pixels to the graphics, you might end up with the graphics in-game having different colours (messed palette). This occurs due to adding too much stuff into the graphics. When you use INHAL to compress them back, the graphics end up taking more space than what they original had within the ROM.

Thankfully, we are going to work our way around this problem to make use of CoilSnake's ability to expand the EarthBound ROM and use that free space to our convenience.

I'm going to use the same example of the Cast text graphics just for consistency, just remember that it varies for each graphic.


0. Before we start...

This is VERY important.

We need to compress our graphics into a CLEAN SMC file. If we end up using the decompressed data for this fix, you will end up with garbled info all over the place. In order for this to work, we are going to create a new SMC file which only has the data of the graphics compressed with INHAL.

For that we are going to use this command:

  • To write compressed data to a new file:

inhal.exe -n infile outfile

For example purposes:

  • To write compressed data to a new file:

inhal.exe -n CastText.smc CastTextCompressed.smc

Once you have this file, open up it up with any HEX Editor and be prepared to copy the ENTIRE HEX DATA some steps down this tutorial.


1. Converting the graphics address from a PC Address to a SNES Address

First of, we need to convert the address for the Cast text (0x21DA35) from PC Address to a SNES address. This can easily be done by adding BFFE00 to the PC address, so by doing the HEX math:

  • 21 DA 35 + BF FE 00 = C1 D8 35

2. Converting the SNES Address to Little-Endian

Now, we are going to grab the new SNES address and put it in reverse, like this:

  • C1 D8 35 -> 35 D8 C1

This is called "little-endian" and it is the format in which the HEX data is handled by the game. We are just going to use the first two pairs of bytes, 35 and D8.


3. Looking for the pointer to the compressed graphics.

Now we need to open up our EarthBound ROM with a HEX Editor (HxD). We are going to search for the pointer to our SNES address. The pointers in EarthBound have the following format:

  • A9 ZZ YY 85 -> ZZ and YY are the two pairs that we just got from converting our SNES address to little endian, which in our case are ZZ= 35 and YY=D8.

NOTE: Because the pointers might have 06, 0A, 0E or 12 after the 85, we will only look for up to the "85" so that we can cover up as many possible pointer types as possible.

So we are going to look for the HEX value "A9 35 D8 85" in our HEX editor, which ended up in one match starting at 0x04E646. This is the pointer address. The full pointer consists of 10 pairs of bytes starting with A9, the full pointer for the Cast text graphics is A9 35 D8 85 0E A9 E1 00 85 10.


4. Converting the pointer address to SNES address.

We are going to convert the pointer address to SNES address, just like we did at the beginning of this part for the graphics address. So for this example, 0x04E646 converted to SNES address is 0xC4E446. This SNES address will be helpful to create a custom CCS file in which we are going to put our entire compressed graphics.


5. Determining the pointer type and creation of a custom CCS file.

Now, remember the complete 10 pairs of bytes pointer we got before?

We are going to take a look into the first pair of bytes that follow the first 85, A9 35 D8 85 0E A9 E1 00 85 10, so for our purposes it will be 0E.

We are going to use that very same "0E" to implement an ASM code into the CCS file. So let's grab the pointer SNES address (0xC4E446) and the "0E" into our CCS file like follows:

import asm65816 ROM[Pointer SNES Address] = ASMLoadAddress0E (Our_graphics_label)

Our_graphics_label:

"[Insert HERE the complete HEX data of the graphics that we just compressed with INHAL into a new SMC file (CastTextCompressed.smc)]"

NOTE: The 0E might vary, it could be a 06, 0A, 0E or 12, depending on what the pointer we found has after the first "85" HEX value.

Remember the SMC file we created at Step 0 with INHAL? This is were it comes in handy.

Now that you have the "CastTextCompressed.smc" opened up in a HEX editor, copy the ENTIRE HEX DATA and paste it inbetween the square brackets "[ ]". For our example of the Cast text, the CCS file should be as follows:

import asm65816 ROM[0xC4E446] = ASMLoadAddress0E (cast_text_graphics)

cast_text_graphics:

"[Insert HERE the complete HEX data of the graphics that we just compressed with INHAL into a new SMC file (CastTextCompressed.smc)]"

Now save your CCS file, add it to your "ccscript" folder and compile your project.


Presto! You now have a fully functional custom compressed graphics without having to worry about the palette data or the next data bank being screwed!

Clone this wiki locally