Skip to content

getting started

Peterson Fernandes edited this page Aug 19, 2026 · 1 revision

Getting Started

This page walks through installing CHDSharp, writing your first program, and using the bundled command-line tool.


1. Installation

NuGet

dotnet add package CHDSharp

or via the Package Manager Console:

Install-Package CHDSharp

The 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.

From source

git clone https://github.com/purelogiccode/CHDSharp.git
cd CHDSharp
dotnet build -c Release

See Building for the full build, pack, and publish workflow.


2. First program

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 ChdFile instance 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.


3. Async usage

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);

4. Working with CD/GD-ROM images

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.


5. The CLI tool (CHDSharpCli)

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.chd

Run CHDSharpCli --help for the full usage text.


6. Next steps

Clone this wiki locally