MSX & Z80 ASSET COMPRESSOR · VERIFIED IN-BROWSER

Pack MSX graphics and data.
Get matching Z80 code.

Drop any binary file, BMP, PNG, or Screen 5–8 image. Every compression route is automatically tested and verified byte-for-byte in your browser, complete with ready-to-assemble Z80 unpackers and a one-click MSX ROM builder.

Screen 5–8 & Linear VRAMByte-Exact Round-Trip ProofInterrupt-Safe (EI) Z80RAM & In-Place TailASCII8/16 · Konami · SCCLocal WebMSX ROMs
AT A GLANCE
Buffered Screen 5–8321 B Z80 (358 B dynamic)1–16 KB RAM
Direct Screen 5–8827 B Z80 (892 B dynamic)ZERO STAGING RAM
RAM Unpackers138–161 B Z80 (Normal & Tail)SHARED Z80 CORE
Cartridge MappersASCII8/16, Konami, SCCAUTO BANK READ

See the Help & format guide for format header IDs and bitwise specifications.

CBS v5.3 · v5.4 · v5.5 · v5.6 compression lab

v5.4 versus v5.3, v5.2 and v4.3

Your file stays local
This is a build-time choice. Packed CB5 files carry no mapper bits.
HL advances linearly in unpaged ROMThe compact original LD A,(HL) reader is retained.
Drop binary, BMP, PNG, SC5–SC8 or CB5 dataContinuous-data comparison or recommended Screen 5–8 direct-VRAM compression · maximum 65,536 packed bytes
No file handy? Try a verified MSX sample:
One linear byte stream tested with v5.4, v5.3, v5.2 formats 0 and 2, and CBS v4.3
5 selected · open Advanced Geometry & Codec Tuning below to customize individual codecs or search window.
Advanced Geometry & Codec Tuning
The same window is used for both v5.2 formats.
v5.4 + v5.3 + v5.2 + v5.2 near + v4.3Adaptive Near LZ (v5.4) · State-Flow LZ (v5.3) · Compact Pair LZ (v5.2) · Compact Pair Near LZ (v5.2) · Historical Baseline (v4.3)
Compressors to run
5 selected · only these searches will run

Recommended runs the four active CBS formats; Select all also adds the slower v4.3 comparison.

Z80 Decruncher Source Generator321 bytes
; =====================================================================
; CBS Cruncher v5.5 - Screen 5-8 reusable-buffer decruncher v1.2
; =====================================================================
; Assembled size:
;   - 321 bytes (fixed Screen 5, standard VDP port 99h)
;   - Category range: 319 to 358 bytes (321 B fixed Screen 5/7, 358 B dynamic)
;
; Decrunches a C3h v5.5 image or a C4h sequence of independent v5.5 chunks.
; Every EOS uploads the completed RAM chunk with HMMC. C4h then advances Y and
; reuses the same caller-selected buffer until the complete image is restored.
;
; Interrupt & Stack Safety:
;   - 100% safe with MSX BIOS interrupts (EI) enabled during token parsing.
;   - Never uses SP as a data pointer or reads below SP.
;   - Uses DI during atomic VDP port setup and HMMC transfer.
;   - Preserves alternate register set (BC', DE', HL' are untouched).
;
; Input:
;   HL = CBS image container (C3h or C4h)
;   DE = packed destination coordinate (D = packed X, E = Y)
;   IX = start of the selected 1/2/4/8/16 KB reusable RAM buffer
;   A  = call route (bits 3-2 = VRAM command page 0-3, bits 1-0 = source)
;
; Public entry points:
;   CBS_DECRUNCH    normal image-decompression entry
; =====================================================================
CBS_DECRUNCH:

CBS_V52_SCREEN58_RAM_TO_VRAM:
        AND     0Ch
        RRCA
        RRCA
        LD      B,D                     ; B = packed X
        LD      D,A                     ; DE = (page << 8) | Y
        LD      (CBS_V52_VRAM_DY),DE

        EX      DE,HL                   ; DE = container
        LD      L,B
        LD      H,00h
        ADD     HL,HL
        LD      (CBS_V52_VRAM_DX),HL
        EX      DE,HL                   ; HL = container

        LD      A,(HL)                  ; C3h or C4h
        INC     HL
        CP      C4h
        LD      A,(HL)                  ; packed width (0 = 256)
        INC     HL
        LD      C,01h                   ; 1 chunk for C3h
        JR      NZ,CBS_V52_VRAM_HEADER_READY
        INC     HL                      ; skip C4h total height
        LD      C,(HL)                  ; C4h chunk count
        INC     HL
CBS_V52_VRAM_HEADER_READY:
        EX      DE,HL
        DEC     A
        LD      L,A
        LD      H,00h
        INC     HL                      ; HL = 16-bit byte width (1..256)
        LD      (CBS_V52_VRAM_ROW_WIDTH+1),HL
        ADD     HL,HL
        LD      A,H
        AND     01h                     ; command NX wraps 512 dots to 000h
        LD      H,A
        LD      (CBS_V52_VRAM_NX),HL
        EX      DE,HL
        LD      A,C
        LD      (CBS_V52_VRAM_CHUNKS+1),A

CBS_V52_VRAM_CHUNK_START:
        LD      A,(HL)                  ; chunk line count (0 = 256)
        INC     HL
        DEC     A
        LD      C,A
        LD      B,00h
        INC     BC
        LD      (CBS_V52_VRAM_NY),BC

        PUSH    IX
        POP     DE                      ; DE = start of reusable RAM buffer
        LD      A,80h                   ; sentinel control-bit reservoir
        LD      BC,FFFFh                ; default negative offset = -1
        PUSH    BC                      ; persistent last offset on stack

CBS_V52_VRAM_ROW_START:
        CALL    CBS_V52_VRAM_GET_GAMMA
        JR      CBS_V52_VRAM_COPY_LITERALS

CBS_V52_VRAM_AFTER_LITERAL:
        CALL    CBS_V52_VRAM_GET_BIT
        JR      C,CBS_V52_VRAM_NEW_OFFSET
        CALL    CBS_V52_VRAM_GET_GAMMA_EOS

CBS_V52_VRAM_COPY_MATCH:
        EX      (SP),HL
        PUSH    HL
        ADD     HL,DE
        LDIR
        POP     HL
        EX      (SP),HL

CBS_V52_VRAM_AFTER_MATCH:
        CALL    CBS_V52_VRAM_GET_BIT
        JR      C,CBS_V52_VRAM_NEW_OFFSET
        CALL    CBS_V52_VRAM_GET_GAMMA_EOS

CBS_V52_VRAM_COPY_LITERALS:
        LDIR
        JR      CBS_V52_VRAM_AFTER_LITERAL

CBS_V52_VRAM_NEW_OFFSET:
        CALL    CBS_V52_VRAM_GET_BIT
        JR      C,CBS_V52_VRAM_GENERAL_OFFSET

CBS_V52_VRAM_ROW_OFFSET:
        CALL    CBS_V52_VRAM_GET_NEG_GAMMA
        INC     BC
        PUSH    DE
        PUSH    HL
CBS_V52_VRAM_ROW_WIDTH:
        LD      DE,0000h
        LD      HL,0000h
CBS_V52_VRAM_MULTIPLY:
        OR      A
        SBC     HL,DE
        INC     C
        JR      NZ,CBS_V52_VRAM_MULTIPLY
        LD      B,H
        LD      C,L
        POP     HL
        POP     DE
        CALL    CBS_V52_VRAM_GET_BIT
        JR      CBS_V52_VRAM_STORE_OFFSET

CBS_V52_VRAM_GENERAL_OFFSET:
        CALL    CBS_V52_VRAM_GET_NEG_GAMMA
        INC     BC
        RR      B
        LD      B,C
        LD      C,(HL)
        INC     HL
        RR      B
        RR      C

CBS_V52_VRAM_STORE_OFFSET:
        EX      (SP),HL
        POP     HL
        PUSH    BC
        LD      BC,0001h
        CALL    NC,CBS_V52_VRAM_GAMMA_LOOP
        INC     BC
        JR      CBS_V52_VRAM_COPY_MATCH

CBS_V52_VRAM_FINISHED:
        POP     BC
        PUSH    HL

        PUSH    IX
        POP     HL
        LD      A,(HL)
        INC     HL
        LD      (CBS_V52_VRAM_CLR),A
        EX      DE,HL

        DI
        LD      HL,CBS_V52_VRAM_COMMAND_DATA
CBS_V52_PORT_CONTROL:
        LD      C,99h
        LD      A,24h
        OUT     (C),A
        LD      A,91h
        OUT     (C),A
        INC     C
        INC     C
        LD      B,0Bh
        OTIR

        DEC     C
        DEC     C
        LD      A,44 + 80h
        OUT     (C),A
        LD      A,91h
        OUT     (C),A
        INC     C
        INC     C

        EX      DE,HL
        LD      A,(CBS_V52_VRAM_NY)
        LD      D,A
        JR      CBS_V52_VRAM_COPY_FIRST

CBS_V52_VRAM_COPY:
        LD      A,(CBS_V52_VRAM_ROW_WIDTH+1)
        LD      B,A
CBS_V52_VRAM_COPY_L:
        LD      A,(HL)
        INC     HL
        OUT     (C),A
CBS_V52_VRAM_COPY_FIRST:
        DJNZ    CBS_V52_VRAM_COPY_L
        DEC     D
        JR      NZ,CBS_V52_VRAM_COPY

        DEC     C
        DEC     C
        LD      A,02h
        OUT     (C),A
        LD      A,8Fh
        OUT     (C),A
CBS_V52_VRAM_EXIT_WAIT:
        IN      A,(C)
        RRCA
        JR      C,CBS_V52_VRAM_EXIT_WAIT
        XOR     A
        OUT     (C),A
        LD      A,8Fh
        OUT     (C),A

        LD      HL,CBS_V52_VRAM_DY
        LD      A,(CBS_V52_VRAM_NY)
        ADD     A,(HL)
        LD      (HL),A
        POP     HL
CBS_V52_VRAM_CHUNKS:
        LD      A,00h
        DEC     A
        RET     Z
        LD      (CBS_V52_VRAM_CHUNKS+1),A
        EI
        JP      CBS_V52_VRAM_CHUNK_START

CBS_V52_VRAM_GET_GAMMA_EOS:
        LD      BC,0001h
        CALL    CBS_V52_VRAM_GET_BIT
        JR      NC,CBS_V52_VRAM_GAMMA_LOOP
        CALL    CBS_V52_VRAM_GET_BIT
        RET     NC
        POP     BC
        JR      CBS_V52_VRAM_FINISHED

CBS_V52_VRAM_GET_GAMMA:
        LD      BC,0001h
        JR      CBS_V52_VRAM_GAMMA_ENTRY

CBS_V52_VRAM_GET_NEG_GAMMA:
        LD      BC,FFFEh
CBS_V52_VRAM_GAMMA_ENTRY:
        CALL    CBS_V52_VRAM_GET_BIT
        RET     C
CBS_V52_VRAM_GAMMA_LOOP:
        CALL    CBS_V52_VRAM_GET_BIT
        RL      C
        RL      B
        JR      CBS_V52_VRAM_GAMMA_ENTRY

CBS_V52_VRAM_GET_BIT:
        ADD     A,A
        RET     NZ
        LD      A,(HL)
        INC     HL
        RLA
        RET

CBS_V52_VRAM_COMMAND_DATA:
CBS_V52_VRAM_DX:
        DW      0
CBS_V52_VRAM_DY:
        DW      0
CBS_V52_VRAM_NX:
        DW      0
CBS_V52_VRAM_NY:
        DW      0
CBS_V52_VRAM_CLR:
        DB      0
        DB      00h
        DB      F0h
Windows · macOS · Linux

The same compressor from a Python command line

The downloadable package uses the same compiled engine and parameters as this page. It handles continuous data, Screen 5–8 images, native BMP/PNG import, SC5–SC8 BSAVE files, CB5 decrunching, RAM-tail output, linear VRAM and one-image MSX test ROMs.

CBS Cruncher v5.6 CLI · release 10

Cross-platform compressor plus the practical Z80 source set

Continuous data
python cbs_cruncher.py game.bin
python cbs_cruncher.py game.bin --ram-tail
Screen image + test ROM
python cbs_cruncher.py picture.png --mode 7 --rom
python cbs_cruncher.py tiles.bin --linear-vram-screen 5 --rom

Requires Python 3.10+ and Node.js 22+. Pillow is needed only for BMP/PNG input. The website-only multi-image demonstration ROM remains intentionally separate from the CLI.

Current release · what is real today

The core system is complete enough for game integration

The browser no longer presents every abandoned experiment. These are the implemented paths that have survived compression, browser round-trip and generated-ROM testing.

01Continuous RAM

Code, maps, text and arbitrary bytes

Compact pair v5.2, combined state-flow v5.3/v5.4 and the v4.3 baseline, with matching RAM decrunchers.

02Measured RAM-tail

Reuse the destination block

Safe files use in-place tail mode and relocate themselves with LDDR before forward expansion.

03Screen 5–8

Buffered or direct VRAM

v5.3, v5.4 and line-aware v5.5 share paired payloads; change the destination without recompressing.

04Linear VRAM

Tiles, fonts and pattern data

v5.3/v5.4 linear VRAM mode follows physical Screen line width without forcing rectangle geometry.

05Cartridge ROM input

Five mapper families

One mapped Screen 5–8 decoder mixes buffered and direct images across ASCII8, ASCII16, ASCII16-X, Konami and Konami SCC banks.

06Real MSX proof

Generated ROMs and WebMSX

Single images and ordered multi-screen mapper ROMs verify decompression, palettes and VDP delivery.

Still planned

MSX Memory Mapper RAM output is the main missing backend

Cartridge ROM mapper reading now serves both buffered and direct VRAM. What remains is unpacking into selected MSX Memory Mapper segments, plus an optional hybrid row/chunk backend if a real game benefits from it.

See the roadmap
1996 → 2026 · reconstructed from sources and project records

How CBS Cruncher grew into v5.6

A Motorola 68000 cruncher and tiny Z80 decruncher became a verified browser tool, a family of RAM/VRAM writers and a real MSX ROM builder.

MEASURED INTEGRATION GUIDE

Decoder cost, RAM cost and speed become one practical choice

The Help page now starts with the compact v5.5 route, publishes exact shipped decruncher sizes, and compares reusable 1, 2, 4, 8 and 16 KB windows on a verified 24 KB Screen 5 image. The 8 KB window is recommended as the usual balance—not a universal winner—while v5.6 is presented as the stronger directional compressor with a larger decoder. The older tile-grid experiment remains available at the end as research rather than the default workflow.

V5.5 REUSABLE BUFFER

Large Screen 5–8 images no longer need one full-image RAM stage

The v5.5 chunked container divides an image into complete-row, EOS-terminated streams sized for the game's selected 1–16 KB buffer. One CBS_DECRUNCH call expands every chunk, uploads it with HMMC, advances Y and reuses the same RAM automatically. The shared v5.5 buffered decoder is 321–358 bytes (321 B fixed Screen 5/7, 358-byte buffered decoder with dynamic init); measured examples showed a substantial display-speed advantage over Direct while allowing each project to trade RAM against packed size.

THE ORIGINAL

CBS Cruncher is written for the Amiga

The 68000 cruncher produces CBS v3. Its small Z80 decruncher originated on the ZX Spectrum and also works on MSX. A ROM-reading MSX version was later developed during the Romancia translation while the executable decoder still ran from RAM.

RECOVERY + FORMAT DESIGN

The surviving sources become a verified browser tool

We restored v3 and v4.3, reproduced the Romancia result, replaced the unsafe four-byte overlap assumption with exact measurement, imported BMP/PNG pixels, and developed the v5.2 compact formats with a documented three-byte header and optimized Z80 RAM core.

LEARNING FROM ZX0

One excellent decoder changes our direction

ZX0's state flow, interlaced Elias coding, last offset on the stack, EX (SP),HL copying and impossible-offset EOS guided v5.3 and v5.4. CBS kept its own headers, offsets, adaptive-near choice and destination system.

DIRECT VRAM + ROM BANKS

Large pictures stop requiring a full RAM buffer

CPU literals, HMMM matches and HMMV fills made direct Screen 5–8 output practical. Five cartridge mapper readers, palettes, RAM decoder relocation, F500h controller code and ordered multi-image ROMs followed.

V5.5 INTEGRATION RELEASE

The experimental pieces become one usable system

v5.3/v5.4 gained one combined RAM decoder; v5.5 line offsets joined buffered and direct image routes; linear VRAM mode was added; measured RAM-tail relocation was added; the Python CLI gained matching outputs; and the website was divided into a focused compressor plus this complete integration guide.

ONE MAPPED IMAGE DECODER

Buffered and direct pictures share the same ROM

The five cartridge-mapper builds gained a shared consecutive-bank reader and an optional mixed destination dispatcher. Direct-only lists now keep the smaller direct decoder; lists containing buffered streams automatically receive the combined RAM-stage/HMMC and direct-VRAM decoder. Machine ports, the initial Screen mode and an unchanged palette are initialized once before playback, while later setup runs only for a real mode or palette transition. The buffered uploader now waits for final HMMC completion before returning, and demo ROMs disable sprites to prevent artifacts while freeing VDP bandwidth.

V5.6 DIRECTIONAL IMAGE RELEASE

Screen 5 images gain directional reconstruction and rolling buffers

v5.6 searches horizontal and vertical traversal orders in both directions, keeps the smallest permitted v5.5-based stream, and reconstructs exact plus horizontally, vertically and two-axis-mirrored rectangles in place with VDP commands. One Screen 5 decoder accepts all four orders. Its VDP ports are patched once from the BIOS, register writes are inlined, unnecessary address helpers and command waits were removed, interrupts remain enabled outside short VDP latch sequences, and compatible HMMM work is coalesced.

The optimized Direct decoder is 2,078 bytes and expands a complete 32 KB tile-image benchmark in 7.831 seconds, faster than the measured v5.4 and v5.5 Direct routes. Optional 1–16 KB rolling builds use the identical packed file and are 2,639 bytes; they currently help horizontal delivery most. v5.5 remains the compact line-aware alternative: its 321–358-byte buffered decoder (321 B fixed Screen 5/7, 358 B dynamic) automatically expands independent EOS-terminated chunks through one reusable caller-selected buffer and advances Y internally. The earlier version restored the same test in roughly 2.5–2.8 seconds depending on the chosen split; those timings predate the latest optimizations.

LOCAL WEBMSX + CLI RELEASE 9

Long mapper ROMs run without an address-length limit

A dedicated local WebMSX player replaced ROM-sized Base64 launch URLs. The browser now transfers complete cartridges directly between local tabs, preserving Japanese MSX2 NTSC, palette and mapper selection without uploading the ROM. The Python CLI was regenerated from the same engine, given reproducible packaging and tested across every continuous codec, buffered/direct images, linear VRAM, RAM-tail, BSAVE handling and all five mapped-ROM readers.

COMPACT TABLE-DRIVEN ROM PLAYER

Large image lists stop consuming the F500h controller area

The multi-image builder replaced per-picture playback code with one shared loop and a compact RAM table containing Screen mode, VRAM page, mapper bank, packed address, palette and clear-command references. The HMMV clear now sends an eleven-byte VDP command block with OTIR, identical mode/black-colour blocks are reused, and a new public CBS_WAIT_VDP decoder entry owns VDP-command waiting. A ten-image mixed ASCII16 player now occupies only 643 bytes at F500h, including its table, palettes and clear parameters.

The Help & format guide contains the byte layout, calling conventions, worked examples and remaining roadmap.