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 > Drawing an .nds banner's icon

#163794 - yellowstar - Sun Oct 12, 2008 2:15 am

I'm attempting to draw an .nds banner's icon on the main screen, Mode 5, on BG3 with 256x256 16-bit settings. I have a console on BG0 for displaying the banner description and other information. I'm using the console on both screens. Since I'm working on WMB Host RSA Mod, I'm using Juglak's 2D initialization code, which I modified slightly. However, this isn't working correctly. There's a blue horizontal line across the screen. This doesn't appear when I disable usage of the main screen console. The icon doesn't display correctly either. Where the icon is supposed to be displayed, there's a 32x16 rectangle starting at 1x16. This rectangle appears in the bottom half of the "icon". I'm not using double-buffers, however I am using swiWaitForVBlank before drawing the icon. Screenshot

display.cpp:
Code:

void R_InitDisplay2D() {

   // basic double buffer main display and single buffer sub
   videoSetMode(DISPLAY_BG0_ACTIVE | MODE_5_2D | DISPLAY_BG3_ACTIVE);
   videoSetModeSub(MODE_5_2D | DISPLAY_BG3_ACTIVE); //sub bg 0 will be used to print text
   vramSetMainBanks(   VRAM_A_MAIN_BG_0x06000000, VRAM_B_MAIN_BG_0x06020000, VRAM_C_SUB_BG, VRAM_D_LCD);
   BG3_CR = BG_BMP16_256x256;
   BG3_XDX = 1 << 8;
   BG3_XDY = 0;
   BG3_YDX = 0;
   BG3_YDY = 1 << 8;
   BG3_CX = 0;
   BG3_CY = 0;
   SUB_BG3_CR = BG_BMP16_256x256;
   SUB_BG3_XDX = 256;
   SUB_BG3_XDY = 0;
   SUB_BG3_YDX = 0;
   SUB_BG3_YDY = 256;
   SUB_BG3_CY = 0;
   SUB_BG3_CX = 0;
   ... //Right here in display.cpp, there's some of Juglak's code which sets some variables, which are never used outside of this function.
   BG3_CR |= BG_BMP_BASE( 2 );
}

void R_SubDebug() {
   videoSetModeSub(MODE_0_2D|DISPLAY_BG0_ACTIVE);
   vramSetBankC(VRAM_C_SUB_BG);
   SUB_BG0_CR = BG_MAP_BASE(31);
   BG_PALETTE_SUB[255] = RGB15(31,31,31);
   consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(31), (u16*)CHAR_BASE_BLOCK_SUB(0), 16);
   consoleClear();
}


main.cpp:
Code:

struct sNdsInfo
{
    tNDSBanner banner;
    ...
};
sNdsInfo NDSInfo;

//This is only temporarily loading the banner from a .nds buffer, other means of loading the banner will be used in the future, once these problems are fixed.
void LoadBanner(unsigned char *nds_data)
{
    unsigned int *bannerOffset = (unsigned int*)&nds_data[0x68];
    if(*bannerOffset)
    {
        memcpy(&NDSInfo.banner, &nds_data[*bannerOffset], sizeof(tNDSBanner));
    }
}

void HideBanner()
{
    memset(&NDSInfo, 0, sizeof(sNdsInfo));
    memset(&NDSInfo.banner.icon, 1, 512);
    NDSInfo.banner.palette[1] = 0x0000;//Black

    swiWaitForVBlank();
    DrawBanner();
}

void DrawBanner()
{
    u16 *video_buffer = (u16*)BG_BMP_RAM(2);
    u16 color;
    int x, y, ti;
    x = 0;
    y = 0;
    ti = 0;

    for(int tiley=0; tiley<4; tiley++)
    {
        for(int tilex=0; tilex<4; tilex++)
        {
            for(int ty=0; ty<8; ty++)
            {
                for(int tx=0; tx<8; tx++)
                {
                    x = (tilex * 8) + tx;
                    y = (tiley * 8) + ty;

                    if(NDSInfo.banner.icon[ti]!=0)
                    {
                        color = NDSInfo.banner.palette[NDSInfo.banner.icon[ti]];
                    }
                    else
                    {
                        color = 0xFFFF;//White
                        //color = 0x0000;
                    }

                    video_buffer[((y + 16) * SCREEN_WIDTH) + (x + 16)] = color;

                    ti++;
                }
            }
        }
    }
}

//This is called when we want to print on the sub screen.
void SwitchPrintSub()
{
    R_SubDebug();
}

//This is called when we want to print on the main screen.
void SwitchPrintMain()
{
    BG0_CR = BG_MAP_BASE(31);
   BG_PALETTE[255] = RGB15(31,31,31);   //by default font will be rendered with color 255
    consoleInitDefault((u16*)SCREEN_BASE_BLOCK(31), (u16*)CHAR_BASE_BLOCK(0), 16);
}

int main(void) {

   irqInitHandler(MY_IRQ);
   irqEnable(IRQ_VBLANK);

   R_InitDisplay2D();
   SwitchPrintSub();

    SwitchPrintMain();

    defaultExceptionHandler();

   ...

        consoleClear();
    HideBanner();//Supposed to hide the banner by clearing the description and writing some values into the palette and icon so the icon becomes all black, however only the top half of the icon is black, the rest still appears. The bottom half is filled, unlike what happens when a banner from a .nds is loaded.

    ...
}


#163812 - yellowstar - Sun Oct 12, 2008 10:04 pm

I tried flushing the cache and using DMA, but I still got the same result. For the indexing in the icon, when the index is not zero for transparent, is it really the index in the icon data, like 1 for palette index 1, or minus one, for palette index zero? More pixels appear when I subtract the index, but the the displayed image still doesn't look anything like the icon from the banner.

#163816 - spinal_cord - Sun Oct 12, 2008 11:14 pm

I'm using the following to draw an nds icon onto a bitmap array, the icon data is read from temp_tex[], which is copied straight from the file.

Code:

   int temp=0, xx=0, yy=0, x=0, y=0, x1=0, y1=0;
   char temp_array[32*32];
   char tx=0, ty=0, tc=0; // temp xmy colour for pasting icon
   for(yy=0; yy<=3; yy++)
   {
      for(xx=0; xx<=3; xx++)
      {
         x=0; y=0;
         while(y<8)
         {
            x1 = (xx*8+x);
            y1 = (yy*8+y);
            temp_array[x1   +(32*y1)] = temp_tex[temp]&15;
            temp_array[x1+1 +(32*y1)] = (temp_tex[temp] >> 4)&15;
            temp+=1;
            x+=2;
            if(x==8){x=0; y++;}
           } // while
       } // xx
   } // yy


It might not be the best, but it works for me.
_________________
I'm not a boring person, it's just that boring things keep happening to me.
Homepage

#163824 - yellowstar - Mon Oct 13, 2008 12:19 am

Ah, so the banner uses 4-bit indexing, not 8-bit indexing. Thanks spinal_cord. I adapted my code to use 4-bit indexing, and the icon is now displayed correctly. Hiding the banner also works correctly now. But there's still that blue horizontal line across the screen... I changed the char block used for BG3 from 2 to 4, and the bar doesn't appear on-screen anymore. But when I use DeSmuME to view VRAM, I can still see this bar. Why is this bar in VRAM? The default console font only takes up 1 char block... And the map used for the console is block 31...

#164581 - SteveH - Sat Nov 08, 2008 3:56 am

That blue bar is actually the font data for the console.

Remember the char blocks for tile mode and the bitmap image for the frame buffer use the same address space.

If you want to prove it's the font data, swap the screens, add some code to draw a dot on the screen with the stylus, and remove it and draw across the blue bar, your text characters will distort, will disappear.

I wish I could remember the link to the table view of the layout of the GBA's screens, as the DS uses a similar / exactly the same memory layout system.

Since each map block is 2048 bytes, and each bitmap screen is 131072 bytes (per 256x256x16 bpp area) your first screen bank will have the bar across, in fact (and if I'm reading the specifications correctly) you will have to use bank 4 as the first real bank to start the storage of bitmap images / map layouts as banks 0-3 are mapped to the same memory space as the tile data.

I found the link - here scroll down to the section that's got an image with "BACKGROUND MEMORY LAYOUT" in the top. I would put a direct link, but the last time I did that I got a warning from WinterMute about it as I had linked direct to his site.

Hope this helps, and thanks for the code as I'm starting to get sick of the R4 screen, and I've been looking into the possibility of writing my own, but using the touch screen to select the icon instead of the top screen. So you have given me a leg up on the start of my little project thanks.[/url]