API Reference
Complete reference for the public API of the CHDSharp package. All types live in the CHDSharp namespace (models in CHDSharp.Models, address helpers in CHDSharp.Utils).
Chd — static class
Entry point for verification, quick checks, and global settings.
| Member | Signature | Description |
|---|---|---|
LoggerFactory |
static ILoggerFactory? |
Set to enable internal logging. See Logging. |
TaskCount |
static int (default 8) |
Number of parallel workers for CheckFile (1–64). Set before calling. |
CheckFile |
static ChdResult CheckFile(Stream s, string filename, bool deepCheck, IProgress<ChdProgress>? progress = null, CancellationToken ct = default) |
Verify a standalone CHD. deepCheck: true decompresses every hunk and validates hashes; false is header-only. Reports progress per hunk when progress is supplied. Throws OperationCanceledException when cancelled. |
CheckFile |
static ChdError CheckFile(Stream, string, bool, out uint? version, out byte[]? sha1, out byte[]? md5, IProgress<ChdProgress>? progress = null, CancellationToken ct = default) |
Out-parameter variant. |
CheckFileWithParent |
static ChdResult CheckFileWithParent(string filename, string? parentFilename, IProgress<ChdProgress>? progress = null, CancellationToken ct = default) |
Verify a (possibly child) CHD, resolving parent references. Pass null for standalone. Single-threaded. |
CheckFileWithParent |
static ChdError CheckFileWithParent(string, string?, out uint?, out byte[]?, out byte[]?, IProgress<ChdProgress>? progress = null, CancellationToken ct = default) |
Out-parameter variant. |
IsChdFile |
static bool IsChdFile(string) / static bool IsChdFile(string, out uint version) |
Quick magic/version sniff. Never throws. |
CheckHeader |
static bool CheckHeader(Stream, out uint length, out uint version) |
Validate signature + version; stream must be at position 0. |
ReadHeader |
static ChdError ReadHeader(string, out ChdHeaderInfo? header) |
Parse the full header DTO from disk without keeping the file open (libchdr chd_read_header parity). |
ReadHeader |
static ChdError ReadHeader(Stream, out ChdHeaderInfo? header) |
Header DTO from an existing seekable stream (stream left open). |
ReadHeaderAsync |
static Task<(ChdError, ChdHeaderInfo?)> ReadHeaderAsync(string) |
Async variant. |
Classify |
static ChdError Classify(string, out string? classification) |
Classify as "cd", "dvd", "hdd", "gd-rom", or null (unknown). |
ChdFile — random-access reader
public sealed class ChdFile : IDisposable, IAsyncDisposable
Open a CHD once, then read hunks or byte ranges on demand. Not thread-safe — serialize all calls on one instance.
Static factory methods
| Overload | Description |
|---|---|
Open(string path, out ChdFile? chd, CancellationToken ct = default) |
Standalone CHD from disk. |
Open(string path, string parentPath, out ChdFile? chd, CancellationToken ct = default) |
Child CHD; the parent is opened internally and owned by the child. |
Open(string path, ChdFile? parent, out ChdFile? chd, CancellationToken ct = default) |
Child with an external parent instance (caller keeps ownership; may be shared). Pass null for standalone. |
Open(Stream stream, bool leaveOpen, out ChdFile? chd, CancellationToken ct = default) |
From any seekable readable stream. |
Open(Stream stream, bool leaveOpen, ChdFile? parent, out ChdFile? chd, CancellationToken ct = default) |
From a stream with an external parent. |
OpenAsync(...) |
Async twins of all five overloads above, each taking an optional trailing CancellationToken. |
All overloads seek from the start. Failure codes: Chderrfilenotfound, Chderrcannotopenfile, Chderrinvalidparameter, Chderrinvalidfile, Chderrreaderror, Chderrrequiresparent, Chderrinvalidparent, Chderrunsupportedversion, Chderrinvaliddata. Cancellation throws OperationCanceledException.
Instance methods
| Method | Signature | Description |
|---|---|---|
ReadHunk |
ChdError ReadHunk(uint hunknum, byte[] buffer, CancellationToken ct = default) |
Decompress one hunk into buffer (≥ HunkBytes). Serves cached hunks when CacheSize > 1. Throws OperationCanceledException when cancelled. |
Read |
ChdError Read(ulong byteOffset, byte[] destination, int destinationOffset, int count, CancellationToken ct = default) |
Read an arbitrary byte range, crossing hunk boundaries. Caches the last hunk. Throws OperationCanceledException when cancelled. |
ReadSector |
ChdError ReadSector(uint lba, byte[] buffer, CancellationToken ct = default) |
Read the 2352-byte sector data at an LBA (CD/GD-ROM only). LBA 0 = the first track’s INDEX 01 (MSF 00:02:00), mapped through the track table: PreGap frames into the image when the pregap is stored physically (metadata PGTYPE:V...), image frame 0 otherwise. Sub-2352 data sizes are zero-padded as stored. Chderrinvaliddata for non-disc images, Chderrinvalidparameter for too-small buffers or out-of-range addresses. |
ReadSectorMsf |
ChdError ReadSectorMsf(byte m, byte s, byte f, byte[] buffer, CancellationToken ct = default) |
Read the 2352-byte sector at a BCD MSF address ((0x00, 0x02, 0x00) = LBA 0). Addresses before 00:02:00 are rejected with Chderrinvalidparameter. |
ReadFrame |
ChdError ReadFrame(uint lba, byte[] buffer, CancellationToken ct = default) |
Read the full 2448-byte frame (2352-byte sector data + 96-byte subcode, zero-filled when unstored) at an LBA. Buffer ≥ UnitBytes. Same mapping and error codes as ReadSector. |
ReadAllBytes |
ChdError ReadAllBytes(out byte[] data, IProgress<ChdProgress>? progress = null, CancellationToken ct = default) |
Decompress the whole image into one array. Reports per hunk when progress is supplied. Chderroutofmemory if the image exceeds 2 GiB. Throws OperationCanceledException when cancelled. |
ConfigureCache |
void ConfigureCache(int maxHunks) |
Set the multi-hunk LRU cache size (decompressed hunks retained). <= 1 disables it (single-slot behaviour). See CacheSize. |
Precache |
ChdError Precache() |
Read the entire compressed file into memory; subsequent hunk reads are served from RAM. Idempotent; restores stream position; Chderroutofmemory for files > 2 GiB, Chderrreaderror on IO failure. |
ReadAllBytes |
ChdError ReadAllBytes(out byte[] data) |
Decompress the whole image into one array. Chderroutofmemory if the image exceeds 2 GiB. |
EnumerateHunks |
IEnumerable<byte[]> EnumerateHunks(IProgress<ChdProgress>? progress = null) |
Yield each decompressed hunk in order. The array is reused — copy it if you need to keep it. Throws InvalidDataException on failure. Reports per hunk when progress is supplied. |
ReadHunkAsync |
Task<ChdError> ReadHunkAsync(uint, byte[], CancellationToken ct = default) |
Async hunk read; cancelled via the token. |
ReadAsync |
Task<ChdError> ReadAsync(ulong, byte[], int, int, CancellationToken ct = default) |
Async byte-range read; cancelled via the token. |
GetMetadata |
ChdError GetMetadata(string? tag, uint index, out ChdMetadataEntry? entry) |
Search metadata by 4-char tag and occurrence index; null/empty tag = wildcard. Returns Chderrmetadatanotfound when absent. |
GenerateCueSheet |
string GenerateCueSheet(string binFileName) |
CUE sheet (single-bin) for CD CHDs. |
GenerateGdiDescriptor |
string GenerateGdiDescriptor(string[] trackFiles) |
GDI descriptor for GD-ROM CHDs. |
ExportToc |
string ExportToc() |
Human-readable TOC dump. |
ExtractToDirectory |
List<string> ExtractToDirectory(string outputDir, string baseFileName, IProgress<ChdProgress>? progress = null, CancellationToken ct = default) |
Extract to files; returns created paths. Throws InvalidDataException on track failures. Reports per hunk when progress is supplied; throws OperationCanceledException when cancelled. |
ExtractToDirectoryWithReporting |
ExtractResult ExtractToDirectoryWithReporting(string outputDir, string baseFileName, IProgress<ChdProgress>? progress = null, CancellationToken ct = default) |
Reporting variant (per-track results, no exceptions). Cancellation still throws OperationCanceledException. |
OpenAsStream |
ChdImageStream OpenAsStream(bool leaveOpen = false) |
Returns a read-only, seekable Stream wrapping the decompressed CHD. Supports Read, ReadAsync, Seek, Position, Length. |
ConfigureReadAhead |
void ConfigureReadAhead(int lookAhead) |
Enable background pre-decompression of the next N hunks. Uses ThreadLocal<ChdCodecState> for thread-safe codec access. |
FlushReadAhead |
void FlushReadAhead() |
Clear stale read-ahead cache entries after seeks. |
Dispose / DisposeAsync |
— | Release the stream (unless leaveOpen) and any internally-owned parent. |
Properties
| Property | Type | Description |
|---|---|---|
Version |
uint |
CHD format version (1–5). |
TotalBytes |
ulong |
Decompressed image size. |
HunkBytes |
uint |
Size of one hunk. |
CacheSize |
int |
Number of decompressed hunks retained by the multi-hunk LRU cache (default 1). Set via ConfigureCache(int). Memory capped at CacheSize * HunkBytes. |
MaxCompressedBlockBytes |
uint |
Max allowed on-disk length of one compressed hunk. Defaults to HunkBytes * 2; a hunk claiming more is rejected with Chderrinvaliddata before allocation (OOM guard). Settable; floors at HunkBytes, set to 0 to reset. |
HunkCount |
uint |
Total number of hunks. |
UnitBytes |
uint |
Unit size for parent-block translation. V5: from header; V1–V4: derived from metadata (GDDD BPS, CD frame 2448, or HunkBytes). |
Sha1 |
byte[]? |
Combined SHA1 (raw data + checksummed metadata). |
RawSha1 |
byte[]? |
SHA1 of the raw image data only. |
Md5 |
byte[]? |
MD5 of the raw image (V1–V3). |
RequiresParent |
bool |
True if this is a differential child. |
IsChild |
bool |
Alias for RequiresParent. |
Tracks |
IReadOnlyList<ChdTrackInfo>? |
CD/GD-ROM track layout; null for non-disc images. |
IsCd |
bool |
CD-ROM track metadata present. |
IsGdRom |
bool |
GD-ROM (Sega Dreamcast) image. |
IsLittleEndianAudio |
bool |
True for legacy GD-ROMs (detected by the CHGT tag / CD_FLAG_GDROMLE) whose CDDA audio tracks are stored little-endian. AUDIO tracks are byte-swapped to big-endian order when extracted. |
IsDvd |
bool |
DVD metadata present. |
IsHdd |
bool |
Hard-disk geometry metadata present (V1/V2: via synthesized GDDD). |
IdentData |
byte[]? |
ATA IDENTIFY DEVICE data (512 bytes) from IDNT metadata. null if not present. |
KeyData |
byte[]? |
Encryption key data from KEY metadata. null if not present. |
PcmciaCisData |
byte[]? |
PCMCIA Card Information Structure from CIS metadata. null if not present. |
Metadata |
IReadOnlyList<ChdMetadataEntry> |
All metadata entries, lazy-loaded. V1/V2 include a synthesized GDDD entry. |
ChdResult — verification result (record)
| Property | Type | Description |
|---|---|---|
Error |
ChdError |
Result code. |
Version |
uint? |
CHD version (1–5). |
Sha1 |
byte[]? |
SHA1 from the header. |
Md5 |
byte[]? |
MD5 from the header. |
IsSuccess |
bool |
Error == Chderrnone. |
Sha1Hex |
string |
Lowercase hex, or "(none)". |
Md5Hex |
string |
Lowercase hex, or "(none)". |
Supports deconstruction: var (err, ver, sha1, md5) = result;
ChdHeaderInfo — full header DTO (record)
Returned by Chd.ReadHeader(...). A snapshot of everything in the CHD header, parsed without opening the file for hunk reads and without keeping a file handle open.
| Property | Type | Description |
|---|---|---|
Length |
uint |
On-disk header length (76 / 80 / 120 / 108 / 124 for V1–V5). |
Version |
uint |
CHD format version (1–5). |
Flags |
uint |
Raw flags field (V1–V4): bit 0 = has parent, bit 1 = writable. Always 0 for V5. |
Compression |
ChdCodec[] |
Codec slots (up to 4 for V5; V1–V4 use slot 0). All None = uncompressed V5. |
HunkBytes |
uint |
Size of one hunk. |
TotalHunks |
uint |
Total number of hunks. |
TotalBytes |
ulong |
Decompressed image size. |
MetaOffset |
ulong |
File offset of the first metadata entry (0 = none). |
MapOffset |
ulong |
File offset of the block map (V5 only; 0 for V1–V4). |
Md5 / ParentMd5 |
byte[]? |
MD5 hashes (V1–V3; null for V4/V5). |
Sha1 / RawSha1 / ParentSha1 |
byte[]? |
SHA1 hashes (V3–V5; null for V1/V2). |
UnitBytes |
uint |
Unit size. V5: from header; V1–V4: derived from metadata (matches ChdFile.UnitBytes). |
UnitCount |
ulong |
ceil(TotalBytes / UnitBytes) (0 if UnitBytes is 0). |
HasParent |
bool |
True if this is a differential child (derived from parent hashes). |
ObsoleteCylinders / ObsoleteHeads / ObsoleteSectors / ObsoleteHunksize |
uint |
Obsolete V1/V2 hard-disk geometry (0 for V3+). |
ChdProgress — long-operation progress (record)
Pass an IProgress<ChdProgress> to Chd.CheckFile, Chd.CheckFileWithParent, ChdFile.ReadAllBytes, ChdFile.EnumerateHunks, or ChdFile.ExtractToDirectory to receive a report after each decompressed hunk. Wrap it in new Progress<ChdProgress>(...) for UI binding or logging.
| Property | Type | Description |
|---|---|---|
CurrentHunk |
long |
Hunks processed so far (1-based; equals TotalHunks when done). |
TotalHunks |
long |
Total hunks in the image. |
BytesProcessed |
long |
Decompressed bytes processed so far. |
TotalBytes |
long |
Total decompressed image size. |
Elapsed |
TimeSpan |
Wall-clock time since the operation started. |
Percent |
double |
CurrentHunk / TotalHunks × 100 (0–100). |
var progress = new Progress<ChdProgress>(p =>
Console.WriteLine($"{p.Percent:F0}% — {p.BytesProcessed:N0}/{p.TotalBytes:N0} bytes ({p.Elapsed.TotalSeconds:F1}s)"));
var result = Chd.CheckFile(File.OpenRead("game.chd"), "game.chd", deepCheck: true, progress);
For Chd.CheckFile(deepCheck: true), reports arrive in hunk order from the internal hashing thread — an IProgress<T> built with new Progress<ChdProgress>(...) marshals them back to the capturing context automatically. All parameters default to null, so existing callers are unaffected.
Cancellation
Every long-running operation accepts an optional trailing CancellationToken (default default) and throws OperationCanceledException when cancellation is requested: Chd.CheckFile, Chd.CheckFileWithParent, ChdFile.Open/OpenAsync (all overloads), ReadHunk/ReadHunkAsync, Read/ReadAsync, ReadAllBytes, and ExtractToDirectory/ExtractToDirectoryWithReporting. Async twins pass the token to Task.Run too, so a pre-cancelled token yields a cancelled task.
For CheckFile(deepCheck: true) the caller token is linked into the verification pipeline’s internal CancellationTokenSource (CreateLinkedTokenSource), so cancellation stops the producer/workers/hasher immediately; the method then throws OperationCanceledException rather than returning a bogus hash-mismatch error over partial data. Cancellation is never swallowed into a ChdError result by extraction — it always propagates as OperationCanceledException.
using var cts = new CancellationTokenSource();
var result = Chd.CheckFile(File.OpenRead("game.chd"), "game.chd", deepCheck: true, cancellationToken: cts.Token);
ChdMetadataEntry — metadata record
public record ChdMetadataEntry(string Tag, byte[] Data)
| Member | Type | Description |
|---|---|---|
Tag |
string |
4-char tag, e.g. "GAME", "DISC", "HARD", "GDDD", "CHT2". |
Data |
byte[] |
Raw payload bytes (ASCII text or binary). |
Flags |
byte (init) |
Entry flags from the header (bit 0 = checksummed). |
IsText |
bool |
True if the data is printable ASCII. |
GetText() |
string |
ASCII text representation (empty for oversized data). |
ToString() |
string |
GAME: gauntlet or TAG: N bytes. |
Equality is based on Tag + Data only (the Flags byte is excluded).
ChdTrackInfo — CD/GD-ROM track (class)
| Property | Type | Description |
|---|---|---|
TrackNumber |
int |
1-based track number. |
TrackType |
ChdTrackType |
Mode1, Mode1Raw, Mode2, Mode2Form1, Mode2Form2, Mode2FormMix, Mode2Raw, Audio. |
SubType |
ChdSubType |
None, Normal, Raw. |
DataSize |
int |
Bytes per sector (2048, 2352, …). |
SubSize |
int |
Subcode bytes per sector (0 or 96). |
Frames |
int |
Frames in the track. |
ExtraFrames |
int |
Padding frames (4-frame alignment). |
PreGap |
int |
Pregap frames (index 00 → 01). |
PostGap |
int |
Postgap frames. |
PreGapType / PreGapSubType |
ChdTrackType / ChdSubType |
Pregap sector format. |
PreGapDataSize / PreGapSubSize |
int |
Pregap sector sizes. |
PadFrames |
int |
GD-ROM pad frames. |
StartFrame |
ulong |
CHD frame offset where the track starts. |
GetTypeString() |
string |
e.g. "MODE1/2048", "AUDIO". |
GetSubTypeString() |
string |
e.g. "RW", "RW_RAW", "NONE". |
CdRomAddress — MSF ↔ LBA conversion (static)
CHDSharp.Utils namespace. Pure math, no dependencies. MSF values are BCD-encoded as found in CD sector headers and drive addressing: 0x02 = 2 minutes, 0x10 = 10 minutes. Per the Red Book, LBA 0 corresponds to MSF 00:02:00 (the 2-second lead-in offset); the Alt variants omit that offset for systems (Sega CD, PC Engine) that address frames relative to the start of the disc data.
| Member | Signature | Description |
|---|---|---|
MsfToLba |
int MsfToLba(byte m, byte s, byte f) |
BCD MSF → LBA, (m*60 + s)*75 + f - 150. Negative for lead-in positions before 00:02:00. |
MsfToLbaAlt |
int MsfToLbaAlt(byte m, byte s, byte f) |
BCD MSF → absolute frame count (no -150). |
LbaToMsf |
(byte m, byte s, byte f) LbaToMsf(int lba) |
LBA → BCD MSF (lba + 150, decompose, pack BCD). |
LbaToMsfAlt |
(byte m, byte s, byte f) LbaToMsfAlt(int lba) |
Frame count → BCD MSF (no +150). |
FramesPerSecond / SecondsPerMinute / PregapFrames |
const int |
75 / 60 / 150. |
Throws ArgumentOutOfRangeException when a byte is not valid BCD (a nibble above 9), when the resulting MSF position would be negative, or when the minute field would exceed 99 (the BCD limit).
using CHDSharp.Utils;
int lba = CdRomAddress.MsfToLba(0x00, 0x02, 0x00); // 0
var (m, s, f) = CdRomAddress.LbaToMsf(8850); // (0x02, 0x00, 0x00)
var (altM, altS, altF) = CdRomAddress.LbaToMsfAlt(150); // (0x00, 0x02, 0x00)
ExtractResult / TrackExtractResult
ExtractResult (record): CreatedFiles (IReadOnlyList<string>), TrackResults (IReadOnlyList<TrackExtractResult>), Error (ChdError), IsCompleteSuccess, HasTrackFailures.
TrackExtractResult (record): TrackNumber, FilePath (string?), Error, IsSuccess.
Enums
ChdCodec — 4-char codec tags
None = 0, Zlib (zlib), Lzma (lzma), Huffman (huff), Flac (flac), Zstd (zstd), Cdzlib (cdzl), Cdlzma (cdlz), Cdflac (cdfl), Cdzstd (cdzs), Avhuff (avhu), Error.
ChdTrackType
Mode1 = 0, Mode1Raw = 1, Mode2 = 2, Mode2Form1 = 3, Mode2Form2 = 4, Mode2FormMix = 5, Mode2Raw = 6, Audio = 7.
ChdSubType
None = 0, Normal = 1, Raw = 2.
CompressionType — per-hunk map entry types
Compressiontype0..3 (codec slots), Compressionnone, Compressionself, Compressionparent, Compressionrlesmall, Compressionrlelarge, Compressionself0/1, Compressionparentself, Compressionparent0/1, Compressionmini, Compressionerror, Compressionzero, Compressiontype2Nd.
ChdError
The complete 29-value error enum — see Error Codes. Every value has a human-readable message via the GetMessage() extension:
ChdError err = ChdFile.Open("missing.chd", out _);
Console.WriteLine(err.GetMessage()); // "File not found"
Extension methods
ChdErrorExtensions.GetMessage(this ChdError) — human-readable error text. ChdSharp also exposes big-endian helpers (BigEndian/EndianHelpers) internally for the test suite.