Gameboy 2BPP Graphics FormatJune 29, 2013
The Nintendo Gameboy uses a palette of four colors. Since only four colors need to be represented in graphics data, there is a relatively straightforward and efficient way of storing this data. It's called 2BPP format, or "2 bits per pixel".
The Gameboy displays its graphics using 8x8-pixel tiles. As the name 2BPP implies, it takes exactly two bits to store the information about a single pixel. There are 64 total pixels in a single tile (8x8 pixels). Therefore, exactly 128 bits, or 16 bytes, are required to fully represent a single tile. As a result, any uncompressed graphics data present in a Gameboy ROM file is represented using exactly 16 bytes.
This is an example of a single tile in Pokémon Red/Blue Version (it's a window from a house):
FF 00 7E FF 85 81 89 83 93 85 A5 8B C9 97 7E FF (Found at location 0x640A0)
If you're unfamiliar with hexadecimal numbers, then this probably looks like nonsense. Hexadecimal numbers are in base 16, and it happens to be extremely convenient to represent eight bits using the hexadecimal system because each four bits represents a single digit in base 16. For example, 01101110 in binary is 6E in hexadecimal. From now on I'll prefix hexadecimal numbers with "0x" to distinguish them from base 10 numbers.
The 2BPP format works in a way such that each consecutive pair of bytes represents a single row in the 8x8 tile. That is, 0xFF 0x00 represents the top row, 0x7E 0xFF represents the second row, and so on. To determine the color of a single pixel, we need to combine those two bytes in a specific way. The first byte is the low byte, and the second byte is the high byte. To determine the first pixel of the row (the pixel on the far-left), we look at the most significant bit of both bytes and combine those two bits by treating the bit coming from the high byte as the most significant bit.
Phew! Let's do an example. 0xFF 0x00 are the two bytes that represent the top row of the tile in the given example. 0x00 is the high byte and 0xFF is the low byte. 0x00 is 00000000 in binary, and 0xFF is 11111111 in binary. The most significant (leftmost) bit of 0x00 is 0 (00000000), and the most significant bit of 0xFF is 1 (11111111). We combine the two bits to get a result of 01 in binary, which is 1 in base 10. Therefore, the top-left pixel of the tile is color #1. Now, let's determine the pixel color of the second pixel in the top row. 0xFF and 0x00 are still the two bytes used. This time, we use the second-most significant bits to determine the color. So, the bits we use are 0 (00000000) and 1 (11111111). Again, 0 comes from the high bytes, so it comes first in the resulting binary number 01. The color of this pixel is also color #1. The whole first row is actually color #1 since the both bytes' bits are all the same.
As described before, the pixel colors of the second row of the 8x8 tiles are determined using the second pair of bytes 0x7E and 0xFF.
This great visual representation of 2BPP format is presented in this informational document about the Gameboy. In the diagram, the sixteen bytes are: 7C 7C 00 C6 C6 00 00 FE C6 C6 00 C6 C5 00 00 00.
Tile: Image: .33333.. .33333.. -> 01111100 -> $7C 22...22. 01111100 -> $7C 11...11. 22...22. -> 00000000 -> $00 2222222. <-- digits 11000110 -> $C6 33...33. represent 11...11. -> 11000110 -> $C6 22...22. color 00000000 -> $00 11...11. numbers 2222222. -> 00000000 -> $00 ........ 11111110 -> $FE 33...33. -> 11000110 -> $C6 11000110 -> $C6 22...22. -> 00000000 -> $00 11000110 -> $C6 11...11. -> 11000110 -> $C6 00000000 -> $00 ........ -> 00000000 -> $00 00000000 -> $00
This is a demo of the 2BPP graphics format. Enter sixteen bytes into the form. The image will change to show how a Gameboy would display the tile that is represented by those sixteen bytes.