08-21-2014, 11:09 AM
08-21-2014, 01:23 PM
I've just given you instant approval, since I don't know why I didn't before..
08-21-2014, 05:36 PM
And so your avatar is finally explained. Well, sort of
08-22-2014, 12:32 AM
Haha. I guess.
Also, so this wouldn't be a "look what I ripped" -thread, maybe you guys would like a... CASE STUDY?
These sprites are the result of Umihara Kawase sprite ripper, which mechaskrom programmed and I directed.. long ago. These are actually a byproduct of my Umihara Kawase map ripping project.
Here are snippets from the original discussion we had, mostly my explanation on how the sprites are made. Interesting read for newbies and pros alike, I guess!
————————My initial proposal to mechaskrom from April 2013————————
[...] I realized that there are no rips of Umihara Kawase sprites, excluding the player sprite! I can't rip them manually myself because the current SNES9x emulates the game incorrectly, and I honestly don't like ZSNES.
So, I though, why not stab two flies in one hit and get rips from each sprite in the game, for the benefit of the collective and to apply fresh clean sprites onto the maps? Here's my plan:
Umihara Kawase Shun: Second Edition Kanzenban for the DS is essentially a 3-in-1 game that also includes the SNES Umihara Kawase game. Since the DS has a filesystem of its own, by decompressing all of the game's files you can access them as if they were real folders and files in Windows Explorer/Finder.
This is particularly exciting because all of the files in the 'sfc' folder are actually the files the SNES game actually uses. You can, for example, search any of the files in the 'sfc/map/' from the original SNES ROM and find the level data. Some data has been re-encoded losslessly, but it's pretty much the same data.
So, instead of searching for the graphics individually in one giant chunk of a file (the SNES ROM), I looked into the 'sfc/obj/' folder and found files of each sprite set in the game. The files also contain palette and tilemap info, so one program that does exactly what I've explained below could easily spew out every single sprite in the game!
.BIN file structure:
All BINs have a $18 byte header that defines eight things:
1. Where the block array begins [BLKADDR, 4 bytes]
2. Where the sprite definition begins [SPRADDR, 4 bytes]
3. Where the palette info begins [PALADDR, 4 bytes]
4. Where the graphics data begins [GFXADDR, 4 bytes]
5. Amount of blocks [BLKAM, 2 bytes]
6. Amount of sprites [SPRAM, 2 bytes]
7. Amount of palettes [PALAM, 2 bytes]
8. Amount of tiles in total [TOTAL, 2 bytes]
Let's take U3_KNG.bin, which is the Goldfish enemy's sprite file. First $18 bytes with appropriate annotations are below:
addr.+------------------------
.....| BLKADDR____ SPRADDR____
$000 | 18 00 00 00 88 00 00 00
.....+
.....| PALADDR____ GFXADDR____
$008 | A0 00 00 00 C0 00 00 00
.....+
.....| BLKAM SPRAM PALAM TOTAL
$010 | 0E 00 05 00 01 00 40 00
-----+------------------------
• Let's dive into the first thing, BLKADDR. Sprites are built from blocks and one block is 8 bytes. This is the address where the 8-byte block array begins. The program reads the bytes backwards so it gets the correct address, which is 0x00000018.
• The second thing, SPRADDR is the offset where the program starts reading the info of what blocks to use to build a sprite. This time it's at 0x00000088.
• Third thing, PALADDR is self-explanatory. Where the Palette data begins. In this case, from 0x000000A0. Palettes are read the same way as the SNES ones I explained earlier in this thread, 1555 BGR.
• Fourth thing, GFXADDR is also pretty obvious; where the graphics data begins. This time 0x000000C0. Format is 4bpp linear, reverse order.
• Fifth thing, BLKAM is 0x000E. What this means is how many blocks there are in total. This time, 0x000E. Also, since one block is 8 bytes, you now know that the block data starts from 0x00000088 and is 112 bytes big (because BLKAM * 8 = $70).
• Sixth thing, SPRAM is 0x0005. What this means is exactly how many sprites are exported in the end. This time, 0x0005. It takes four bytes to define a sprite, so you now know that the sprite data begins from 0x00000088 and is 20 bytes big (because SPRAM * 4 = $14).
• Seventh thing, PALAM, is again pretty clear. Usually sprites have one or two palettes, but in this case it's 0x0001. One palette is 32, or, $20 bytes. There's one palette this time so obviously it takes only 32 bytes as is.
• The eighth thing serves little purpose. It just tells us how many tiles there are in total. This time 64, or, $40.
So, after the header, we're in address 0x018. This is where the blocks are listed, I've written them down for easy readability and added annotations:
addr.+-xx XX yy YY tt pp BP UU-+--NR--.
$018 | F3 FF F6 FF 00 00 60 00 | 0000 |
$020 | F3 FF 06 00 08 00 50 00 | 0100 |
$028 | FA FF EE FF 18 00 00 00 | 0200 |
$030 | F2 FF F6 FF 0C 00 60 00 | 0300 |
$038 | F2 FF 06 00 14 00 50 00 | 0400 |
$040 | FA FF EE FF 25 00 00 00 | 0500 |
$048 | F2 FF F6 FF 19 00 60 00 | 0600 |
$050 | F2 FF 06 00 21 00 50 00 | 0700 |
$058 | FA FF EE FF 32 00 00 00 | 0800 |
$060 | F2 FF F6 FF 26 00 60 00 | 0900 |
$068 | F2 FF 06 00 2E 00 50 00 | 0A00 |
$070 | FA FF EE FF 3F 00 00 00 | 0B00 |
$078 | F2 FF F6 FF 33 00 60 00 | 0C00 |
$080 | F2 FF 06 00 3B 00 50 00 | 0D00 |
-----+-------------------------+------'
I'll explain each of the eight bytes here, using the first block an example.
xx XX = X position of block, two bytes, read backwards, so in this case it would be $FFF3. See this grid for reference.
yy YY = Y position of block, two bytes, read backwards, so in this case it would be $FFF6.
tt pp = tile to use and its property†. In this case it would be tile 00 with property 00.
BP = Block type‡ and Palette to use for the block. The palette is always 0 so I don't see how this would be so useful.
UU = Unused.
NR = Block Number. Just for reference! This is not in the ROM, I just put it to the right of the table to help visualize what block we're in right now. You'll need to know this later. From the first block definition it's just counting upwards from 00 00, bytes backwards.
†: property byte is kind of funny. Of its 8 bits, only the first two are used. vhUU UUUU, where v means vertical flip of block's tiles and h horizontal flip, respectively (and U=unused).
‡: There are twelve block types. They essentially tell how the block is made, or, arrange a predetermined amount of tiles to a certain arrangement to form the block. See this for reference. $C_, $D_, $E_ and $F_ are unused.
Now, if the program would read the data, it would now have the information of how many blocks there are in total, how to form the correct blocks and where to put them. However, this would lead into all blocks being on top of each other, forming one sprite-cake. The next bytes, SPRADDR tells where to snip them apart, or, how many blocks build a sprite. Again, I've formatted and annotated the data for easy understanding.
addr.+ AMONT FROMB-.
$088 | 02 00 00 00 |
$08C | 03 00 02 00 |
$090 | 03 00 05 00 |
$094 | 03 00 08 00 |
$098 | 03 00 0B 00 |
-----+-------------'
Because SPRAM is $0005, we know that this file defines only five sprites. It takes four bytes to define a sprite an again, these two-byte combos are read backwards.
AMONT = Amount of blocks this sprite is built from...
FROMB = ...when counting from this Block Number.
In this case, it would be like this:
• Sprite one is two blocks: 0000 and 0100.
• Sprite two is three blocks: 0200, 0300 and 0400.
• Sprite three is three blocks: 0500, 0600 and 0700.
• Sprite four is three blocks: 0800, 0900, 0A00.
• Sprite five is three blocks: 0B00, 0C00, 0D00
And that's it. Load next file and repeat. I did this informational GIF that should help understand what's happening in the sprite creation. If you have a chance, view it frame by frame. Basically it's just "Get X, get Y, get tile, check if flips, use correct block type"
————————END————————
Also, so this wouldn't be a "look what I ripped" -thread, maybe you guys would like a... CASE STUDY?
These sprites are the result of Umihara Kawase sprite ripper, which mechaskrom programmed and I directed.. long ago. These are actually a byproduct of my Umihara Kawase map ripping project.
Here are snippets from the original discussion we had, mostly my explanation on how the sprites are made. Interesting read for newbies and pros alike, I guess!
————————My initial proposal to mechaskrom from April 2013————————
[...] I realized that there are no rips of Umihara Kawase sprites, excluding the player sprite! I can't rip them manually myself because the current SNES9x emulates the game incorrectly, and I honestly don't like ZSNES.
So, I though, why not stab two flies in one hit and get rips from each sprite in the game, for the benefit of the collective and to apply fresh clean sprites onto the maps? Here's my plan:
Umihara Kawase Shun: Second Edition Kanzenban for the DS is essentially a 3-in-1 game that also includes the SNES Umihara Kawase game. Since the DS has a filesystem of its own, by decompressing all of the game's files you can access them as if they were real folders and files in Windows Explorer/Finder.
This is particularly exciting because all of the files in the 'sfc' folder are actually the files the SNES game actually uses. You can, for example, search any of the files in the 'sfc/map/' from the original SNES ROM and find the level data. Some data has been re-encoded losslessly, but it's pretty much the same data.
So, instead of searching for the graphics individually in one giant chunk of a file (the SNES ROM), I looked into the 'sfc/obj/' folder and found files of each sprite set in the game. The files also contain palette and tilemap info, so one program that does exactly what I've explained below could easily spew out every single sprite in the game!
.BIN file structure:
All BINs have a $18 byte header that defines eight things:
1. Where the block array begins [BLKADDR, 4 bytes]
2. Where the sprite definition begins [SPRADDR, 4 bytes]
3. Where the palette info begins [PALADDR, 4 bytes]
4. Where the graphics data begins [GFXADDR, 4 bytes]
5. Amount of blocks [BLKAM, 2 bytes]
6. Amount of sprites [SPRAM, 2 bytes]
7. Amount of palettes [PALAM, 2 bytes]
8. Amount of tiles in total [TOTAL, 2 bytes]
Let's take U3_KNG.bin, which is the Goldfish enemy's sprite file. First $18 bytes with appropriate annotations are below:
addr.+------------------------
.....| BLKADDR____ SPRADDR____
$000 | 18 00 00 00 88 00 00 00
.....+
.....| PALADDR____ GFXADDR____
$008 | A0 00 00 00 C0 00 00 00
.....+
.....| BLKAM SPRAM PALAM TOTAL
$010 | 0E 00 05 00 01 00 40 00
-----+------------------------
• Let's dive into the first thing, BLKADDR. Sprites are built from blocks and one block is 8 bytes. This is the address where the 8-byte block array begins. The program reads the bytes backwards so it gets the correct address, which is 0x00000018.
• The second thing, SPRADDR is the offset where the program starts reading the info of what blocks to use to build a sprite. This time it's at 0x00000088.
• Third thing, PALADDR is self-explanatory. Where the Palette data begins. In this case, from 0x000000A0. Palettes are read the same way as the SNES ones I explained earlier in this thread, 1555 BGR.
• Fourth thing, GFXADDR is also pretty obvious; where the graphics data begins. This time 0x000000C0. Format is 4bpp linear, reverse order.
• Fifth thing, BLKAM is 0x000E. What this means is how many blocks there are in total. This time, 0x000E. Also, since one block is 8 bytes, you now know that the block data starts from 0x00000088 and is 112 bytes big (because BLKAM * 8 = $70).
• Sixth thing, SPRAM is 0x0005. What this means is exactly how many sprites are exported in the end. This time, 0x0005. It takes four bytes to define a sprite, so you now know that the sprite data begins from 0x00000088 and is 20 bytes big (because SPRAM * 4 = $14).
• Seventh thing, PALAM, is again pretty clear. Usually sprites have one or two palettes, but in this case it's 0x0001. One palette is 32, or, $20 bytes. There's one palette this time so obviously it takes only 32 bytes as is.
• The eighth thing serves little purpose. It just tells us how many tiles there are in total. This time 64, or, $40.
So, after the header, we're in address 0x018. This is where the blocks are listed, I've written them down for easy readability and added annotations:
addr.+-xx XX yy YY tt pp BP UU-+--NR--.
$018 | F3 FF F6 FF 00 00 60 00 | 0000 |
$020 | F3 FF 06 00 08 00 50 00 | 0100 |
$028 | FA FF EE FF 18 00 00 00 | 0200 |
$030 | F2 FF F6 FF 0C 00 60 00 | 0300 |
$038 | F2 FF 06 00 14 00 50 00 | 0400 |
$040 | FA FF EE FF 25 00 00 00 | 0500 |
$048 | F2 FF F6 FF 19 00 60 00 | 0600 |
$050 | F2 FF 06 00 21 00 50 00 | 0700 |
$058 | FA FF EE FF 32 00 00 00 | 0800 |
$060 | F2 FF F6 FF 26 00 60 00 | 0900 |
$068 | F2 FF 06 00 2E 00 50 00 | 0A00 |
$070 | FA FF EE FF 3F 00 00 00 | 0B00 |
$078 | F2 FF F6 FF 33 00 60 00 | 0C00 |
$080 | F2 FF 06 00 3B 00 50 00 | 0D00 |
-----+-------------------------+------'
I'll explain each of the eight bytes here, using the first block an example.
xx XX = X position of block, two bytes, read backwards, so in this case it would be $FFF3. See this grid for reference.
yy YY = Y position of block, two bytes, read backwards, so in this case it would be $FFF6.
tt pp = tile to use and its property†. In this case it would be tile 00 with property 00.
BP = Block type‡ and Palette to use for the block. The palette is always 0 so I don't see how this would be so useful.
UU = Unused.
NR = Block Number. Just for reference! This is not in the ROM, I just put it to the right of the table to help visualize what block we're in right now. You'll need to know this later. From the first block definition it's just counting upwards from 00 00, bytes backwards.
†: property byte is kind of funny. Of its 8 bits, only the first two are used. vhUU UUUU, where v means vertical flip of block's tiles and h horizontal flip, respectively (and U=unused).
‡: There are twelve block types. They essentially tell how the block is made, or, arrange a predetermined amount of tiles to a certain arrangement to form the block. See this for reference. $C_, $D_, $E_ and $F_ are unused.
Now, if the program would read the data, it would now have the information of how many blocks there are in total, how to form the correct blocks and where to put them. However, this would lead into all blocks being on top of each other, forming one sprite-cake. The next bytes, SPRADDR tells where to snip them apart, or, how many blocks build a sprite. Again, I've formatted and annotated the data for easy understanding.
addr.+ AMONT FROMB-.
$088 | 02 00 00 00 |
$08C | 03 00 02 00 |
$090 | 03 00 05 00 |
$094 | 03 00 08 00 |
$098 | 03 00 0B 00 |
-----+-------------'
Because SPRAM is $0005, we know that this file defines only five sprites. It takes four bytes to define a sprite an again, these two-byte combos are read backwards.
AMONT = Amount of blocks this sprite is built from...
FROMB = ...when counting from this Block Number.
In this case, it would be like this:
• Sprite one is two blocks: 0000 and 0100.
• Sprite two is three blocks: 0200, 0300 and 0400.
• Sprite three is three blocks: 0500, 0600 and 0700.
• Sprite four is three blocks: 0800, 0900, 0A00.
• Sprite five is three blocks: 0B00, 0C00, 0D00
And that's it. Load next file and repeat. I did this informational GIF that should help understand what's happening in the sprite creation. If you have a chance, view it frame by frame. Basically it's just "Get X, get Y, get tile, check if flips, use correct block type"
————————END————————
08-22-2014, 12:49 AM
Interesting stuff! You seem to have quite the knack for cracking open SNES formats (I'm still using your information about Super Metroid to make a ripping program, sorry that's taking so long).
How do you go about figuring this stuff out? I've tried it with some DS filetypes but they always leave me scratching my head. I can only do it with relatively simple archives or file formats for PC or mobile games that don't use tiled graphics.
How do you go about figuring this stuff out? I've tried it with some DS filetypes but they always leave me scratching my head. I can only do it with relatively simple archives or file formats for PC or mobile games that don't use tiled graphics.
08-22-2014, 02:13 AM
(08-22-2014, 12:49 AM)puggsoy Wrote: [ -> ]Interesting stuff! You seem to have quite the knack for cracking open SNES formats (I'm still using your information about Super Metroid to make a ripping program, sorry that's taking so long).Hah! It's okay. [insert quote how taking time to perfect a product is worth it]
Can't wait for the finished thing.
you again Wrote:How do you go about figuring this stuff out? I've tried it with some DS filetypes but they always leave me scratching my head. I can only do it with relatively simple archives or file formats for PC or mobile games that don't use tiled graphics.Well, most of the times it's actually very simple. I'll go into depth about this in my later rips. Hell, I should write a case study on every rip I do from now on.
In fact, I've had some plans of a general sprite ripper that automatically rips EVERY SPRITE FROM ANY SNES GAME but it's still very very theoretical.