Long time no see... I'd like to ask some information about the way tilesets are stored in Pokémon Red/Blue/Yellow (I know, it's becoming old).
Well, what I know is this:
Code:
Notes:
R/B Pointers to Map Headers: 0x01AE
R/B Map Header Banks: 0xC23D
R/B Pointer to Tileset Headers: 0xC767
Maximum tileset size in VRAM: 6 rows of 16 tiles (9000-95FF)
...............................................................................
===============================================================================
Tileset Header Structure (*Incomplete*)
===============================================================================
12 bytes per header...
Format:
~~~~~~~
[1 BYTE: Bank No. of Blocks/Tiles]
[2 BYTES: Pointer to Blocks (-10 for some reason)]
[2 BYTES: Pointer to Tiles]
[7 BYTES: ???]
last 7 bytes ideas: collison data pointer? something to do with animations?
R/B Pointers to Map Headers: 0x01AE
R/B Map Header Banks: 0xC23D
R/B Pointer to Tileset Headers: 0xC767
Maximum tileset size in VRAM: 6 rows of 16 tiles (9000-95FF)
...............................................................................
===============================================================================
Tileset Header Structure (*Incomplete*)
===============================================================================
12 bytes per header...
Format:
~~~~~~~
[1 BYTE: Bank No. of Blocks/Tiles]
[2 BYTES: Pointer to Blocks (-10 for some reason)]
[2 BYTES: Pointer to Tiles]
[7 BYTES: ???]
last 7 bytes ideas: collison data pointer? something to do with animations?
Source: http://www.datacrystal.org/wiki/Pokemon_Red/Blue:Notes
Well, this seems a pretty good start, so let's try this. The address 0xC767 seems not exactly correct, 0xC7CB seems more correct (Pokémon red, GB version).
Some I'm trying to read n headers at this address, and this is what I got:
Code:
bank_id=112 | block data: 0xE052 | gfx: 0x494D | collision: 0xFF17 | FF FF FF | 00 1A
bank_id=191 | block data: 0xBF53 | gfx: 0x534D | collision: 0x1817 | 19 1E FF | 00 1A
bank_id=255 | block data: 0xFF69 | gfx: 0x6563 | collision: 0xFF17 | FF FF 20 | 01 19
bank_id=112 | block data: 0xE052 | gfx: 0x494D | collision: 0xFF17 | FF FF FF | 00 1A
bank_id=127 | block data: 0x7F46 | gfx: 0x5940 | collision: 0x3A17 | FF FF FF | 02 1A
bank_id=191 | block data: 0xBF53 | gfx: 0x534D | collision: 0x1817 | 19 1E FF | 00 1A
bank_id=127 | block data: 0x7F46 | gfx: 0x5940 | collision: 0x3A17 | FF FF FF | 02 19
bank_id=128 | block data: 0xA059 | gfx: 0x7553 | collision: 0xFF17 | FF FF FF | 00 1A
bank_id=255 | block data: 0x0F5B | gfx: 0x7F56 | collision: 0x1717 | 32 FF FF | 00 1A
bank_id=255 | block data: 0x0F5B | gfx: 0x7F56 | collision: 0x1717 | 32 FF FF | 00 1B
bank_id=240 | block data: 0x607E | gfx: 0x2F7D | collision: 0xFF17 | FF FF FF | 00 1A
bank_id=255 | block data: 0x0F5B | gfx: 0x7F56 | collision: 0x1717 | 32 FF FF | 00 1B
bank_id= 48 | block data: 0x9069 | gfx: 0x8A63 | collision: 0xFF17 | FF FF FF | 01 19
bank_id=240 | block data: 0x106B | gfx: 0x9566 | collision: 0xFF17 | FF FF FF | 01 1B
bank_id=192 | block data: 0x0045 | gfx: 0x9A40 | collision: 0x1217 | FF FF FF | 00 19
bank_id= 80 | block data: 0x6073 | gfx: 0xA26D | collision: 0xFF17 | FF FF FF | 00 1B
bank_id=192 | block data: 0xA050 | gfx: 0xAC4C | collision: 0xFF17 | FF FF FF | 01 1B
bank_id=160 | block data: 0xC05E | gfx: 0xB858 | collision: 0x1517 | 36 FF FF | 00 19
bank_id=144 | block data: 0xB061 | gfx: 0xC05B | collision: 0xFF17 | FF FF FF | 00 1B
[...]
bank_id=191 | block data: 0xBF53 | gfx: 0x534D | collision: 0x1817 | 19 1E FF | 00 1A
bank_id=255 | block data: 0xFF69 | gfx: 0x6563 | collision: 0xFF17 | FF FF 20 | 01 19
bank_id=112 | block data: 0xE052 | gfx: 0x494D | collision: 0xFF17 | FF FF FF | 00 1A
bank_id=127 | block data: 0x7F46 | gfx: 0x5940 | collision: 0x3A17 | FF FF FF | 02 1A
bank_id=191 | block data: 0xBF53 | gfx: 0x534D | collision: 0x1817 | 19 1E FF | 00 1A
bank_id=127 | block data: 0x7F46 | gfx: 0x5940 | collision: 0x3A17 | FF FF FF | 02 19
bank_id=128 | block data: 0xA059 | gfx: 0x7553 | collision: 0xFF17 | FF FF FF | 00 1A
bank_id=255 | block data: 0x0F5B | gfx: 0x7F56 | collision: 0x1717 | 32 FF FF | 00 1A
bank_id=255 | block data: 0x0F5B | gfx: 0x7F56 | collision: 0x1717 | 32 FF FF | 00 1B
bank_id=240 | block data: 0x607E | gfx: 0x2F7D | collision: 0xFF17 | FF FF FF | 00 1A
bank_id=255 | block data: 0x0F5B | gfx: 0x7F56 | collision: 0x1717 | 32 FF FF | 00 1B
bank_id= 48 | block data: 0x9069 | gfx: 0x8A63 | collision: 0xFF17 | FF FF FF | 01 19
bank_id=240 | block data: 0x106B | gfx: 0x9566 | collision: 0xFF17 | FF FF FF | 01 1B
bank_id=192 | block data: 0x0045 | gfx: 0x9A40 | collision: 0x1217 | FF FF FF | 00 19
bank_id= 80 | block data: 0x6073 | gfx: 0xA26D | collision: 0xFF17 | FF FF FF | 00 1B
bank_id=192 | block data: 0xA050 | gfx: 0xAC4C | collision: 0xFF17 | FF FF FF | 01 1B
bank_id=160 | block data: 0xC05E | gfx: 0xB858 | collision: 0x1517 | 36 FF FF | 00 19
bank_id=144 | block data: 0xB061 | gfx: 0xC05B | collision: 0xFF17 | FF FF FF | 00 1B
[...]
So what then? I'm trying to get the 0x645E0 address related to the "tileset id=0" from all this stuff, and I can't figure out how. Actually, I've hardcoded that first tileset address. From there I read the blocks info and it works well: the maps for the tileset "0" are well rendered. I just need to get all the others tilesets now.
Also I've tried to debug the game using BGB (http://bgb.bircd.org/), which include some pretty interesting reversing tools. But as I don't know it very well, I was to unable to get the "breakpoint on memory access" working (what a shame on me ).
So if you have any clue about how all this stuff work, I'd be glad if you can share it
Thanks folks!
December 16, 2009, 04:55:22 pm - (Auto Merged - Double Posts are not allowed before 7 days.)
Al'right, so here it is, I've found some stuff.
The correct address wasn't 0xC767 neither 0xC7CB, but 0xC7BE for my GB/US Pokémon Red version.
So here is the new stuff I get:
Code:
bank_id= 25 | block data: 0x45E0 | gfx: 0x4000 | collision: 0x1735 | FF FF FF | 52 02
bank_id= 69 | block data: 0x4000 | gfx: 0x1735 | collision: 0xFFFF | FF 52 02 | 19 70
bank_id= 64 | block data: 0x1735 | gfx: 0xFFFF | collision: 0x52FF | 02 19 70 | 52 E0
bank_id= 23 | block data: 0xFFFF | gfx: 0x52FF | collision: 0x1902 | 70 52 E0 | 4D 49
bank_id=255 | block data: 0x52FF | gfx: 0x1902 | collision: 0x5270 | E0 4D 49 | 17 FF
bank_id= 82 | block data: 0x1902 | gfx: 0x5270 | collision: 0x4DE0 | 49 17 FF | FF FF
bank_id= 25 | block data: 0x5270 | gfx: 0x4DE0 | collision: 0x1749 | FF FF FF | FF 00
bank_id= 82 | block data: 0x4DE0 | gfx: 0x1749 | collision: 0xFFFF | FF FF 00 | 1A BF
bank_id= 77 | block data: 0x1749 | gfx: 0xFFFF | collision: 0xFFFF | 00 1A BF | 53 BF
bank_id= 23 | block data: 0xFFFF | gfx: 0xFFFF | collision: 0x1A00 | BF 53 BF | 4D 53
bank_id= 69 | block data: 0x4000 | gfx: 0x1735 | collision: 0xFFFF | FF 52 02 | 19 70
bank_id= 64 | block data: 0x1735 | gfx: 0xFFFF | collision: 0x52FF | 02 19 70 | 52 E0
bank_id= 23 | block data: 0xFFFF | gfx: 0x52FF | collision: 0x1902 | 70 52 E0 | 4D 49
bank_id=255 | block data: 0x52FF | gfx: 0x1902 | collision: 0x5270 | E0 4D 49 | 17 FF
bank_id= 82 | block data: 0x1902 | gfx: 0x5270 | collision: 0x4DE0 | 49 17 FF | FF FF
bank_id= 25 | block data: 0x5270 | gfx: 0x4DE0 | collision: 0x1749 | FF FF FF | FF 00
bank_id= 82 | block data: 0x4DE0 | gfx: 0x1749 | collision: 0xFFFF | FF FF 00 | 1A BF
bank_id= 77 | block data: 0x1749 | gfx: 0xFFFF | collision: 0xFFFF | 00 1A BF | 53 BF
bank_id= 23 | block data: 0xFFFF | gfx: 0xFFFF | collision: 0x1A00 | BF 53 BF | 4D 53
Oh, this seems more convenient:
The address for tileset 0 (actually the blocks) is 0x645E0 (the value I was hardcoding). To get it, the formula seems to be:
Quote
bank_id * 0x4000 + block_data % 0x4000
You can also apply this formula for the tiles addresses.
I continue the adventure, see you