load sprites from filesystem

TheLazy1
Posts: 2
Joined: Wed May 05, 2010 7:28 pm

Re: load sprites from filesystem

Post by TheLazy1 » Wed May 05, 2010 7:31 pm

I noticed a few bugs with my handling of DMA in my GRF loading functions as well.
They were missed because I got incredibly lucky and it worked randomly each time I tested it at first, then failed afterwards.

I'm not sure what state the last version is in but the next update should come soon and be a bit better/more robust.
It's probably safer to just use memcpy anyway, you're not really going to load tons of gfx during a game loop eh? :D

User avatar
coreyh2
Posts: 33
Joined: Tue Feb 02, 2010 12:43 am

Re: load sprites from filesystem

Post by coreyh2 » Thu May 06, 2010 5:22 am

I can imagine it being useful for long animations. If you look at a game like Disgaea other 2d rpgs they have moments when they load in the animation and sound for an attack. If it is possible to load a frame of animation in 1 or 2 vblanks it would be possible to have a smoother experience then if you had to load the whole animation to main memory first. It might be unreliable on slower microsd.

Thanks for working on the code. Is it going directly into libnds or somewhere else?

dheart88
Posts: 44
Joined: Sun Dec 13, 2009 3:00 pm

Re: load sprites from filesystem

Post by dheart88 » Thu May 06, 2010 11:14 am

There's no problem with me.. because i use memcpy in the beginning of class, and I copy sprite/background from filesystem and copy it into RAM and later, when I need that sprite/background, I just call dmaCopy function to copy from RAM into RAM

Personally, I still prefer to use gfx2gba013 to convert sprite/background into
bgPal.bin
bgTiles.bin
bgMap.bin

and then I just call it from nitro fs.. it's really simple, just a simple memcpy and no other decompressing method...

Well, next time I'll post my complete code...

WinterMute
Site Admin
Posts: 1865
Joined: Tue Aug 09, 2005 3:21 am
Location: UK
Contact:

Re: load sprites from filesystem

Post by WinterMute » Thu May 06, 2010 2:35 pm

Grit can output the same files, it's also the preferred method since grit is open source and supplied with the toolchain.
Help keep devkitPro toolchains free, Donate today

Personal Blog

TheLazy1
Posts: 2
Joined: Wed May 05, 2010 7:28 pm

Re: load sprites from filesystem

Post by TheLazy1 » Fri May 07, 2010 1:36 pm

dheart88 wrote:There's no problem with me.. because i use memcpy in the beginning of class, and I copy sprite/background from filesystem and copy it into RAM and later, when I need that sprite/background, I just call dmaCopy function to copy from RAM into RAM

Personally, I still prefer to use gfx2gba013 to convert sprite/background into
bgPal.bin
bgTiles.bin
bgMap.bin

and then I just call it from nitro fs.. it's really simple, just a simple memcpy and no other decompressing method...

Well, next time I'll post my complete code...
I tried that before but ended up getting frustrated with the loose files and multiple file operations to do a single thing.
Granted, nitrofs solves the first problem but I found the grf format to be a nice clean system which is totally underrated.

If anyone works with my example please give me feedback/suggestions/flames/whatever so improvements can be made :)

User avatar
coreyh2
Posts: 33
Joined: Tue Feb 02, 2010 12:43 am

Re: load sprites from filesystem

Post by coreyh2 » Sat May 08, 2010 11:15 am

If i process man.png in grf-example without -Zl the first frame of the facing up set of frames has a black glitched group of pixels in the top left corner. I couldn't figure out the cause so far.

.edit.
I switched GRF_Decompress to using memcpy and it worked. I still don't understand dmaCopy. :(

.second edit

Changing DC_FlushRange to DC_FlushAll also worked. I don't understand why.
Last edited by coreyh2 on Sun May 09, 2010 11:57 am, edited 1 time in total.

dheart88
Posts: 44
Joined: Sun Dec 13, 2009 3:00 pm

Re: load sprites from filesystem

Post by dheart88 » Sun May 09, 2010 4:03 am

btw, what is inside dmaCopy? i mean the process inside... So far, I know dmaCopy copying block faster than memcpy, but It won't work well if it's used to copy data from sd card to ram.

btw, I found something odd about filesytem, if I use nitrofs to load a save file or any binary file from fat:/, i have to reinit nitrofs so I can use nitrofs again. Is this occured because i don't use nitro:/ as the prefix??

I always call this in sprite initialization:
....
loadBinary(BG_PALETTE,(char*)"/bgPal.bin")

or should I change it into

loadBinary(BG_PALETTE,(char*)"nitro:/bgPal.bin")

so I won't have to reinit nitroFS after loading fat.

..............
Btw, is fat the only way to create a save file?

User avatar
coreyh2
Posts: 33
Joined: Tue Feb 02, 2010 12:43 am

Re: load sprites from filesystem

Post by coreyh2 » Sun May 09, 2010 12:37 pm

I figured it out. :P I didn't remember cearn's example code correctly.

TheLazy1's function GRF_Decompress

Code: Select all

int GRF_Decompress( u32* Source, void* Dest ) {
	u32 Header;
	u32 Size;
	
	if ( Source && Dest ) {
		Source+= 2;
		
		Header = *Source;
		Size = Header >> 8;
		
		DC_FlushRange( Source, Size );
		
		switch ( Header & 0xF0 ) {
			case 0x00: {
				dmaCopy( Source + 1, Dest, Size );
				break;
			}
			case 0x10: {
				decompress( Source, Dest, LZ77Vram );
				break;
			}
			case 0x20: {
				decompress( Source, Dest, HUFF );
				break;
			}
			case 0x30: {
				decompress( Source, Dest, RLEVram );
				break;
			}
			default: return 0;
		};
		
		// This fixed it :)
		//DC_InvalidateRange( Dest, Size );
		DC_FlushRange( Dest, Size );
		return 1;
	}
	
	return 0;
}
changed version

Code: Select all

int GRF_Decompress( u32* Source, void* Dest ) {
	u32 Header;
	u32 Size;
	
	if ( Source && Dest ) {
		Source+= 2;
		
		Header = *Source;
		Size = Header >> 8;
		

		
		switch ( Header & 0xF0 ) {
			case 0x00: {

				DC_FlushRange( Source + 1, Size );
				DC_FlushRange( Dest, Size );
				dmaCopy( Source + 1, Dest, Size );
				break;
			}
			case 0x10: {
				decompress( Source, Dest, LZ77Vram );
				break;
			}
			case 0x20: {
				decompress( Source, Dest, HUFF );
				break;
			}
			case 0x30: {
				decompress( Source, Dest, RLEVram );
				break;
			}
			default: return 0;
		};
		
		// This fixed it :)
		//DC_InvalidateRange( Dest, Size );

		return 1;
	}
	
	return 0;
}
cearn's dmaCopySafish also works instead of the stuff in case 0x00

Code: Select all

#define CACHE_LINE_SIZE 32

// Assuming cached regions. Add tests for that yourself.
void dmaCopySafish(const void *src, void *dst, u32 size)
{
    DC_FlushRange(src, size);                       // Flush source.
   
    u32 addr= (u32)dst;
    if(addr % CACHE_LINE_SIZE)                      // Check head
        DC_FlushRange((void*)(addr), 1);
       
    if((addr+size) % CACHE_LINE_SIZE)               // Check tail.
        DC_FlushRange((void*)(addr+size), 1);

    dmaCopy(src, dst, size);                        // Actual copy.
    DC_InvalidateRange(dst, size);                  // Final invalidate.
}

main memory to main memory dma isn't supposed to be faster then assembly memcpy without using async so it probably doesn't matter.

Is it useful to store graphics data uncompressed on flash anyway? Flash is supposed to be slow. So having the data smaller in the slowest place might be a good idea.

memory corruption is sure annoying to debug. :P I had no idea what was going on.

WinterMute
Site Admin
Posts: 1865
Joined: Tue Aug 09, 2005 3:21 am
Location: UK
Contact:

Re: load sprites from filesystem

Post by WinterMute » Mon May 10, 2010 12:05 pm

DS DMA isn't async capable, any attempt by the CPU to access the external bus will result in a stall until DMA completes. DMA from main ram to VRAM & back to VRAM is much faster than straight RAM to RAM due to non sequential penalties.
Help keep devkitPro toolchains free, Donate today

Personal Blog

User avatar
coreyh2
Posts: 33
Joined: Tue Feb 02, 2010 12:43 am

Re: load sprites from filesystem

Post by coreyh2 » Tue May 11, 2010 9:11 am

I didn't remember correctly. The examples of using the functions like dmaCopyWordsAsynch are addressing vram not main ram. I don't understand how they are set up though though. Something about making sure none of the memory being copied is in main ram? Its beyond my knowledge. There seems to be conflicting advice.

http://forum.gbadev.org/viewtopic.php?t=13242&start=15
http://forum.gbadev.org/viewtopic.php?t ... ordsasynch
http://forum.gbadev.org/viewtopic.php?t ... ordsasynch
http://forum.gbadev.org/viewtopic.php?t ... c&start=15

There should be some documentation on how the dmaCopyWordsAsynch functions can be used.

Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests