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 > Garbage instead of Sprite

#158668 - sverx - Mon Jun 16, 2008 11:15 am

Hi there, I'm sorry to be here asking another question again so soon but I really can't find any idea to solve that. I've read some 12 topics about sprites on this forum but nothing seems to be 'my case'...

In a little test program I draw some sprites (in 256 colors, on SUBENGINE, using extended palettes) and I see them appearing on screen with Dualis.

On no$gba, instead, I just get some garbage on the upper left corner of the screen, they seems just random pixel. But it's 8x8, that's strange too.

On the hardware -unfortunatly for me- it's like on the no$gba.

video mode is:
Code:
MODE_0_2D | DISPLAY_BG0_ACTIVE | DISPLAY_BG2_ACTIVE | DISPLAY_BG1_ACTIVE | DISPLAY_BG_EXT_PALETTE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_2D_LAYOUT | DISPLAY_SPR_EXT_PALETTE


I'm loading data into VRAM D and palette into VRAM I
Code:
vramSetBankD(VRAM_D_SUB_SPRITE);
vramSetBankI(VRAM_I_SUB_SPRITE_EXT_PALETTE);

(of course I load the palette into VRAM_I before setting it to this mode...)

Then I reset the OAM_SUB (I'm NOT using a copy of OAM_SUB, it's a test so I'm just writing directly into it) with that
Code:
   SpriteArray* SubSpriteCTRL = (SpriteArray*) OAM_SUB;

   for (i=0;i<128;i++) {
     SubSpriteCTRL->Sprite[i].y_attrib_0 = ATTR0_DISABLED | ATTR0_COLOR_256 | OBJ_Y(10);
     SubSpriteCTRL->Sprite[i].x_attrib_1 = ATTR1_SIZE_8 | OBJ_X(10);
     SubSpriteCTRL->Sprite[i].attrib_2   = 0;
   }


and finally activating some sprites on the screen, for example here's one:
Code:
   SubSpriteCTRL->Sprite[3].y_attrib_0= ATTR0_SQUARE | ATTR0_COLOR_256 | OBJ_Y(30);
   SubSpriteCTRL->Sprite[3].x_attrib_1= ATTR1_SIZE_16 | OBJ_X(10);
   SubSpriteCTRL->Sprite[3].attrib_2 = TILE256(0) | ATTR2_PALETTE(0);


If I disable the sprites in the video mode, then the garbage disappear (so actually it's not something else...). Nothing changes if I deactivate extended palettes, if I move the sprite to another position, if I change them to 16 colors... etc... etc...

Any idea? :|

#158673 - silent_code - Mon Jun 16, 2008 12:52 pm

Dualis is OLD!
Although I like it for it's massive "degugging" features, it's quite outdated and gives me a "R15 unaligned" error every time I run a rom that has been build with the latest toolchain. :^(

Stick with no$gba instead. It has its own quirks (like not displaying 512x256 BGs), but is often a lot more accurate.

Well, back on topic: I guess your mapping might be off somewhere, so that you copy things to a different place than you should. Mixing up the whole char/screen/map/whatever base stuff can lead to that.

Good luck finding the bug! :^)

PS: Post your BG/OBJ memory setup and where you load what to.
_________________
July 5th 08: "Volumetric Shadow Demo" 1.6.0 (final) source released
June 5th 08: "Zombie NDS" WIP released!
It's all on my page, just click WWW below.

#158674 - sverx - Mon Jun 16, 2008 1:32 pm

silent_code wrote:
Dualis is OLD! [...] Stick with no$gba instead.


I've learned... it's funny anyway that Dualis is showing the sprites 'correctly' :|

silent_code wrote:
I guess your mapping might be off somewhere, so that you copy things to a different place than you should.


I guess this could happen... btw I'm copying to spriteMemory, defined that way.

Code:
   vramSetBankD(VRAM_D_LCD);
   u16* spriteMemory = (u16*)VRAM_D;


(and also I guess the beginning of VRAM_D is corresponding to the tile index number 0 that I should put into my sprite 'attrib_2'...)

#158682 - silent_code - Mon Jun 16, 2008 3:13 pm

I'm not familiar with extended palette graphics, but where did you see that you have to do it that way? I seriously suggest using the "normal" method and setting up VRAM propperly. ;^)

About Dualis: You never tried 4bit sprites, did you? The sprite viewer will display them correctly, but the main gameplay display will not. ;^)
_________________
July 5th 08: "Volumetric Shadow Demo" 1.6.0 (final) source released
June 5th 08: "Zombie NDS" WIP released!
It's all on my page, just click WWW below.

#158683 - sverx - Mon Jun 16, 2008 3:25 pm

silent_code wrote:
I'm not familiar with extended palette graphics, but where did you see that you have to do it that way? I seriously suggest using the "normal" method and setting up VRAM propperly. ;^)


One of the few things I'm quite sure I understood about programming the DS is that when using the extended palettes you should copy the palettes to some 'special' VRAM banks but unfortunatly you can't access those banks when they're used for extended palettes.
So you should first set them to a mode which is 'accessible', like LCD mode, then write the palettes into it and then change mode again.
It works, I'm using that system for backgrounds too.
(BTW, about my bug, even if I turn extended palettes off, sprites don't appears on the screen :| )

silent_code wrote:
About Dualis: You never tried 4bit sprites, did you? The sprite viewer will display them correctly, but the main gameplay display will not. ;^)


Never used 16 color bgs/sprites (...yet? ;) )

#158684 - eKid - Mon Jun 16, 2008 3:38 pm

Hmm, the code in the first post looks correct. What does SpriteArray look like?

#158685 - Cydrak - Mon Jun 16, 2008 3:39 pm

If you're seeing sprites then some VRAM must be mapped. If you have a colored BG/backdrop set up, you could see if any sprites have turned black, in that case the palette in I has likely gone missing. However, 8x8's at top-left is what you get with OAM zeroed out... which sounds like it isn't being written at all... huh.

What's the definition for SpriteArray? OAM -really- wants 16 bit access; C bitfield structs, for example, are reported to be chancy at best. If DMA works okay, that might be the problem.

#158686 - sverx - Mon Jun 16, 2008 3:46 pm

eKid wrote:
Hmm, the code in the first post looks correct. What does SpriteArray look like?


it's an array of SpriteType, defined in this way:

Code:
typedef struct {
   u16 y_attrib_0;
   u16 x_attrib_1;
   u16 attrib_2;
   u16 donotuseme;
}__attribute__ ((__packed__)) SpriteType;

typedef struct {
   SpriteType Sprite[128];
}__attribute__ ((__packed__)) SpriteArray;

#158687 - silent_code - Mon Jun 16, 2008 3:47 pm

Uh, I didn't mean writing palettes, but graphics data (sprites)! You need to set up a sprite bank and then write to the right memory area.

In my zombie particle demo, I use the following setup:
Code:
   vramSetMainBanks(   VRAM_A_MAIN_BG_0x06000000,
                  VRAM_B_MAIN_SPRITE_0x06400000,
                  VRAM_C_SUB_BG_0x06200000,
                  VRAM_D_LCD);

   videoSetMode(   MODE_5_2D |            //set the graphics mode to Mode 5
               DISPLAY_SPR_ACTIVE |   //turn on sprites
               DISPLAY_BG3_ACTIVE |   //turn on background(s)
               DISPLAY_BG2_ACTIVE |
               DISPLAY_SPR_1D);


Then, you can copy graphics data like that:
Code:
   // obj tile 0-63
   for(i = 0; i < 1024; i++)
      SPRITE_GFX[i] = ((u16*)some_sprite_image)[i];


I'm using 1D-4bit sprites, but I believe, that expal sprites should be loaded in the same way. Well, I probably should check gbatek. :^)

PS: I assume you are not using PAlib (no offense), because that would require different usage from what I posted.
_________________
July 5th 08: "Volumetric Shadow Demo" 1.6.0 (final) source released
June 5th 08: "Zombie NDS" WIP released!
It's all on my page, just click WWW below.

#158688 - eKid - Mon Jun 16, 2008 3:49 pm

Try removing the __attribute__ ((__packed__)). It could be causing the compiler to use 8-bit writes.

#158689 - elhobbs - Mon Jun 16, 2008 3:54 pm

I am not familiar with using sprites but I have run into some issues using multiple layers. In my case I was able to see lower priority layers peeking through the top layer because I had completely black sections on the top layer. On the DS I did not see this but in the emulators I would. So you might want to look at your layer priorities since your code appears to be using 3 layers (BG0, BG1, and BG2).

#158690 - sverx - Mon Jun 16, 2008 3:57 pm

Cydrak wrote:
If you're seeing sprites then some VRAM must be mapped. If you have a colored BG/backdrop set up, you could see if any sprites have turned black, in that case the palette in I has likely gone missing. However, 8x8's at top-left is what you get with OAM zeroed out... which sounds like it isn't being written at all... huh.


I'm seeing sprites only with Dualis. No sprites on no$gba and on NDSL (the hardware!). No black 'squares' over my background, palettes should be ok...

BTW I read that one minute ago, it says that when using sprite 2D mapping, tile boudary (whatever it is...) won't be considered ( here DISPCNT register...) but anyway changing mode to 1D mapping doesn't affect what I see on screen :|

#158691 - sverx - Mon Jun 16, 2008 4:06 pm

silent_code wrote:
Then, you can copy graphics data like that:
Code:
   // obj tile 0-63
   for(i = 0; i < 1024; i++)
      SPRITE_GFX[i] = ((u16*)some_sprite_image)[i];


What's SPRITE_GFX[]? In memory.h it's defined:
Code:
#define SPRITE_GFX         ((uint16*)0x6400000)
#define SPRITE_GFX_SUB      ((uint16*)0x6600000)


but what's for? If it's the place where I should store the images for my sprites, then I should do something like that, right?:
Code:
   vramSetBankD(VRAM_D_SUB_SPRITE);
   u16* spriteMemory = (u16*)SPRITE_GFX_SUB;


but it doesn't work :| No changes at all.

#158692 - sverx - Mon Jun 16, 2008 4:10 pm

elhobbs wrote:
I am not familiar with using sprites but I have run into some issues using multiple layers. In my case I was able to see lower priority layers peeking through the top layer because I had completely black sections on the top layer. On the DS I did not see this but in the emulators I would. So you might want to look at your layer priorities since your code appears to be using 3 layers (BG0, BG1, and BG2).


I tryed completely removing the background but... no, that wasn't the problem (anyway I have most of the sprites with ATTR2_PRIORITY(0) so they should be on top of any bgs...)

#158693 - sverx - Mon Jun 16, 2008 4:12 pm

eKid wrote:
Try removing the __attribute__ ((__packed__)). It could be causing the compiler to use 8-bit writes.


??? :| How could I access the OAM correctly, then?

#158694 - eKid - Mon Jun 16, 2008 4:18 pm

The packed attribute just prevents the compiler from adding padding to the struct (so it can access non byte-sized data easier). In this case there will be no padding since the struct size is a multiple of four bytes, so you don't need the packed attribute.

Last time I checked, the packed attribute causes the compiler to always use 8-bit read/writes. The behavior you described is most likely because of 8-bit writes to OAM.

#158695 - sverx - Mon Jun 16, 2008 4:26 pm

eKid wrote:
The packed attribute just prevents the compiler from adding padding to the struct (so it can access non byte-sized data easier). In this case there will be no padding since the struct size is a multiple of four bytes, so you don't need the packed attribute.

Last time I checked, the packed attribute causes the compiler to always use 8-bit read/writes. The behavior you described is most likely because of 8-bit writes to OAM.


oh my God :|

I removed the
Code:
__attribute__ ((__packed__))
and 3 (out of 9) sprites just appeared!

edit: all the sprites appeared! (I disabled the other 6 before while searching for the mistake...)

Going to check the rest of the code now, I'll let you know...

Thank you so much! :)

#158696 - sverx - Mon Jun 16, 2008 4:36 pm

... so finally the problem was that Dualis allowed these 8 bit writes to the OAM, right?

Today I've learned one more thing. I wish it could happen every day :)

Thanks eveybody for the priceless help :)

#158701 - Cydrak - Mon Jun 16, 2008 5:23 pm

Yay! Well, I'll still try to answer the other questions.

sverx wrote:
I'm seeing sprites only with Dualis. No sprites on no$gba and on NDSL (the hardware!). No black 'squares' over my background, palettes should be ok...

I meant the garbage; it's still a sprite (more likely all 128, all bunched up). It's normal to see junk in the corner if OAM is left zeroed/uninitialized; the DS will still try to render them.

sverx wrote:
BTW I read that one minute ago, it says that when using sprite 2D mapping, tile boundary (whatever it is...) won't be considered ( here DISPCNT register...) but anyway changing mode to 1D mapping doesn't affect what I see on screen :|

This has to do with the 1D tile index. Unlike BGs, sprites don't really go by tile, it's more of a byte count. The "boundary" is the step size--how many bytes per index. Indices only go up to 1024, but increasing the step allows a range of up to 256K, at the expense of coarser addressing (say every 2, 4 or 8 tiles).

For 2D the index is a coordinate out of 32x32 *16 color* tiles, and the step is irrelevant. (Although see GBATEK:OBJ Tile Number.. for 256 colors, tiles are double size so apparently tile-X should be even.)

sverx wrote:
What's SPRITE_GFX[]?

SPRITE_GFX (and BG_GFX) address whatever VRAM--if any--is assigned to OBJ and BG, respectively. It is "what the hardware sees", and access outside of vblank will be slower (delayed) because the DS is using it. VRAM_x specifically addresses a bank, and is nearly always full speed, but it only works for banks in LCD mode. Either way ought to work fine.

#158753 - sverx - Tue Jun 17, 2008 2:34 pm

Thanks a lot for the useful details :)

Ciao! :)