Cyclone wrote:Hey all, as far as I know the sprites are uncompressed right?
Well I want to extract them. I want to find the banana sprite location in the rom for starters as I think that is only one tile.
Where is it stored in the rom?
Thanks in advance.
Cyclone wrote:I just want to edit the sprite manually in a hex editor. So I need to know the location of the sprite graphics.
Cyclone wrote:Right now I’m just trying to understand how to read the gfx data and nothing else. I think I found where the first frame of the banana sprite is stored. Now I just need to understand how to read the data in the hex editor.
VRAM 8x8 Pixel Tile Data (BG and OBJ)
Each 8x8 tile occupies 16, 32, or 64 bytes (for 4, 16, or 256 colors). BG tiles can be 4/16/256 colors (depending on BG Mode), OBJs are always 16 color.
Color Bits (Planes) Upper Row ........... Lower Row
Plane 0 stored in bytes 00h,02h,04h,06h,08h,0Ah,0Ch,0Eh ;\for 4/16/256 colors
Plane 1 stored in bytes 01h,03h,05h,07h,09h,0Bh,0Dh,0Fh ;/
Plane 2 stored in bytes 10h,12h,14h,16h,18h,1Ah,1Ch,1Eh ;\for 16/256 colors
Plane 3 stored in bytes 11h,13h,15h,17h,19h,1Bh,1Dh,1Fh ;/
Plane 4 stored in bytes 20h,22h,24h,26h,28h,2Ah,2Ch,2Eh ;\
Plane 5 stored in bytes 21h,23h,25h,27h,29h,2Bh,2Dh,2Fh ; for 256 colors
Plane 6 stored in bytes 30h,32h,34h,36h,38h,3Ah,3Ch,3Eh ;
Plane 7 stored in bytes 31h,33h,35h,37h,39h,3Bh,3Dh,3Fh ;/
In each byte, bit7 is left-most, bit0 is right-most.
Plane 0 is the LSB of color number.
Cyclone wrote:I found this which may be useful that Simion posted.
viewtopic.php?f=38&t=1167&p=21466&hilit=Sprite+format#p21467
76543210 - byte #1 in a given word
76543210 - byte #2 in a given word
C7 = 11000111 (1)
34 = 00110100 (2)
= 11220311
2bpp = 1 block of 8 words
4bpp = 2 blocks of 8 words
8bpp = 4 blocks of 8 words
C7 = 11000111 (1)
34 = 00110100 (2)
56 = 01010110 (4)
39 = 00111001 (8)
= 15AE8759
WesternTanager794 wrote:The way the SNES stores graphics is confusing. Did they make it that way to keep people from tinkering with the system? Like with creating their own games?
Kingizor wrote:Individual tiles are always 8x8 pixels, so a single tile contains 64 pixels worth of data. Sprites are typically made up of many tiles!
So we have:
· palette data (contains the colours)
· tilemap data (which palette block to use)
· tileset data (bitplane data, which colours to use in the block)
And that's everything needed to decode and construct a tile. (you won't need tilemap data if you know the palette used by a particular tile)
Cyclone wrote:I played around with hex editor. All I can seem to do is make the pixels in the tiles black or transparent…
How can I for example make it a solid yellow square? Or something easy to change by changing bitplane values
Cyclone wrote:I was able to change the Pallet ok using your RainbowZ Editor but the sprite editor menu is grayed out...
Cyclone wrote:Sorry user error! I pressed apply thinking it would write to the rom and not the write button.
Rainbow on another post wrote:'Write' always writes to rom, where 'Apply' makes changes on a program level.
Sprite Header
Byte 0 is number of 2x2 chars
Byte 1 is number of 1x1 chars in group 1
Byte 2 is relative position of first 1x1 char of group 1
Byte 3 is number of 1x1 chars in group 2
Byte 4 is position of group 2
Byte 5 is number of chars in dma group 1
Byte 6 is where to place dma group 2 (0 if none)
Byte 7 is number of chars in dma group 2 (0 if none)
These 8 bytes are followed by 2 bytes each representing bytes 0, 1, and 3 of the header. Those 2 bytes are the X and Y coordinate of each graphic.
00 ff 00 ff 00 ff 00 ff 00 ff 00 ff 00 ff 00 ff
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
2 3 2 3 2 3 2 3 2 3 2 3 2 3 2 3
Cyclone wrote:I don't know if this is user error but I keep getting a green square when I select index 8. Again see screenshot.
Cyclone wrote:what is the palette name for the Red heart then? I was using the default. And I didn't see it in the drop down list.
Thanks.
Cyclone wrote:That's really odd. I wonder why RARE made an exception just for that sprite.
Cyclone wrote:Yes but it makes sense.
Any ideas on a single tile sprite with a proper palette?
I still need to play around with something simple until I get the hang of things.
Thanks!
Cyclone wrote:Edit. What palette is used for the heart? I mean how do I know what colours are available for it?
Bitwise AND: & (check)
Bitwise OR: | (set)
Bitwise XOR: ^ (toggle)
Bitwise NOT: ~ (negate)
Left Shift: <<
Right Shift: >>
Logical NOT: ! (useful for reducing single bits)
AND: If A and B are set, then C is set
|~~~|~~~|~~~|
|AND| 0 | 1 |
0 & 0 = 0 |~~~|~~~|~~~|
0 & 1 = 0 | 0 | 0 | 0 |
1 & 0 = 0 |~~~|~~~|~~~|
1 & 1 = 1 | 1 | 0 | 1 |
|~~~|~~~|~~~|
OR: If A or B is set, then C is set
|~~~|~~~|~~~|
| OR| 0 | 1 |
0 & 0 = 0 |~~~|~~~|~~~|
0 & 1 = 1 | 0 | 0 | 1 |
1 & 0 = 1 |~~~|~~~|~~~|
1 & 1 = 1 | 1 | 1 | 1 |
|~~~|~~~|~~~|
XOR: If one of A and B is set, then C is set.
|~~~|~~~|~~~|
|XOR| 0 | 1 |
0 & 0 = 0 |~~~|~~~|~~~|
0 & 1 = 1 | 0 | 0 | 1 |
1 & 0 = 1 |~~~|~~~|~~~|
1 & 1 = 0 | 1 | 1 | 0 |
|~~~|~~~|~~~|
int a = 0b1111 & ~01100; // a = 0b0011
int a = 0xF & ~0xC ; // a = 0x3
int a = 15 & ~12 ; // a = 3
int a = 0b1100 >> 2; // a = 0b0011
int a = 0xB >> 2; // a = 0x3
int a = 11 >> 2; // a = 3
int a = 0b1100 << 2; // a = 0b110000
int a = 0xC << 2; // a = 0x30
int a = 12 << 2; // a = 48
int a = !5; // a = 0
int a = !12345678; // a = 0
int a = !0; // a = 1
int a = !!5; // a = 1
int a = !!12345678; // a = 1
int a = !!0; // a = 0
int a = !!(0xFF & 0x80); // a = 1
Kingizor wrote:"interleaved" is more common here than "intertwined". The "twin" in the latter would make me think of two threads of data, like a DNA strand. Perhaps call that an interleaved pair? Interleaved doesn't have a number associated with it which is more suitable for bitplanes which we can think of as having eight threads of data, one for each column all packed into a single byte.
int main()
{
int ROW0 = 0b00011000;; //to store number
int ROW1 = 0b00111100;
int ROW2 = 0b01111110;
int ROW3 = 0b11011011;
int ROW4 = 0b11111111;
int ROW5 = 0b00100100;
int ROW6 = 0b01011010;
int ROW7 = 0b10000001;
int N = 7; //to store bit
int NB = 7;
int NC = 7;
int ND = 7;
int NE = 7;
int NF = 7;
int NG = 7;
int NH = 7;
int c = 0;
BYTE* buf = new BYTE[8 * 5];
for (int j = 0; j < 8; j++) // Row 7
{
if (ROW7 & (1 << NH))
{
buf[c + 0] = (BYTE)0;
buf[c + 1] = (BYTE)0;
buf[c + 2] = (BYTE)0;
}
else
{
buf[c + 0] = (BYTE)255;
buf[c + 1] = (BYTE)255;
buf[c + 2] = (BYTE)255;
}
c += 3;
NH--;
}
for (int j = 0; j < 8; j++) // Row 6
{
if (ROW6 & (1 << NG))
{
buf[c + 0] = (BYTE)0;
buf[c + 1] = (BYTE)0;
buf[c + 2] = (BYTE)0;
}
else
{
buf[c + 0] = (BYTE)255;
buf[c + 1] = (BYTE)255;
buf[c + 2] = (BYTE)255;
}
c += 3;
NG--;
}
for (int j = 0; j < 8; j++) // Row 5
{
if (ROW5 & (1 << NF))
{
buf[c + 0] = (BYTE)0;
buf[c + 1] = (BYTE)0;
buf[c + 2] = (BYTE)0;
}
else
{
buf[c + 0] = (BYTE)255;
buf[c + 1] = (BYTE)255;
buf[c + 2] = (BYTE)255;
}
c += 3;
NF--;
}
for (int j = 0; j < 8; j++) // Row 4
{
if (ROW4 & (1 << NE))
{
buf[c + 0] = (BYTE)0;
buf[c + 1] = (BYTE)0;
buf[c + 2] = (BYTE)0;
}
else
{
buf[c + 0] = (BYTE)255;
buf[c + 1] = (BYTE)255;
buf[c + 2] = (BYTE)255;
}
c += 3;
NE--;
}
for (int j = 0; j < 8; j++) // Row 3
{
if (ROW3 & (1 << ND))
{
buf[c + 0] = (BYTE)0;
buf[c + 1] = (BYTE)0;
buf[c + 2] = (BYTE)0;
}
else
{
buf[c + 0] = (BYTE)255;
buf[c + 1] = (BYTE)255;
buf[c + 2] = (BYTE)255;
}
c += 3;
ND--;
}
for (int j = 0; j < 8; j++) // Row 2
{
if (ROW2 & (1 << NC))
{
buf[c + 0] = (BYTE)0;
buf[c + 1] = (BYTE)0;
buf[c + 2] = (BYTE)0;
}
else
{
buf[c + 0] = (BYTE)255;
buf[c + 1] = (BYTE)255;
buf[c + 2] = (BYTE)255;
}
c += 3;
NC--;
}
for (int j = 0; j < 8; j++) // Row 1
{
if (ROW1 & (1 << N))
{
buf[c + 0] = (BYTE)0;
buf[c + 1] = (BYTE)0;
buf[c + 2] = (BYTE)0;
}
else
{
buf[c + 0] = (BYTE)255;
buf[c + 1] = (BYTE)255;
buf[c + 2] = (BYTE)255;
}
c += 3;
N--;
}
for (int j = 0; j < 8; j++) // Row 0
{
if (ROW0 & (1 << NB))
{
buf[c + 0] = (BYTE)0;
buf[c + 1] = (BYTE)0;
buf[c + 2] = (BYTE)0;
}
else
{
buf[c + 0] = (BYTE)255;
buf[c + 1] = (BYTE)255;
buf[c + 2] = (BYTE)255;
}
c += 3;
NB--;
}
SaveBitmapToFile((BYTE*)buf,
8,
8,
24,
0,
"C:\\Users\\Chris\\Desktop\\bluesquare.bmp");
delete[] buf;
1bpp: (bits * (255 / ((1 << 1)-1))) = { 0, 255 }
2bpp: (bits * (255 / ((1 << 2)-1))) = { 0, 85, 170, 255 }
4bpp: (bits * (255 / ((1 << 4)-1))) = { 0, 36, 72, 109, 145, 182, 218, 255}
8bpp: (bits * (255 / ((1 << 8)-1))) = { 0..255 }
Kingizor wrote:You've got eight loops that are very similar. The first loop operates on the ROW7 and NH variables, the second on ROW6 and HG, and so on. If you put all your ROW7 variables into an array and your N# variables into another array you could loop over them with another loop, so you'd only need one copy of the current 'j' loop instead of eight of them. If the N# variables all start at 7 you might not even need all the separate variables for them. (brackets { } denote scope, so normal variables declared inside them are local to them)
rainbowsprinklez wrote:Another consideration for this is let's say you want to make 1 tweak. The way you have it, you would need to make that tweak in 8 places, rather than 1. Further, you would have to remember to make 8 changes. Trust me, when it's been a while, you'll likely forget you did it that way and get frustrating bugs cause you forgot.
int main()
{
int ROW[] = { 0b10000001 , 0b01011010, 0b00100100, 0b11111111, 0b11011011, 0b01111110, 0b00111100, 0b00011000 }; // Array to to store numbers
int N = 7; //to store bit
int c = 0;
BYTE* buf = new BYTE[8 * 5];
for (int p = 0; p < 8; p++)
{
for (int j = 0; j < 8; j++) // Row 6
{
if (ROW[p] & (1 << N))
{
buf[c + 0] = (BYTE)0;
buf[c + 1] = (BYTE)0;
buf[c + 2] = (BYTE)0;
}
else
{
buf[c + 0] = (BYTE)255;
buf[c + 1] = (BYTE)255;
buf[c + 2] = (BYTE)255;
}
c += 3;
N--;
}
N = 7;
}
SaveBitmapToFile((BYTE*)buf, 8, 8, 24, 0, "C:\\Users\\Chris\\Desktop\\1bppSprite.png");
delete[] buf;
return 0;
Cyclone wrote:
- Code: Select all
int main()
{
int ROW[] = { 0b10000001 , 0b01011010, 0b00100100, 0b11111111, 0b11011011, 0b01111110, 0b00111100, 0b00011000 }; // Array to to store numbers
int N = 7; //to store bit
int c = 0;
BYTE* buf = new BYTE[8 * 5];
for (int p = 0; p < 8; p++)
{
for (int j = 0; j < 8; j++) // Row 6
{
if (ROW[p] & (1 << N))
{
buf[c + 0] = (BYTE)0;
buf[c + 1] = (BYTE)0;
buf[c + 2] = (BYTE)0;
}
else
{
buf[c + 0] = (BYTE)255;
buf[c + 1] = (BYTE)255;
buf[c + 2] = (BYTE)255;
}
c += 3;
N--;
}
N = 7;
}
SaveBitmapToFile((BYTE*)buf, 8, 8, 24, 0, "C:\\Users\\Chris\\Desktop\\1bppSprite.png");
delete[] buf;
return 0;
for (int p = 0; p < 8; p++, N=7)
This checks if a bit is set → if (Bitplane0_ROW[p] & (1 << N)){ // do something.}
but i'm not sure how to check is a bit not set like this → if (! Bitplane0_ROW[p] & (1 << N)){// do something}
int main()
{
int Bitplane0_ROW[] = { 0b01100110 , 0b11111111, 0b01011010, 0b01111110, 0b00000000, 0b10000001, 0b11111111, 0b01111110 }; // Array to to store numbers Last Row is first.
int Bitplane1_ROW[] = {0b01111110, 0b11111111, 0b11111111, 0b11011011, 0b11111111, 0b01111110, 0b00000000, 0b00000000};
int N = 7; //to store bit
int c = 0;
BYTE* buf = new BYTE[8 * 5];
for (int p = 0; p < 8; p++)
{
for (int j = 0; j < 8; j++) // Row 6
{
if (Bitplane0_ROW[p] & (1 << N))
{
if (Bitplane1_ROW[p] & (1 << N))
{
// Index 3
buf[c + 0] = (BYTE)154;
buf[c + 1] = (BYTE)194;
buf[c + 2] = (BYTE)237;
}
else
{
// Index 1
buf[c + 0] = (BYTE)53;
buf[c + 1] = (BYTE)189;
buf[c + 2] = (BYTE)104;
}
}
else if (Bitplane1_ROW[p] & (1 << N) )
{
if (Bitplane0_ROW[p] & (1 << N)){}
else
{ // Index 2
buf[c + 0] = (BYTE)59;
buf[c + 1] = (BYTE)85;
buf[c + 2] = (BYTE)142;
}
}
else
{
// Index 0
buf[c + 0] = (BYTE)255;
buf[c + 1] = (BYTE)255;
buf[c + 2] = (BYTE)255;
}
c += 3;
N--;
}
N = 7;
}
SaveBitmapToFile((BYTE*)buf, 8, 8, 24, 0, "C:\\Users\\Chris\\Desktop\\bluesquare.png");
delete[] buf;
return 0;
}
Cyclone wrote:How do you check if a bit not set? I'm sure its something obvious. sorry.
if ((a & bit) == 0) { ...
if (!(a & bit)) { ...
Kingizor wrote:The extra parentheses can be helpful, but they're not strictly necessary in the first case. Some compilers will warn about it because of how easy it is to mix up bitwise AND (&) logical AND (&&) which have different behaviours.
Users browsing this forum: No registered users and 1 guest