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.

Beginners > Sprites being overwritten

#49269 - blacksun - Wed Jul 27, 2005 11:31 pm

I have a little tic-tac-toe game that uses 2 different sprites. I have a function that when the user presses A the X sprite will be placed and when B is pressed the O sprite is placed. This works for the most part. However, when the user inputs two of the same sprites at the beginning the rest of the sprites placed will be of that sprite. Their tile index changes accordingly though. I have the X sprite at 512 and O at 514 because they are 8x8, 256 color in Mode 3.

Another problem is if the O sprite is added first, then an X sprite is added, it swaps the images but keeps the index the same.

So here is the code that I have for these two functions.

Code:
void AddSprite(int x, int y, int type)
{
   u16 i;

   int index = numOfSprites - 1;
   u16 spriteIndex;

   sprites[index].attribute0 = COLOR_256 | SQUARE | y;
   sprites[index].attribute1 = SIZE_8 | x;

   if(type == 1)
   {
      spriteIndex = 512;

      for(i = (index) * xDim * X_FRAMES; i < (xDim * X_FRAMES) * (index) + (xDim * X_FRAMES); i++)
               OAMData3[i] = xData[i - (index) * xDim * X_FRAMES];

   }
   else if(type == 2)
   {
      spriteIndex = 514;

      for(i = (index) * oDim * O_FRAMES; i < (oDim * O_FRAMES) * (index) + (oDim * O_FRAMES); i++)
         OAMData3[i] = oData[i - (index) * oDim * O_FRAMES];

   }

    sprites[index].attribute2 = spriteIndex;
}


numOfSprites is a global variable that updates before the sprite is added.

OAMData3 is the address 0x6014000

#49300 - Cearn - Thu Jul 28, 2005 9:15 am

blacksun wrote:
Code:
OAMData3 is the address 0x6014000
It's good that you added this remark, as this isn't actually OAM data at all, but the part of VRAM that houses object tiles. Anyhoo ...

I have a feeling that updating the graphics is off. I'm assuming that xData and oData contain the sprites, and that numOfSprites is updated after every placement, right? This code:
blacksun wrote:
Code:
      for(i = (index) * xDim * X_FRAMES; i < (xDim * X_FRAMES) * (index) + (xDim * X_FRAMES); i++)
               OAMData3[i] = xData[i - (index) * xDim * X_FRAMES];

is equivalent to (the simpler and clearer)
Code:
int nn= xDim*X_FRAMES;
for(i=0; i<nn; i++)
   OAMData3[i+index*nn]= xData[i];

And you have this in both 1 and 2 types. What this does is fill successive tiles in VRAM after each call. OAM (the stuff at 0x0700:0000 and the sprites array) merely points to the tiles you want to use. Since you only use 512 and 514, you'll always just use the first two 8bpp tiles. That is to say, the tiles that are filled in the first two calls of AddSprite; the rest are pretty much ignored.

Remove the tile-writing from AddSprite and fill both tiles at startup. (And perhaps rename OAMData3, 0x0601:4000 is not part of OAM and can only lead to confusion (Oh, and don't use halfwords for local variables, ints are faster))

#49319 - tepples - Thu Jul 28, 2005 5:17 pm

The name "OAMData3" for sprite cel VRAM comes from some old and deprecated tutorial. Here's my own macro that may help you understand better:
Code:
#define SPR_VRAM(x) ((u32 *)(0x06010000 | ((x) << 5)))

Thus, the locations in sprite cel VRAM in question would be SPR_VRAM(512) and SPR_VRAM(514).
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#49334 - blacksun - Thu Jul 28, 2005 9:39 pm

Wow, I'm shocked I even got anything working. With your suggestions and looking at other examples, I finally got my act together. Thanks a bunch you two.

This is how it looks like now for all those who are interested.

Here is the new InitSprites function that sets up the SpriteData
Code:

void InitSprites()
{
   int i;
   
   int xn = xDim * X_FRAMES;
   int on = oDim * O_FRAMES;

   for(i = 0; i < xn; i++)
      SpriteData3[i] = xData[i];

   for(i = 0; i < on; i++)
      SpriteData3[i+xn] = oData[i];
   
}


Renamed OAMData3 to SpriteData3 (with memory loc at 0x6014000) for a more accurate representation of the address.

So now all I have to do is access those tiles:
Code:

void AddSprite(int x, int y, int type)
{
   int i;

   int index = numOfSprites - 1;

   sprites[index].attribute0 = COLOR_256 | SQUARE | y;
   sprites[index].attribute1 = SIZE_8 | x;

   if(type == 1)
      sprites[index].attribute2 = 512;
   else if(type == 2)
      sprites[index].attribute2 = 514;

}


Then just copy the sprites array into OAM memory (0x7000000) and it works.