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.

Graphics > Fast Map Copying

#55344 - thegamefreak0134 - Tue Sep 27, 2005 9:23 pm

I made it through the Pong Demo, and noticed a problem I do not like. You can see the Map being drawn onto the screen, rather than it being instantaneous. What's the deal?

Is there a way to quickly copy maps to the screen, or does it have do be done with somewhat of a frame buffer?
_________________
What if the hokey-pokey really is what it's all about?

[url=http:/www.darknovagames.com/index.php?action=recruit&clanid=1]Support Zeta on DarkNova![/url]

#55345 - tepples - Tue Sep 27, 2005 9:41 pm

You can copy an entire tile map along with tile data from ROM to VRAM during vblank time. You can copy an entire mode 4 or 5 frame from ROM to VRAM during vblank time. You may not be able to decompress an entire image during vblank time.

What is the URL of this demo?
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#55347 - DiscoStew - Tue Sep 27, 2005 9:56 pm

If something is gonna take time to decompress into VRAM, one thing you might want to try is doing some visual transition before hand, like fade to black, load the needed stuff, then fade back.

Or, for something simplier, just disable the layers that would show the change, and then reenable them once everything is done.

There are many ways to prevent the visual loading of items. Hopefully the ones I gave may lead to others....

But like tepples said, for something that is not being decompressed, it should fit into the vblank time. If you are doing that, maybe you are not doing the loading right as the vblank starts?
_________________
DS - It's all about DiscoStew

#55366 - headspin - Wed Sep 28, 2005 1:52 am

If you use gfx2gba, it will create an array of the map data that you can just DMACopy() to VRAM. It is quick, you won't notice the re-draw effect you get from using a loop.

If your using compressed data, say compressed with GBACrusher using LZ77 for example, you can use my function I wrote with the help of Tepples. It uses the GBA's built in LZ77 decompression routine in the BIOS and returns the size of the uncompressed data. It's important to get the size so you can DMACopy() directly to VRAM.

Code:
// UnCompress LZ77 Data to WRAM and return size of uncompressed data
u32 LZ77UnCompWRAM(u32 source, u32 dest) {
u32 size;
asm volatile (
"mov r0, %1  \n"   // put first parameter into r0
"mov r1, %2  \n"   // put second parameter into r1
"push {r0}   \n"   // push r0 onto the stack (pointer to header)
"swi 0x11    \n"   // call the BIOS function (r0 gets trashed)
"pop {r0}    \n"   // pull r0 off the stack
"ldr r0, [r0]\n"   // load the value r0 (header) into r0
"lsr r0, #8  \n"   // right shift 8 bits
"mov %0, r0  \n"   // move r0 into size (to return)
:"=r" (size)
:"r" (source), "r" (dest)
:"r0", "r1", "r2" );
return size;
}

// --------------------------------

// Uncompress to Buf and return size of uncompressed data
gfxSize = LZ77UnCompWRAM((u32) pGfx, (u32) Buf);

// Now we DMA Copy to the appropriate tile address using the size
DMA_Copy(3, (void*) Buf, (void*) TileAddr, gfxSize, DMA_16NOW);


Then there is always the LZ77 BIOS decompression function that decompresses directly to VRAM. Make sure you use the VRAM (safe) option in GBACrusher. Although I could never get it to work without getting corrupt data on the screen.

Code:
// UnCompress LZ77 Data to VRAM
inline void LZ77UnCompVRAM(u32 source, u32 dest) {
asm("mov r0, %0\n"
"mov r1, %1\n"
"swi 0x12\n"
:
:"r" (source), "r" (dest)
:"r0", "r1" );
}

LZ77UnCompVRAM((u32) pGfx, (u32) TileAddr);

_________________
Warhawk DS | Manic Miner: The Lost Levels | The Detective Game

#55406 - Cearn - Wed Sep 28, 2005 9:12 am

Pong Demo ... you mean this thing? The code there is among the slowest you can possibly get. For overall speed-ups, use thumb code and compile with at least some optimisations on. Add -mthumb -mthumb-interwork -O2 to the compiler flags.
Also, don't use halfwords or bytes as local variables, use int or u32 only. In particular, don't ever use u16 for a loop variable; view every code that uses it with just a little suspicion. Extra code needs to be generated for dealing with the smaller types, so it will be slower. This also goes for mempry copies: copying u32-arrays is almost twice as fast as u16-arrays. But even the standard memcpy() is faster than that, and if you really want speed, use DMACopy or CPUFastSet.

Code:
// --- minimal DMA information (browse around for more) ---
#define REG_DMA3SAD       *(vu32*)(0x040000D4)
#define REG_DMA3DAD       *(vu32*)(0x040000D8)
#define REG_DMA3CNT       *(vu32*)(0x040000DC)

#define _DMA_16     (0x0000<<16)
#define DMA_32      (0x0400<<16)
#define DMA_ON      (0x8000<<16)

#define DMA_16NOW    DMA_NOW | _DMA_16
#define DMA_32NOW    DMA_NOW | DMA_32

/*!
    \param src Source address; must be word aligned
    \param dst Destination address; must be word aligned
    \param count number of (half)words to copy
    \param mode DMA mode (see list above)
*/
static inline void dmacpy3(const void *src, void *dst, u32 count, u32 mode)
{
    REG_DMA3SAD= src;
    REG_DMA3DAD= dst;
    REG_DMA3CNT= count | mode;
}


// --- CpuFastSet (it's been a while since I used inline asm; hope this is ok ---

#if   defined   ( __thumb__ )
#define   swi_call(x)    asm volatile("swi\t"#x ::: "r0", "r1", "r2", "r3")
#else
#define   swi_call(x)    asm volatile("swi\t"#x"<<16" ::: "r0", "r1", "r2", "r3")
#endif

/*!
    \param src Source address; must be word aligned
    \param dst Destination address; must be word aligned
    \param count Length/mode
        Bit 0-15: Number of words to copy (must be multiple of 8).
        Bit 24: Fixed source flag (for fills)
*/
void CpuFastSet(const void *src, void *dst, u32 count)
{    swi_call(0x0C);    }

#55581 - thegamefreak0134 - Thu Sep 29, 2005 5:23 pm

Yes, I mean "This Thing." (see above, not dealing with links right now.) I am kind of a new programmer, so a lot of you are speaking greek to me. The DMACopy() is about the only thing I recognise as a possible solution to my problem. I didn't know untill this point that the GBA supported compression of any kind. (although I don't suppose it does, that's done with code isn't it?) Temm me how to use the DMACopy() please and I'll me on my way.

BTW, I am only familier with Mode 3, due to the tutorial. I am perfectly aware of the other modes, but I will devote a separate chunk of my life to learning about them later. Right now I want a quick fix. Thanx in advance!
_________________
What if the hokey-pokey really is what it's all about?

[url=http:/www.darknovagames.com/index.php?action=recruit&clanid=1]Support Zeta on DarkNova![/url]

#55584 - poslundc - Thu Sep 29, 2005 6:07 pm

thegamefreak0134 wrote:
Yes, I mean "This Thing." (see above, not dealing with links right now.) I am kind of a new programmer, so a lot of you are speaking greek to me. The DMACopy() is about the only thing I recognise as a possible solution to my problem. I didn't know untill this point that the GBA supported compression of any kind. (although I don't suppose it does, that's done with code isn't it?) Temm me how to use the DMACopy() please and I'll me on my way.


Call the dmacpy3() function that Cearn posted.

Read the comments that he put above the function definition to see how.

DMA is not a magic fix. Your program may be suffering from any number of other timing issues. Are you sure you're copying your data during VBlank?

Dan.

#55868 - thegamefreak0134 - Mon Oct 03, 2005 4:45 pm

No, I'm not even really sure what that means. The tutorial wasn't exactly in-depth by any means. I can get games running, but this is just one of the issues I really didn't like.

Come to think of it, I don't think the tutorial even game me the DMAcopy function at all. I'll have to add it. How do you check to see if you are in VBlank? Or perhaps would copying the data right after a VSync call do the same purpose?
_________________
What if the hokey-pokey really is what it's all about?

[url=http:/www.darknovagames.com/index.php?action=recruit&clanid=1]Support Zeta on DarkNova![/url]

#55872 - poslundc - Mon Oct 03, 2005 5:37 pm

Work through Cearn's TONC tutorial.

Dan.