gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Graphics > Weird 16 color sprite data problem

#20420 - mr_schmoe - Tue May 11, 2004 12:46 am

I've been developing a bmp to gba convert and I've ran into a little snag that I can't seem to figure out. Everything works fine in 256 color mode, but when I try 16 colors, it doesn't seem to work properly

My program goes something like this.

load the bitmap data so the data in memory equals this
unsigned char bmpdata[] = { 0xA1, 0xB0, 0x1E, 0x1E, ... }

convert the data to GBA format and type cast the data to 16 bit words

so you end up with,
{ 0xA1B0, 0x1E1E, ... }

I figure the problem isn't in my conversion program, but how the GBA displays sprite data. If you look at it, the first pixel of the sprite should be color index A (or 10), right? Then then next two are ones and the fourth is a 0, right? But when I load the program on the GBA, it's sort of screwed up. It looks like the first pixel is a color index 0 and the next is a 10 (or A). Or in other words it looks like this 0x0B1A.

So like me break it down this way.

The bitmap data is stored like this:
{ 0xA1B0, 0x1E1E, ... }

In the GBA memory sprite data addresss (0x06010000), it looks like this:
{ 0xA1B0, 0x1E1E, ... }

On the screen it looks like it should be more like:
{ 0x0B1A, 0xE1E1, ... }

Is there something I'm missing here?

And as I was writing this, I went back check on somethings and now I'm not so sure my 256 color mode conversion works. I'll check that and get back with you. But in the mean time, does anyone know how would I go about reversing the data so it shows up on the screen correctly? Thanks a million.

#20421 - DiscoStew - Tue May 11, 2004 1:10 am

The way you have your data stored is reversed every 4 pixels.
Value of 0xA1B0 and 0xE1E1 would have the pixels in this order: 0 B 1 A 1 E 1 E
Reversing to 0x0B1A and 0x1E1E would display: A 1 B 0 E 1 E 1

Every 2 bytes in 16 color mode is 4 pixels, with the first 4 bits being the 1st pixel, then next 4 bits for the 2nd pixel, then the 3rd, then the 4th, therefore in a 2 byte hexidecimal format, the bit are arranged from right to left. So if you had a pixel layout like this row of 12 pixels...

0, 0, 4, 7, 6, 3, 8, 7, 2, F, A, 4,

...the format would look like this...

0x7400, 0x7836, 0x4AF2

From the look of it, every 4 pixels looks like it is in a reversed format.

Hope that helps
_________________
DS - It's all about DiscoStew

#20422 - mr_schmoe - Tue May 11, 2004 1:15 am

Good, that coinsided with what I figured out and provided the clarity. Thanks for the help. But how would I go about coding that? Is there an operator or something that does that or do I have to do it manually? Like this:

hi = data / 16;
lo = data % 16;
data = lo * 16 + hi;

#20424 - DiscoStew - Tue May 11, 2004 2:43 am

For simplicity, assume you have your picture array where every byte represents a pixel, with each value representing a palette index from 0 to 15 (16 colors). To stuff 4 pixels into a 2-byte value, do the following:

(2-byte value) = (1st pixel) + ((2nd pixel) << 4) + ((3rd pixel) << 8) + ((4th pixel) << 12);

Now, by looking at the way you have your data stored, you have 2 pixels per byte, am I right, where if you had a value of "0xA1", "A" would be the 2nd pixel and "1" would be the first pixel? If not, assume it was. To convert with this method, try this...

(2-byte value) = (2nd byte) + ((1st byte) << 8);

If the above is correct, except that the pixels are swapped, where "A" would be the 1st pixel, and "1" is the second pixel, then do this...

(2-byte value) = (((1st byte) & 0xF0) >> 4) + (((1st byte) & 0x0F) << 4) + (((2nd byte) & 0xF0) << 4) + (((2nd byte) & 0x0F) << 12);

I know it looks odd, but it would do something like this...

{0xA1, 0x8F} -> 0xF81A


I know there is a lot here, but I wasn't quite sure what you were suggesting, so I gave you what I thought you needed.
_________________
DS - It's all about DiscoStew

#20454 - scknight - Tue May 11, 2004 5:03 pm

I just finished a first pass at writing something really similar. I put the code up so you can check it out if you want.

http://www.wideopenwest.com/~scknight/bmp2gba.zip

The exe probally isnt going to run unless you have the cygwin installed on your system.

I think its all easier than what others said. Dont worry reading two bytes at a time, just read byte by byte but when you read 4bit images remeber that you only need half as many bytes and you need to swap hi and lo.

(num<<4) | (num>>4)

That will do the swapping. Anyway take a look at the code and see if it helps. It extracts out raw information for both palette and data. The palette files can be read by Peebrains gbpal program. The output files are designed to be directly linked in rather than used in a c header.