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 > Unlocking VRAM

#142221 - NeX - Sat Oct 06, 2007 4:36 pm

How do I do this? I am trying to copy 32 32x32 8-bit textures into VRAM A every frame. Maybe I'm asking a bit much of the hardware. But anyhow, I've tried dmaCopying to the VRAM and things, but nothing seems to work. I have read that I need to "unlock" VRAM and this can be a little awkward, with all sorts of complications. I've tried reassigning the VRAM bank to LCD whilst copying and then back, but not only does this not do anything, it blanks half the screen. I've googled and I've searched this forum. I could do with some pointers.
_________________
Strummer or Drummer?.
Or maybe you would rather play with sand? Sandscape is for you in that case.

#142222 - Sausage Boy - Sat Oct 06, 2007 4:47 pm

Quote:
<sgstair> if you're locking vram to update textures, that's going to cause flickering most of the time.
<sgstair> the only safe time to do it is after rendering is complete for a frame (somewhere between scanline 144 and 192 - you'll have to poll the register to know exactly when), and you must have all the data loaded into vram by scanline 214
<sgstair> Another reasonable way to do it is to have 2 VRAM banks for textures, but only use one at a time (or 4, use 2 at a time) - load data to the vram banks not in use, and switch the banks that are engaged as texture memory when vblank starts.
<sgstair> ideally though, you don't want to be changing the textures every frame.
<sgstair> if you can avoid it, that's best.


Here are some lines from sgstair about the matter which I rescued from IRC. I think having 2 VRAM banks would be the best thing in your case. And yeah, you need to assign a bank to LCD before you can copy anything to it.
_________________
"no offense, but this is the gayest game ever"

#142224 - zeruda - Sat Oct 06, 2007 5:16 pm

2 VRAM banks are not necessary. Are you using the standard libnds texture loading function? Because the RAM is unlocked and relocked in that anyway. In terms of doing this, it's quite simple. You need to have a VBLank interrupt running, as soon as that is called inside it you call the texture loading routine. That stuff is in the libnds examples or in doubles tutorials.

You set up interrupts with:

Code:
void InitInterruptHandler()
{
  REG_IME = 0;
  IRQ_HANDLER = on_irq;
  REG_IE = IRQ_VBLANK;
  REG_IF = ~0;
  DISP_SR = DISP_VBLANK_IRQ;
  REG_IME = 1;
}


Before your main loop call these:

irqInit(); // Basic IRQ setup
irqSet(IRQ_VBLANK, 0);
InitInterruptHandler();

In you main loop you call:
swiWaitForVBlank();

Here's what the VBlank routine looks like.

Code:
void on_irq()
{
    if(REG_IF & IRQ_VBLANK) {
        // I think this is glTexImage2D in libnds
        Texture.Load(17, TEXTURE_SIZE_256, GL_RGB, "flipface.pcx");

        // Tell the DS we handled the VBLANK interrupt
        VBLANK_INTR_WAIT_FLAGS |= IRQ_VBLANK;
        REG_IF |= IRQ_VBLANK;
    } else {
        REG_IF = REG_IF; // Ignore all other interrupts
    }
}


I managed to load a 256*256 16 bit texture in the VBlank without any flickering. That is equivalent to 64 32*32 textures so what you require should definitely be possible.

Oh and you unlock VRAM like so:
vramSetBankE(VRAM_E_LCD);
and relock it like so:
vramSetBankE(VRAM_E_TEX_PALETTE);

Obviously you have to choose which bank to unlock and what mode you are relocking it to. Alternatively you can unlock all the main vram banks.

u32 vramTemp = vramSetMainBanks(VRAM_A_LCD,VRAM_B_LCD,VRAM_C_LCD,VRAM_D_LCD); // unlock VRAM
MessAroundWithVRAMBanks();
vramRestoreMainBanks(vramTemp);