Skip to content
View in the app

A better way to browse. Learn more.

NHL'94 Forums

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

HOW TO: "Decompress" Graphics in Sega Genesis

Featured Replies

When we say the hacked ROMs for Genesis had the graphics "decompressed", that's not exactly the right terminology.  The graphics that are used, at least in the EA series that I've looked at, have shared tiles.  They are not "compressed" as you can still see all the graphics when you open Tile Molester, but it won't look exactly like the "what you see is what you get (WYSIWYG)" in the game.  That's due to the use of shared tiles.  Back in the 90's, chip size was important/expensive, so the smaller you can make the game work the better.  Graphic data by far takes up the most space on the ROM, so if you can re-use certain tiles for an image, that would help reduce the size without impacting the game.  

I'll explain how this works, and how @wboy and others fixed this.  I won't go into how to find the locations/palettes as this can be found elsewhere in the forums.  I'd also like to thank @slapshot67 for explaining this to me a while back.

A few basics:

  • Everything uses Hex values.  This means each digit goes to F instead of 9 (base 16 instead of 10).  Google for more info separately, but it's not that hard to grasp.
  • Graphics in Genesis are broken down into tiles.  Each tile is 8x8 pixels, or 64 pixels in total.
    • Tiles are basically a "paint by number"  - I explain that here
  • Each tile can use one 16 color palette.  
    • There can be 4 different palettes to choose from

 

First, let's take a look at how the data structure works in Hex for MOST graphics.  There are instances where this may not be the same, but for the vast majority of graphics work this way.

Let's start with the Anaheim Ducks team selection logo.  This is a 6x6 (tiles) logo.  The location of the information for the Anaheim logo is BF8D0 in the original ROM.   Here's how everything looks in Hex.  I'll break down each section and explain.

Anaheim Logo - Original Hex - Colors.png

The start of the graphic is always a 10 byte header, which I highlighted in green.  I think it will make more sense to explain the header later. 

The purple highlighted section is the graphic tile data.  This is the data that is much better viewed in Tile Molester.  I'll explain and show you how TM translates this data to a user friendly interface. 

As I mentioned earlier, graphic tiles are 8x8 pixels.  Each tile is represented in hex by 32 bytes, with each byte representing 2 pixels ,for a total of 64.  Each digit is simply what color on the palette to load, starting on the top of the tile, working from left to right.  For example, here is the first tile (first section of purple) translated from hex in TM:

Hex to TM.png

Not the greatest example, but it's easy to follow.  When you see a bunch of "5555", that's the 6th color (starts at 0) in the palette, in this case white throughout the first tile. 

So the purple section is all the tile information for 34 total tiles (explained later).  

After all the graphic data, you'll see the tile layout information begin with the orange section.  The orange section tells you what the layout is in the number of tiles in length x width.  In our logo example, this is 6x6.  That's pretty straightforward. 

The last highlighted section is the tile layout.  Each 2 bytes represents which tile to use, and you'll find 36 tile layouts for the 6x6 logo graphic.  

The first digit is the palette being used:

0 - Palette 1
2 - Palette 2
4 - Palette 3
6 - Palette 4

If the tile is flipped vertically, the number is 1 higher (1,3,5,7).  The next byte will show the horizontal flip.  0 is normal and 8 will flip horizontal.  You're likely not going to be flipping tiles vertically or horizontally for your new image, so don't worry too much about that.  

The next byte is the tile number used.  In our example, you'll see the tile layout starts with 2000, 2001, 2002...until all 36 are listed.  This means the logo is using palette 2, tile 00, tile 01, etc. 

Now back to the header!  The first 4 bytes of the header is the length of the data.  This is usually just adding the header (10 bytes) and the graphic data (tiles).  Remember, the graphic data is 32 bytes for every tile.  

The next 4 bytes is usually the length of the data plus the palette if it's located.  A lot of times a graphic will have the palette located right after the tiles, and these bytes will account for the extra palette information. Our team logos do not, and as such the 4 bytes will both be the same.  I'll show another example that has a palette later.  

The final two bytes is the number of tiles represented in hex.  

So in our Anaheim logo example header reads as follows "0000 044A 0000 044A 0022"

Starting at the end - "0022" says that this graphic has 34 tiles (22 is hex for 34).

The beginning and middle both have "000 044A".  That represents a data length of 1,098 bytes (044A is hex for 1,098).  Here's the math --  34 tiles x 32 bytes equals 1,088.  Add 10 for the header and you have 1,098!  

This is important to understand because when we expand the graphic, we will have to adjust the header accordingly for the game to understand.


SO NOW, how do we "decompress" or make the graphics more hacking-friendly?

Using our logo example, the first thing we need to do is make each graphic 36 tiles.  You may have picked up that our Anaheim logo in the game has 34 tiles, which means that 2 tiles are used more than once in the graphic. If you looked closely at the layout, you will see that tile 17 is used 3x.  This actually the blank tile, which is pretty common.  

Anaheim Logo - Original TM w tile number.png

 

So let's "decompress" Anaheim's logo to fix the shared tiles problem.  The first thing we need to do is find some room in the ROM for the new logo!  Wboy expanded the original ROM from 1MB to 2MB, thereby giving him plenty of space to put in some new graphics.  Expanding from 1MB to 2MB is pretty easy, but I won't cover that here.  Just know you need to find some space.  The 95 ROM actually had enough blank space already for new graphics.  

Use TM to paste in the new picture in the empty part of the ROM, say location 1C85B8, and that picture is now 36 full tiles for Anaheim logo, not 34.  Right before the tile data, we need to update the header for the graphic.  The new size will be 36 tiles x 32 bytes or 1,152 bytes.  Add 10 for the header and our data length is 1,162, or 048A in hex.  We also know we are using 36 tiles, and that is 0024 in Hex. 

Our new header should read "0000 048A 0000 048A 0024

Immediately after the TM data, we need to now put the tile layout in Hex.  The logo remains 0006 0006 (6x6) and the tile layout will be sequential since we are not using any shared tiles.  The layout will be 2000, 2001, 2002....all the way to tile 36 (2023).  

This is how it looks like in the 30 team ROM:

30 team Anaheim Hex -colors.png

I highlighted the header and tile layout.  

Anaheim Logo -  30 team.png

 

So now that you have the full "uncompressed" graphic loaded, the final step is to change the pointers in the game to the new graphic.  A pointer is just what it sounds like -- it points the ROM to the new graphic.  You can typically find the pointer by looking for the header location in the ROM itself.  

So in our example, the Anaheim logo header for the original game was BF8D0.  If you search for hex values "000B F8D0" in the ROM you'll find that the pointer is located at F86F2.  If you change F86F2 to your new location (1C85AE), the game will now read the new logo.  

pointer.png

NOTE: In wboy's 30 team ROM, he also changed the location of the pointer table, so this particular part of our example won't be 1:1.

I hope this was a helpful crash course into how graphics work and how we "decompress", or get rid of shared tiles.  

I'll give another example of a graphic that has the palette information within the data structure as a response to this post.  This took me a little longer than I thought, lol.  But basically every graphic that was hacked followed this procedure.  

In short:

* Make or find room in the ROM for a new graphic
* Make sure the header and layout information reflects that graphic correctly.
* Change the pointer to the new graphic

@kingraph that's why your one of the best. This will help me with so many other games to better understand the graphics components. Here is a few that this will majorly help.

NBA Live 98 - Already hacking the images and have the palettes, but this will allow it to look clean. 

Tecmo Super Bowl 3 (Sega) - will help to find and update the logos.

World Series Baseball - Already hacked the logos on the Nationals and Orioles ( They are a 7x7 graphics and are played out top row of 1x4 seven times and than 1x3 for the bottom row seven times. This is the same for NBA Live 98)

A tip of the hat is always well deserved for acknowledgment and respect. You get both my friend. 

  • 1 year later...
On 8/6/2020 at 6:23 PM, kingraph said:
  • Graphics in Genesis are broken down into tiles.  Each tile is 8x8 pixels, or 64 pixels in total.
    • Tiles are basically a "paint by number"  - I explain that here
  • Each tile can use one 16 color palette.  
    • There can be 4 different palettes to choose from

@kingraphVery interesting post! Do you know if this same logic can be applied when looking at SNES graphics? Is SNES also broken into tiles with 8x8 pixels and do we know if SNES also has 4 different palettes of 16 colors? Are SNES logos also 6 X 6 tiles?

  • Author
49 minutes ago, dangler said:

@kingraphVery interesting post! Do you know if this same logic can be applied when looking at SNES graphics? Is SNES also broken into tiles with 8x8 pixels and do we know if SNES also has 4 different palettes of 16 colors? Are SNES logos also 6 X 6 tiles?

The graphics in SNES are way more advanced than Sega, and I can't even comment on how it actually works as I haven't done much SNES hacking.  This article summarizes the graphic differences nicely: nicely: https://en.wikipedia.org/wiki/List_of_video_game_console_palettes

So tiles are 8x8, but the palettes are more complex (see article).  As far as logos, I venture to guess they are 7x7 solely based on the screenshots I've taken of logos (56x56 pixels)

The big issue with SNES is that the graphics are actually compressed.  Meaning, you won't find any graphics if you open up a SNES '94 ROM in Tile Molester.  There is some algorithm that the SNES applies to translate pieces of code into the graphics we see.  Even more difficult, those compression routines are unique to each game (or my understanding is some games have similar compression routines), so it's not like a piece of software exists that decompresses ALL SNES graphics for you to edit, and then recompress to the ROM.  You basically have to figure out the routine for '94 yourself.  My understanding is it's complicated too.  And that's why we haven't had any progress on SNES graphic hacks. 

Recently, on the '94 Discord Server (#rom-hacking), and I think you've seen this, there was a Microsoft Direct X developer who gave some good advice on how to possibly think about this differently for SNES (thanks for sharing @INDIO)

"I haven't tried to edit logos yet. I had some notes and observations when doing stuff for the player profile photos that might help

For editing player profile photos, I went with a "path of least resistance". I didn't try to reverse-engineer the whole decompression mechanism. Instead I put full decompressed images into the ROM and changed the decompress into a very dumb copy. I have a thing of "work smarter not harder" given I want only a certain end result, doesn't matter how elegant it is or whether it requires ROM expansion. For purposes of this project I treat ROM expansion as free. If you have the same priorities, you might want to do the same thing.

Why do the same thing? Because the decompression code is organized weirdly and is complicated. Although I didn't strictly have to I looked at it out of curiosity for profile images. And team logos use the same thing, from what I can tell. But if you still want to know about it:

I disassembled most of the decompression code, added some labels, factored out some loops. See here: https://github.com/clandrew/nhl94e/blob/main/docs/rough/DecompressProfileMain.asm

There is a bunch of code with data sprinkled in. That data is jump tables. Each element of the jump tables in general is short offset.
The real meat of the decompression is in this function: DecompressFB30(). To get started you would probably want to set a breakpoint there at 0x80BBB3. That's a common path between profile images and team logos.

General vibe is the compression optimizes for sequential series of like numbers. So like, if there's a sea of 99 0s, rather than store 0 repeatedly it will just store "99" "0" so to speak."

 

 

  • 5 months later...

This is an awesome post! But I think some EA Sports games have compressed graphics following its own way of compression.
There is no way to find the EA Sports logo of the intro or even the background in FIFA series, among other stuff.

Regarding this issue of using of repeated tiles, sometimes it limits the romhacking work but I think there must be a way to be rewritten.
As far as I'm concerned in some games exist "a pattern code" that can be rewritten, so you can choose what tile/tiles of the tile map in a specific image is gonna be repeated and where.

Patrones Mapa.png

As you can see attached, this is a file I created on TM where I show every single Super Monaco GP, Grand Prixes maps.
The first GP is San Marino, which is not using any repeated tile but has (like every map) its own way to be shown in a 7x11 tile map.
The following one is Brazil GP. Red marked tile is the original tile that's gonna be repeated. Those repeated ones are also red but with a blue spot based on the original red with no spots. Also, you can see a yellow marked tile which is a tile that is gonna be repeated BUT in this case, its tile that is based on is flipped. Those are yellow marked tiles with a blue spot.

I know where these pattern orders are located, but there is no way to understand a logic sequence on them.

Edited by TA_Marcos_Translations

  • Author
9 hours ago, TA_Marcos_Translations said:


I know where these pattern orders are located, but there is no way to understand a logic sequence on them.

I'm not sure if it's the same in FIFA/Super Monaco, but I do explain how the tile pattern layout works in '94:

From my OP, here's how the layout logic works (which is located after each image):

"Each 2 bytes represents which tile to use, and you'll find 36 tile layouts for the 6x6 logo graphic.  

The first digit is the palette being used:

0 - Palette 1
2 - Palette 2
4 - Palette 3
6 - Palette 4

If the tile is flipped vertically, the number is 1 higher (1,3,5,7).  The next byte will show the horizontal flip.  0 is normal and 8 will flip horizontal.  You're likely not going to be flipping tiles vertically or horizontally for your new image, so don't worry too much about that.  

The next byte is the tile number used.  In our example, you'll see the tile layout starts with 2000, 2001, 2002...until all 36 are listed.  This means the logo is using palette 2, tile 00, tile 01, etc."

  • 2 years later...

Hey @kingraph, sorry to reopen an old topic. i was recently dabbling with adding gatorade bottles to the tops of the nets and found they use mirrored tiles for both sides so the only options were to either have 2 on each net or have one across the middle but turn out looking iffy with 2 tops on them, like so.

gatorade.jpg

At first this was enough for me but then I had the thought of "uncompressing" the net images so that they wouldn't use mirrored tiles and that way i could get the bottles on the nets to be to one side and look much better. So i came across this posts tutorial and I;m pretty certain i have all the legwork done (image created in open space and all the tile layout/header info in order. 

tm nets ref.png

Now the only issue i am running into is that i cant find the pointers for the nets. I've tried searching the offsets in the hex code but nothing is coming up, anything beyond that for finding pointers is beyond my understanding.

 

tm nets ref og.png

Is what im trying even possible with the nets? Im not sure where to go from here. Any help would be greatly appreciated.

Thanks in advance.

Crown Royal Hockey Game net.bin

Edited by BRCbruce

  • Author
45 minutes ago, BRCbruce said:

 

Is what im trying even possible with the nets? Im not sure where to go from here. Any help would be greatly appreciated.

Thanks in advance.

Crown Royal Hockey Game net.bin 2 MB · 0 downloads

The net is a bit of a different animal as it part of the entire rink background.  I think this reference from @AdamCatalyst will be useful for anything regarding rink alterations: https://forum.nhl94.com/index.php?/topic/26232-how-to-edit-the-rink-sideboards-more-nhl-94/

 

Having said that I don't have much experience editing the rink background myself, and I have not been doing much with '94 graphic editing in years, so I can only point you to a (hopefully) helpful direction.   

@kingraph thank you for the response. I had a feeling it might be a little trickier when I couldn't find the offset reference in Hex. @AdamCatalyst any knowledge on this specific instance? I shall keep digging. Thanks again!

Edited by BRCbruce

18 minutes ago, BRCbruce said:

@kingraph thank you for the response. I had a feeling it might be a little trickier when I couldn't find the offset reference in Hex. @AdamCatalyst any knowledge on this specific instance? I shall keep digging. Thanks again!

Are you trying to copy over the net sprite tiles, or are you trying to have the code point to your new ones?

38 minutes ago, chaos said:

Are you trying to copy over the net sprite tiles, or are you trying to have the code point to your new ones?

@chaos Code point to my new graphic..since the tiles are all mirrored tiles, I believe even drawing over them will still give me the same mirrored result rather than being able to have the bottle to just one side. Unless there's an easier solution?

Edited by BRCbruce

13 hours ago, BRCbruce said:

@chaos Code point to my new graphic..since the tiles are all mirrored tiles, I believe even drawing over them will still give me the same mirrored result rather than being able to have the bottle to just one side. Unless there's an easier solution?

Frames 405 and 406 are the net frames (405 is the top net).

 

Look at the Frame Data (NHL93-94) section of this post. This gets complicated though, since you are adding more sprite tiles than were originally there. So you would have to change the data for that frame, then update the Frame pointer list for all the frames after that. 

The better solution would be to move the Frame list and all the Frame Data and Hot Spots to a new location, add your frames to the end of the list, then update the location where it chooses the frame for the nets in the code. You would also have to update the locations that point to the frame list and the frame data.

 

 

@chaos another idea i had in my head was for the top net tiles 003 and 005 are different by one pixel, I could keep 003 and use that as a shared tile and replace the 2 005 tiles needed freeing it up redraw it to be part of the net with a water bottle and adjust the tile map accordingly...just not sure how to find that tile map to test it

tiles.png

Edited by BRCbruce

18 minutes ago, BRCbruce said:

@chaos another idea i had in my head was for the top net tiles 003 and 005 are different by one pixel, I could keep 003 and use that as a shared tile and replace the 2 005 tiles needed freeing it up redraw it to be part of the net with a water bottle and adjust the tile map accordingly...just not sure how to find that tile map to test it

tiles.png

Read the linked post, it will tell you how to find the tiles. Frame 405 and 406 are the nets.

17 hours ago, BRCbruce said:

Now the only issue i am running into is that i cant find the pointers for the nets. I've tried searching the offsets in the hex code but nothing is coming up, anything beyond that for finding pointers is beyond my understanding.

Is what im trying even possible with the nets? Im not sure where to go from here. Any help would be greatly appreciated.

Thanks in advance.

This might help you track it down:

 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

Who's Online (See full list)

  • There are no registered users currently online

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.