need help allocating and copying sprite tiles efficiently

DayTripperID
Posts: 22
Joined: Tue Aug 07, 2012 8:57 pm

need help allocating and copying sprite tiles efficiently

Post by DayTripperID » Sun Sep 16, 2012 7:22 pm

Hi everyone! I've been making my space shooter game with devkitARM for about a month and a half now, and i'm starting to run into problems allocating and copying sprite tiles into memory.

Ok, so let me explain my problem before I show the code. I've run into a couple of problems where I am getting corrupted tiles when using u16* arrays for sprites with more than one gfx frame. The corruption never exceeds a 32x32 pixel area and is contiguous, usually occupying either an entire 32x32 sprite, or the top 1024 pixels of a 64x64 sprite. Up to this point I have been able to solve this by rearranging the order in which the various graphics are allocated and copied into memory. Today, however, i ran into an issue that i can't handle this way. I added a 64x64 graphic with 6 frames. After I allocate its memory, the program freezes when I swiCopy() the graphics to memory, and when I dmaCopy(), the program doesn't freeze, but the last member of the array is always addressing to 0x64000, and displaying all the tiles that are actually in that area of memory. I have tried increasing and decreasing the size of the graphics and arrays, and it always has the same result. Here is the code I am working with:

Code: Select all

void SpriteList::loadTiles(){
 
	u16 i;
	
	/* Create pointers & allocate memory for sprite tiles used in this level. (main engine) */
	/* Copy tiles data into main OAM. */
	
	afterburnTiles_ptr  = oamAllocateGfx(oam, SpriteSize_8x8, SpriteColorFormat_16Color);
	swiCopy(afterburn_gfxTiles, afterburnTiles_ptr, afterburn_gfxTilesLen);
	
	asteroidTiles_ptr  = oamAllocateGfx(oam, SpriteSize_32x32, SpriteColorFormat_16Color);
	swiCopy(asteroid_gfxTiles, asteroidTiles_ptr, asteroid_gfxTilesLen);

        laserTiles_ptr  = oamAllocateGfx(oam, SpriteSize_32x32, SpriteColorFormat_16Color);
 	swiCopy(lazer_gfxTiles, laserTiles_ptr, lazer_gfxTilesLen);

	membraneTiles_ptr  = oamAllocateGfx(oam, SpriteSize_32x32, SpriteColorFormat_16Color);
	swiCopy(membrane_gfxTiles,  membraneTiles_ptr,  membrane_gfxTilesLen);

	roamerTiles_ptr  = oamAllocateGfx(oam, SpriteSize_32x32, SpriteColorFormat_16Color);
	swiCopy(roamer_gfxTiles, roamerTiles_ptr, roamer_gfxTilesLen);
	
	sporeTiles_ptr  = oamAllocateGfx(oam, SpriteSize_32x32, SpriteColorFormat_16Color);
	swiCopy(spore_gfxTiles, sporeTiles_ptr, spore_gfxTilesLen);
	
	for(i=0; i<3; i++) astxplodTiles_ptr[i] = oamAllocateGfx(oam, SpriteSize_32x32, SpriteColorFormat_16Color);
	for(i=0; i<3; i++) swiCopy(&astxplod_gfxTiles[i*128], astxplodTiles_ptr[i], astxplod_gfxTilesLen/3);
	
	for(i=0; i<3; i++) mbrndslvTiles_ptr[i] = oamAllocateGfx(oam, SpriteSize_32x32, SpriteColorFormat_16Color);
	for(i=0; i<3; i++) swiCopy(&mbrndslv_gfxTiles[i*128], mbrndslvTiles_ptr[i], mbrndslv_gfxTilesLen/3);
	
	for(i=0; i<5; i++) outlawTiles_ptr[i]  = oamAllocateGfx(oam, SpriteSize_32x32, SpriteColorFormat_16Color);
	for(i=0; i<5; i++) swiCopy(&outlaw_gfxTiles[i*128], outlawTiles_ptr[i], outlaw_gfxTilesLen/5);
	
	for(i=0; i<3; i++) explode32x32Tiles_ptr[i] = oamAllocateGfx(oam, SpriteSize_32x32, SpriteColorFormat_16Color);
	for(i=0; i<3; i++) swiCopy(&explode32x32_gfxTiles[i*128], explode32x32Tiles_ptr[i], explode32x32_gfxTilesLen/3);
	
	for(i=0; i<4; i++)	shooterTiles_ptr[i] = oamAllocateGfx(oam, SpriteSize_32x32, SpriteColorFormat_16Color);
	for(i=0; i<4; i++) swiCopy(&shooter_gfxTiles[i*128], shooterTiles_ptr[i], shooter_gfxTilesLen/4);
					
	for(i=0; i<4; i++) skirmerTiles_ptr[i] = oamAllocateGfx(oam, SpriteSize_32x32, SpriteColorFormat_16Color);
	for(i=0; i<4; i++) swiCopy(&skirmer_gfxTiles[i*128], skirmerTiles_ptr[i], skirmer_gfxTilesLen/4);

	for(i=0; i<4; i++) skirmLordTiles_ptr[i] = oamAllocateGfx(oam, SpriteSize_64x64, SpriteColorFormat_16Color);
	for(i=0; i<4; i++) swiCopy(&skirmLord_gfxTiles[i*512], skirmLordTiles_ptr[i], skirmLord_gfxTilesLen/4);

	for(i=0; i<6; i++) explode64x64Tiles_ptr[i] = oamAllocateGfx(oam, SpriteSize_64x64, SpriteColorFormat_16Color);
	for(i=0; i<6; i++) swiCopy(&explode64x64_gfxTiles[i*512], explode64x64Tiles_ptr[i], explode64x64_gfxTilesLen/6);
The last line is the one giving me issues. I don't think I am running myself out of memory, but I'm not sure how to properly calculate that-- they are 4bpp depth, so would it be 4x8x8= 256bits per 8x8 tile? And if I add up everything, how much room do I actually have to work with in a vram bank? (using bank B). I don't have that many graphics, so I'm wondering if I'm overlooking something else? Any insight/advice is greatly appreciated! Thanks!

DayTripperID
Posts: 22
Joined: Tue Aug 07, 2012 8:57 pm

Re: need help allocating and copying sprite tiles efficientl

Post by DayTripperID » Sun Sep 16, 2012 10:45 pm

I added up graphics and it came to about 8.41K. VRAM_B has 128K so I think I can rule out memory overflow.

mtheall
Posts: 210
Joined: Thu Feb 03, 2011 10:47 pm

Re: need help allocating and copying sprite tiles efficientl

Post by mtheall » Mon Sep 17, 2012 6:51 am

What sprite mapping are you using in oamInit()?

elhobbs
Posts: 354
Joined: Thu Jul 02, 2009 1:19 pm

Re: need help allocating and copying sprite tiles efficientl

Post by elhobbs » Mon Sep 17, 2012 1:22 pm

dmaCopy reads directly from main memory bypassing the data cache. you need to make sure that you flush the data cache before using dmaCopy. You can call DC_FlushAll to flush the entire data cache at once, or you can use DC_FlushRange to flush a specific region. dmaCopy is the fastest method to copy chunks of main memory to vram, so it is probably a better choice than swiCopy for this task.

mtheall
Posts: 210
Joined: Thu Feb 03, 2011 10:47 pm

Re: need help allocating and copying sprite tiles efficientl

Post by mtheall » Mon Sep 17, 2012 5:14 pm

I added up the graphics and calculated 33436 bytes. If you used SpriteMapping_1D_32, then you have gone out of bounds of sprite graphics index (max 32KB). If you are mapping 128KB of VRAM for objects (which it appears you have), then I would suggest switching to SpriteMapping_1D_128.

Make sure to check for NULL from oamAllocateGfx().

DayTripperID
Posts: 22
Joined: Tue Aug 07, 2012 8:57 pm

Re: need help allocating and copying sprite tiles efficientl

Post by DayTripperID » Mon Sep 17, 2012 8:40 pm

Yes i'm currently using Sprite_Mapping_1D_32. I guess I added up the gfx wrong, but I think you are right that I am slightly over bounds because that's how the program behaves. I trimmed the gfx down and started using lookup tables for animation so i could eliminate redundant frames, but I'm going to add alot more gfx in the future, so I'll switch to Sprite_Mapping_128. Thanks for pointing it out!

And no, I wasn't flushing the cache with the dmaCopy(), in fact the only reason I used it was to get around the swiCopy() from freezing up. I don't know if it was a failed assertion but I'll check the header. I wasn't getting any text on sub screen, I just wasn't getting anything at all. But from now on I'll flush the cache when I use dmaCopy()!

Thanks alot for your help guys! 8)

DayTripperID
Posts: 22
Joined: Tue Aug 07, 2012 8:57 pm

Re: need help allocating and copying sprite tiles efficientl

Post by DayTripperID » Mon Sep 17, 2012 9:01 pm

Confirmed-- the sprite mapping change fixed it.

mtheall
Posts: 210
Joined: Thu Feb 03, 2011 10:47 pm

Re: need help allocating and copying sprite tiles efficientl

Post by mtheall » Mon Sep 17, 2012 9:41 pm

swiCopy may be hanging if you give it an invalid pointer. I don't think dmaCopy will hang in some (if not all) circumstances.

Foxi4
Posts: 14
Joined: Wed Feb 22, 2012 10:49 pm

Re: need help allocating and copying sprite tiles efficientl

Post by Foxi4 » Sat Nov 10, 2012 1:26 pm

I'd suggest switching from swiCopy to dmaCopy with cache flushing - it'll likely benefit you performance-wise if you're copying large chunks of data, plus, you can perform 4 copy operations (DMA has 4 channels) at once, asynchronously from the CPU, so you're wasting less time than when using swi or memcpy.

mtheall
Posts: 210
Joined: Thu Feb 03, 2011 10:47 pm

Re: need help allocating and copying sprite tiles efficientl

Post by mtheall » Sat Nov 10, 2012 5:24 pm

Foxi4 wrote: I'd suggest switching from swiCopy to dmaCopy with cache flushing - it'll likely benefit you performance-wise if you're copying large chunks of data, plus, you can perform 4 copy operations (DMA has 4 channels) at once, asynchronously from the CPU, so you're wasting less time than when using swi or memcpy.
Well this is somewhat misleading. Yes, it is accurate that there are four DMA channels, so you can have four separate DMA operations set up at the same time. However, they have priorities. Only one can be actually working at a time (the one with the highest priority) and it will stall the others until it is complete. Yes, the DMA operations can occur asynchronously from the CPU, but ONLY if the CPU is not accessing DMA-accessible memory. If the CPU attempts to access main RAM or VRAM, then the CPU will stall, too.

Post Reply

Who is online

Users browsing this forum: No registered users and 4 guests