mirror of
https://github.com/risingPhil/libpokemegb.git
synced 2026-03-21 17:44:24 -05:00
142 lines
5.6 KiB
Plaintext
142 lines
5.6 KiB
Plaintext
Copied from https://github.com/LinusU/pokemon-sprite-compression/blob/main/doc/gen2.txt :
|
|
|
|
POKEMON GRAPHICS COMPRESSION DOCUMENT
|
|
Version 1.0
|
|
|
|
-Pokemon uses a unique compression routine to pack all of those 251
|
|
pokemon into a single game boy cartridge. Here's my documentation of this
|
|
compression:
|
|
|
|
|
|
|
|
Look at the first (high) 3 bits of the first byte -
|
|
(Bitwise AND with 224 - 0xE0, binary 11100000).
|
|
The value in these high 3 bits are a 'control code' for the processing of
|
|
the following information.
|
|
There are 7 possible control codes:
|
|
In binary, 000, 001, 010, 011, 100, 101, 111.
|
|
Keeping the extra 5 bits as zeroes, this gives us the seven hex values of
|
|
00, 20, 40, 60, 80, A0, C0 and E0 as control codes.
|
|
Look at the last(low) 5 bits of the first byte -
|
|
(Bitwise AND with 31 - 0X1F, binary 00011111), call that value x.
|
|
|
|
00: Read (x + 1) following amount of bytes from the ROM and print to the
|
|
graphics output.
|
|
|
|
20: Read one byte from the ROM, call that value y. Print value (y),
|
|
(x+1) number of times to the graphics output.
|
|
|
|
40: Read two bytes from the ROM, call those values (y-z).
|
|
Print y and z alternately (x+1) number of times total to the graphics
|
|
output. Example: If x = 5, print yzyzy.
|
|
|
|
60: Print (x+1) bytes with value zero to the graphics output.
|
|
|
|
|
|
***The control bytes 80, A0 and C0 deal with values already stored in the
|
|
graphics output, as a way of 'reusing' data to save space.***
|
|
|
|
|
|
|
|
80: Read a byte from the rom, call that value A.
|
|
If the high bit of A (Bitwise AND with 128 - 0x80, binary 10000000) is clear:
|
|
Read the next byte from the rom, call that value N.
|
|
Copy (x+1) consecutive bytes from the graphics buffer to the graphics output,
|
|
starting at (A*0x100) + (N+1).
|
|
|
|
If the high bit of A is set:
|
|
(AND A with 127(0x7F) to clear the high bit)
|
|
Copy (x+1) consecutive bytes from the graphics buffer to the graphics output,
|
|
starting A bytes back from the end of the buffer.
|
|
|
|
A0: Read a byte from the rom, call that value A.
|
|
If the high bit of A is clear:
|
|
Read the next byte from the rom, call that value N.
|
|
Copy (x+1) consecutive bytes from the graphics buffer to the graphics output,
|
|
starting at (A*0x100) + (N+1), REVERSING the bit order.
|
|
Example: Byte k in graphics buffer = 0xD7 (11010111 binary).
|
|
New byte to be printed to graphics output = 0xEB(11101011 binary).
|
|
|
|
If the high bit of A is set:
|
|
(clear the high bit of A)
|
|
Copy (x+1) consecutive bytes from the graphics buffer to the graphics output,
|
|
starting A bytes back from the end of the buffer, REVERSING the bit order.
|
|
|
|
|
|
C0: Read a byte from the rom, call that value A.
|
|
If the high bit of A is clear:
|
|
Read the next byte from the rom, call that value N.
|
|
Copy (x+1) reverse consecutive bytes from the graphics buffer to the graphics
|
|
output, starting at (A*0x100) + (N+1).
|
|
"reverse consecutive" meaning starting from the above point in the graphics
|
|
buffer, read a byte from buffer and print to the end of the output,
|
|
then read the previous byte and print to the end of the output, etc.
|
|
|
|
If the high bit of A is set:
|
|
(clear the high bit of A)
|
|
Copy (x+1) reverse consecutive bytes from the graphics buffer to the graphics
|
|
output, starting A bytes back from the end of the buffer.
|
|
|
|
|
|
E0: The E0 control code is special:
|
|
|
|
Take the high 3 bits of x (remember, x is currently the low 5 bits of the
|
|
first byte, so AND that byte with (28decimal/0x1C/00011100 binary),
|
|
this will be the new 3-bit control code.
|
|
Get another byte from the ROM, call it w.
|
|
The new X value consists of (the lowest two bits of the old x
|
|
(AND with 03, 00000011 binary) * 0x100) + w.
|
|
Go back to the top of the loop with the new control code and x value.
|
|
|
|
|
|
That's the compression!
|
|
|
|
Here are some addresses that might be handy:
|
|
(NOTE: UNOWN, pokemon # 201 has its graphics stored in some special
|
|
manner (most likely because there are 26 separate images),
|
|
thus its pointer points to nothing. I've simply skipped UNOWN #201
|
|
in my program, but if someone else wants to look for him, go ahead and let
|
|
me know and i'll update this doc.)
|
|
|
|
0x48000 - start of Pokemon graphics pointers - 6 bytes per pokemon.
|
|
First three bytes is pointer to the pokemon facing you,
|
|
next three is pointer to the pokemon with its back facing you.
|
|
Here is the layout of the 3 pointer bytes:
|
|
|
|
1st byte: Bank byte. Byte * 4000h to get the bank address. However:
|
|
If 1st byte = 0x13 then change it to 0x1F
|
|
If 1st byte = 0x14 then change it to 0x20
|
|
If 1st byte = 0x1F then change it to 0x2E
|
|
Don't ask why; it's simply in the game's code.
|
|
|
|
2nd byte: Low byte of address.
|
|
3rd byte: High byte of address.
|
|
|
|
To correctly calculate the ROM address of the start of the graphics data
|
|
using the 3-byte pointer:
|
|
Address = (byte 1) * 0x4000 + (byte 3) * 0x100 + (byte 2)
|
|
|
|
|
|
0xAD3D - Start of Palette data. 8 bytes for each pokemon.
|
|
2 color schemes for each pokemon, first 4 bytes = normal color scheme,
|
|
next 4 bytes = "shiny" pokemon color scheme.
|
|
|
|
Each pokemon has four colors: white(color 0), black(color 3), and two colors
|
|
defined by the 4 palette bytes(1 and 2), 2 bytes per color.
|
|
The bytes use RGB. First, rearrange the two bytes so the second byte is
|
|
first (common 16-bit practice). The RGB arrangement is as follows for the
|
|
16-bit pair:
|
|
0bbbbbgggggrrrrr, each color attribute having five bytes,
|
|
and the high bit unused.
|
|
|
|
That's it!
|
|
My QBasic program uses all of the information above to decompress
|
|
Pokemon images from the ROM and output them to the screen.
|
|
Check out the source for further clarification QBasic-style.
|
|
|
|
-necrosaro (radimvice@geocities.com)
|
|
http://members.aol.com/sabindude/pokemon.html
|
|
-For an archive of all 251 pokemon from Gold and Silver, shiny and regular,
|
|
facing fowards and backwards, in PNG format, go to
|
|
http://www.geocities.com/radimvice/pokepng.zip
|