The VG Resource

Full Version: Super Metroid ripping project
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
On July 18th, 2013 around 12:07 AM, ittan-moment made an important observation.
(07-17-2013, 07:07 PM)ittan-momen Wrote: [ -> ]The super Metroid section's more than a bit dated as it were. Big over sized sheets, superfluous frames, and several missing parts.

i've been driven to the point of italics. the man is right.
look at this shit. LOOK AT IT. What is this, Ninsprites? yeah i exaggerated, no offense to original rippers. they ain't bad but cmon they could be a lot better.

In the same thread we kinda went off-topic but in a good way, with hints of new, fresh, accurate rips in the horizon. Well, I'm more of a technical smash-the-game-apart-guy more than an old school screenshot-til-you-drop-guy and I've dwelled into Super Metroid in the past. This is why I suggest that we create SMUSHER. The Super Metroid Ultimate SHEet Ripper. god that was lame.

You see, most of Super Metroid's sprites follow a pretty straightforward format. I've written about it in the past, but it was only a scratch of the surface. Now I've made a much more thorough document that should give the project programmer all the info he/she needs to integrate to the viewer.
In short, the goal is to have one easy-to-use program that can view every* individual sprite in the game. I can't program worth shit but here's what I know of the game's sprites. The ROM we'll be using is a headerless [!] (JU) SMC, MD5 hash 21f3e98df4780ee1c667b84e57d88675.

I. – DNA

At least every Samus-interacting sprite in the game has a unique, 64-byte DNA. It essentially tells what the game must know about the sprite to summon it, like where its graphics are stored, what its name is, hitbox size, etc. Most of the bytes in the DNA are useless to us because over half of the DNA defines non-visual stuff like initiation routines, "what sound to make", "how to explode" etc. Out of the 64 bytes, only twelve bytes are important to us. Size, Palette pointer, Master Bank, Piece amount, Graphics address and Enemy name.
The giant array of 64-byte DNA after another is located in 0x104EBF. There are at least 165 unique DNAs of which at least three are unidentified or broken.
165 * 64 = 10560 bytes of DNA data.

II. – EBI's sequence

Before we begin, you must make yourself familiar with converting SNES addresses to PC addresses. The pointers and words in the ROM are always little-endian and, of course, SNES addresses instead of PC.
From this point onwards, I'll also write in Courier because it's a monospaced font.

So, right. For our example, I'll use a randomly chosen DNA. This DNA is EBI's.
In 0x10663F, (SNES address $A0:E63F), we see 64 bytes. I've noted each.

SIZEB PALET ..... ..... ..... ..... MB .. ..... ..... ..... PIECE ..... ..... ..... ..... .....
00 06 87 86 2C 01 64 00 10 00 14 00 A8 00 4A 00 00 00 E0 87 03 00 00 00 1B 89 0F 80 4C 80 41 80

..... ..... ..... ..... ..... ..... ..... ..... ..... ..... ..... GRAPHADR .. ..... ..... ENAME
00 00 04 00 00 00 00 00 0C 8B 00 00 00 00 00 00 06 8B 12 8B 00 00 00 94 B1 05 50 F3 CE EF 23 DE

SIZEB = How many bytes of data to rip from the ROM for this sprite to use. In this case, 0x0600.
PALET = Pointer to the 32-byte palette in the same bank as MB. In this case, $A8:8687, which is 0x140687 in PC. That's where the palette is.
..... = irrelevant bytes.
MB = Master Bank. Combined with many things, for example, the palette pointer.
PIECE = How many parts the sprite is made from. In this case 0x0003.
GRAPHADR = Address where the graphics are loaded. In this case, $B1:9400 which is 0x189400 in PC. That's where the graphics are.
ENAME = Pointer to enemy name, always from bank $34. In this case, $34Big GrinE23, which is 0x1A5E23 in PC. That' where the name is, in ASCII. Not all enemies have names. Dunno if this is even useful for the program, but I guess it isn't that irrelevant.

III. – Frame Duration/Pointer Arrays

"But, but, there isn't a byte in the enemy's DNA at all for where the tilemap data is!"
Correct, but apparently $20 bytes after PALET there's usually† something called the Frame Duration/Pointer Array.

Counting (PALET + 0x20) will get you the offset where a Frame Duration/Pointer Array of the sprite in question begins. We want to see EBI's FD/PA, so let's count, PALET ($A8:8687) plus 0x20 equals $A8:86A7, which is 0x1406A7 in PC.

Here's a snippet from that very address (0x1406A7):

0A 00 59 8B 0A 00 88 8B 0A 00 B7 8B 0A 00 E6 8B 0A 00 15 8C 0A 00 44 8C

DURAT = Duration of the frame. Exactly how long the frame is displayed in the sprite's animation. I'm not sure whether should this be considered an irrelevant byte, since these end up in a static PNG sheet anyway. Maybe useful for animators?
FRMPT = Frame pointer. This one's the important one. Remember how the first guide I posted tells you how the sprites are built? A frame pointer tells exactly where that info for one frame of the current sprite is. These frames are also always from the same bank as MB. In this case, $A8:8B59, which is 0x140B59 in PC.

Let's head over there. (I formatted these because you know how the format works already) 0x140B59:
09 00
FE 81 FB 06 21
EE 81 FB 04 21
FE 81 EB 02 21
EE 81 EB 00 21
02 80 FB 08 21
01 80 01 08 21
FF 81 07 0C 21
FE 01 10 26 21
FE 01 08 25 21

And THOSE, my friend, are the instructions of how to build the first frame of EBI. Those nine parts make this:
[Image: iavw0dB.png]

IV. – Final words

"But, but, where are the graphics loaded from?"
GRAPHADR, silly. Which was 0x189400. 4bpp planar, composite (2x2bpp):
[Image: v5bYElE.png]

"But, but, he looks all crazy colored! Where's the palette?"
PALET, silly. Which was 0x140687. 15bpp BGR:
[Image: WZEbBnM.png]

"But, but, does he need all those graphics himself?"
No, silly. The correct amount of bytes the character in question needs is determined by SIZEB. Which was $600 bytes:
[Image: Y9leERU.png]

"But, but, that's only one frame! What about the next one?"
Let's return to the frame pointer array. We already covered the $A8:8B59 (which lasted 0x000A frames, by the way), the next frame according to the frame pointer array is $A8:8B88, which is 0x140B88 in PC:
09 00
FE 81 FB 06 21
EE 81 FB 04 21
FE 81 EB 02 21
EE 81 EB 00 21
02 80 FC 08 21
01 80 02 08 21
FF 81 07 0C 21
FE 01 10 26 21
FE 01 08 25 21

I made a GIF of this one so you get the idea:
[Image: tuIPzxo.gif]
The succeeding block/tile goes always behind the preceding one. In this one, tile $25 is the 'bottom' one, thus 'behind' everything. But hey, now we already have the second frame!!

"But, but, how do we know when to stop? How many frames does a sprite have?"

[Image: TJjIFX6.jpg]

Yeah that's kinda where the fun ends. I don't know. I can't know. There's no single table of how many individual frames a sprite has because some variable frames are built on-the-fly by arbitrarily executed code.
That's why I propose the viewer should look something like this:
[Image: NGBBokT.png]

That isn't meant to be final, but just to get the idea. It reads the DNA array, 64 bytes at a time. Clicking 'next' goes to the next DNA and so on. You could also type the address by hand (or via dropdown menu?).
The little hex viewer down there shows the Frame Duration/Pointer Arrays of current DNA (which it gets by counting PALET + $20, remember?). Then you could click(?) on the nearby four byte DURAT/FRMPT-combos and they'd get updated to the sprite viewer.
Fake Kraid, though, is an example. It's PALET is 0x13198C, and adding $20 to it gets you to 0x1319AC. If you try to read the data from that address, it will load it incorrectly. Fake Kraid's first real DURAT/FRMPT-combo is at 0x1319AE, two bytes after the expected.
Like I mentioned in †, it's only usually. As we just saw, Fake Kraid's stuff is $22 bytes after the palette. That's why an 'explorer' is needed.

Also here's a bonus gif of building Fake Kraid's first frame.

uuuhghgh too much text for one day. Questions? Suggestions? Ideas? I'm out for now. apologies for any typos or inconsistencies..
Holy crap, dude. You're blowing me away. I'm so hyped up for this. Wonderful work so far!
This is exciting! Are Samus' current sheets complete or are they gonna need to be re-ripped?
From what I can tell, there are a lot of variables in the sprites in this game, so Samus probably isn't compete.
I did not know this thread existed until now.

I'll take a better look at this later on today and see if I can start coding this. It looks relatively simple, to be honest the GUI might be the toughest bit Tongue

EDIT: Finally found out how to convert SNES addresses to PC addresses, since this was a necessary first step. I'll start actually trying to put sprites together now. I wonder though, what is PIECE used for? You say that it's how many "parts" the sprite is made from, but that's pretty vague and I don't see any further reference to it.
Also, although I haven't tried it yet, how should I read palette data? I have about zero experience in ROM hacking, this is my first time I've ever actually handled binary ROM data, so it might not be obvious to me.

EDIT2: Well OK, I think I've sorted out how the palette works. But how do I get the actual graphics, what do I do at GRAPHADR?

EDIT3: OK, so I've finally managed to correctly load the graphics with the proper palette, and generate EBI's tilemap. I was a bit confused as to how to know the size of the tilemap, but I discovered that it's always a width of 16 tiles, and the height is determined by SIZEB. I also discovered that the background/transparency colour is the first in the palette.
I still have no idea what PIECE is for, though.

EDIT4: Ugh, sorry for all the edits, but I keep getting confused. I've been using your tile editing document to use the frame instructions, but for some reason the bits aren't coming together. I mean, EBI's body slots together perfectly, but the bits of his wings are at completely different locations. Is there some sort of calculation I should perform on the X and Y offsets of tiles?

EDIT5: OK, after taking a very careful look at the tile editing document it appears that the dimensions are somewhat shifted. Anything above 0x7F must have 0x7F subtracted from it, and inversely anything lower than (or equal to) 0x7F must have 0x7F added to it. Kind of weird, but I'm glad I finally figure it out. Scratch that, I was over-complicating the matter. I just realised that if I read the offsets as signed bytes (I was reading them as unsigned), simply adding them to 0x7F gives the correct coordinates.
There are also some other things I'd like to know. They're not really hindering me, but I'm confused what to do with bit 0 of Priority A (adding 0xFF when it's set messes up the sprite), bits 5 and 4 of Priority B (isn't "depth" dependant on the order of tiles?) and bit 0 of Priority B ("next graphics page"?).
So I saw this topic yesterday and felt it was something probably worth investing in. Not sure how other guy's progress on a viewer is going but this is what ive come up with so far.
[Image: lGby59K.png]
It would obviously really help improve accuracy if you could explain what all the bits in those attribute bytes do.
Oh, wow. Amazing that people can just whip this up in no time. Tongue
Oh my goodness. I swear, I was gonna upload screenshots last night but it had gotten too late, no kidding.

Well, here they are now:

[Image: iYybjIs2y2SyU.png]

[Image: ib0oaMjLaZ1gsq.png]

As you can see the GUI's still a bit primitive to Greiga's, but the actual result looks about the same. Right now all it does is opens up the ROM and displays a sprite's tilemap and its first frame. The DNA it loads is currently hardcoded, but that stepper on the left will soon let you choose them yourself. I'll also make a little hex explorer for the frames like suggested.
By the way, I also took some care in making sure that it can open both headered and unheadered ROMs. There's also the possibility that the selected ROM won't be Super Metroid, so it checks the SNES header for that as well.

Guess I'm a tad slow, seeing how Greiga Master managed to whip his up in a day. I did have to learn all of the SNES-specific stuff (palette, graphics data, addresses) from scratch though. Even if Greiga's program gets done first, I'll finish mine, albeit just for personal satisfaction.
Honestly, I'm not sure how much further I could get considering the lack of proper documentation. Also, glad to see you're keeping a positive attitude about your project.
I suppose we'll have to wait for Raccoon Sam for that stuff. Not sure how frequently he visits so it could be a while, I dunno.

Yeah, I spent a lot of effort into this project, and it's been a huge stepping stone in my education about ROM hacking, and programming in general. It'd be a shame if I didn't finish it, even if your program is better or done first.
Wasn't there another SNES game that was built on Super Metroid's engine? Could this tool be tweaked for use on that too?
If it's a ROM hack, almost certainly. If it's a proper game separately compiled but using the same engine, not sure. Simple logic would cause me to think that it would have a similar ROM architecture, but since I'm not really experienced with this I could be completely wrong. It would certainly be cool, that's for sure.

Do you know the name of the game? It would be cool to snoop around and see if it's similar.
(08-06-2013, 10:54 PM)Ton Wrote: [ -> ]Wasn't there another SNES game that was built on Super Metroid's engine? Could this tool be tweaked for use on that too?

I'm not completely sure, but you may be thinking of the original Metroid which is supposed to use the same engine as Kid Icarus. Unless you're completely sure it was for the snes.
I think it was the original Donkey Kong Country, actually, but that game has been ripped to death already.
Although I may be thinking of Metroid Fusion/Wario Land 4.
oh shit, good job guys!! I had totally forgot about this thread %D
I'm at work atm but I'll dig into your questions as soon as I get home
SORRY everyone :XX

edit: also ton, you're probably thinking about wario land 4/metroid fusion/zero mission. no other game uses SM engine. also, Donkey Kong Country 1 has a built-in sprite viewer iirc
edit 2: actually fuck that i'm getting wasted. tomorrow it is
Pages: 1 2