Class MetadataWriter

Namespace
CHDSharp.Encoder
Assembly
CHDSharpLib.dll

Writes CHD metadata entries (linked list at the end of the file, before the map). The on-disk format mirrors MAME's chd_file::write_metadata (src/lib/util/chd.cpp): each entry is a 16-byte header (tag, flags, 24-bit length, 64-bit next) followed by the payload. The first entry's file offset is stored in the CHD header's metaoffset field.

public static class MetadataWriter
Inheritance
MetadataWriter
Inherited Members

Fields

AvLdMetadataTag

'AVLD' laserdisc VBI metadata tag (big-endian), MAME's AV_LD_METADATA_TAG.

public const uint AvLdMetadataTag = 1096174660

Field Value

uint

AvMetadataTag

'AVAV' A/V metadata tag (big-endian), MAME's AV_METADATA_TAG.

public const uint AvMetadataTag = 1096171862

Field Value

uint

CdRomOldMetadataTag

'CHCD' legacy CD-ROM track metadata tag (big-endian, binary format).

public const uint CdRomOldMetadataTag = 1128809284

Field Value

uint

CdRomTrackMetadata2Tag

'CHT2' CD-ROM track metadata v2 tag (big-endian).

public const uint CdRomTrackMetadata2Tag = 1128813618

Field Value

uint

CdRomTrackMetadataTag

'CHTR' CD-ROM track metadata v1 tag (big-endian, text format, 4 fields).

public const uint CdRomTrackMetadataTag = 1128813650

Field Value

uint

ChdMdflagsChecksum

CHD_MDFLAGS_CHECKSUM: the entry is covered by the combined SHA-1 verification.

public const byte ChdMdflagsChecksum = 1

Field Value

byte

DvdMetadataTag

'DVD ' DVD-ROM metadata tag (big-endian).

public const uint DvdMetadataTag = 1146504224

Field Value

uint

GdRomOldMetadataTag

'CHGT' legacy GD-ROM track metadata tag (big-endian, LE CDDA).

public const uint GdRomOldMetadataTag = 1128810324

Field Value

uint

GdRomTrackMetadataTag

'CHGD' GD-ROM track metadata tag (big-endian).

public const uint GdRomTrackMetadataTag = 1128810308

Field Value

uint

HardDiskMetadataTag

'GDDD' hard-disk geometry metadata tag (big-endian).

public const uint HardDiskMetadataTag = 1195656260

Field Value

uint

IdentMetadataTag

'IDNT' hard disk ATA IDENTIFY DEVICE metadata tag (big-endian).

public const uint IdentMetadataTag = 1229213268

Field Value

uint

KeyMetadataTag

'KEY ' hard disk encryption key metadata tag (big-endian).

public const uint KeyMetadataTag = 1262836000

Field Value

uint

MetadataHeaderSize

The metadata entry header size in bytes.

public const int MetadataHeaderSize = 16

Field Value

int

PcmciaCisMetadataTag

'CIS ' PCMCIA Card Information Structure metadata tag (big-endian).

public const uint PcmciaCisMetadataTag = 1128878880

Field Value

uint

Methods

BuildAvLdMetadata(byte[])

Builds the 'AVLD' laserdisc VBI metadata entry from packed per-frame records (16 bytes each, see MetadataPack(Span<byte>, uint, VbiMetadata)). Matches chdman createld's post-compression write with flags 0 (not covered by the SHA-1).

public static MetadataEntry BuildAvLdMetadata(byte[] packedFrames)

Parameters

packedFrames byte[]

The concatenated per-frame VBI records.

Returns

MetadataEntry

BuildAvMetadata(ulong, uint, uint, bool, uint, uint)

Builds the 'AVAV' A/V metadata entry for a laserdisc image, matching chdman createld and MAME's AV_METADATA_FORMAT: FPS:%d.%06d WIDTH:%d HEIGHT:%d INTERLACED:%d CHANNELS:%d SAMPLERATE:%d (null-terminated, checksummed).

public static MetadataEntry BuildAvMetadata(ulong fpsTimes1Million, uint width, uint height, bool interlaced, uint channels, uint sampleRate)

Parameters

fpsTimes1Million ulong

Frame rate in frames per 1,000,000 seconds.

width uint

Video width in pixels.

height uint

Video height in lines (field height for interlaced sources).

interlaced bool

Whether the source is interlaced.

channels uint

Audio channel count.

sampleRate uint

Audio sample rate in Hz.

Returns

MetadataEntry

BuildCdMetadataEntries(CdToc)

Builds the metadata entries (tag, checksum flag, null-terminated payload) for a CD or GD-ROM table of contents, in track order: 'CHT2' entries for CDs, 'CHGD' entries (with the PAD field) for GD-ROMs.

public static List<MetadataEntry> BuildCdMetadataEntries(CdToc toc)

Parameters

toc CdToc

Returns

List<MetadataEntry>

BuildChd2String(CdTrack)

Builds the CHT2 metadata string for a track, matching MAME's CDROM_TRACK_METADATA2_FORMAT: TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d PREGAP:%d PGTYPE:%s PGSUB:%s POSTGAP:%d. When the track has pregap data (PgDataSize > 0), the pregap type is prefixed with 'V' to indicate the pregap sectors are physically present.

public static string BuildChd2String(CdTrack track)

Parameters

track CdTrack

Returns

string

BuildDvdMetadata()

Builds the 'DVD ' metadata entry for a DVD-ROM image, matching chdman createdvd (chd->write_metadata(DVD_METADATA_TAG, 0, "")). The std::string overload in chd.h:351 passes input.length() + 1, so the payload written for an empty string is exactly one NUL byte (length 1), not an empty payload.

public static MetadataEntry BuildDvdMetadata()

Returns

MetadataEntry

BuildGdRomString(CdTrack)

Builds the GD-ROM metadata string for a track, matching MAME's GDROM_TRACK_METADATA_FORMAT: TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d PAD:%d PREGAP:%d PGTYPE:%s PGSUB:%s POSTGAP:%d.

public static string BuildGdRomString(CdTrack track)

Parameters

track CdTrack

Returns

string

BuildHardDiskMetadata(uint, uint, uint, uint)

Builds the 'GDDD' hard-disk geometry metadata entry with explicit CHS values. Used when a template (HardDiskTemplates) supplies the geometry instead of guessing from the file size. Matches MAME's HARD_DISK_METADATA_FORMAT.

public static MetadataEntry BuildHardDiskMetadata(uint cylinders, uint heads, uint sectors, uint bytesPerSector)

Parameters

cylinders uint

Number of cylinders.

heads uint

Number of heads.

sectors uint

Sectors per track.

bytesPerSector uint

Bytes per sector (BPS).

Returns

MetadataEntry

BuildHardDiskMetadata(ulong, uint)

Builds the 'GDDD' hard-disk geometry metadata entry, matching MAME's HARD_DISK_METADATA_FORMAT ("%u/%u/%u/%u", written by chdman createhd). Uses fixed 16 heads and 63 sectors/track to compute the cylinder count from totalBytes, exactly like MAME.

public static MetadataEntry BuildHardDiskMetadata(ulong totalBytes, uint bytesPerSector)

Parameters

totalBytes ulong

The logical image size in bytes.

bytesPerSector uint

The sector size in bytes (BPS; normally the unit size).

Returns

MetadataEntry

BuildIdentMetadata(byte[])

Builds the 'IDNT' metadata entry for an ATA IDENTIFY DEVICE response (512 bytes). Used by OG Xbox and other platforms that need to preserve the original drive's model, serial, CHS geometry, and firmware revision.

public static MetadataEntry BuildIdentMetadata(byte[] identData)

Parameters

identData byte[]

The 512-byte ATA IDENTIFY DEVICE response data.

Returns

MetadataEntry

Exceptions

ArgumentNullException

identData is null.

ArgumentException

identData is not exactly 512 bytes.

ComputeCombinedSha1(byte[], IEnumerable<MetadataEntry>)

Computes the combined SHA-1 of a compressed CHD: SHA1(rawsha1 ‖ sorted hashes) where each hash is the big-endian 4-byte metadata tag followed by the SHA-1 of the entry payload (checksummed entries only, sorted byte-wise). Matches MAME's compute_overall_sha1 (src/lib/util/chd.cpp) and the CHDSharpLib reader.

public static byte[] ComputeCombinedSha1(byte[] rawSha1, IEnumerable<MetadataEntry> entries)

Parameters

rawSha1 byte[]
entries IEnumerable<MetadataEntry>

Returns

byte[]

GetSubtypeString(int)

Returns the metadata string for a subcode type (MAME's get_subtype_string).

public static string GetSubtypeString(int subtype)

Parameters

subtype int

Returns

string

GetTypeString(int)

Returns the metadata string for a track type (MAME's get_type_string).

public static string GetTypeString(int trackType)

Parameters

trackType int

Returns

string

GuessChs(ulong, uint)

Replicates chdman's guess_chs (chdman.cpp:1119): given a byte count and sector size, finds the smallest sector-count ≥ totalBytes/bps that is expressible as cylinders × heads × sectors, preferring the largest sectors per track (63 down to 2) and the largest heads (16 down to 2). Returns the guessed geometry.

public static MetadataWriter.ChsGeometry GuessChs(ulong totalBytes, uint bytesPerSector)

Parameters

totalBytes ulong
bytesPerSector uint

Returns

MetadataWriter.ChsGeometry

IsLegacyCdMetadata(uint)

Returns true if the tag is a legacy CD/GD-ROM metadata tag (CHCD, CHTR, or CHGT) that should be upgraded during copy.

public static bool IsLegacyCdMetadata(uint tag)

Parameters

tag uint

Returns

bool

IsLegacyGdRomMetadata(uint)

Returns true if the tag is a legacy GD-ROM metadata tag (CHGT) whose CDDA audio is stored in little-endian byte order.

public static bool IsLegacyGdRomMetadata(uint tag)

Parameters

tag uint

Returns

bool

TagFromString(string)

Converts a four-character metadata tag string ("CHT2", "GDDD", ...) to its big-endian Tag value.

public static uint TagFromString(string tag)

Parameters

tag string

The four-character tag.

Returns

uint

Exceptions

ArgumentException

tag is not exactly 4 characters.

WriteCdMetadata(Stream, CdToc)

Appends one CHT2 metadata entry per track at the current stream position, linking them into a forward linked list (each entry's next points at the following entry; the last entry has next = 0).

public static long WriteCdMetadata(Stream stream, CdToc toc)

Parameters

stream Stream

The output stream; entries are appended at the current position.

toc CdToc

The CD table of contents to serialize.

Returns

long

The byte offset of the first metadata entry (for the header's metaoffset).

WriteCdMetadata(Stream, IEnumerable<MetadataEntry>)

Appends the given metadata entries at the current stream position, linking them into a forward linked list (each entry's next points at the following entry; the last entry has next = 0).

public static long WriteCdMetadata(Stream stream, IEnumerable<MetadataEntry> entries)

Parameters

stream Stream

The output stream; entries are appended at the current position.

entries IEnumerable<MetadataEntry>

The metadata entries to write.

Returns

long

The byte offset of the first metadata entry (for the header's metaoffset).