Decoding Non-standard Image Formats
May 18, 2024
A while back I started work on a project to decode the CZ# image formats used in the LUCA System[1] game engine created by Prototype Ltd. and used in various visual novels (eg. Little Busters!! English Edition, LOOPERS). The formats are used for storing game assets and text bitmaps, so they're of great interest to groups trying to translate the game, or otherwise modify it in some way. Recently, I mostly finished my main goal of the project by being able to decode all the image formats perfectly, and additionally re-encode some of the formats as well!
I used the reverse engineering already done by the GARbro and LuckSystem/ LucaSystemTools projects as a starting point, as they had already figured out many aspects of the formats, and did some reverse engineering I am not capable of (yet!). I would like to express my thanks to the creators of and contributors to these projects, without which mine would not have been possible.
The first thing I did was to figure out the header format of the files, as it turned after some investigation with a hex editor that they all shared a similar header layout. This common header section contains information about the image including the length of the header, dimensions of the image, and the bit-depth of the image. Depending on the format, the header can also contain an extended section which has more information which could be considered metadata. This information includes cropping information, crop boundaries, and positioning info for display within the engine.
After the header, the images contain an optional section which details the palette of colors which are used in the image. This section only exists if the image has a bit-depth of 8 or 4, in which case the "pixels" in the image data actually correspond to an index in the palette.
Following the palette information, there's a section for compressed CZ# images (which is everything except CZ0) which describes information about the sizes of the compressed data.
Then you get into the actual compressed image data, the format of which depends on the format of CZ file.
Anyway, if you want to check out this work, the repository is here:
https://github.com/G2-Games/lbee-utils
And more information about the actual format is on the repository's wiki, but it is incomplete:
https://github.com/G2-Games/lbee-utils/wiki/CZ-Image-Formats