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.

DS development > Corrupted Sprites

#85059 - PacoChan - Fri May 26, 2006 9:09 pm

Hi, sorry for my english, but I'm spanish. I have a problem drawing sprites. I draw a bitmap 32*32 in SPRITE_GFX with this:

Code:
for(i=0;i<32*32;i++) SPRITE_GFX[i]=((u16*)enemigo_bin)[i] | (1<<15);


And it works fine.

But when I draw the same bitmap or another one on another position of SPRITE_GFX, it doesn't appear correctly:

Code:
for(i=32*32;i<32*32*2;i++) PRITE_GFX[i]=((u16*)enemigo_bin)[i] | (1<<15);


Here is all the code:

Code:


#include <nds.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <nds/arm9/console.h> //basic print funcionality

#include "enemigo_bin.h"

SpriteEntry sprites[128];

//turn off all the sprites
void initSprites(void)
{
   int i;
   
   for(i = 0; i < 128; i++)
   {
      sprites[i].attribute[0] = ATTR0_DISABLED;
      sprites[i].attribute[1] = 0;
      sprites[i].attribute[2] = 0;
      sprites[i].attribute[3] = 0;
    }
}

//copy our sprite to object attribute memory
void updateOAM(void)
{
   DC_FlushAll();
    dmaCopy(sprites, OAM, 128 * sizeof(SpriteEntry));
}

//---------------------------------------------------------------------------------
int main(void) {
//---------------------------------------------------------------------------------
   
   powerON(POWER_ALL_2D);

    //irqs are nice
   irqInit();
   irqSet(IRQ_VBLANK, 0);
   
   touchPosition touchXY;
   
    //enable vram and map it to the right places
    vramSetMainBanks(   VRAM_A_MAIN_SPRITE,        //A and B maped consecutivly as sprite memory
                        VRAM_B_MAIN_SPRITE,        //this gives us 256KB which is the max
                        VRAM_C_SUB_BG,  //map C to background memory
                        VRAM_D_MAIN_BG_0x6000000               //not using D
                        );
   
   //set the video mode
    videoSetMode(  MODE_0_2D |
                   DISPLAY_SPR_ACTIVE |    //turn on sprites
                   DISPLAY_BG0_ACTIVE |    //turn on background 0
                   DISPLAY_SPR_1D |        //this is used when in tile mode
                   DISPLAY_SPR_1D_BMP      //and this in bitmap mode
                    );
   
   BG_PALETTE[0]=RGB15(0,0,0);
   
   videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE);   //sub bg 0 will be used to print text
   
   SUB_BG0_CR = BG_MAP_BASE(31);

   BG_PALETTE_SUB[0] = RGB15(31,15,0);   //by default font will be rendered with color 255
   BG_PALETTE_SUB[255] = RGB15(31,31,0);   //by default font will be rendered with color 255

   //consoleInit() is a lot more flexible but this gets you up and running quick
   consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(31), (u16*)CHAR_BASE_BLOCK_SUB(0), 16);

   initSprites();
   
   int i;
   
   for(i=0;i<32*32;i++) SPRITE_GFX[i]=((u16*)enemigo_bin)[i] | (1<<15);
   for(i=32*32;i<32*32*2;i++) SPRITE_GFX[i]=((u16*)enemigo_bin)[i] | (1<<15);
   
   sprites[0].attribute[0] = ATTR0_BMP | 0;
   sprites[0].attribute[1] = ATTR1_SIZE_32 | 0;
   sprites[0].attribute[2] = ATTR2_ALPHA(1) | 0;
   
   sprites[1].attribute[0] = ATTR0_BMP | 0;
   sprites[1].attribute[1] = ATTR1_SIZE_32 | 32;
   sprites[1].attribute[2] = ATTR2_ALPHA(1)| 16;
   
   int x=0, y=0;
   
   lcdSwap();

   while(1) {
      
      scanKeys();
      touchXY=touchReadXY();
      iprintf("\x1b[10;0HTouch x = %04X, %04X\n", touchXY.x, touchXY.px);
      iprintf("Touch y = %04X, %04X\n", touchXY.y, touchXY.py);
      
      if(keysHeld() & KEY_RIGHT) x++;
      if(keysHeld() & KEY_LEFT) x--;
      if(keysHeld() & KEY_UP) y--;
      if(keysHeld() & KEY_DOWN) y++;
      
      swiWaitForVBlank();
      updateOAM();

   }

   return 0;
}


I'm a noob working with sprites, so try to explain me how to solve this issue in a way that a noob can understand. Thanks.[/code]

#85080 - silent_code - Fri May 26, 2006 10:50 pm

what i do is just make a counter (like int c) and increment it together with i, then set i for the next loop to c... works for me. another way that works is:

Code:

for(i = 0; i < 512; i++, c++)
   SPRITE_GFX[c] = ((u16*)player8_img_bin)[i];

for(i = 0; i < 512; i++, c++)
   SPRITE_GFX[c] = ((u16*)zombie8_img_bin)[i];


hope that fixes your problem ;)

greets,

Rob

ps: i have a sprite rotation related problem... jump to "mode 5 sprites odd" to check it out... maybe you can finde something that helps me :D (what would be VERY nice!)

#85130 - PacoChan - Sat May 27, 2006 8:04 am

Thanks, but that did not solve my problem. But if you say that it works for you, then the problem will be another thing.

#85141 - Dark Knight ez - Sat May 27, 2006 12:06 pm

A couple of things...

sprites[0].attribute[0] = some stuff you want | ATTR0_SQUARE | y-position;
sprites[0].attribute[1] = some stuff you want | ATTR1_SIZE_32 | x-position; // I'm assuming you have a 32x32 tile that is.
sprites[0].attribute[2] = the offset of where the tile is in SPRITE_GFX;

According to your i-values, the first object would be at offset 0 in SPRITE_GFX, and the second object would be at 32*32. (See your initial i values in the for-loops.)


This should be code used to put a bin in your SPRITE_GFX by the way:
Code:
for (i=0; i< (sprite_bin_size >> 1); i++)
        SPRITE_GFX[i] = ((uint16*)sprite_bin)[i];

#85154 - PacoChan - Sat May 27, 2006 2:42 pm

Thanks, I finally solved the problem. It was caused by a little detail. I changed this:

Code:
for(i=32*32;i<32*32*2;i++) SPRITE_GFX[i] = ((u16*)enemigo_bin)[i] | (1<<15);


By this:

Code:
for(i=32*32;i<32*32*2;i++) SPRITE_GFX[i] = ((u16*)enemigo_bin)[i-(32*32)] | (1<<15);


Now it works.

#85158 - Cearn - Sat May 27, 2006 3:52 pm

PacoChan wrote:
Code:
for(i=32*32;i<32*32*2;i++) SPRITE_GFX[i] = ((u16*)enemigo_bin)[i-(32*32)] | (1<<15);

If you're using offsets in copies, apply the offset to the thing you're actually offsetting, in this case the destination:
Code:
for(i=0; i<32*32; i++)
    SPRITE_GFX[i+32*32]= (u16*)enemigo_bin[i] | (1<<15);

Or better yet, copy in word-sized chunks, which should be about twice as fast.
Code:
u32 *src= (u32*)enemigo_bin;
u32 *dst= (u32*)&SPRITE_GFX[32*32];

for(ii=0; ii<32*32/2; ii++)
    *dst++= *src++ | 0x80008000;

Aside from that, you're now copying the same thing into object VRAM twice, why not simply use attr2 to point to the same graphics?

#85189 - Dark Knight ez - Sat May 27, 2006 7:15 pm

You're absolutely right, Cearn. In his first post he mentioned:
Quote:
But when I draw the same bitmap or another one on another position of SPRITE_GFX, it doesn't appear correctly

This leads me to believe he was just testing with the same sprite graphics, to make sure it's not something graphics-wise but code-wise that went wrong. Now he should be able to replace the sprite graphics.

And, PacoChan, glad you've managed to get it to work. :)