Hacking Reading the NDS Icon Data

hankchill

I Pwn n00bs.
OP
Member
Joined
Nov 5, 2005
Messages
2,338
Trophies
0
Age
38
Location
Outer Space
Website
www.hankchill.com
XP
421
Country
Canada
Hey Everyone,

I'm in the middle of implementing the Icon Reading into my Rominator program, but since I've never extracted data like this before (tile and palette data) I'm a little puzzled on how it's done.

Currently, it reads the Icon Location from 0x68 to 0x6B. It jumps to that location, and reads the specified data:
Icon Offset + 0x20 = Tile Data (512 Bytes)
Icon Offset + 0x220 = Palette Data (32 Bytes)

I've got 'em all loaded, but am not sure how the system works.

If anyone's got any pointers (or source code) it would be greatly appreciated
smile.gif


Regards.
 

FAST6191

Techromancer
Editorial Team
Joined
Nov 21, 2005
Messages
36,798
Trophies
3
XP
28,321
Country
United Kingdom
It should just be standard GBA/DS 4bits per pixel 15bit BGR palette pictures. No source for you to play with I am afraid (it is fairly basic but the images and palette style should be in just about every GBA and even SNES emu going)

Copy and paste from GBATek: http://nocash.emubase.de/gbatek.htm
The ROM offset of the Icon/Title is defined in Cartridge Header [68h].
If it is present (nonzero), then Icon/Title are displayed in the bootmenu.

Addr Siz Expl.
000h 2 Version (0001h)
002h 2 CRC16 across entries 020h..83Fh
004h 1Ch Reserved (zero-filled)
020h 200h Icon Bitmap (32x32 pix) (4x4 tiles, each 4x8 bytes, 4bit depth)
220h 20h Icon Palette (16 colors, 16bit, range 0000h-7FFFh)
(Color 0 is transparent, so the 1st palette entry is ignored)
240h 100h Title 0 Japanese (128 characters, 16bit Unicode)
340h 100h Title 1 English ("")
440h 100h Title 2 French ("")
540h 100h Title 3 German ("")
640h 100h Title 4 Italian ("")
740h 100h Title 5 Spanish ("")
840h ? (Maybe newer/chinese firmware do also support chinese title?)
840h - End of Icon/Title structure (next 1C0h bytes usually FFh-filled)

Here is a picture, the tile editor is not in the DS rom here but the banner file ndstool generates, palette read from 220hex/544 decimal in it (BGR snes not that it matters). The principle is the same however and it should just be a matter of altering offesets according to the header:
icondemoru9.jpg
 

hankchill

I Pwn n00bs.
OP
Member
Joined
Nov 5, 2005
Messages
2,338
Trophies
0
Age
38
Location
Outer Space
Website
www.hankchill.com
XP
421
Country
Canada
I'm aware of the data's location and have extracted all the necessary bytes of data.

The only problem that I'm having is actually putting the image together. I am not too sure how to convert the Hex values to RGB, and how to piece the image together accordingly.

Regards.
 

hankchill

I Pwn n00bs.
OP
Member
Joined
Nov 5, 2005
Messages
2,338
Trophies
0
Age
38
Location
Outer Space
Website
www.hankchill.com
XP
421
Country
Canada
I'm still completely confuzzled how I convert the data read to pixels
tongue.gif


If I can get any help at all to convert the data, it would be most appreciated
smile.gif


Here's a little bit on what I extracted:
As far as I know, the Palette is a 16 color palette with 2 bytes per color. I got this:
0000
0C67
280A
10A9
382D
250D
1913
etc.

And the tile data is 512 bytes long, 2 bytes per pixel, yes?
Here's a bit on what I got:
BBBB
17BB
BBBB
17BB
BBBB
17BB
29BB
BBBB
BBBB
BBBB
etc.

What I don't understand, is how do these values relate to the palette, and how can I convert the palette values I received to an RGB format?

Regards,
--Henry
 

FAST6191

Techromancer
Editorial Team
Joined
Nov 21, 2005
Messages
36,798
Trophies
3
XP
28,321
Country
United Kingdom
I am not overly familiar with graphics display coding (and I doubt a bunch of ASM will be that useful to you if it is going in your cross platform app anyhow) so while having some code to sample is probably the better route I will try and explain what you might want to do, I guess you will know most of the terms/maths but I would like to think someone else will read this one day that may not so if I come off as condescending I quite assure you it is not my intention.

Remember the GBA/DS is big endian, basically this means you need to flip the palette: ff7f becomes 7fff etc. Discard the first byte as it is seethrough as well.
Read the remaining 15 bytes and place them in the order they come out.
The palette's numbers merely reflect the intensity of the colour so it may get interesting trying to replicate it, to this end I will leave this one up to you (using the default the computer default RGB but switching the numbers from the GBA/DS BGR usually works very well to the point where it is differences in screen rather than your code)

read 16 bytes of the bitmap and call it a tile, repeat in rows of 4 tiles until all 512 bytes are used.
4bpp is 4 bits per pixel so every byte is 2 pixels and each tile has 32 i.e. 8x8 pixels.
The arrangement is known to the DS/GBA so these bytes merely define what colours are used, this is where it gets a bit tricky though as the nibbles will need flipping, I only have hex workshop installed which to my knowledge does not have the capability so no simple pictures. Either way each nibble points to the colour at that place in the palette. (in the example below F points to the 15th colour which is white and you can see it repeated)
Here is a picture of the super robot taisen icon with the palette in hex form as follows (first line is 8 colours):
0000 0000 0000 0421 2D04 2128 0174 39CD
01D9 4E73 023F 62F6 675A 739C 7FFF
dsicondemoht1.png


Each line of hex corresponds to 8 pixels and the three orange pixels on the top left tile I added in myself so you can try and get your bearings.

Here is some code for a tile editor (linux one) that could help if you become especially unstuck:
http://sourceforge.net/projects/gbafromscratch
If not I know for a fact VBA has GBA to windows paint palette options as well.
It might take a bit of thought but there are also a few RGB to BGR libs available for GBA/DS dev purposes which should not be that hard to repurpose either.
 

Nesco

New Member
Newbie
Joined
Dec 17, 2007
Messages
3
Trophies
0
XP
136
Country
Netherlands
Hi, I'm working on the same thing now and I have to admit your story thoroughly confuses me.



Remember the GBA/DS is big endian, basically this means you need to flip the palette: ff7f becomes 7fff etc. Discard the first byte as it is seethrough as well.

I'm with you on this one, except for the first byte being the seetrough. Don't you mean the first bit, since it's a 5-5-5 bit schema for BGR?

QUOTE(FAST6191 @ Mar 5 2007, 09:08 PM)read 16 bytes of the bitmap and call it a tile, repeat in rows of 4 tiles until all 512 bytes are used.
4bpp is 4 bits per pixel so every byte is 2 pixels and each tile has 32 i.e. 8x8 pixels.

16 bytes times 2 makes 32 bits, but 8 by 8 bits make 64, so I'm guessing now a tile is 4 bits deep by 8 bits long, since there are rows of 4 tiles, thus 32 bits, making a total depth of 8 tiles?

I'm still not getting my icon to display right in my windows application. I hope someone can shed some further light on this matter or provide a good explanation about the GBA / NDS tile structure

Thanks a lot!
 

hankchill

I Pwn n00bs.
OP
Member
Joined
Nov 5, 2005
Messages
2,338
Trophies
0
Age
38
Location
Outer Space
Website
www.hankchill.com
XP
421
Country
Canada
Wow, thanks for reviving a LONG DEAD topic. This was accomplished LONG ago
tongue.gif


FAST's explanation is confusion, but you know what, it's right
smile.gif
The palette needs to be converted to an RGB value (Right now I believe it's ABGR), and then the bits in the bytes need to be swapped in the order you read it, and each number corresponds to the colour number in the palette.
 

Nesco

New Member
Newbie
Joined
Dec 17, 2007
Messages
3
Trophies
0
XP
136
Country
Netherlands
Yeah that's the part I actually got
biggrin.gif


The colors are not my problem, it's the order of processing them and arranging them into tiles that's not going right somewhere. I process each byte from offset 32 in the banner, and do that for each of the 512 bytes, so 1024 pixels which make the 32x32 icon.

What I do now is taht I have tiles of 8x8 pixels, arranged so that byte 1 (pixel 1 and 2) are horizontally arranged, like this:

1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16

etcetera. After that I add another tile in the same way horizontally next to the first tile, and do that 4 times (so now I have a 4 by 32 pixel image)

and I continue doing this for 3 more rows. Problem is, the image, though it looks like the icon, is dostorted in some form. So I now wonder if I'm doing the tiling correctly.

Any help on this one?

And yeah, it's old, it's been done, it's probably trivial. Just not yet for me
smile.gif

Wow, thanks for reviving a LONG DEAD topic. This was accomplished LONG ago
tongue.gif


FAST's explanation is confusion, but you know what, it's right
smile.gif
The palette needs to be converted to an RGB value (Right now I believe it's ABGR), and then the bits in the bytes need to be swapped in the order you read it, and each number corresponds to the colour number in the palette.
 

Ecconia

New Member
Newbie
Joined
Aug 13, 2020
Messages
1
Trophies
0
Age
44
XP
42
Country
Germany
LONG DEAD - yet this thread can be found on Google
Apparently nobody explained a proper solution in this thread.
So it didn't help me a lot.

Eventually I managed to parse the .NDS game icon and display it.

Above there is a link to a documentation about NDS and everything related. You can find it if you search for "gbatek". It contains the two lines, which had been pasted into this thread already (can also be found in the Desmume source code):
200h Icon Bitmap (32x32 pix) (4x4 tiles, 4bit depth) (4x8 bytes/tile)
20h Icon Palette (16 colors, 16bit, range 0000h-7FFFh)
Both describe which data is relevant. And if they are not wrong, then they are very difficult to understand.

I will now try to explain how to parse/use this data:

Color palette:
Array of 16 entries, each 16 bits (Little-Endian: First the lower 8 bits, then the higher 8 bits).
Each entry represents one color. Each color has 5 bit for each channel: red green and blue.
The word should be interpreted as follows: 0b*BBBBBGGGGGRRRRR (the highest bit is unused and red and blue are swapped for reasons).

Bitmap:
Array of 512 bytes, each byte represents two pixels / two entries into the color palette. (32 * 32 / 2 = 512).
The resulting image is 32 * 32 pixels.
Lower and higher 4 bits of each byte can be used to lookup the color in the color palette.

Assemble pixels:
The whole icon can be divided into 8*8 chunks. The chunks are aligned left to right then down. (Fill a row, then the next).
Each chunk (8*8 pixels) is also structured row first then next row. Means you read 4 bytes to fill a row, then you continue with the next 4 bytes.
For rows you have two options:
- Reading bitmap as Little-Endian integers 32 bit. (I did it this way)
In this case each integer represents one row exactly.
Assuming the left pixel is 0 and the right one is 7 the order in the integer is following: 0x76543210
As in, the lowest nibble goes to the left most pixel in a row and the highest nibble to the right most pixel.
- Reading bitmap as bytes.
Basically the same as above, but this time the 32 bits would be read as Big-Endian. Means you have to swap the order and each pair of pixels. The 32 bit representation should look like this now: 0x10325476 (I didn't use this, wouldn't be much change in code, but still kind of ugly).

I hope that from now on, people trying to parse the NDS icon and finding this thread will be able to easily parse the icon.
 

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
  • No one is chatting at the moment.
    SylverReZ @ SylverReZ: Sup