Log In  

This post is mostly just to share an experiment I did when playing around with compressing graphics.

I noticed when looking around, that many PICO-8 carts that do compress graphics were using some form of LZ or RLE compression. Out of curiosity, I decided to do some research on how the Generation 1 Pokemon games compressed an impressive amount of graphics data into the small cart size. It turns out that they use a form of RLE compression. I won't go into detail myself, but instead refer to a great YouTube video that very precisely describes how it works.

Essentially, this compression algorithm stands out because:

  • It splits the graphics into bit planes (i.e. 1 bit-per-pixel images)
  • It operates on pixel pairs, only encoding runs of pairs of 0's
  • It uses several flags to control how the bit planes are mixed in order to increase compression ratios
  • The original algorithm compresses 2bpp images (i.e. 4 colours). That being said, there is no reason why it cannot be extended to higher colour depths

Anyway, here is an implementation of a decompression routine for the Pokemon Generation 1 RLE image compression format. Overall, I'm not sure how useful this will be. It costs 400 tokens and decoding the sample 15x15 sprite in the demo cart takes 12 [email protected] On the plus side, it fits neatly into 544 bytes (less than a single row in the sprite editor), compared to its decompressed size of 7200 bytes, albeit with only a quarter of the colours. Note that the compression ratio greatly depends on the data. Also, I did not put much effort into optimizing the implementation for neither tokens nor CPU cyles.

In my opinion some of the "cool stuff" that this approach to compression does (that can be applied to other algorithms) is:

  • Using a reduced colour depth greatly reduces graphics size
  • RLE compressing a bit plane has some neat properties (the linked video goes into some more detail about this)

Cart #pkz_01-0 | 2021-02-24 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

P#88121 2021-02-24 21:00

Well this is great!! I’ve wanted to look into writing encode/decode code since I watched that video.

Do you have other compressed images to demo?

P#88162 2021-02-25 15:45

No, I didn't compress any other images out of laziness :P. However, you should be able to extract image data from any of the Gen1 game ROMs (this is what I used for test data). For example, this reads the compressed graphics for a (surprise :P) Pokemon located at offset 183637 and 244 bytes long from Yellow (English) version:

dd if=pkmn-yellow-en.gb of=surprise.pkz ibs=1 skip=183637 count=244

The cart makes use of the PICO-8 serial feature for dropped files, so if you have a compressed image, you should be able to load it by just drag-n-dropping it onto the running cart.

Additionally, the creator of the Youtube video I linked also created a web page for compressing/decompressing images. So if you have any 2bpp grayscale images that you want to try out, you should be able to compress them here: http://www.dotsarecool.com/rgme/tech/gen1decompress.html

P#88220 2021-02-26 20:34 ( Edited 2021-02-27 19:13)

Thanks for the link to the compress tool!

I already all sprites from gen 1 and 2 around, so I compressed one of these.

Do you have thoughts on adding colours?

P#88465 2021-03-03 19:31

I think the most straight forward way to add colours would be to set the palette before drawing the sprite. The current implementation uses colours 0-3.

P#88600 2021-03-05 22:40

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2023-06-08 08:42:39 | 0.036s | Q:19