#27307 - Fluffz - Fri Oct 08, 2004 11:21 pm
hi there, i have a problem :x
i have a bitmap with sprites. each has 256 colors and a size of 32x32 which results in a bitmap size of 128x128 in total. 4x4 sprites / bitmap. i made a .h file. now i want to load a single sprite from that sheet into OAMData. i came up with following (working) code:
tempOAMData being the spritesheets.h, inx/iny the spriteline/spriterow
Code: |
void LoadOAMData(u16* tempOAMData, int inx, int iny) //this is to strange for me
{
int x,y,i=0;
u16* firstOAMData = ((u16*)0x06014000);
//iin*=1024;
inx*=4;
iny*=32*4;
for(x = inx; x < (inx + 32); x++)
{
for(y = iny; y < (iny + 32*4); y++)
{
firstOAMData[i++] = tempOAMData[x*128*4+y];
}
}
}
|
my problem is, i dont understand why this code works at all. especially why inx has to be *=4 instead of *=32. all the *4 bother me actually. i assume it has to do with the sice of the adresses and stuff? or is it because of these 8x8 titles a 32x32 sprite consists of? sadly i have no clue...
thanks for any help u could give me
#27308 - sajiimori - Fri Oct 08, 2004 11:52 pm
When people post code that uses magic numbers that have no apparent meaning, it's already hard to understand -- and that's even when the original author knows what the numbers mean. If the author doesn't even know... well, good luck.
Use named constants (using #define or otherwise) instead of inserting numbers into your code.
#27311 - getch - Sat Oct 09, 2004 1:39 am
First of all I just want to say you chose a bad naming system for variables. A lot of posts I see dont seem to understand what OAM is.
It stands for Object Attribute Memory. It has information on the Attributes of the sprites, NOT the graphic data.
Second, I want to try and help but as the other poster said, your code is really hard to read. So instead of answering your question (why does my code work) I'll just give some info on what you are doing.
Your 32x32 sprite will be split up into 16 sprite tiles (cos they're 8x8 each).
If you are storing this in 1D mode (which I recommend) these 16 tiles will all be contiguous.
A 256 color tile takes up 64 bytes so in total a single sprite will be (16*64) 1024 bytes.
The VRAM is accessed as a (u16*) pointer (someone correct me if i'm wrong. I dont know much about thumb/arm modes)
Thats 2 bytes per read/write , so your first sprite should take up SpriteData[0] ar far as SpriteData[511].
The next SpriteData[512] ar far as SpriteData[1023] e.t.c.
Hope that helps somewhat.
-edit : where did you get this code? did you just try multiplying by different numbers until it worked?
#27317 - Fluffz - Sat Oct 09, 2004 10:25 am
hm ok, in my gba.h i have a OAMdata 0x6010000 firstOAMdata adds 512 bytes and therefore points to the first place i can store sprites to. so much for the magic numbers and bad naming, ill change that.
Quote: |
where did you get this code? did you just try multiplying by different numbers until it worked? |
heh, no, i watched the output which always gave me 1/4 of each sprite in the first row. so i multiplicated with 4 and viola. thats for the y value. x is still totaly strange to me.
let me modify my question, why does the following code not store the first 32x32 pixels from a 128x128 bitmap. spriteData is the .h saved 128x128 bitmap. 256 colors, 4x4 sprites each 32x32 in size.
Code: |
for(x = 0; x < 32; x++)
{
for(y = 0; y < 32; y++)
{
firstMEMData[i++] = spriteData[x*128+y];
}
}
|
what this does instead is saving the top 8 pixellines (8x128 ?). can it be that the bitmap is stored in a strange way, i refuse to understand that this is a problem with sizes.
Code: |
for(x = 4; x < 4+32; x++)
{
for(y = 0; y < 32*4; y++)
{
firstMEMData[i++] = spriteData[x*128*4+y];
}
}
|
this saves the first 32x32 pixels in spriteline 1 (spriteline1 = pixelline 32-64). where i can accept the lines to be multiplicated with 4, the x=4 is my personal horror.
spriteline 0 (pixelline 0-32) would be x=0; x<32. that doesnt make sense at all?!
edit: i think its because of the 8x8 titles, but i am not clever enough to figure it out. dont bother with it to much, it works and thats what is has to do :p
#27320 - getch - Sat Oct 09, 2004 3:54 pm
I'll try to explain this as clearly as I can. You are right in that it has something to do with the 8x8 pixel tiles.
You must put your sprite into memory as a series of 4 tiles in this order:
top-left tile, top-right tile, bottom-left tile, bottom-right tile.
Inside each tiles the pixels are stored in the order of: entire first line, entire second line, etc.
Here's some [bad] psudocode:
Code: |
BITMAP_OFFSET is the address of the bitmap in ROM
SPRITELINE_OFFSET = BITMAP_OFFSET
do this 2 times //because there's 2 sprites vertically
SPRITE_OFFSET = SPRITELINE_OFFSET
do this 2 times //because there's 2 sprites horizontally
TILELINE_OFFSET = SPRITE_OFFSET
do this 4 times //cos theres 4 tiles p/sprite vertically
TILE_OFFSET = TILELINE_OFFSET
do this 4 times //cos theres 4 tiles p/sprite horizontally
PIXELLINE_OFFSET = TILE_OFFSET
do this 8 times
copy 8 pixels from PIXELLINE_OFFSET to VRAM
PIXELLINE_OFFSET += BITMAP_WIDTH
TILE_OFFSET += 8
TILELINE_OFFSET += (8 * BITMAP_WIDTH)
SPRITE_OFFSET += 32 //pixel width of sprite
SPRITELINE_OFFSET += (32 * BITMAP_WIDTH)
|
Not very readable but thats what I use to convert my sprite and tile bitmaps to .h files. (splitting up the tiles beforehand saves the GBA CPU some processing time)
#27342 - Fluffz - Sun Oct 10, 2004 11:33 pm
it makes a little bit more sense now, thank you :)