a pointless analysis of the graphics compression in batman (gb)
don’t know why i did this but i reverse engineered the graphics compression scheme this game uses. it’s very simple, but it turns out it’s not very well-suited to pixel art.
basically, it takes a byte and uses its bits to keep track of which of the next 8 bytes of the output is a repeat of the previous.
the issue with game boy pixel art is that byte-by-byte repetition doesn’t happen too often. one reason is just the density of detail in the art. another (more technical) reason is that because of the way the game boy encodes its graphics, but if you had 4 squares of solid color, two of them wouldn’t even compress. it’s kinda stupid how sunsoft chose to handle it, in a way.
at the very least, it turns out the rom is very well-organized on the inside. each bank with assets just has a bunch of pointers at the beginning, so once i got the decompressor working i tossed the pointers at it and a bunch of graphics popped out for free (sometimes, technology is good)
anyhow, i configured my script to dump out some nerd stats (higher percent is better):
Bank | Resource | Unpacked | Packed | Ratio |
---|---|---|---|---|
3 | 0 | 656 | 665 | 98.65% |
3 | 1 | 1344 | 946 | 142.07% |
3 | 2 | 3408 | 2976 | 114.52% |
3 | 3 | 1024 | 1086 | 94.29% |
3 | 4 | 512 | 507 | 100.99% |
3 | 5 | 512 | 534 | 95.88% |
3 | 6 | 512 | 528 | 96.97% |
3 | 7 | 512 | 534 | 95.88% |
3 | 8 | 512 | 510 | 100.39% |
3 | 9 | 512 | 485 | 105.57% |
3 | A | 512 | 505 | 101.39% |
3 | B | 512 | 517 | 99.03% |
3 | C | 512 | 537 | 95.34% |
3 | D | 512 | 536 | 95.52% |
3 | E | 912 | 898 | 101.56% |
3 | F | 224 | 232 | 96.55% |
3 | 10 | 432 | 479 | 90.19% |
3 | 11 | 944 | 953 | 99.06% |
3 | 12 | 880 | 864 | 101.85% |
3 | 13 | 1792 | 1300 | 137.85% |
- | Sub-Total | 16736 | 15592 | 107.34% |
— | — | — | — | — |
4 | 0 | 256 | 65 | 393.85% |
4 | 1 | 1024 | 783 | 130.78% |
4 | 2 | 1280 | 905 | 141.44% |
4 | 3 | 640 | 630 | 101.59% |
4 | 4 | 1536 | 1296 | 118.52% |
4 | 5 | 768 | 629 | 122.10% |
4 | 6 | 1280 | 1121 | 114.18% |
4 | 7 | 1024 | 867 | 118.11% |
4 | 8 | 1152 | 951 | 121.14% |
4 | 9 | 1536 | 1189 | 129.18% |
4 | A | 1536 | 1171 | 131.17% |
- | Sub-Total | 12032 | 9607 | 125.24% |
— | — | — | — | — |
5 | 0 | 576 | 331 | 174.02% |
5 | 1 | 1392 | 1318 | 105.61% |
5 | 3 | 1328 | 1286 | 103.27% |
5 | 4 | 576 | 212 | 271.70% |
5 | 5 | 1392 | 1322 | 105.30% |
5 | 7 | 640 | 558 | 114.70% |
5 | 8 | 576 | 330 | 174.55% |
5 | C | 576 | 312 | 184.62% |
5 | D | 1392 | 1396 | 99.71% |
5 | F | 944 | 972 | 97.12% |
5 | 10 | 576 | 282 | 204.26% |
5 | 11 | 576 | 230 | 250.43% |
5 | 12 | 1392 | 1423 | 97.82% |
5 | 14 | 2064 | 1715 | 120.35% |
5 | 15 | 560 | 207 | 270.53% |
5 | 16 | 2064 | 1688 | 122.27% |
Sub-Total | 10144 | 8225 | 123.33% | |
Grand | Total | 38912 | 33424 | 116.42% |
(removed some duplicates, may not have caught everything)
the best compressed chunk of graphics (bank 4, file 0) has a compression ratio of 393.85%. it is entirely blank space, so it’s probably mathematically provable that’s the best case scenario for the compression scheme.
here’s what one of the worst compressing ones (bank 3, file 0x03) looks like. it’s 62 bytes bigger compressed:
densely packed and detailed, by some standards, but simple-looking enough that you just know a slightly better algorithm could crunch it down easily.
also, i don’t actually recognize these enemies. i think they might actually be unused (!!) (or are they from a different game?)
here’s what one of the better compressing ones looks like (bank 3, file 0x13):
lots of blank space, as expected.
bank 5 is full of cutscene graphics. some of the files there have a compression ratio in excess of 200%. i wonder what they look like:
i’m pretty sure that’s a tilemap, actually. that would explain it.
maybe i’ll figure out how to recompress this stuff, and that will inspire someone to make batman minus infinity (idk)