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 > Help about icon.

#112313 - tecljg - Fri Dec 15, 2006 4:48 am

hi,

the documents say the NDS icon 32x32 pixels, 4x4 tile, i write a program under windows, but can not display the icon properly,anybody can give more detailed explaination. what's the 4x4 tile?

Below is my program:

void displat_icon()
{
// read icon from nds file
readicon(ico);

unsigned short color[16];
unsigned short *ptr = (unsigned short *)(ico+544);

// Get palette
for(i=0;i<16;i++)
{
color[i]=*ptr++;
}

BYTE *ptr2 = ico+32; // point to icon data

// x, y is draw start position
int x=100, y=100, count=0;

for(i=0;i<32;i++) // 32 pixels width
{
for(int j=0;j<32;j++) // 32 pixels height
{
BYTE b = ptr2[count/2]; // one byte consist of two pixels
BYTE b2,b3;

// one pixel is 4 bits,
b2 = (b>>4)&0xf; // first pixel color palette index
b3 = b&0xf; // second pixel color palette index

unsigned short c1=color[b2], c2=color[b3];
BYTE rr1,gg1,bb1;
BYTE rr2,gg2,bb2;

// first pixel\'s RGB
rr1=(c1&0x1f)<<3;
gg1=((c1>>5)&0x1f)<<3;
bb1=((c1>>10)&0x1f)<<3;

// second pixel\'s RGB
rr2=(c2&0x1f)<<3;
gg2=((c2>>5)&0x1f)<<3;
bb2=((c2>>10)&0x1f)<<3;

CDC *dc = GetDC();
if(b2) // 0 is transparent
dc->SetPixel(x,y,RGB(r1,g1,bb1));

x++; // drawing move to next
if(b3) // 0 is transparent
dc->SetPixel(x,y,RGB(r2,g2,bb2));

count+=1;
}
x=100;
y++; // next line
}

Thanks.

#112315 - tepples - Fri Dec 15, 2006 5:17 am

Have you ever programmed for the Game Boy Advance system? Most 2D graphics on the GBA and Nintendo DS are divided into 8x8 pixel tiles. You'll need one pair of loops to scan the tiles and one pair to scan the pixels inside the tiles. It might be clearer to put these loops into separate functions, as I did in the following (untested) code:

Code:

inline unsigned int translateRGB5(unsigned int dsColor) {
  unsigned int r = dsColor & 0x1F;
  unsigned int g = (dsColor >> 5) & 0x1F;
  unsigned int b = (dsColor >> 10) & 0x1F;
  return makecol(r << 3 | r >> 2, g << 3 | g >> 2, b << 3 | b >> 2);
}

void displayTile(BITMAP *dc,
        const unsigned char *src, const unsigned short *palette,
        int dstX, int dstY) {
  for (int y = tileY; y < tileY + 8; ++y) {
    for (int x = tileX; x < tileX + 8; x += 2) {
      unsigned int data = *src++;

      unsigned int leftColorIndex = data & 0x0F;
      if (leftColorIndex) {
        unsigned int leftColor = translateRGB5(palette[leftColorIndex]);
        putpixel(dc, x, y, leftColor);
      }

      unsigned int rightColorIndex = (data & 0xF0) >> 4;
      if (rightColorIndex) {
        unsigned int rightColor = translateRGB5(palette[rightColorIndex]);
        putpixel(dc, x + 1, y, rightColor);
      }
    }
  }
}

void displayGBACel32x32(BITMAP *dc,
        const unsigned char *src, const unsigned short *palette,
        int dstX, int dstY) {
  for (int tileY = 0; tileY < 32; tileY += 8) {
    for (int tileX = 0; tileX < 32; tileX += 8) {
      displayTile(dc, src, palette, dstX + tileX, dstY + tileY);
      src += 32;
    }
  }
}

void displat_icon() {
  // read icon from nds file
  readicon(ico);

  displayGBACel32x32(dc,
        ico+32,
        (unsigned short *)(ico+544),
        100, 100);
}

_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#112317 - tecljg - Fri Dec 15, 2006 5:56 am

Great!

I tried and done!

thank you!

#112524 - headspin - Sun Dec 17, 2006 2:19 pm

Here some code from WMBFront that will convert an NDS icon to a windows icon.

Code:
HICON CWMBFrontDlg::MakeIcon(COLORREF *lpData, COLORREF clrTransparent)
{
   HICON hIcon;
   DWORD dwSize;

   HBITMAP hMask, hColor;
   LPCOLORREF lpColorData, lpMaskData;

   BITMAPINFOHEADER bmi;
   bmi.biBitCount = 32;
   bmi.biClrImportant = 0;
   bmi.biClrUsed = 0;
   bmi.biCompression = BI_RGB;
   bmi.biHeight = 32;
   bmi.biPlanes = 1;
   bmi.biSize = sizeof(BITMAPINFOHEADER);
   bmi.biSizeImage = 0;
   bmi.biWidth = 32;
   bmi.biXPelsPerMeter = 0;
   bmi.biYPelsPerMeter = 0;

   hColor = CreateDIBSection(NULL, (LPBITMAPINFO) &bmi, 0, (void**)&lpColorData, NULL, DIB_RGB_COLORS);

   if(hColor == NULL)
      return NULL;

   hMask = CreateDIBSection(NULL, (LPBITMAPINFO) &bmi, 0, (void**)&lpMaskData, NULL, DIB_RGB_COLORS);

   if(hMask == NULL)
   {
      ::DeleteObject(hColor);
      return NULL;
   }

   dwSize = 32*32;

   for(DWORD d=0; d<dwSize; d++)
   {
      if(*lpData == clrTransparent)
      {
         lpMaskData[d] = 0xFFFFFF;
         lpColorData[d] = 0;
      }
      else
      {
         lpMaskData[d] = 0;
         lpColorData[d] = *lpData;
      }
      lpData++;
   }

   ICONINFO ii;
   ii.fIcon = 1;
   ii.hbmColor = hColor;
   ii.hbmMask = hMask;
   ii.xHotspot = 0;
   ii.yHotspot = 0;
   hIcon = CreateIconIndirect(&ii);

   ::DeleteObject(hMask);
   ::DeleteObject(hColor);

   return hIcon;
}

HICON CWMBFrontDlg::DSIconToWinIcon(char *buf)
{
   HICON hIcon = NULL;
   BANNER* pBanner = (BANNER *) buf;

   HDC hdc = CreateCompatibleDC(NULL);
   BITMAPINFO bi;
   ZeroMemory(&bi.bmiHeader, sizeof(BITMAPINFOHEADER));
   bi.bmiHeader.biWidth = 32;
   bi.bmiHeader.biHeight = 32;
   bi.bmiHeader.biPlanes = 1;
   bi.bmiHeader.biBitCount = 24;
   bi.bmiHeader.biSizeImage = 0;
   bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
   bi.bmiHeader.biClrUsed = 0;
   bi.bmiHeader.biClrImportant = 0;

   VOID* pvBits;

   HBITMAP hbmp = CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, &pvBits, NULL, 0);

   RGBQUAD palette[16];

   for (int i=0; i < 16; i++) {
      palette[i].rgbRed = (pBanner->palette[i] & 0x1F) << 3;
      palette[i].rgbGreen = ((pBanner->palette[i]>>5) & 0x1F) << 3;
      palette[i].rgbBlue = ((pBanner->palette[i]>>10) & 0x1F) << 3;
      palette[i].rgbReserved = 0;
   }

   palette[0].rgbRed = 255;
   palette[0].rgbGreen = 0;
   palette[0].rgbBlue = 255;

   // tile data (4 bit / tile, 4x4 total tiles)
   // 32 bytes per tile (in 4 bit mode)
   for (int row=0; row<4; row++)
   {
      for (int col=0; col<4; col++)
      {
         for (int y=0; y<8; y++)
         {
            for (int x=0; x<8; x+=2)
            {
               ((RGBQUAD *)pvBits)[(((3-row)*8 + (7-y))*32)+(col*8 + x + 0)] = palette[(pBanner->tile_data[row][col][y][x/2] & 0xF)];
               ((RGBQUAD *)pvBits)[(((3-row)*8 + (7-y))*32)+(col*8 + x + 1)] = palette[(pBanner->tile_data[row][col][y][x/2] >> 4) & 0xF];
            }
         }
      }
   }

   hIcon = MakeIcon((COLORREF *) pvBits, RGB(255,0,255));

   DeleteObject(hbmp);
   DeleteDC(hdc);
   
   return hIcon;
}

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