-
Notifications
You must be signed in to change notification settings - Fork 0
getting started
This page walks through installing CHDSharp, writing your first program, and using the bundled command-line tool.
dotnet add package CHDSharpor via the Package Manager Console:
Install-Package CHDSharpThe package targets net8.0, net9.0, and net10.0 and has no native dependencies. The only runtime dependency is ZstdSharp.Port (a pure-C# Zstd decompressor); every other codec is implemented from scratch in managed code.
git clone https://github.com/purelogiccode/CHDSharp.git
cd CHDSharp
dotnet build -c ReleaseSee Building for the full build, pack, and publish workflow.
The two central types are:
-
Chd— a static class for verification and quick checks. -
ChdFile— an instance-based random-access reader.
using CHDSharp;
using CHDSharp.Models;
// 1. Is this even a CHD?
if (!Chd.IsChdFile("game.chd", out uint version))
{
Console.WriteLine("Not a CHD file");
return;
}
Console.WriteLine($"Detected CHD V{version}");
// 2. Deep verification: decompress every hunk, compare SHA1/MD5.
using var stream = File.OpenRead("game.chd");
var result = Chd.CheckFile(stream, "game.chd", deepCheck: true);
Console.WriteLine(result.IsSuccess
? $"OK — V{result.Version}, SHA1: {result.Sha1Hex}"
: $"FAILED — {result.Error.GetMessage()}");
// 3. Random access: open once, read on demand.
var err = ChdFile.Open("game.chd", out var chd);
if (err != ChdError.Chderrnone)
{
Console.WriteLine($"Open failed: {err.GetMessage()}");
return;
}
using (chd)
{
// Metadata (game name, disc label, ...)
foreach (var meta in chd.Metadata)
Console.WriteLine(meta); // e.g. "GAME: gauntlet"
// A single decompressed hunk
var hunk = new byte[chd.HunkBytes];
chd.ReadHunk(0, hunk);
// An arbitrary byte range (crosses hunk boundaries automatically)
var buf = new byte[4096];
chd.Read(byteOffset: 1_000_000, buf, 0, buf.Length);
// The whole image in one shot
chd.ReadAllBytes(out var image);
}Thread safety: a
ChdFileinstance is not thread-safe — it seeks a shared stream and mutates shared buffers. Serialize all calls on one instance. Multiple instances over separate streams can be used in parallel.
Every blocking operation has an async twin:
var (err, chd) = await ChdFile.OpenAsync("game.chd");
if (err != ChdError.Chderrnone) return;
await using (chd)
{
var hunk = new byte[chd.HunkBytes];
await chd.ReadHunkAsync(0, hunk);
var buf = new byte[1024];
await chd.ReadAsync(0x10000, buf, 0, buf.Length);
}Async overloads exist for all Open variants, including the parent-aware ones:
// Standalone
await ChdFile.OpenAsync("game.chd");
// Child with parent path
await ChdFile.OpenAsync("child.chd", "parent.chd");
// Child with an already-open parent instance
await ChdFile.OpenAsync("child.chd", parent);
// From a stream
await ChdFile.OpenAsync(stream, leaveOpen: true);
// From a stream with a parent
await ChdFile.OpenAsync(stream, leaveOpen: true, parent);CHDSharp parses the CD track layout (TOC) stored in the metadata and can generate standard descriptor files:
var err = ChdFile.Open("game.chd", out var chd);
using (chd)
{
if (chd.IsCd)
{
// Track layout
foreach (var track in chd.Tracks!)
Console.WriteLine($"Track {track.TrackNumber}: {track.GetTypeString()} " +
$"{track.Frames} frames, pregap {track.PreGap}");
// CUE sheet for burning/emulation
var cue = chd.GenerateCueSheet("game.bin");
File.WriteAllText("game.cue", cue);
}
else if (chd.IsGdRom)
{
var gdi = chd.GenerateGdiDescriptor(["track01.bin", "track02.bin"]);
File.WriteAllText("game.gdi", gdi);
}
// One-call extraction
var created = chd.ExtractToDirectory("out", "game");
Console.WriteLine(string.Join("\n", created));
}See Extraction for details.
CHDSharpCli is a small console app that exercises the library end to end. It is useful both as a verification tool and as a reference for calling the API.
# Verify all .chd files in one or more directories (recursive)
CHDSharpCli D:\CHD
# Verify every path listed in a text file
CHDSharpCli --list chd_paths.txt
# Random-access self-test on a single CHD
CHDSharpCli --random game.chd
# Verify a child CHD against its parent
CHDSharpCli --parent child.chd parent.chd
# Print the table of contents of a CD/GD-ROM CHD
CHDSharpCli --toc game.chd
# Generate a CUE sheet
CHDSharpCli --cue game.chd
# Classify the media type
CHDSharpCli --classify game.chdRun CHDSharpCli --help for the full usage text.
- Read the API Reference for every member.
- Learn how the format works in the CHD Format Reference.
- Understand verification semantics in Verification.
- Handle differential CHDs with Parent/Child CHDs.
CHDSharp
Format & internals
API & usage
Operations
Writing CHDs
Reference