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.

C/C++ > Function Data Passing, Sprite Image Errors... pointers.

#50034 - justinGBA - Thu Aug 04, 2005 6:39 pm

I'm haveing some trouble with setting up a sprite class, the problem lies in what i believe is the passing of the array of data. Without the information being classed up it all works fine, so if anyone can take at look at this code, and maybe point out what im doing wrong...

Here are some of my defines i use...
Code:

//define object attribute memory state address
#define SpriteMem ((unsigned short*)0x7000000)
//define object attribute memory image address
#define SpriteData ((unsigned short*)0x6010000)
//define object attribute memory palette address
#define SpritePaletteMemoryPointer ((unsigned short*)0x5000200)

#define OBJ_MAP_2D 0x0
#define OBJ_MAP_1D 0x40
#define OBJ_ENABLE 0x1000
//attribute0 stuff
#define ROTATION_FLAG        0x100
#define SIZE_DOUBLE        0x200
#define MODE_NORMAL         0x0
#define MODE_TRANSPARENT    0x400
#define MODE_WINDOWED        0x800
#define MOSAIC            0x1000
#define COLOR_16            0x0000
#define COLOR_256            0x2000
#define SQUARE              0x0
#define TALL                0x4000
#define WIDE                0x8000
//attribute1 stuff
#define ROTDATA(n)        ((n) << 9)
#define HORIZONTAL_FLIP    0x1000
#define VERTICAL_FLIP        0x2000
#define SIZE_8              0x0
#define SIZE_16             0x4000
#define SIZE_32             0x8000
#define SIZE_64             0xC000
//Attribute2 stuff
#define PRIORITY(n)        ((n) << 10)
#define PALETTE(n)        ((n) << 12)

typedef struct tagSprite
{
    unsigned short attribute0;
    unsigned short attribute1;
    unsigned short attribute2;
    unsigned short attribute3;
   }Sprite,*pSprite;


here is the working block of code...
Code:

//format of data...
//const unsigned short airplaneData[] ={ ... }

DMAFastCopy((void*)airplanePalette, (void*)SpritePaletteMemoryPointer,
            256, DMA_16NOW);

//copy the tiles into sprite tile mem
DMAFastCopy((void*)airplaneData, (void*)SpriteData, sizeof(airplaneData), DMA_32NOW);
   
   Sprite mySprite;
   int sY = 126;
   int sX = 240 / 2 - 16;
   int sVelX = 1;
   int anim = 0;
   mySprite.attribute2 = anim*32;               //tileIndex
   mySprite.attribute0 = COLOR_256 | sY;      //color mode, y pos
   mySprite.attribute1 = SIZE_32 | sX;         //spriteSize, x pos

DMAFastCopy((void*)&mySprite, (void*)SpriteMem, sizeof(mySprite), DMA_32NOW);


So that chunk of code works fine, no issues at all. So i know my DMAFastCopy function works. So here is the sprite class code that doesnt.

Sprite Header...
Code:

#ifndef GBASPRITE_H
#define GBASPRITE_H

#include "gba.h"

class gbaSprite  {
   public:
      gbaSprite(const unsigned short spriteTiles[], int width, int height, int totalFrames);
      ~gbaSprite();
      
      void Activate();
      void UpdateOAM();
      
      void LoadAnimationStates(char* statename, unsigned short startFrame, unsigned short endFrame);
      void SetAnimationLoop(unsigned short startFrame, unsigned short endframe);
      void SetAnimationLoop(char* stateName);
      void SetFrame(unsigned short);
      unsigned short GetFrame();
      
      int posX;
      int posY;
      int velX;
      int velY;
      
   private:
      Sprite sprite;
      int currentFrame;
      int totalFrames;
      int indexOffset;
};

#endif


Sprite Cpp...
Code:

#include "gbaSprite.h"

gbaSprite::gbaSprite(const unsigned short spriteTiles[], int width, int height, int Frames)  {
   posX = 200;
   posY = 126;
   velX = 0;
   velY = 0;
   currentFrame = 0;
   totalFrames = Frames;
   indexOffset = height;
   
   sprite.attribute2 = 0*32;               //tileIndex
   sprite.attribute0 = COLOR_256 | posY;      //color mode, y pos
   //if( width == 8 && height == 8)
   //   sprite.attribute1 = SIZE_8 | posX;         //spriteSize, x pos
   //if( width == 16 && height == 16)
   //   sprite.attribute1 = SIZE_16 | posX;         //spriteSize, x pos
   //if( width == 32 && height == 32)
      sprite.attribute1 = SIZE_32 | posX;         //spriteSize, x pos
   
   DMAFastCopy((void*)spriteTiles, (void*)SpriteData, sizeof(spriteTiles), DMA_32NOW);
   
   DMAFastCopy((void*)&sprite, (void*)SpriteMem, sizeof(sprite), DMA_32NOW);
}


void gbaSprite::UpdateOAM()  {
   //Updates the OAM data from our private sprite memory
   DMAFastCopy((void*)&sprite, (void*)SpriteMem, sizeof(sprite), DMA_32NOW);
}



Guess:
It appears of if it is copying data over, but for some reason it seams to copy in data missing a chunk of the sprite... Just guessing... The first method displays the airplane fine, colorkeyed and all. The class, displays the arplane with the bottom half f the tale on the top half of the sprite rect, and the top half of the plane on the bottom half of the sprite rect. However it is colorkeyed properly.

#50094 - Cearn - Fri Aug 05, 2005 9:11 am

sizeof()

sizeof() is an operator that is resolved at compile time and should be thought of as a way of getting the number of bytes a variabletype uses, not the actual variable. That's the size in bytes and the size of the type.

sizeof(sprite) will probably give a value of 8: 4x u16 attributes. I think it'll give something larger if you ever plan on using virtual functions, but maybe wrong there. sizeof(spriteTiles) will give you the size of spriteTiles, which is actually a pointer, so it will give the size of a pointer which is 4. I.e., not the size of the whole array. sizeof() and arrays have a funny relationship: if you pass the array-name directly, it'll give the size of the array (but only if it can actually see it at compile time); the array-declaration works as a sort of type declaration then. In all other cases, you'll end up with the size of the pointer, which is generally useless. There are a number of threads on the use of sizeof() around, feel free to check them out too.

Also, remember that the count in DMA is the number of transfers, not the number of bytes if you do use sizeof(), divide by four somewhere. If you want to copy variables, you can also use the assignment operator ('='), rather than a function. That's what it's there for after all. And there's no need to cast to (void*); everything casts to that implicitly.

#50132 - justinGBA - Fri Aug 05, 2005 7:25 pm

Cool. It works, now. i never would of guessed that the sizeof() was a problem. I just pass the size to the sprite class now.

But that leaves me with one more question... if i know that the current sprite tile is 1536 in size... how can i use this number to offset the sprite tile Memory in the gba?

so my airplane is an array of 1536 unsigned shorts.
Would i convert that to bytes or bits, then logical or it on to the devine for where sprite memory starts? if so how?

#50338 - Cearn - Mon Aug 08, 2005 9:00 am

justinGBA wrote:
Cool. It works, now. i never would of guessed that the sizeof() was a problem. I just pass the size to the sprite class now.

For a single sprite you don't need to use DMAFastCopy, just use '='. For small-length copies (~32 bytes?) anything else is pretty much a waste of time.
Code:

Sprite s1, s2; // two sprites
...
s1= s2; // copy sprite s2 to sprite s1


justinGBA wrote:
But that leaves me with one more question... if i know that the current sprite tile is 1536 in size... how can i use this number to offset the sprite tile Memory in the gba?

so my airplane is an array of 1536 unsigned shorts.
Would i convert that to bytes or bits, then logical or it on to the devine for where sprite memory starts? if so how?

Don't quite understand that last part here. What do you need the offset for, and what does "devine" mean? ("device" doesn't make much sense in this context either)
Anyway, the 1536 you mention is 1536 shorts (halfwords), sizes are usually given in byte-units, so that'd be 1536*2= 3072. So the sprite takes up 3072 bytes of VRAM. The rest of VRAM is still free to use, just grab a tile-aligned address (32 byte boundaries) and go.