CSO to TAR.GZ

Nothing you choose here leaves your browser, and nothing is downloaded to make it work. A CSO is a disc image cut into blocks and squeezed with deflate — which your browser has done natively for years.

…or drop one anywhere on this page.

The same again, compressed.

A tar through gzip: the permissions a tar keeps, at something like a ZIP's size. Both the unpacking and the repacking are done by the browser's own compression, so nothing is fetched for either half.

What a CSO is

A disc image, usually of a PSP or PlayStation 2 game, chopped into blocks of 2,048 bytes and each block squeezed on its own. Squeezing them separately rather than the whole image at once is what lets an emulator jump to any point on the disc without unpacking everything first — and it is why this page can undo it with nothing but the browser's own deflate.

24 bytesthe header: CISO, the size of the original ISO, the block size, a version and a shift
then the tableone 32-bit offset per block, plus one more
then the blocksraw deflate, or stored as they are where squeezing made them bigger

The layout above is from maxcso's own repository — its README_CSO.md and src/cso.h — rather than worked out by staring at files. The format is BOOSTER's; maxcso is Unknown W. Brackets's and is ISC licensed. None of its code is used here, only its description of the layout. If you need to go the other way, or need a ZSO, maxcso is the tool.

There is one more entry than there are blocks

Nothing in a CSO records how long a block is. A block's length is the next entry's offset minus its own — which is why the table has a spare entry at the end, marking where the data stops. Treat that sentinel as a block and you read off the end of the file.

The high bit of an entry means the block is stored as it is rather than squeezed, which the format does when deflate would have made it bigger. Already-compressed data on the disc, usually — video, audio, textures.

One field in the header is not to be trusted

The header carries a header_size, and maxcso's own documentation says of it: “Does not always contain a reliable value.” It looks exactly like the thing to seek by to find the table, and a file written by something careless will then land you in the middle of it — producing an image of the right length with the wrong bytes in it, and no error anywhere.

The table follows the 24-byte header, always. This page reads it from there and says so on screen when a file's field disagrees, rather than quietly coping.

A ZSO is not a CSO, and version 2 is not version 1

Two near-relations, both refused here by name rather than half-read:

What it will not do

Where to go next