chd

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 7, 2026 License: GPL-3.0 Imports: 14 Imported by: 0

Documentation

Overview

Package chd provides parsing for CHD (Compressed Hunks of Data) disc images. CHD is MAME's compressed disc image format, widely used by RetroArch and other emulators.

Package chd provides parsing for CHD (Compressed Hunks of Data) disc images.

Index

Constants

View Source
const (
	// CodecNone indicates uncompressed data.
	CodecNone uint32 = 0x00000000

	// CodecZlib is the standard zlib codec ("zlib").
	CodecZlib uint32 = 0x7a6c6962

	// CodecLZMA is the LZMA codec ("lzma").
	CodecLZMA uint32 = 0x6c7a6d61

	// CodecHuff is the CHD Huffman codec ("huff").
	CodecHuff uint32 = 0x68756666

	// CodecFLAC is the FLAC audio codec ("flac").
	CodecFLAC uint32 = 0x666c6163

	// CodecZstd is the Zstandard codec ("zstd").
	CodecZstd uint32 = 0x7a737464

	// CodecCDZlib is the CD zlib codec ("cdzl").
	// Compresses CD data sectors with zlib, subchannel with zlib.
	CodecCDZlib uint32 = 0x63647a6c

	// CodecCDLZMA is the CD LZMA codec ("cdlz").
	// Compresses CD data sectors with LZMA, subchannel with zlib.
	CodecCDLZMA uint32 = 0x63646c7a

	// CodecCDFLAC is the CD FLAC codec ("cdfl").
	// Compresses CD audio sectors with FLAC, subchannel with zlib.
	CodecCDFLAC uint32 = 0x6364666c

	// CodecCDZstd is the CD Zstandard codec ("cdzs").
	// Compresses CD data sectors with Zstandard, subchannel with zlib.
	CodecCDZstd uint32 = 0x63647a73
)

Codec tag constants (as 4-byte big-endian integers representing ASCII strings). CD-ROM specific codecs handle both data and subchannel compression.

View Source
const (
	// MaxCompMapLen is the maximum compressed map size (100MB).
	MaxCompMapLen = 100 * 1024 * 1024

	// MaxNumHunks is the maximum number of hunks (10M = ~200GB uncompressed).
	MaxNumHunks = 10_000_000

	// MaxMetadataLen is the maximum metadata entry size (16MB, matches 24-bit limit).
	MaxMetadataLen = 16 * 1024 * 1024

	// MaxNumTracks is the maximum number of tracks (200, generous for any disc).
	MaxNumTracks = 200

	// MaxMetadataEntries is the maximum metadata chain entries (prevents loops).
	MaxMetadataEntries = 1000
)

Allocation limits to prevent DoS from malicious CHD files.

View Source
const (
	HunkCompTypeCodec0   = 0  // Compressed with compressor 0
	HunkCompTypeCodec1   = 1  // Compressed with compressor 1
	HunkCompTypeCodec2   = 2  // Compressed with compressor 2
	HunkCompTypeCodec3   = 3  // Compressed with compressor 3
	HunkCompTypeNone     = 4  // Uncompressed
	HunkCompTypeSelf     = 5  // Reference to another hunk in this CHD
	HunkCompTypeParent   = 6  // Reference to parent CHD
	HunkCompTypeRLESmall = 7  // RLE: repeat last compression type (small count)
	HunkCompTypeRLELarge = 8  // RLE: repeat last compression type (large count)
	HunkCompTypeSelf0    = 9  // Self reference to same hunk as last
	HunkCompTypeSelf1    = 10 // Self reference to last+1
	HunkCompTypeParSelf  = 11 // Parent reference to self
	HunkCompTypePar0     = 12 // Parent reference same as last
	HunkCompTypePar1     = 13 // Parent reference last+1
)

Hunk compression types (V5 map entry types).

View Source
const (
	// MetaTagCHT2 is the CD Track v2 metadata tag ("CHT2")
	MetaTagCHT2 = 0x43485432

	// MetaTagCHCD is the CD metadata tag ("CHCD")
	MetaTagCHCD = 0x43484344

	// MetaTagCHTR is the CD Track v1 metadata tag ("CHTR")
	MetaTagCHTR = 0x43485452

	// MetaTagGDTR is the GD-ROM track metadata tag ("CHGD")
	MetaTagGDTR = 0x43484744
)

Metadata tag constants (as 4-byte big-endian integers)

Variables

View Source
var (
	// ErrInvalidMagic indicates the file does not have a valid CHD magic word.
	ErrInvalidMagic = errors.New("invalid CHD magic: expected MComprHD")

	// ErrInvalidHeader indicates the header structure is invalid.
	ErrInvalidHeader = errors.New("invalid CHD header")

	// ErrUnsupportedVersion indicates an unsupported CHD version.
	ErrUnsupportedVersion = errors.New("unsupported CHD version")

	// ErrUnsupportedCodec indicates an unsupported compression codec.
	ErrUnsupportedCodec = errors.New("unsupported compression codec")

	// ErrInvalidHunk indicates an invalid hunk index.
	ErrInvalidHunk = errors.New("invalid hunk index")

	// ErrDecompressFailed indicates decompression failed.
	ErrDecompressFailed = errors.New("decompression failed")

	// ErrCorruptData indicates data corruption was detected.
	ErrCorruptData = errors.New("data corruption detected")

	// ErrNoTracks indicates no track metadata was found.
	ErrNoTracks = errors.New("no track metadata found")

	// ErrInvalidMetadata indicates invalid metadata format.
	ErrInvalidMetadata = errors.New("invalid metadata format")
)

Common errors for CHD parsing.

Functions

func IsCDCodec

func IsCDCodec(tag uint32) bool

IsCDCodec returns true if the codec tag is a CD-ROM specific codec.

func RegisterCodec

func RegisterCodec(tag uint32, factory func() Codec)

RegisterCodec registers a codec factory for the given tag.

Types

type CDCodec

type CDCodec interface {
	Codec

	// DecompressCD decompresses CD-ROM data with sector/subchannel handling.
	// hunkBytes is the total size of a decompressed hunk.
	// frames is the number of CD frames (sectors) in the hunk.
	DecompressCD(dst, src []byte, hunkBytes, frames int) (int, error)
}

CDCodec decompresses CD-ROM specific hunk data. CD codecs handle the separation of sector data and subchannel data.

type CHD

type CHD struct {
	// contains filtered or unexported fields
}

CHD represents a CHD (Compressed Hunks of Data) disc image.

func Open

func Open(path string) (*CHD, error)

Open opens a CHD file and parses its header and metadata.

func (*CHD) Close

func (c *CHD) Close() error

Close closes the CHD file.

func (*CHD) DataTrackSectorReader

func (c *CHD) DataTrackSectorReader() io.ReaderAt

DataTrackSectorReader returns an io.ReaderAt for the first data track, providing 2048-byte logical sectors. This is essential for discs like Neo Geo CD that have audio tracks before the data track.

func (*CHD) DataTrackSize

func (c *CHD) DataTrackSize() int64

DataTrackSize returns the logical size of the first data track in bytes. For ISO9660 parsing, this is the size in 2048-byte sectors.

func (*CHD) FirstDataTrackOffset

func (c *CHD) FirstDataTrackOffset() int64

FirstDataTrackOffset returns the byte offset to the first data track. This is useful for reading disc headers for Sega Saturn/CD identification.

func (*CHD) Header

func (c *CHD) Header() *Header

Header returns the parsed CHD header.

func (*CHD) RawSectorReader

func (c *CHD) RawSectorReader() io.ReaderAt

RawSectorReader returns an io.ReaderAt that provides access to raw 2352-byte sectors. This is useful for reading disc headers that may be at the start of raw sector data.

func (*CHD) SectorReader

func (c *CHD) SectorReader() io.ReaderAt

SectorReader returns an io.ReaderAt that provides access to decompressed sector data with 2048-byte logical sectors (Mode1/Mode2 data portion only). This is suitable for ISO9660 filesystem parsing. Note: For multi-track CDs with audio tracks first, use DataTrackSectorReader() instead.

func (*CHD) Size

func (c *CHD) Size() int64

Size returns the total logical size (uncompressed) of the CHD data.

func (*CHD) Tracks

func (c *CHD) Tracks() []Track

Tracks returns the parsed track information.

type Codec

type Codec interface {
	// Decompress decompresses src into dst.
	// dst must be pre-allocated to the expected decompressed size.
	// Returns the number of bytes written to dst.
	Decompress(dst, src []byte) (int, error)
}

Codec decompresses CHD hunk data.

func GetCodec

func GetCodec(tag uint32) (Codec, error)

GetCodec returns a codec instance for the given tag.

type Header struct {
	Magic        [8]byte   // "MComprHD"
	HeaderSize   uint32    // Header length in bytes
	Version      uint32    // CHD version (3, 4, or 5)
	Compressors  [4]uint32 // Compression codec tags (V5)
	LogicalBytes uint64    // Total uncompressed size
	MapOffset    uint64    // Offset to hunk map
	MetaOffset   uint64    // Offset to metadata
	HunkBytes    uint32    // Bytes per hunk
	UnitBytes    uint32    // Bytes per unit (sector size)
	RawSHA1      [20]byte  // SHA1 of raw data
	SHA1         [20]byte  // SHA1 of raw + metadata
	ParentSHA1   [20]byte  // Parent SHA1 (for delta CHDs)

	// V3/V4 specific fields
	Flags       uint32 // V3/V4 flags
	Compression uint32 // V3/V4 compression type
	TotalHunks  uint32 // V3/V4 total number of hunks
}

Header represents a CHD file header. This struct supports V5 format (current standard) with fields for earlier versions.

func (*Header) IsCompressed

func (h *Header) IsCompressed() bool

IsCompressed returns true if the CHD uses compression.

func (*Header) NumHunks

func (h *Header) NumHunks() uint32

NumHunks returns the total number of hunks in the CHD file.

type HunkMap

type HunkMap struct {
	// contains filtered or unexported fields
}

HunkMap manages the hunk map and caching for a CHD file.

func NewHunkMap

func NewHunkMap(reader io.ReaderAt, header *Header) (*HunkMap, error)

NewHunkMap creates a new hunk map from the CHD header and reader.

func (*HunkMap) HunkBytes

func (hm *HunkMap) HunkBytes() uint32

HunkBytes returns the size of each hunk in bytes.

func (*HunkMap) NumHunks

func (hm *HunkMap) NumHunks() uint32

NumHunks returns the total number of hunks.

func (*HunkMap) ReadHunk

func (hm *HunkMap) ReadHunk(index uint32) ([]byte, error)

ReadHunk reads and decompresses a hunk by index.

type HunkMapEntry

type HunkMapEntry struct {
	Offset     uint64
	CompLength uint32
	CRC16      uint16
	CompType   uint8
}

HunkMapEntry represents a single entry in the V5 hunk map.

type Track

type Track struct {
	Type       string
	SubType    string
	Number     int
	Frames     int
	Pregap     int
	Postgap    int
	DataSize   int
	SubSize    int
	StartFrame int
}

Track represents a CD track in the CHD file.

func (*Track) IsDataTrack

func (t *Track) IsDataTrack() bool

IsDataTrack returns true if this is a data track (not audio).

func (*Track) SectorSize

func (t *Track) SectorSize() int

SectorSize returns the total size of each sector including subchannel data.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL