Skip to content

v1.4.0

Choose a tag to compare

@drpetersonfernandes drpetersonfernandes released this 26 Aug 03:03
· 58 commits to main since this release

What's New in CHDSharp v1.4.0

Release date: August 26, 2026

This release is the biggest correctness milestone for CHDSharp: the CLI now has full chdman argument parity, the encoder is byte-for-byte identical to MAME for every codec, and a dedicated battle-test harness keeps 2611/2611 synthetic + 3003/3003 real-world parity checks passing against chdman.exe.


Headline: full chdman parity

1. Full chdman CLI argument parity

The CLI (binary renamed from CHDSharpCli to CHDSharp) now accepts every chdman subcommand with matching option names and exit-code conventions:

info       verify      createraw    createhd   createcd
createdvd  createld    extractraw   extracthd  extractcd
extractdvd extractld   copy         addmeta    delmeta
dumpmeta   listtemplates

Common options mirror chdman exactly: --input/-i, --output/-o, --inputparent/-ip, --outputparent/-op, --compression/-c, --hunksize/-hs, --unitsize/-us, --numprocessors/-np, --force/-f, --verbose/-v, --chs, --sectorsize/-ss, and more.

The convenience commands from earlier versions remain available: directory scan, --list, --random, --parent, --toc, --cue, --classify, --detect, --hash, and --batch.

# chdman-style
CHDSharp info -i game.chd
CHDSharp verify -i game.chd
CHDSharp createcd -o game.chd -i game.cue
CHDSharp extractraw -o game.bin -i game.chd
CHDSharp copy -o new.chd -i old.chd -c zstd
CHDSharp addmeta -i game.chd -t GAME -vt "gauntlet"

# convenience extensions
CHDSharp D:\CHD
CHDSharp --random game.chd
CHDSharp --classify game.chd

2. Byte-for-byte parity with chdman for all codecs

Every encoder output now matches MAME's chdman byte-for-byte. This closes the three previously non-exact paths:

  • createld (laserdisc AVHuff) — fixed an off-by-four AVI idx1 base offset that shifted audio by one sample and misaligned video; the AVHuff codec now correctly compresses zero-padded single-frame hunks; and the mono-FLAC encoder now evaluates every fixed-predictor order per frame (matching libFLAC 1.4.3 for the mono/48 kHz avhu path).
  • cdzs (CD Zstandard) — the in-repo VendoredZSTD port now emits frames byte-identical to C zstd for the same hunk buffers.
  • zstd (raw Zstandard) — same fix; createraw -c zstd output is now byte-identical to chdman.

3. Full chdman battle-test parity — 2611/2611 synthetic + 3003/3003 real-world

The new CHDSharpBattleTest harness exhaustively cross-checks the CHDSharpLib decoder and the CHDSharp.Encoder encoder against chdman.exe:

  • chdman create* parity (ours and reference both verify clean)
  • byte-identical encode for every writable codec
  • decode, extract, and info parity
  • delta/parent, CD, and A/V laserdisc scenarios

It runs on a deterministic corpus (seed 1337) and can also scan real-world CHD folders:

dotnet run --project CHDSharpBattleTest                       # 2611/2611
dotnet run --project CHDSharpBattleTest -- --quick         # smoke run
dotnet run --project CHDSharpBattleTest -- --real "D:\CHD" # real collection

Zero external dependencies

The ZstdSharp.Port NuGet package has been replaced by the in-repo VendoredZSTD project — the ZstdSharp 0.7.6 source tree, a full C-to-C# port of the zstd 1.5.5 source (the same version MAME bundles), including both the encoder and the decoder.

The library now has zero external runtime NuGet dependencies. Every codec (zlib, lzma, huffman, flac, zstd, AVHuff, and all CD variants) is vendored in-repo in pure C#.


38 bugs fixed from a deep code review

A code review across the CLI, library, and battle harness resolved 38 issues. Highlights:

  • Exit codes & error handling — proper CLI exit codes (0/1/3), CheckFile(Stream) catches IOException, VerifyList logs exception types verbatim.
  • Encoding — createcd defaults to cdlz,cdzl,cdfl; createhd --input routes to EncodeRaw; verify --inputparent is passed to CheckFileWithParent; all create/copy commands require --force to overwrite; extractcd --splitbin and GD-ROM .gdi updates; LzmaStream.Seek returns the correct position.
  • Concurrency — thread-safe parallel-verification master error (StrongBox + Interlocked), DisposeAsync drains per-thread codec states, read-ahead no longer over-releases its semaphore.
  • Robustness — ReadHunk(Span) caches hunks on success, FindRepeatedBlocks validates map offset bounds, ValidateSizeLimits rejects Unitbytes == 0, MemoryMappedFile disposed on view failure, extractraw writes to a temp file first.
  • Diagnostics — Interlocked progress callbacks, version display uses Build, bug reports scrub PII, API keys no longer stored in plain text.
  • CLI helpers — --batch extension filtering, exact .chd extension checks, symlink skipping, complete help coverage, addmeta rejects non-ASCII tags.

Plus: flaky-test fixes for .NET 8/9/10, and all compiler/analyzer/Rider warnings resolved across VendoredZSTD and VendoredZLib.


Breaking changes

  • CLI binary renamed: CHDSharpCli.exe → CHDSharp.exe. The subcommand syntax changed to the chdman style (CHDSharp createcd -o out.chd -i in.cue); the old --create/--createcd/--createhd/--copy forms are gone.
  • ZstdSharp.Port package removed: replaced by the in-repo VendoredZSTD. Direct consumers of that package should switch to the library's own codecs.

Quick install

dotnet add package CHDSharp --version 1.4.0

Targets net8.0, net9.0, and net10.0. Zero native dependencies — runs on Windows, Linux, and macOS.


Full changelog: docs/ReleaseNotes.md

Full Changelog: v1.2.0...v1.4.0