Amiga LZX in Rust

LLM assisted clean-ish-room implementation of Amiga LZX.

Made by decompiling the compressor with Ghidra, writing spec documents for it and using unlzx.c to document the decompressor, then hiding the sources and re-implementing from the spec.

Install

From crates.io:

cargo install amiga-lzx-cli

This installs a binary called lzx (the historic Amiga tool name). Pre-built binaries for Linux (x86_64 / aarch64), macOS (universal), and Windows are also attached to each GitHub release.

Usage

# Create an archive from files and/or directories (walked recursively).
lzx c out.lzx file1 file2 mydir/

# List entries in an archive.
lzx l out.lzx

# Extract everything into ./out (or any directory).
lzx x out.lzx ./out

# Verify an archive without writing files.
lzx t out.lzx

Compression level: -1 quick, -2 normal (default), -3 maximum β€” matching the original Amiga lzx tool.

lzx -3 c best.lzx mydir/

File modification times are preserved on both create and extract.

Library

[dependencies]
amiga-lzx = "0.1"
use std::io::{Cursor, Write};
use amiga_lzx::{ArchiveWriter, ArchiveReader, EntryBuilder, Level};

let mut buf = Cursor::new(Vec::new());
let mut ar = ArchiveWriter::new(&mut buf)?;
let mut entry = ar.add_entry(EntryBuilder::new("hello.txt").level(Level::Normal))?;
entry.write_all(b"hello, world")?;
entry.finish()?;
ar.finish()?;

let mut reader = ArchiveReader::new(Cursor::new(buf.into_inner()))?;
while let Some(entry) = reader.next_entry()? {
    println!("{} ({} bytes)", entry.filename, entry.data.len());
}
# Ok::<(), amiga_lzx::Error>(())

License

WTFPL with warranty clause: don’t blame me.