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 > Libnds questions - newbie

#144526 - nulL - Sat Nov 03, 2007 7:34 am

Hi I'm having trouble drawing directly to the second screen (bottom) as well as the top screen at the same time.

Code:
void ClearScreen(void) {
    int i;
   
    for(i = 256 * 10; i < 256 * 192; i++)
        VRAM_A[i] = RGB15(0, 15, 0);
   
}

int main() {
    irqInit();
    irqEnable(IRQ_VBLANK);
   
    videoSetMode(MODE_FB0);
    vramSetBankA(VRAM_A_LCD);
   
    while(1) {
        swiWaitForVBlank();
        ClearScreen();
    }
}


The above code draws the top sceen green. How can I use simular code to draw the top screen green and the bottem red at the same time?

Sorry if this sounds like a stupid question.

Also where can I find the libnds api documentation. I have found http://devkitpro.sourceforge.net/devkitProWiki/libnds/index.html but the video section is not avaliable. Or do I have to use the headers for the documentation?

Thanks

#144528 - HyperHacker - Sat Nov 03, 2007 8:12 am

Hold on I see all sorts of problems here.

Code:
for(i = 256 * 10; i < 256 * 192; i++)
        VRAM_A[i] = RGB15(0, 15, 0);
The high bit of each pixel needs to be set for it to show up in most modes (maybe not framebuffer mode?).

Code:
videoSetMode(MODE_FB0);
vramSetBankA(VRAM_A_LCD);
I don't know of any good reason to use framebuffer mode instead of a 256x256 extended rotation bitmap. You get the same result but you have rotation, shearing, scaling, transparency, etc. Also, assigning a bank to "LCD" (no idea why it's named that) means it won't be used for VRAM at all.

Code:
while(1) {
        swiWaitForVBlank();
        ClearScreen();
    }
}
There's no sense clearing the screen every frame, that just wastes CPU power.

VRAM management can be a bit of a pain. If you just want each screen to have a 16-bit bitmap, you can do something like this:
Code:
vramSetMainBanks(VRAM_A_MAIN_BG, VRAM_B_SUB_BG, VRAM_C_LCD, VRAM_D_LCD); //Bank A at 0x06000000, bank B at 0x06200000
videoSetMode(MODE_5_2D | DISPLAY_BG3_ACTIVE);
videoSetModeSub(MODE_5_2D | DISPLAY_BG3_ACTIVE);

BG3_CR = BG_BMP16_256x256; //256x256 16-bit bitmap
BG3_XDX = 1 << 8; //Identity matrix (no rotation, scaling or shearing)
BG3_XDY = 0;
BG3_YDX = 0;
BG3_YDY = 1 << 8;
BG3_CX = 0; //Position at 0, 0
BG3_CY = 0;

SUB_BG3_CR = BG_BMP16_256x256; //256x256 16-bit bitmap
SUB_BG3_XDX = 1 << 8; //Identity matrix (no rotation, scaling or shearing)
SUB_BG3_XDY = 0;
SUB_BG3_YDX = 0;
SUB_BG3_YDY = 1 << 8;
SUB_BG3_CX = 0; //Position at 0, 0
SUB_BG3_CY = 0;


Now you can just write your pixel data to 0x06000000 for the main screen and 0x06200000 for the subscreen, but make sure to set the high bit or else it won't show up. It gets a bit more complex if you want multiple bitmaps, text layers, sprites, etc.

Beware of the limited CPU power you have, though. Updating two 256x192 bitmaps every frame doesn't leave much for the rest of the program. You'll want to avoid making large changes to what's on the screen as much as possible. If speed isn't important, you can look into having two bitmaps per screen, and toggle between them for a double-buffering effect.
_________________
I'm a PSP hacker now, but I still <3 DS.

#144570 - nulL - Sun Nov 04, 2007 12:51 am

Thanks for the help HyperHacker.

Ive added the following code to yours.

Code:
    unsigned int* pixelLocation;
    unsigned short int colour = RGB15(0, 15, 0);
    int i;
   
    pixelLocation = (unsigned int*) 0x06200000;
   
    colour = colour | (1<<15);

    for(i = 0; i < 256 * 256; i++)
        pixelLocation[i] = colour;
   
    pixelLocation = (unsigned int*) 0x06000000;
   
    colour = RGB15(15, 0, 0);
    colour = colour | (1<<15);
   
    for(i = 0; i < 256 * 256; i++)
        pixelLocation[i] = colour;


But I get the following result.
[Images not permitted - Click here to view it]
It seems every second column is black. Im not sure why.

Also on actual DS hardware nothing is drawn to the second screen (bottom screen).

#144571 - DragonMinded - Sun Nov 04, 2007 1:15 am

Because you defined pixelLocation to be an integer, not a uint16. Therefore, every index to it will be on a 4 byte boundary, not a two byte boundary, hence leaving every other pixel dark.
_________________
Enter the mind of the dragon.

http://dragonminded.blogspot.com

Seriously guys, how hard is it to simply TRY something yourself?

#144574 - nulL - Sun Nov 04, 2007 2:39 am

Ahh yes that makes way to much sence now. Thanks DragonMinded.

Sorry to be a pain but I still have the probelm of the second screen not showing anything (dark/black) on actual DS hardware. Though on Desmume it works fine (top screen red, bottom green).

Here is my full code


Code:

int main() {
       
    vramSetMainBanks(VRAM_A_MAIN_BG, VRAM_C_SUB_BG, VRAM_C_LCD, VRAM_D_LCD); //Bank A at 0x06000000, bank B at 0x06200000
    videoSetMode(MODE_5_2D | DISPLAY_BG3_ACTIVE);
    videoSetModeSub(MODE_5_2D | DISPLAY_BG3_ACTIVE);

    BG3_CR = BG_BMP16_256x256; //256x256 16-bit bitmap
    BG3_XDX = 1 << 8; //Identity matrix (no rotation, scaling or shearing)
    BG3_XDY = 0;
    BG3_YDX = 0;
    BG3_YDY = 1 << 8;
    BG3_CX = 0; //Position at 0, 0
    BG3_CY = 0;

    SUB_BG3_CR = BG_BMP16_256x256; //256x256 16-bit bitmap
    SUB_BG3_XDX = 1 << 8; //Identity matrix (no rotation, scaling or shearing)
    SUB_BG3_XDY = 0;
    SUB_BG3_YDX = 0;
    SUB_BG3_YDY = 1 << 8;
    SUB_BG3_CX = 0; //Position at 0, 0
    SUB_BG3_CY = 0;

    unsigned short int* pixelLocation;
    unsigned short int colour = RGB15(15, 0, 0);
    int i;
   
    pixelLocation = (unsigned short*) 0x06200000;
   
    colour = colour | (1<<15);

    for(i = 0; i < 256 * 256; i++)
        pixelLocation[i] = colour;
   
    pixelLocation = (unsigned short*) 0x06000000;
   
    colour = RGB15(0, 15, 0);
    colour = colour | (1<<15);
   
    for(i = 0; i < 256 * 256; i++)
        pixelLocation[i] = colour;
   
}

#144577 - tepples - Sun Nov 04, 2007 3:11 am

Too many DS emulators are more forgiving than the DS hardware in a few aspects. If you're trying to make a program that uses bitmap mode run correctly on DS hardware, check these first:
  • VRAM banks
  • Alpha bit
Specifically, check this:
Code:
vramSetMainBanks(VRAM_A_MAIN_BG, VRAM_C_SUB_BG, VRAM_C_LCD, VRAM_D_LCD);

Why does C appear twice?
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.