Skip to content

Releases: purelogiccode/CHDSharp

CHDSharp v1.5.2

Choose a tag to compare

@github-actions github-actions released this 21 Oct 20:49

CHDSharp v1.5.2 - What's New

Released: 2026-10-21 - Full changelog - NuGet

CHDSharp v1.5.2 rolls up the v1.5.1 cue-layout parity fixes and adds a repo-wide code-quality pass plus fully automated wiki and
documentation-site deployment.


Download (CLI)

Platform Bundle
Windows x64 CHDSharp_win-x64_v1.5.2.zip
Windows ARM64 CHDSharp_win-arm64_v1.5.2.zip
Linux x64 CHDSharp_linux-x64_v1.5.2.zip
Linux ARM64 CHDSharp_linux-arm64_v1.5.2.zip
macOS Intel CHDSharp_osx-x64_v1.5.2.zip
macOS Apple Silicon CHDSharp_osx-arm64_v1.5.2.zip

Every bundle contains a framework-dependent single-file CHDSharp / CHDSharp.exe
build (the .NET runtime is not embedded) plus LICENSE.txt, README.md, README.txt
and this document. The .NET 10 runtime
is required.


Fixed: REM LEAD-OUT at or before the session's last track

The parser compared the track's frame count with leadOut - index00 using two int values.
MAME compares a uint32_t frame count against a signed int32_t end frame
(cdrom.cpp:2748), so a negative end frame converts to a huge unsigned value and the trim is
skipped. Cues that declare REM LEAD-OUT 00:00:00 (or any address at or before the last track
of the session) therefore failed with:

Track 2: the session lead-out values leave a negative length (-11400 frames); the cue's
REM SESSION/LEAD-OUT values do not match the image.

while chdman createcd encoded the same cue, because the no-op lead-out leaves the cue's INDEX
positions in charge of the layout. The parser now performs the same unsigned comparison, so the
track layout and the CHD bytes match chdman.

Fixed: a pad larger than its track zeroed the whole track

The CD reader treated the last PadFrames frames of a track as zero-filled padding. In chdman
the pad start is an unsigned offset from the track start (chdman.cpp:471-472); when the pad is
larger than the track the offset wraps below the track start, the pad region is unreachable, and
every frame is read from the source file. The encoder now mirrors that rule, and the GD-ROM
data/pad/split ordering follows the same frame layout (splitStart = frames - splitFrames,
padStart = splitStart - padFrames).

Code quality (new in v1.5.2)

The whole solution is now clean under the ReSharper command-line inspector:
jb inspectcode CSharp_CHDSharp.sln --severity=WARNING reports zero warnings or errors
(308 before the cleanup). The policy lives in the root .editorconfig:

  • Vendored codecs are exempt and untouched. VendoredZLib, VendoredLZMA, VendoredFlac
    and VendoredZSTD are third-party ports; byte-for-byte chdman parity depends on them staying
    verbatim, so their style/quality inspections are disabled instead of "fixed".
  • Consumer-facing models are exempt from "never used" inspections - public library records,
    the JSON corpus manifest, and the WPF data models are read by callers, serializers and XAML
    bindings rather than by the declaring assembly.
  • First-party findings were fixed: redundant null checks in the CLI encode paths, a write-only
    AVI stream field, and dead tester state (LogEntry/LogEntries and the unread
    PerFileResult.FilePath).

CI, wiki & docs (new in v1.5.2)

  • Docs deploy from CI. After the three-OS build/test matrix passes on a push to main, the
    CI workflow regenerates the GitHub wiki from docs/ and requests a Pages rebuild. The release
    workflow does the same for tags, so the wiki and the documentation site stay in sync with the
    code.
  • Dark theme by default. The documentation site uses a dark palette with a persisted
    light/dark toggle and color-scheme metadata.
  • Badges everywhere. Every README (root, library, CLI, tests, generator, tester, benchmarks
    and docs/) starts with its CI/NuGet/platform badge row.
  • Release routine documented. AGENTS.md now records the version bump, verification, tag,
    bundle and wiki/Pages steps used for this release.

Verification

  • New chdman createcd byte-parity fixtures: zero lead-out, lead-out before the track, and the
    pad-larger-than-track layout.
  • Parser regression tests for both lead-out shapes.
  • CHDSharpEncoderTest 454/454, CHDSharpTest 4214/4214, battle harness --quick 905/905 checks.
  • Full dotnet test across net8.0/net9.0/net10.0: 14,004 passed, 0 failed; full battle
    harness: 3,174/3,174 checks, byte-identical chdman output.

Upgrading

No public API changes. Replace the package; cues that encoded before produce the same bytes, and
the two layouts above now encode instead of throwing.

CHDSharp v1.5.0

Choose a tag to compare

@github-actions github-actions released this 16 Oct 22:12

CHDSharp v1.5.0 — What's New

Released: 2026-10-16 · Full changelog · NuGet

CHDSharp v1.5.0 is the first release produced end-to-end by the GitHub Actions pipeline:
one tag push builds the six platform bundles, creates the GitHub release, publishes the
NuGet package, and updates the wiki and
the documentation site.


Download (CLI)

Platform Bundle
Windows x64 CHDSharp_win-x64_v1.5.0.zip
Windows ARM64 CHDSharp_win-arm64_v1.5.0.zip
Linux x64 CHDSharp_linux-x64_v1.5.0.zip
Linux ARM64 CHDSharp_linux-arm64_v1.5.0.zip
macOS Intel CHDSharp_osx-x64_v1.5.0.zip
macOS Apple Silicon CHDSharp_osx-arm64_v1.5.0.zip

Every bundle contains a framework-dependent single-file CHDSharp / CHDSharp.exe
build (the .NET runtime is not embedded) plus LICENSE.txt, README.md, README.txt
and this document. The .NET 10 runtime
is required. On Linux/macOS run chmod +x CHDSharp if the binary is not executable after
unzipping.


Fixed: built-in update check

The CLI's "a new version is available" notice now links directly to the download for
your platform
. The bundle the release ships (CHDSharp_<os>-<arch>_v<version>.zip) is
exactly the name the update check looks up; previously it searched for the wrong asset
name built from the currently running version, so the direct link never resolved and
users were sent to the releases page instead.

Release engineering

  • One tag, one release — Release workflow: bundles (win/linux/osx × x64/arm64),
    GitHub release, NuGet push, wiki sync, Pages rebuild. The workflow refuses to run if
    the tag does not match Directory.Build.props.
  • NuGet publishing is idempotent — re-running the workflow skips a version that is
    already on nuget.org.
  • GitHub releases now ship only the CLI — the WPF Tester remains source-only.

Also in this release

  • Wiki + documentation site in sync — the docs/ folder is deployed twice from CI:
    as the documentation site and as the
    GitHub wiki, both with the same side menu.
  • Dark theme by default on the documentation site (with a persisted light/dark toggle).
  • Test harness hardening — test-spawned CLI runs set CHDSHARP_NO_BUG_REPORTS=1 /
    CHDSHARP_NO_TELEMETRY=1, so local full-suite runs no longer file bug reports.
  • Badges on every README (CI, release, NuGet, platform, parity, license).

Upgrading from v1.4.3 (or earlier)

v1.5.0 rolls up everything from v1.4.4 and v1.4.5:

  • Multisession cue parity — ports MAME's REM SESSION / REM LEAD-IN / REM LEAD-OUT
    / session-pregap layout rules (IsoBuster/ImgBurn single-bin trim with zero-filled
    inter-session gaps, Redump/DiscImageCreator synthesized lead-in/out, .img heuristic).
    Multisession cues now encode byte-identically to chdman createcd.
  • Redump multi-cue Dreamcast GD-ROM parity — cues with REM SINGLE-DENSITY AREA /
    REM HIGH-DENSITY AREA markers get the full is_gdicue layout (split pregap regions,
    LBA-45000 padding, CHGD metadata); verified byte-identical on a real 1.19 GB Redump
    multi-cue with a byte-perfect chdman extractcd round-trip.
  • cdrdao TOC START parity — a bare START line (cdrdao's documented form) is
    accepted as "no pregap", matching MAME 0.289's parse_toc exactly.

NuGet

dotnet add package CHDSharp --version 1.5.0

Targets net8.0, net9.0 and net10.0 — pure C#, zero native dependencies. Every
codec (zlib, lzma, huffman, flac, zstd, AVHuff and the CD variants) is implemented
in-repo and ships inside the package.

v1.4.3

Choose a tag to compare

@drpetersonfernandes drpetersonfernandes released this 02 Sep 01:21

CHDSharp v1.4.3

Consolidates all changes since v1.4.2. Closes the partial-tail raw-encode corruption and the last FLAC byte-parity divergence. Battle harness green: 3174/3174 synthetic vs MAME 0.289.

Partial-tail raw-encode corruption fix

EncodeRaw/createraw on inputs of ≥ 513 hunks whose length is not a hunk multiple could produce a self-consistent-but-wrong CHD: stale compression ring-buffer slots from the previous fill cycle leaked into partial final hunks. The fix landed alongside guardrail tests so the class of bug cannot silently return:

  • a synthetic partial-tail probe that pins the exact stale-slot bytes,
  • partial-last-hunk unit tests per codec,
  • a resized long-tail case in the battle harness (raw-encode long-tail x flac/zlib/zstd).

FLAC encoder byte parity

The vendored FLAC encoder now matches chdman byte-for-byte on the remaining divergence: the fixed-predictor analysis window and the tukey window's cosf rounding (native cosf semantics replicated). Verified byte-identical on:

  • the 7.8 GB Perfect Dark Zero XGD2 image (1,912,816 hunks, chdman default codec list),
  • a 100 MB partial-tail slice of the same source,
  • three single-hunk repro cases.

Byte-parity fixes earlier in the cycle

  • Stale work-buffer tail + LZMA match-finder insert parity (raw encode).

Diagnostics and output

  • Detailed decompression-failure messages: hunk index, codec, CRC/truncation reasons.
  • chdman-style progress + speed-meter output.

Verification status

  • CHDSharpTest: 12,648/12,648 (436/436 per TFM on net8.0/net9.0/net10.0 → 1,308/1,308 aggregate via the console runners).
  • CHDSharpEncoderTest: 1,308/1,308.
  • CHDSharpBattleTest: 3174/3174, including raw-encode long-tail x * for all three codecs.

NuGet Package

dotnet add package CHDSharp --version 1.4.3

Targets net8.0, net9.0, net10.0. Pure C# - zero native dependencies.

Full Changelog: v1.4.2...v1.4.3

v1.4.2

Choose a tag to compare

@drpetersonfernandes drpetersonfernandes released this 29 Aug 19:17

What's New in CHDSharp

Final chdman parity gaps closed — battle 2907/2907

  • LZMA byte-parity hash-update-order bug fixed (c470879): raw encoding now replicates chd.cpp's 256-hunk compression work buffer (RingBufferedRawReader) — ring slots past EOF keep stale bytes from the previous 128-hunk batch and the raw SHA-1 folds only valid bytes, exactly like m_compsha1.append(dest, numbytes). Also touches FlacLpcMath, LzmaEncoder and the FLAC encoder for byte-exact output.
  • createhd size / CHS quirks (e4f3735): size parsing now matches chdman.cpp:2035 (sscanf("%I64u") reads leading digits only, so "512K" = 512 bytes) and small sizes are rounded up to the guessed CHS product (guess_chs parity), including the IDENT/GDDD wide-CHS case.
  • Laserdisc AVI byte-parity (e4f3735): AviWriter output is now byte-identical to chdman createld/extractld.
  • Strict info/verify options (e4f3735): full-argument option validation (duplicate -i/--input detection, per-command option sets), info returns exit code 1 on failure, verify parity with chdman's report_error handling.
  • DVD metadata empty payload (c470879): DVD_METADATA_TAG written with zero-length payload per chdman.
  • CLI exit codes (c470879): failure paths now return chdman-consistent non-zero exit codes.
  • Test fixes in CHDSharpEncoderTest/CHDSharpTest accompany the parity work.
  • Missmatch.md replaces the deleted divergency.md and records the battle result: 2907 checks — 2907 passed, 0 failed against MAME 0.289.

CLI improvements

  • createraw now also accepts --hunk-size / --unit-size aliases alongside --hunksize / --unitsize / -hs / -us (ea375e1).
  • extractcd filename template %t regex fixed (named capture groups; escaped %% handling) (ea375e1).
  • hash command help corrected: --result text|json|sfv and --tracks flags (ea375e1).
  • createhd geometry override via LogicalLengthBytes for byte-parity encoding of over-/under-sized sources (c470879).

Build & tests

  • CHDSharpBattleTest multi-targets net8.0;net9.0;net10.0 with LangVersion=latest and copies the built CLI into its output for self-contained battle runs (e4f3735).
  • Analyzer warnings silenced (MA0008 StructLayout, unused-variable suppressions) (aaad13d).
  • Formatting and style pass across CLI, encoder, and vendored codecs (2e3a1e9, b858192).

Documentation

  • New CLI command reference: docs/cli-commands.md (413 lines) plus expanded CHDSharpCli/README.md — full chdman/CHDSharp argument tables for every command (2bef641e).
  • CHD format history added to docs/chd-format.md; language simplified and stale DVD metadata notes corrected (d208521).
  • Wiki home page (docs/README.md) rewritten with CHD history; ReleaseNotes added to sidebar and _config.yml (ff51e98).
  • Docs site URL fixed to the GitHub repository (3dedc71).
  • Peterson Fernandes added to key contributors across all docs (dfb74b7).

v1.4.1

Choose a tag to compare

@drpetersonfernandes drpetersonfernandes released this 28 Aug 04:12

CHDSharp v1.4.1

What's New

GD-ROM support is now complete

  • extractcd correctly handles Dreamcast GD-ROM Redump images (REM SINGLE-DENSITY / HIGH-DENSITY, 45000-frame boundary, has_physical_pregap fixup). Works for both GDI and CUE/BIN.
  • Per-track extraction now uses the correct mode automatically (GDI vs CUEBIN vs TOC).

Smarter copy and parent handling

  • copy now picks the right default codecs for each image type automatically (HD/DVD → lzma,zlib,huff,flac / CD/GD → cdlz,cdzl,cdfl / laserdisc → avhu), same as chdman.
  • Parent CHDs: hunk size is inherited from the parent when omitted, and mismatched sizes are rejected as expected.

Fixed

Hard disks (createhd / createraw)

  • createhd -i image.img now writes GDDD geometry metadata — output is now byte-identical to chdman (was 51 bytes short).
  • createhd --ident now correctly reads CHS from the ATA IDENTIFY data.
  • Blank hard disks now correctly require -c none (was silently accepting compressed codecs).
  • createhd now validates interactions between -tp, -chs and -size / parent images.
  • createraw now correctly requires --unitsize when no parent is given and validates hunk size (16 B – 1 MiB, multiple of unit size).
  • listtemplates now shows all 17 templates (was missing 4 Quantum Fireball drives).

CD / GD-ROM extraction (extractcd)

  • extractcd now defaults to cooked sectors (2048/2352 bytes, no subcode, audio byte-swapped) — now matches chdman extractcd for all 43 CDs + 3 GD-ROMs. Use --raw to keep 2448-byte raw frames.
  • Library ExtractToDirectory(..., cooked: true) does the same — the default cooked: false is kept for backward compatibility.
  • Large extractions now use a 32 MiB aligned buffer and correct audio byte-swap (CUEBIN always, GDI only for CHD v5+).

DVD

  • createdvd / BuildDvdMetadata now writes an empty DVD tag (length 0) instead of a 0x00 byte — matches chdman.

Metadata

  • addmeta --valuetext no longer adds a trailing NUL (was text+'\0', now text).

CLI — stricter, now matches chdman

  • Unknown options, duplicate options and missing values now error correctly.
  • Each command now only accepts its valid options (e.g. createraw rejects -tp).
  • -isb/-ish/-ib/-ih slicing now correctly rejects mixing bytes and hunks.
  • 10MB with trailing B is now handled, and --size plain numbers are strict.

Diagnostics

  • info --verbose and verify --verbose now show per-codec hunk stats (SELF/PARENT/MINI buckets).
  • Progress now throttles to 0.5 s and errors go to stderr as Error: ....

Docs / Code quality

  • createcd -c cdzl on audio CDs is now documented: container bytes may differ due to FLAC subframe choice, but SHA-1 / verify are identical.
  • Zero build warnings. Added Meziantou.Analyzer to all projects.

Upgrade Notes

  • No API break. Library code keeps compiling.
  • CLI is now stricter. Scripts that passed invalid combos before (e.g. createhd blank with -c zlib, extractcd -tp 1, --splitbin without %t) will now fail — same as chdman. Fix the flags.
  • Cooked vs raw: If you compared ExtractToDirectory output to chdman extractcd, pass cooked: true.

Full Changelog: v1.4.0...v1.4.1

v1.4.0

Choose a tag to compare

@drpetersonfernandes drpetersonfernandes released this 26 Aug 03:03

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

v1.2.0

Choose a tag to compare

@drpetersonfernandes drpetersonfernandes released this 23 Jul 03:01

What's New — CHDSharp v1.2.0

Highlights

  • CD/GD-ROM track (TOC) parsing — Full track layout and sector type information from CHD metadata
  • Internal build consolidation — Centralized versioning and build properties via Directory.Build.props
  • Reproducible builds — Deterministic compilation and embedded SourceLink for debuggable NuGet packages

New Features

CD-ROM & GD-ROM Track Info

New ChdTrackInfo model and ChdTocParser parse the table of contents (TOC) embedded in CHD metadata, providing per-track details:

  • Track number, type (Mode1, Mode2, Audio, etc.)
  • Sector data size and subcode size
  • Pregap, postgap, and padding frame counts
  • GD-ROM support (CHGD/CHGT metadata tags)
  • Start frame offset for locating track data

Supports all metadata tag formats: CHTR/CHT2 (text key-value), CHCD (binary), and CHGD/CHGT (GD-ROM).

var tracks = chd.GetTrackInfo();
foreach (var track in tracks)
{
    Console.WriteLine($"{track.TrackNumber}: {track.GetTypeString()} " +
                      $"{track.Frames} frames, pregap={track.PreGap}");
}

Improved UnitBytes Calculation

UnitBytes property on ChdFile now derives sector size from metadata for all CHD versions:

  • V5 — Reads from header
  • V1–V4 — Detects HDD (512B), CD (2448B), or defaults to hunk size

New Enums

  • ChdTrackType — Matches MAME cdrom.h track types (Mode1, Mode1Raw, Mode2, Mode2Form1, Mode2Form2, Mode2FormMix, Mode2Raw, Audio)
  • ChdSubType — Subcode types (None, Normal, Raw)

Package Improvements

  • Centralized versioning — All 7 projects share version 1.2.0 via Directory.Build.props. Bump once and all projects update.
  • Deterministic builds — <Deterministic>true</Deterministic> enables byte-for-byte reproducible builds
  • Improved CI detection — ContinuousIntegrationBuild now detects GitHub Actions natively
  • Updated release notes — Package metadata accurately reflects v1.2.0 features
  • Stale artifacts removed — Old build artifacts cleaned from repository

Test Suite

  • Track info tests — Validates TOC parsing across all metadata formats and edge cases
  • CLI integration tests — End-to-end tests for the command-line tool
  • Expanded encoder tests — CRC16, SHA1, and Deflate validation in CHDSharpEncoderTest

Breaking Changes

None. All public APIs from v1.1.0 remain compatible.


Upgrading

dotnet add package CHDSharp --version 1.2.0

Full Changelog: v1.1.0...v1.2.0

v1.1.0

Choose a tag to compare

@drpetersonfernandes drpetersonfernandes released this 18 Jul 02:44

New: UnitBytes property on ChdFile

ChdFile now exposes UnitBytes — the unit size used for parent block address translation.

Version Source
V5 Read directly from the CHD header (big-endian uint32 at offset 60)
V1-V4 HDD Derived from GDDD metadata: parses BPS (bytes-per-sector) from the "CYLS:%d,HEADS:%d,SECS:%d,BPS:%d" format
V1-V4 CD/GD-ROM Detects CHCD, CHTR, CHT2, CHGT, CHGD metadata tags → returns 2448 (CD frame size: 2352 data + 96 subcode)
V1-V4 fallback Returns HunkBytes (1:1 mapping)

The V1-V4 derivation logic mirrors libchdr's header_guess_unitbytes() exactly.

Usage

ChdFile.Open("game.chd", out var chd);
using (chd)
{
    Console.WriteLine($"HunkBytes: {chd.HunkBytes}");
    Console.WriteLine($"UnitBytes: {chd.UnitBytes}");
    // For a CD-ROM CHD:    HunkBytes=19584, UnitBytes=2448
    // For a hard disk CHD:  HunkBytes=4096,  UnitBytes=512
    // For a raw image CHD:  HunkBytes=4096,  UnitBytes=4096
}

Internal: refactoring

  • CdFrameSize constant visibility changed from private to internal in CHDReaders.cs (needed by ChdFile.GuessUnitBytes())
  • Pattern matching used for metadata tag checks in GuessUnitBytes()

Version

All assemblies bumped from 1.0.0 to 1.1.0. NuGet package CHDSharp version updated to 1.1.0.

v1.0.0

Choose a tag to compare

@drpetersonfernandes drpetersonfernandes released this 18 Jul 01:01

Initial release of CHDSharp — a fork of RomVault/CHDSharp by Gordon Jefferyes, heavily extended and modernized.

Available on NuGet:

dotnet add package CHDSharp

Targets net8.0, net9.0, and net10.0. Zero native dependencies — every codec is implemented in pure C#.


Highlights

  • Zstd codec support (zstd + cdzs), backed by the managed ZstdSharp.Port
  • V5 parent/child (differential) CHD chains with wrong-parent detection and CheckFileWithParent()
  • Random-access API — ChdFile.Open(), ReadHunk(), Read() (arbitrary byte ranges across hunk boundaries), ReadAllBytes(), EnumerateHunks()
  • Async API — OpenAsync, ReadHunkAsync, ReadAsync, IAsyncDisposable
  • Metadata support — expose game name, disc labels, and other CHD header metadata
  • Comprehensive xUnit test suite with generated test data, cross-checked byte-for-byte against MAME chdman (info, verify, extractraw)
  • New Compressionzero compression type for unallocated hunks in uncompressed V5 CHDs

New Applications

  • CHDSharpCli — verify directories recursively, verify from a path list, random-access self-test, parent/child verification
  • CHDSharpTester — WPF UI for batch testing, with progress status bar, About window, and exit confirmation during runs

API Modernization

  • Published as a proper NuGet package (CHDSharp) with SourceLink, symbols package, and package icon
  • Namespace renamed to CHDSharp; public API renamed to idiomatic PascalCase (Chd, ChdFile, ChdError, ChdResult, …)
  • New TaskCount property (1–64, validated) to configure parallel verification threads
  • New helpers: IsChdFile(), CheckHeader(), ChdResult with IsSuccess, Sha1Hex, and friendly error messages
  • Models and interfaces reorganized into dedicated namespaces; XML documentation added across the public API

Reliability & Hardening

  • Buffer bounds, null, and overflow checks across all codecs and readers
  • ReadByteChecked throws on truncated streams instead of silently mis-reading
  • FLAC BitReader safe lookahead fix
  • Guard against cyclic metadata chains
  • Fixed off-by-one, pointer, and null-check bugs in the codec state (ChdCodecState)
  • Fixed header version check; added cancellation token and proper task cleanup to the parallel decompression queue
  • Fixed compression name display; removed dead code, unused LZMA/FLAC classes, and telemetry

Licensing

  • Licensed under MIT

Special Thanks

Full Changelog: initial release