Imported from sadnescity/psx-spx-claude-plugin (
skills/cdrom-file-disc-images/SKILL.md). Install upstream withnpx skills add sadnescity/psx-spx-claude-plugin --skill cdrom-file-disc-images. Copyright stays with the author.
CDROM Disk Images CCD/IMG/SUB (CloneCD)
File.IMG - 2352 (930h) bytes per sector
Contains the sector data, recorded at 930h bytes per sector. Unknown if other sizes are also used/supported (like 800h bytes/sector, or even images with mixed sizes of 800h and 930h for different tracks).
File.SUB - 96 (60h) bytes per sector (subchannel P..W with 96 bits each)
Contains subchannel data, recorded at 60h bytes per sector.
00h..0Bh 12 Subchannel P (Pause-bits, usually all set, or all cleared)
0Ch..17h 12 Subchannel Q (ADR/Control, custom info, CRC-16-CCITT)
18h..5Fh .. Subchannel R..W (usually zero) (can be used for CD-TEXT)
Optionally, the .SUB file can be omitted (it's needed only for discs with non-standard subchannel data, such like copy-protected games). And, some CloneCD disc images are bundled with an empty 0-byte .SUB file (which is about same as completely omitting the .SUB file).
File.CCD - Lead-in info in text format
Contains Lead-in info in ASCII text format. Lines should be terminated by 0Dh,0Ah. The overall CCD filestructure is:
[CloneCD] ;File ID and version
[Disc] ;Overall Disc info
[CDText] ;CD-TEXT (included only if present)
[Session N] ;Session(s) (numbered 1 and up)
[Entry N] ;Lead-in entries (numbered 0..."TocEntries-1")
[TRACK N] ;Track info (numbered 1 and up)
Read on below for details on the separate sections.
[CloneCD]
Version=3 ;-version (usually 3) (rarely 2)
[Disc]
TocEntries=4 ;-number of [Entry N] fields (lead-in info blocks)
Sessions=1 ;-number of sessions (usually 1)
DataTracksScrambled=0 ;-unknown purpose (usually 0)
CDTextLength=0 ;-total size of 18-byte CD-TEXT chunks (usually 0)
CATALOG=NNNNNNNNNNNNN ;-13-digit EAN-13 barcode (included only if present)
[CDText]
Entries=N ;number of following entries (CDTextLength/18) (not /16)
Entry 0=80 00 NN NN NN NN NN NN NN NN NN NN NN NN NN NN ;entry 0
Entry 1=80 NN NN NN NN NN NN NN NN NN NN NN NN NN NN NN ;entry 1
...
Entry XX=8f NN NN NN NN NN NN NN NN NN NN NN NN NN NN NN ;entry N-1
Note: Each entry contains 16 bytes (ie. "18-byte CD-TEXT" with CRC excluded)
"NN NN NN.." consists of 2-digit lowercase HEX numbers (without leading "0x")
[Session 1]
PreGapMode=2 ;-unknown purpose (usually 1 or 2) (or 0)
PreGapSubC=1 ;-unknown purpose (usually 0 or 1)
Above are unknown, PreGapMode might be 0=Audio, 1=Mode1, 2=Mode2 for pregap, though unknown for which pregap(s) of which track(s), presumably for first track?
[Entry 0]
[Entry 0..2] are usually containing Point A0h..A2h info. [Entry 3..N] are usually TOC info for Track 1 and up.
Session=1 ;-session number that this entry belongs to (usually 1)
Point=0xa0 ;-point (0..63h=Track, non-BCD!) (A0h..XXh=specials) Q2
ADR=0x01 ;-lower 4bit of ADR/Control (usually 1) Q0.lo
Control=0x04 ;-upper 4bit of ADR/Control (eg. 0=audio, 4=data) Q0.hi
TrackNo=0 ;-usually/always 0 (as [Entry N]'s are in Lead-in) Q1
AMin=0 ;\current MSF address Q3
ASec=0 ; (dummy zero values) (actual content Q4
AFrame=0 ; would be current lead-in position) Q5
ALBA=-150 ;/ALBA=((AMin*60+ASec)*75+AFrame)-PreGapSize
Zero=0 ;-probably reserved byte from Q channel Q6
PMin=1 ;\referenced MSF address (non-BCD!), for certain Q7
PSec=32 ; Point's, PMin may contain a Track number, and PSec Q8
PFrame=0 ; the disc type value (that without non-BCD-glitch) Q9
PLBA=6750 ;/PLBA=((PMin*60+PSec)*75+PFrame)-PreGapSize
[TRACK 1] ;-track number (non-BCD) (1..99)
MODE=2 ;-mode (0=Audio, 1=Mode1, 2=Mode2)
ISRC=XXXXXNNNNNNN ;-12-letter/digit ISRC code (included only if present)
INDEX 0=N ;-1st sector with index 0, missing EVEN if any?
INDEX 1=N ;-1st sector with index 1, usually same as track's PLBA
INDEX 2=N ;-1st sector with index 2, if any
etc.
Missing Sectors & Sector Size
The .CCD file doesn't define the "PreGapSize" (the number of missing sectors at begin of first track). It seems to be simply constant "PreGapSize=150". Unless one is supposed to calculate it as "PreGapSize=((PMin*60+PSec)*75+PFrame)-PLBA". The SectorSize seems to be also constant, "SectorSize=930h".
Non-BCD Caution
All Min/Sec/Frame/Track/Index values are expressed in non-BCD, ie. they must be converted to BCD to get the correct values (as how they are stored on real CDs). Exceptions are cases where those bytes have other meanings: For example, "PSec=32" does normally mean BcdSecond=32h, but for Point A0h it would mean DiscType=20h=CD-ROM-XA). The Point value is also special, it is expressed in hex (0xNN), but nonetheless it is non-BCD, ie. Point 1..99 are specified as 0x01..0x63, whilst, Point A0h..FFh are specified as such (ie. as 0xA0..0xFF).
Versions
Version=1 doesn't seem to exist (or it is very rare). Version=2 is quite rare, and it seems to lack the [TRACK N] entries (meaning that there is no MODE and INDEX information, except that the INDEX 1 location can be assumed to be same as PLBA). Version=3 is most common, this version includes [TRACK N] entries, but often only with INDEX=1 (and up, if more indices), but without INDEX 0 (on Track 1 it's probably missing due to pregap, on further Tracks it's missing without reason) (so, only ways to reproduce INDEX=0 would be to guess it being located 2 seconds before INDEX=1, or, to use the information from the separate .SUB file, if that file is present; note: presence of index 0 is absolutely required for some games like PSX Tomb Raider 2).
Entry & Points & Sessions
The [Entry N] fields are usually containing Point A0h,A1h,A2h, followed by Point 1..N (for N tracks). For multiple sessions: The session is terminated by Point B0h,C0h. The next session does then contain Point A0h,A1h,A2h, and Point N+1..X (for further tracks). The INDEX values in the [TRACK N] entries are originated at the begin of the corresponding session, whilst PLBA values in [Entry N] entries are always originated at the begin of the disk.
CDROM Disk Images CDI (DiscJuggler)
Overall Format
Sector Data (sector 00:00:00 and up) ;-body
Number of Sessions (1 byte) <--- located at "Filesize-Footersize"
Session Block for 1st session (15 bytes) ;\
nnn-byte info for 1st track ; 1st session
nnn-byte info for 2nd track (if any) ;
etc. ;/
Session Block for 2nd session (15 bytes) ;\
nnn-byte info for 1st track ; 2nd session (if any)
nnn-byte info for 2nd track (if any) ;
etc. ;/
etc. ;-further sessions (if any)
Session Block for no-more-sessions (15 bytes) ;-end marker
nnn-byte Disc Info Block ;-general disc info
Entrypoint (4 bytes) <--- located at "Filesize-4"
Sector Data
Contains Sector Data for sector 00:00:00 and up (ie. all sectors are stored in the file, there are no missing "pregap" sectors). Sector Size can be 800h..990h bytes/sector (sector size may vary per track).
Number of Sessions (1 byte)
00h 1 Number of Sessions (usually 1)
Session Block (15-bytes)
00h 1 Unknown (00h)
01h 1 Number of Tracks in session (01h..63h) (or 00h=No More Sessions)
02h 7 Unknown (00h-filled)
09h 1 Unknown (01h)
0Ah 3 Unknown (00h-filled)
0Dh 2 Unknown (FFh,FFh)
Track/Disc Header (30h+F bytes) (used in Track Blocks and Disc Info Block)
00h 12 Unknown (FFh,FFh,00h,00h,01h,00h,00h,00h,FFh,FFh,FFh,FFh)
0Ch 3 Unknown (DAh,0Ah,D5h or 64h,05h,2Ah) (random/id/chksum?)
0Fh 1 Total Number of Tracks on Disc (00h..63h) (non-BCD)
10h 1 Length of below Path/Filename (F)
11h (F) Full Path/Filename (eg. "C:\folder\file.cdi")
11h+F 11 Unknown (00h-filled)
1Ch+F 1 Unknown (02h)
1Dh+F 10 Unknown (00h-filled)
27h+F 1 Unknown (80h)
28h+F 4 Unknown (00057E40h) (=360000 decimal) (disc capacity 80 minutes?)
2Ch+F 2 Unknown (00h,00h)
2Eh+F 2 Medium Type (0098h=CD-ROM, 0038h=DVD-ROM)
Track Block (E4h+F+I+T bytes)
00h 30h+F Track/Disc Header (see above)
30h+F 02h Number of Indices (usually 0002h) (I=Num*4)
32h+F (I) 32bit Lengths (per index) (eg. 00000096h,00007044h)
32h+FI 04h Number of CD-Text blocks (usually 0) (T=Num*18+VariableLen's)
36h+FI (T) CD-Text (if any) (see "mirage_parser_cdi_parse_cdtext")
36h+FIT 02h Unknown (00h,00h)
38h+FIT 01h Track Mode (0=Audio, 1=Mode1, 2=Mode2/Mixed)
39h+FIT 07h Unknown (00h,00h,00h,00h,00h,00h,00h)
40h+FIT 04h Session Number (starting at 0) (usually 00h)
44h+FIT 04h Track Number (non-BCD, starting at 0) (00h..62h)
48h+FIT 04h Track Start Address (eg. 00000000h)
4Ch+FIT 04h Track Length (eg. 000070DAh)
50h+FIT 0Ch Unknown (00h-filled)
5Ch+FIT 04h Unknown (00000000h or 00000001h)
60h+FIT 04h read_mode (0..4)
0: Mode1, 800h, 2048
1: Mode2, 920h, 2336
2: Audio, 930h, 2352
3: Raw+PQ, 940h, 2352+16 non-interleaved (P=only 1bit)
4: Raw+PQRSTUVW, 990h, 2352+96 interleaved
64h+FIT 4 Control (Upper 4bit of ADR/Control, eg. 00000004h=Data)
68h+FIT 1 Unknown (00h)
69h+FIT 4 Track Length (eg. 000070DAh) (same as above)
6Dh+FIT 4 Unknown (00h,00h,00h,00h)
71h+FIT 12 ISRC Code 12-letter/digit (ASCII?) string (00h-filled if none)
7Dh+FIT 4 ISRC Valid Flag (0=None, Other?=Yes?)
81h+FIT 1 Unknown (00h)
82h+FIT 8 Unknown (FFh,FFh,FFh,FFh,FFh,FFh,FFh,FFh)
8Ah+FIT 4 Unknown (00000001h)
8Eh+FIT 4 Unknown (00000080h)
92h+FIT 4 Unknown (00000002h) (guess: maybe audio num channels??)
96h+FIT 4 Unknown (00000010h) (guess: maybe audio bits/sample??)
9Ah+FIT 4 Unknown (0000AC44h) (44100 decimal, ie. audio sample rate?)
9Eh+FIT 2Ah Unknown (00h-filled)
C8h+FIT 4 Unknown (FFh,FFh,FFh,FFh)
CCh+FIT 12 Unknown (00h-filled)
D8h+FIT 1 session_type ONLY if last track of a session (else 0)
(0=Audio/CD-DA, 1=Mode1/CD-ROM, 2=Mode2/CD-XA)
D9h+FIT 5 Unknown (00h-filled)
DEh+FIT 1 Not Last Track of Session Flag (0=Last Track, 1=Not Last)
DFh+FIT 1 Unknown (00h)
E0h+FIT 4 address for last track of a session? (otherwise 00,00,FF,FF)
Disc Info Block (5Fh+F+V+T bytes)
00h 30h+F Track/Disc Header (see above)
30h+F 4 Disc Size (total number of sectors)
34h+F 1 Volume ID Length (V) ;\from Primary Volume Descriptor[28h..47h]
35h+F (V) Volume ID String ;/(ISO Data discs) (unknown for Audio)
35h+FV 1 Unknown (00h)
36h+FV 4 Unknown (01h,00h,00h,00h)
3Ah+FV 4 Unknown (01h,00h,00h,00h)
3Eh+FV 13 EAN-13 Code 13-digit (ASCII?) string (00h-filled if none)
4Bh+FV 4 EAN-13 Valid Flag (0=None, Other?=Yes?)
4Fh+FV 4 CD-Text Length in bytes (T=Num*1)
53h+FV (T) CD-Text (for Lead-in) (probably 18-byte units?)
53h+FVT 8 Unknown (00h-filled)
5Bh+FVT 4 Unknown (06h,00h,00h,80h)
Entrypoint (4 bytes) (located at "Filesize-4")
00h 4 Footer Size in bytes
CDROM Disk Images CUE/BIN/CDT (Cdrwin)
.CUE/.BIN (CDRWIN)
CDRWIN stores disk images in two separate files. The .BIN file contains the raw disk image, starting at sector 00:02:00, with 930h bytes per sector, but without any TOC or subchannel information. The .CUE file contains additional information about the separate track(s) on the disk, in ASCII format, for example:
FILE "PATH\FILENAME.BIN" BINARY
TRACK 01 MODE2/2352
INDEX 01 00:00:00 ;real address = 00:02:00 (+2 seconds)
TRACK 02 AUDIO
PREGAP 00:02:00 ;two missing seconds (NOT stored in .BIN)
INDEX 01 08:09:29 ;real address = 08:13:29 (+2 seconds +pregap)
TRACK 03 AUDIO
INDEX 00 14:00:29 ;real address = 14:04:29 (+2 seconds +pregap)
INDEX 01 14:02:29 ;real address = 14:06:29 (+2 seconds +pregap)
TRACK 04 AUDIO
INDEX 00 18:30:20 ;real address = 18:34:20 (+2 seconds +pregap)
INDEX 01 18:32:20 ;real address = 18:36:20 (+2 seconds +pregap)
The .BIN file does not contain ALL sectors, as said above, the first 2 seconds are not stored in the .BIN file. Moreover, there may be missing sectors somewhere in the middle of the file (indicated as PREGAP in the .CUE file; PREGAPs are usually found between Data and Audio Tracks). The MM:SS:FF values in the .CUE file are logical addresses in the .BIN file, rather than physical addresses on real CDROMs. To convert the .CUE values back to real addresses, add 2 seconds to all MM:SS:FF addresses (to compensate the missing first 2 seconds), and, if the .CUE contains a PREGAP, then the pregap value must be additionally added to all following MM:SS:FF addresses. The end address of the last track is not stored in the .CUE, instead, it can be only calculated by converting the .BIN filesize to MM:SS:FF format and adding 2 seconds (plus any PREGAP values) to it.
FILE <filename> BINARY|MOTOTOLA..or..MOTOROLA?|AIFF|WAVE|MP3
(must appear before any other commands, except CATALOG)
(uh, may also appear before further tracks)
FLAGS DCP 4CH PRE SCMS
INDEX NN MM:SS:FF
TRACK NN datatype
AUDIO ;930h ;bytes 000h..92Fh
CDG ;? ;?
MODE1/2048 ;800h ;bytes 010h..80Fh
MODE1/2352 ;930h ;bytes 000h..92Fh
MODE2/2336 ;920h ;bytes 010h..92Fh
MODE2/2352 ;930h ;bytes 000h..92Fh
CDI/2336 ;920h ;?
CDI/2352 ;930h ;bytes 000h..92Fh
PREGAP MM:SS:FF
POSTGAP MM:SS:FF
Duration of silence at the begin (PREGAP) or end (POSTGAP) of a track. Even if it isn't specified, the first track will always have a 2-second pregap. The gaps are NOT stored in the BIN file.
REM comment
Allows to insert comments/remarks (which are usually ignored). Some third-party tools are mis-using REM to define additional information.
CATALOG 1234567890123
ISRC ABCDE1234567
(ISRC must be after TRACK, and before INDEX)
PERFORMER "The Band"
SONGWRITER "The Writer"
TITLE "The Title"
These entries allow to define basic CD-Text info directly in the .CUE file. Some third-party utilites allow to define additional CD-Text info via REM lines, eg. "REM GENRE Rock". Alternately, more complex CD-Text data can be stored in a separate .CDT file.
CDTEXTFILE "C:\LONG FILENAME.CDT"
Specifies an optional file which may contain CD-TEXT. The .CDT file consists of raw 18-byte CD-TEXT fragments (which may include any type of information, including exotic one's like a "Message" from the producer). For whatever reason, there's a 00h-byte appended at the end of the file. Alternately to the .CDT file, the less exotic types of CD-TEXT can be defined by PERFORMER, TITLE, and SONGWRITER commands in the .CUE file.
Missing
Unknown if newer CUE/BIN versions do also support subchannel data.
Malformed .CUE files
Some .CCD files are bundled with uncommon/corrupted .CUE files, with entries as so:
TRACK 1 MODE2/2352 ;three spaces indent, and 1-digit track
INDEX 1 00:00:00 ;three spaces indent, and 1-digit index
Normally, that should look as so:
TRACK 01 MODE2/2352 ;two spaces indent, and 2-digit track
INDEX 01 00:00:00 ;four spaces indent, and 2-digit index
The purpose of the malformed .CUE might be unsuccessful compatibility, or tricking people into thinking that .CCD works better than .CUE.
CDROM Disk Images MDS/MDF (Alcohol 120%)
File.MDF - Contains sector data (optionally with sub-channel data)
Contains the sector data, recorded at 800h..930h bytes per sector, optionally followed by 60h bytes subchannel data (appended at the end of each sector). The stuff seems to be start on 00:02:00 (ie. the first 150 sectors are missing; at least it is like so when "Session Start Sector" is -150). The subchannel data (if present) consists of 8 subchannels, stored in 96 bytes (each byte containing one bit per subchannel).
Bit7..0 = Subchannel P..W (in that order, eg. Bit6=Subchannel Q)
The 96 bits (per subchannel) can be translated to bytes, as so:
1st..8th bit = Bit7..Bit0 of 1st byte (in that order, ie. MSB/Bit7 first)
9st..16th bit = Bit7..Bit0 of 2nd byte ("")
17th.. = etc.
File.MDS - Contains disc/lead-in info (in binary format)
An MDS file's structure consists of the following stuff ...
Header (58h bytes)
Session block(s) (usually one 18h byte entry)
Data blocks (N*50h bytes)
Index blocks (usually N*8 bytes)
Filename blocks(s) (usually one 10h byte entry)
Filename string(s) (usually one 6 byte string)
Read error(s) (usually none such)
Header (58h bytes)
00h 16 File ID ("MEDIA DESCRIPTOR")
10h 2 Unknown (01h,03h or 01h,04h or 01h,05h) (Fileformat version?)
12h 2 Media Type (0=CD-ROM, 1=CD-R, 2=CD-RW, 10h=DVD-ROM, 12h=DCD-R)
14h 2 Number of sessions (usually 1)
16h 4 Unknown (02h,00h,00h,00h)
1Ah 2 Zero (for DVD: Length of BCA data)
1Ch 8 Zero
24h 4 Zero (for DVD: Offset to BCA data)
28h 18h Zero
40h 4 Zero (for DVD: Offset to Disc Structures) (from begin of .MDS file)
44h 0Ch Zero
50h 4 Offset to First Session-Block (usually 58h) (from begin of .MDS file)
54h 4 Offset to Read errors (usually 0=None) (from begin of .MDS file)
Session-Blocks (18h bytes)
00h 4 Session Start Sector (starting at FFFFFF6Ah=-150 in first session)
04h 4 Session End Sector (XXX plus 150 ?)
08h 2 Session number (starting at 1) (non-BCD)
0Ah 1 Number of Data Blocks with any Point value (Total Data Blocks)
0Bh 1 Number of Data Blocks with Point>=A0h (Special Lead-In info)
0Ch 2 First Track Number in Session (01h..63h, non-BCD!)
0Eh 2 Last Track Number in Session (01h..63h, non-BCD!)
10h 4 Zero
14h 4 Offset to First Data-Block (usually 70h) (from begin of .MDS file)
Data-Blocks (50h bytes)
Block 0..2 are usually containing Point A0h..A2h info. Block 3..N are usually TOC info for Track 1 and up.
00h 1 Track mode (see below for details)
01h 1 Number of subchannels in .MDF file (0=None, 8=Sector has +60h bytes)
02h 1 ADR/Control (but with upper/lower 4bit swapped, ie. MSBs=ADR!) Q0
03h 1 TrackNo (usually/always 00h; as this info is in Lead-in area) Q1
04h 1 Point (Non-BCD!) (Track 01h..63h) (or A0h and up=Lead-in info) Q2
05h 4 Zero (probably dummy MSF and reserved byte from Q channel) Q3..Q6?
09h 1 Minute (Non-BCD!) ;\MM:SS:FF of Point'ed track Q7
0Ah 1 Second (Non-BCD!) ; (or disc/lead-out info when Point>=A0h) Q8
0Bh 1 Frame (Non-BCD!) ;/ Q9
For Point>=A0h, below 44h bytes at [0Ch..4Fh] are zero-filled
0Ch 4 Offset to Index-block for this track (from begin of .MDS file)
10h 2 Sector size (800h..930h) (or 860h..990h if with subchannels)
12h 1 Unknown (02h) (maybe number of indices?)
13h 11h Zero
24h 4 Track start sector, PLBA (00000000h=00:02:00)(or 00000096h=00:02:00?)
28h 8 Track start offset (from begin of .MDF file)
30h 4 Number of Filenames for this track (usually 1)
34h 4 Offset to Filename Block for this track (from begin of .MDS file)
38h 18h Zero
Trackmode:
(upper 4bit seem to be meaningless?)
00h=None (used for entries with Point=A0h..FF)
A9h=AUDIO ;sector size = 2352 930h ;bytes 000h..92Fh
AAh=MODE1 ;sector size = 2048 800h ;bytes 010h..80Fh
ABh=MODE2 ;sector size = 2336 920h ;bytes 010h..92Fh
ACh=MODE2_FORM1 ;sector size = 2048 800h ;bytes 018h..817h (incomplete!)
ADh=MODE2_FORM2 ;sector size = 2324+0? 914h ;bytes 018h..91Bh (incomplete!)
ADh=MODE2_FORM2 ;sector size = 2324+4? 918h ;bytes ??..?? (contains what?)
ECh=MODE2 ;sector size = 2448 990h ;(930h+60h) (with subchannels)
Index Blocks (usually 8 bytes per track)
00h 4 Number of sectors with Index 0 (usually 96h or zero)
04h 4 Number of sectors with Index 1 (usually size of main-track area)
Index blocks are usually/always 8 bytes in size (two indices per track, even when recording a CD with more than 2 indices per track). The MDS file does usually contain Index blocks for <all> Data Blocks (ie. including unused dummy Index Blocks for Data Blocks with Point>=A0h).
Filename Blocks (10h bytes)
00h 4 Offset to Filename (from begin of .MDS file)
04h 1 Filename format (0=8bit, 1=16bit characters)
05h 11 Zero
Normally all tracks are sharing the same filename block (although theoretically the tracks could use separate filename blocks; with different filenames).
Filename Strings (usually 6 bytes)
00h 6 Filename, terminated by zero (usually "*.mdf",00h)
Contains the filename of the of the sector data (usually "*.mdf", indicating to use the same name as for the .mds file, but with .mdf extension).
Read errors aka DPM data blocks (present if errors occured during recording)
00h 4 Unknown (1)
04h 4 Offset to following stuff
08h 4 Unknown (2)
0Ch 4 Unknown (7)
10h 4 Unknown (1)
14h 4 Number of read errors (E)
18h E*4 LBA's for sectors with read errors (0 and up)
Instead of (or additionally to) read errors, there may be also hundreds of Kbytes of unknown stuff appended (text strings in 8bit or 16bit format, binary numbers, and huge zerofilled blocks).
Missing
Unknown if/how this format supports EAN-13, ISRC, CD-TEXT.
CDROM Disk Images NRG (Nero)
.NRG (NERO)
Nero is probably the most bloated and most popular CD recording software. The first part of the file contains the disk image, starting at sector 00:00:00, with 800h..930h bytes per sector. Additional chunk-based information is appended at the end of the file, usually consisting of only four chunks: CUES,DAOI,END!,NERO (in that order).
Chunk Entrypoint (in last 8/12 bytes of file)
4 File ID "NERO"/"NER5"
4/8 Fileoffset of first chunk
Cue Sheet (summary of the Table of Contents, TOC)
4 Chunk ID "CUES"/"CUEX"
4 Chunk size (bytes)
below EIGHT bytes repeated for each track/index, of which, first FOUR bytes are same for both CUES and CUEX,
1 ADR/Control from TOC (usually LSBs=ADR=1=fixed, MSBs=Control=Variable)
1 Track (BCD) (00h=Lead-in, 01h..99h=Track N, AAh=Lead-out)
1 Index (BCD) (usually 00h=pregap, 01h=actual track)
1 Zero
next FOUR bytes for CUES,
1 Zero
1 Minute (BCD) ;starting at 00:00:00 = 2 seconds before ISO vol. descr.
1 Second (BCD)
1 Sector (BCD)
or, next FOUR four bytes for CUEX,
4 Logical Sector Number (HEX) ;starting at FFFFFF6Ah (=00:00:00)
Caution: Above may contain two position 00:00:00 entries: one nonsense entry for Track 00 (lead-in), followed by a reasonable entry for Track 01, Index 00.
Disc at Once Information
4 Chunk ID "DAOI"/"DAOX"
4 Chunk size (bytes)
4 Garbage (usually same as above Chunk size)
13 EAN-13 Catalog Number (13-digit ASCII) (or 00h-filled if none/unknown)
1 Zero
1 Disk type (00h=Mode1 or Audio, 20h=XA/Mode2) (and probably 10h=CD-I?)
1 Unknown (01h)
1 First track (Non-BCD) (01h..63h)
1 Last track (Non-BCD) (01h..63h)
below repeated for each track,
12 ISRC in ASCII (eg. "USXYZ9912345") (or 00h-filled if none/unknown)
2 Sector size (usually 800h, 920h, or 930h) (see Mode entry for more info)
1 Mode:
0=Mode1/800h ;raw mode1 data (excluding sync+header+edc+errorinfo)
3=Mode2/920h ;almost full sector (exluding first 16 bytes; sync+header)
6=Mode2/930h ;full sector (including first 16 bytes; sync+header)
7=Audio/930h ;full sector (plain audio data)
Mode values from wikipedia:
00h for data Mode1/800h
02h
03h for Mode 2 Form 1 data eh? FORM1??? Mode2/920h
05h for raw data Mode1?/930h
06h for raw Mode 2/form 1 data Mode2/930h
07h for audio Audio/930h
0Fh for raw data with sub-channel Mode1?/930h+WHAT?
10h for audio with sub-channel Audio/930h+WHAT?
11h for raw Mode 2/form 1 data with sub-channel Mode2/WHAT?+WHAT?
Note: Some newer files do actually use different sector sizes for each
track (eg. 920h for the data track, and 930h for any following audio
tracks), older files were using the same sector size for all tracks
(eg. if the disk contained 930-byte Audio tracks, then Data tracks
were stored at the same size, rather than at 800h or 920h bytes).
3 Unknown (always 00h,00h,01h)
4/8 Fileoffset 1 (Start of Track's Pregap) (with Index=00h)
4/8 Fileoffset 2 (Start of actual Track) (with Index=01h and up)
4/8 Fileoffset 3 (End of Track) (aka begin of next track's pregap)
End of chain
4 Chunk ID "END!"
4 Chunk size (always zero)
Track Information (contained only in Track at Once images)
4 Chunk ID "TINF"/"ETNF"/"ETN2"
4 Chunk size (bytes)
below repeated for each track,
4/4/8 Track fileoffset ;\32bit in TINF/ETNF chunks,
4/4/8 Track length (bytes) ;/64bit in ETN2 chunks
4 Mode (should be same as in DAO chunks, see there) (implies sector size)
0/4/4 Start lba on disc ;\only in ETNF/ETN2 chunks,
0/4/4 Unknown? ;/not in TINF chunks
Unknown 1 (contained only in Track at Once images)
4 Chunk ID "RELO"
4 Chunk size (bytes)
4 Zero
Unknown 2 (contained only in Track at Once images)
4 Chunk ID "TOCT"
4 Chunk size (bytes)
1 Disk type (00h=Mode1 or Audio, 20h=XA/Mode2) (and probably 10h=CD-I?)
1 Zero (00h)
Session Info (begin of a session) (contained only in multi-session images)
4 Chunk ID "SINF"
4 Chunk size (bytes)
4 Number of tracks in session
CD-Text (contained only in whatever images)
4 Chunk ID None/"CDTX"
4 Chunk size (bytes) (must be a multiple of 18 bytes)
below repeated for each fragment,
18 Raw 18-byte CD-text data fragments
Media Type? (contained only in whatever images)
4 Chunk ID "MTYP"
4 Chunk size (bytes)
4 Unknown? (00000001h for CDROM) (maybe other value for DVD)
Optional Filenames (names where the image was generated from?)
4 Chunk ID "AFNM"
4 Chunk size (bytes)
.. Track Filenames (eg. "Track1.wav",0,"Track2.wav",0)
Optional Volume name
4 Chunk ID "VOLM"
4 Chunk size (bytes)
.. Name (eg. "Audio CD",00h)
Notes
Newer/older .NRG files may contain 32bit/64bit values (and use "OLD"/"NEW" chunk names) (as indicated by the "/" slashes). CAUTION: All 16bit/32bit/64bit values are in big endian byte-order.
Missing
Unknown if newer NRG versions do also support subchannel data.
CDROM Disk Image/Containers CDZ
.CDZ is a compressed disk image container format (developed by pSX Author, and used only by the pSX emulator). The disk is split into 64kbyte blocks, which allows fast random access (without needing to decompress all preceeding sectors). However, the compression ratio is surprisingly bad (despite of being specifically designed for cdrom compression, the format doesn't remove redundant sector headers, error correction information, and EDC checksums).
.CDZ File Structure
FileID ("CDZ",00h for cdztool v0/v1, or "CDZ",01h for cdztool v2 and up)
One or two Chunk(s)
.CDZ Chunk Format
Chunk Header in v0 (unreleased prototype):
4 32bit Decompressed Size (of all blocks) (must be other than "ZLIB")
Chunk Header in v1 (first released version):
4 ZLIB ID ("ZLIB")
8 64bit Decompressed Size (of all blocks)
Chunk Header in v2 and up (later versions):
4 Chunk ID (eg. "CUE",00h)
8 Chunk Size in bytes (starting at "ZLIB" up to including Footer, if any)
4 ZLIB ID ("ZLIB")
8 64bit Decompressed Size (of all blocks)
Chunk Body (same in all versions):
4 Number of Blocks (N)
4 Block 1 Compressed Size (CS.1)
4 Block 1 Decompressed Size (always 00010000h, except last block)
CS.1 Block 1 Compressed ZLIB Data (starting with 78h,9Ch)
... ... ;\
4 Block N Compressed Size (CS.N) ; further block(s)
4 Block N Decompressed Size ; (if any)
CS.N Block N Compressed ZLIB Data ;/
Chunk Footer in v0 (when above header didn't have the "ZLIB" ID):
4*N Directory Entries for N blocks ;-this ONLY for BIN chunk
Chunk Footer in v1 and up:
BPD*(N-1) Directory Entries for N-1 blocks ;\this ONLY for BIN chunk
1 Bytes per Directory Entry (BPD) ;/(not for CUE/CCD/MDS)
The "Compressed ZLIB Data" parts contain Deflate'd data (starting with 2-byte ZLIB header, and ending with 4-byte ZLIB/ADLER checksum), for details see: CDROM File Compression ZIP/GZIP/ZLIB (Inflate/Deflate)
.CDZ Chunks / Content
The chunk(s) have following content:
noname+noname --> .CUE+.BIN (cdztool v1 and below)
"BIN",0 --> .ISO (cdztool v2? and up)
"CUE",0+"BIN",0 --> .CUE+.BIN (cdztool v2 and up)
"CCD",0+"BIN",0 --> .CCD+.IMG (cdztool v2 and up)
"CCD",0+"BIN",01h --> .CCD+.IMG+.SUB (930h sectors, plus 60h subchannels)
"MDS",0+"BIN",0 --> .MDS+.MDF (cdztool v5 only)
Note: cdztool doesn't actually recognize files with .ISO extension (however, one can rename them to .BIN, and then compress them as CUE-less .BIN file).
Cdztool.exe Versions
cdztool.exe v0, unrelased prototype
cdztool.exe v1, 22 May 2005, CRC32=620dbb08, 102400 bytes, pSX v1.0-5
cdztool.exe v2, 02 Jul 2006, CRC32=bcb29c1e, 110592 bytes, pSX v1.6
cdztool.exe v3, 22 Jul 2006, CRC32=4062ba82, 110592 bytes, pSX v1.7
cdztool.exe v4, 13 Aug 2006, CRC32=7388dd3d, 118784 bytes, pSX v1.8-11
cdztool.exe v5, 22 Jul 2007, CRC32=f25c1659, 155648 bytes, pSX v1.12-13
Note: v0 wasn't ever released (it's only noteworthy because later versions do have backwards compatibility for decompressing old v0 files). v1 didn't work with all operating systems (on Win98 it just says "Error: Couldn't create <output>" no matter what one is doing, however, v1 does work on later windows versions like WinXP or so?).
CDROM Disk Image/Containers ECM
ECM (Error Code Modeler by Neill Corlett) is a utility that removes unneccessary ECC error correction and EDC error detection values from CDROM-images. This is making the images a bit smaller, but the real size reduction isn't gained until subsequently compressing the images via tools like ZIP. Accordingly, these files are extremly uncomfortable to use: One most first UNZIP them, and then UNECM them.
.EXT.ECM - Double extension
ECM can be applied to various CDROM-image formats (like .BIN, .CDI, .IMG, .ISO, .MDF, .NRG), as indicated by the double-extension. Most commonly it's applied to .BIN files (hence using extension .BIN.ECM).
Example / File Structure
45 43 4D 00 ;FileID "ECM",00h
3C ;Type 0, Len=10h (aka 0Fh+1)
00 FF FF FF FF FF FF FF FF FF FF 00 00 02 00 02 ;16 data bytes
02 ;Type 2, Len=1 (aka 00h+1)
00 00 08 00 00 00 00 00 00 00 00 ..... 00 00 00 ;804h data bytes
3C ;Type 0, Len=10h (aka 0Fh+1)
00 FF FF FF FF FF FF FF FF FF FF 00 00 02 01 02 ;16 data bytes
02 ;Type 2, Len=1 (aka 00h+1)
00 00 08 00 00 00 00 00 00 00 00 ..... 00 00 00 ;804h data bytes
...
FC FF FF FF 3F ;End Code (Len=FFFFFFFFh+1)
NN NN NN NN ;EDC (on decompressed data)
Type/Length Byte(s)
Type/Length is encoded in 1..5 byte(s), with "More=1" indicating that further length byte(s) follow:
1st Byte: Bit7=More, Bit6-2=LengthBit4-0, Bit1-0=Type(0..3)
2nd Byte: Bit7=More, Bit6-0=LengthBit5-11
3rd Byte: Bit7=More, Bit6-0=LengthBit12-18
4th Byte: Bit7=More, Bit6-0=LengthBit19-25
5th Byte: Bit7-6=Reserved/Zero, Bit5-0=LengthBit26-31
Length=FFFFFFFFh=End Indicator The actual decompression LEN is: "LEN=Length+1"
ECM Decompression
Below is repeated LEN times (with LEN being the Length value plus 1):
Type 0: load 1 byte, save 1 byte
Type 1: load 803h bytes [0Ch..0Eh,10h..80Fh], save 930h bytes [0..92Fh]
Type 2: load 804h bytes [14h..817h], save 920h bytes [10h..92Fh]
Type 3: load 918h bytes [14h..91Bh], save 920h bytes [10h..92Fh]
Type 1-3 are reconstructing the missing bytes before saving. Type 2-3 are saving only 920h bytes, so (if the original image contained full 930h byte sectors) the missing 10h bytes must be inserted via Type 0. Type 0 can be also used for copying whole sectors as-is (eg. Audio sectors, or Data sectors with invalid Sync/Header/ECC/EDC values). And, Type 0 can be used to store non-sector data (such like the chunks at the end of .NRG or .CDI files).
Central Mistakes
There's a lot of wrong with the ECM format. The two central problems are that it doesn't support data-compression (and needs external compression tools like zip/rar), and, that it doesn't contain a sector look-up table (meaning that random access isn't possible unless when scanning the whole file until reaching the desired sector).
Worst-case Scenario
As if ECM as such wouldn't be uncomfortable enough, you may expect typical ECM users to get more things messed up. For example:
A RAR file containing a 7Z file containing a ECM file containing a BIN file.
The BIN containing only Track 1, other tracks stored in APE files.
And, of course, the whole mess without including the required CUE file.
CDROM Subchannel Images
SBI (redump.org)
SBI Files start with a 4-byte FileID:
4 bytes FileID ("SBI",00h)
Then followed by entries as so:
3 bytes real absolute MM:SS:FF address where the sub q data was bad
1 byte Format: the format can be 1, 2 or 3:
Format 1: complete 10 bytes sub q data (Q0..Q9)
Format 2: 3 bytes wrong relative MM:SS:FF address (Q3..Q5)
Format 3: 3 bytes wrong absolute MM:SS:FF address (Q7..Q9)
Note: The PSX libcrypt protection relies on bad checksums (Q10..Q11), which will cause the PSX cdrom controller to ignore Q0..Q9 (and to keep returning position data from most recent sector with intact checksum). Ironically, the SBI format cannot store the required Q10..Q11 checksum. The trick for using SBI files with libcrypted PSX discs is to ignore the useless Q0..Q9 data, and to assume that all sectors in the SBI file have wrong Q10..Q11 checksums.
M3S (Subchannel Q Data for Minute 3) (ePSXe)
M3S files are containing Subchannel Q data for all sectors on Minute=03 (the region where PSX libcrypt data is located) (there is no support for storing the (unused) libcrypt backup copy on Minute=09). The .M3S filesize is 72000 bytes (60 seconds * 75 sectors * 16 bytes). The 16 bytes per sector are:
Q0..Q9 Subchannel Q data (normally position data)
Q10..Q11 Subchannel Q checksum
Q12..Q15 Dummy/garbage/padding (usually 00000000h or FFFFFFFFh)
Unfortunately, there are at least 3 variants of the format:
1. With CRC (Q0..Q11 intact) (and Q12..Q15 randomly 00000000h or FFFFFFFFh)
2. Without CRC (only Q0..Q9 intact, but Q10..Q15 zerofilled)
3. Without anything (only Q0 intact, but Q1..Q15 zerofilled)
The third variant is definetly corrupt (and one should ignore such zerofilled entries). The second variant is corrupt, too (but one might attempt to repair them by guessing the missing checksum: if it contains normal position values assume correct crc, if it contains uncommon values assume a libcrypted sector with bad crc). The M3S format is intended for libcrypted PSX games, but, people seem to have also recorded (corrupted) M3S files for unprotected PSX games (in so far, more than often, the M3S files might cause problems, instead of solving them). Note: The odd 16-byte format with 4-byte padding does somehow resemble the "P and Q Sub-Channel" format 'defined' in MMC-drafts; if the .M3S format was based on the MMC stuff: then the 16th byte might contain a Subchannel P "pause" flag in bit7.
CDROM Images with Subchannel Data
Most CDROM-Image formats can (optionally) contain subchannel recordings. The downsides are: Storing all 8 subchannels for a full CDROM takes up about 20MBytes. And, some entries may contain 'wrong' data (read errors caused by scratches cannot be automatically repaired since subchannels do not contain error correction info). If present, the subchannel data is usually appended at the end of each sector in the main binary file (one exception is CloneCD, which stores it in a separate .SUB file instead of in the .IMG file).
CCD/IMG/SUB (CloneCD) P-W 60h-bytes Non-interleaved (in separate .SUB file)
CDI (DiscJuggler) P-Q 10h-bytes Non-interleaved (in .CDI file)
"" P-W 60h-bytes Interleaved (in .CDI file)
CUE/BIN/CDT (Cdrwin) N/A
ISO (single-track) N/A
MDS/MDF (Alcohol 120%) P-W 60h-bytes Interleaved (in .MDF file)
NRG (Nero) P-W 60h-bytes Interleaved (in .NRG file)
Interleaved Subchannel format (eg. Alcohol .MDF files):
00h-07h 80 C0 80 80 80 80 80 C0 ;P=FFh, Q=41h=ADR/Control, R..W=00h
08h-0Fh 80 80 80 80 80 80 80 C0 ;P=FFh, Q=01h=Track, R..W=00h
10h-17h 80 80 80 80 80 80 80 C0 ;P=FFh, Q=01h=Index, R..W=00h
18h-1Fh 80 80 80 80 80 80 80 80 ;P=FFh, Q=00h=RelMinute, R..W=00h
20h-27h 80 80 80 80 80 80 80 80 ;P=FFh, Q=00h=RelSecond, R..W=00h
28h-2Fh 80 80 80 80 80 80 80 80 ;P=FFh, Q=00h=RelSector, R..W=00h
30h-37h 80 80 80 80 80 80 80 80 ;P=FFh, Q=00h=Reserved, R..W=00h
38h-3Fh 80 80 80 80 80 80 80 80 ;P=FFh, Q=00h=AbsMinute, R..W=00h
40h-47h 80 80 80 80 80 80 C0 80 ;P=FFh, Q=02h=AbsSecond, R..W=00h
48h-4Fh 80 80 80 80 80 80 80 80 ;P=FFh, Q=00h=AbsSector, R..W=00h
50h-57h 80 80 C0 80 C0 80 80 80 ;P=FFh, Q=28h=ChecksumMsb, R..W=00h
58h-5Fh 80 80 C0 C0 80 80 C0 80 ;P=FFh, Q=32h=ChecksumLsb, R..W=00h
Non-Interleaved Subchannel format (eg. CloneCD .SUB files):
00h-0Bh FF FF FF FF FF FF FF FF FF FF FF FF ;Subchannel P (Pause)
0Ch-17h 41 01 01 00 00 00 00 00 02 00 28 32 ;Subchannel Q (Position)
18h-23h 00 00 00 00 00 00 00 00 00 00 00 00 ;Subchannel R
24h-2Fh 00 00 00 00 00 00 00 00 00 00 00 00 ;Subchannel S
30h-3Bh 00 00 00 00 00 00 00 00 00 00 00 00 ;Subchannel T
3Ch-47h 00 00 00 00 00 00 00 00 00 00 00 00 ;Subchannel U
48h-53h 00 00 00 00 00 00 00 00 00 00 00 00 ;Subchannel V
54h-5Fh 00 00 00 00 00 00 00 00 00 00 00 00 ;Subchannel W
Non-Interleaved P-Q 10h-byte Subchannel format:
This is probably based on MMC protocol, which would be as crude as this:
The 96 pause bits are summarized in 1 bit. Pause/Checksum are optional.
00h-09h 41 01 01 00 00 00 00 00 02 00 ;Subchannel Q (Position)
0Ah-0Bh 28 32 ;<-- OPTIONAL, can be zero! ;Subchannel Q (Checksum)
0Ch-0Eh 00 00 00 ;Unused padding (zero)
0F 80 ;<-- OPTIONAL, can be zero! ;Subchannel P (Bit7=Pause)
CDROM Disk Images PBP (Sony)
.PBP
Sony's disc image format used on PSP. Can store multi-disc images in a single file. Supports deflate data compression and some yet unknown audio compression. A homebrew compressor can compress whole discs with deflate (which works, but it isn't very good to compress audio sectors that way).
PBP Format (rev-engineered from homebrew DBALL.PBP)
000000h 4 ID (00h,"PBP")
000004h 4 Version? (10000h) (but, reportedly "always 100h or 1000100h")
000008h 4 Offset of the file PARAM.SFO (28h)
00000Ch 4 Offset of the file ICON0.PNG (3D8h)
000010h 4 Offset of the file ICON1.PMF (3D8h) or ICON1.PNG
000014h 4 Offset of the file PIC0.PNG (3D8h) or UNKNOWN.PNG
000018h 4 Offset of the file PIC1.PNG (3D8h) or PICT1.PNG
00001Ch 4 Offset of the file SND0.AT3 (3D8h)
000020h 4 Offset of the file DATA.PSP (3D8h)
000024h 4 Offset of the file DATA.PSAR (10000h)
000028h .. PARAM.SFO file (zerofilled in homebrew PBP)
0003D8h .. PNG files etc (zerofilled in homebrew PBP)
010000h 0Ch ID "PSISOIMG0000"
01000Ch 4 PBP Size-10000h (144740h)
010010h 4 PBP Size-6420h (???) (14E320h)
010014h .. Zerofilled
010400h 0Bh Game ID ("_SCUS_94476" for Hot Shots Golf 2)
01040Bh .. Zerofilled
010800h A00h TOC List (0Ah-byte per entry) (unused entries are zerofilled)
011200h 20h Zerofilled
011220h 4 PBP Size-D2CFh (???) (147471h)
011224h 4 Zero
011228h 4 Unknown (7FFh)
01122Ch 11h Game Name ("Hot Shots Golf",C2h,AEh,"2")
01123Dh .. Zerofilled
014000h .. Sector List (20h-byte per entry) (unused entries are zerofilled)
... .. Zerofilled
110000h .. Deflated sectors (9300h bytes after decompression)
15467Dh B8h One extra compression block that is NOT in Sector List ???
154735h 0Bh Weird padding with ASCII "00000000000"
154740h - End of file
TOC List (Subchannel Q with ADR=1 during Lead-In):
000h 1 ADR/Control (eg. 41h=Data Track)
001h 1 Track (always 00h=Lead-in for all TOC List entries)
002h 1 Point (A0h, A1h, A2h, or Track 01h and up) (BCD?)
003h 3 Dummy MSF (usually 00:00:00 or weirdly 00:02:01) (BCD?)
006h 1 Reserved (00h)
007h 3 Actual MSF (or TOC info for Point=A0h,A1h) (BCD?)
Example TOC (DBALL.PBP):
41 00 A0 00 00 00 00 01 20 00 ;First Track (1) and Type (20h=CDROM-XA)
41 00 A1 00 00 00 00 01 00 00 ;Last Track Number (1)
41 00 A2 00 00 00 00 27 19 22 ;Lead-Out, uh at 27:19:22 in DBALL.PBP ???
41 00 01 00 02 01 00 00 02 00 ;Track 1 at 00:02:00
(remaining entries are zerofilled)
Example TOC (PSALM69.PBP):
01 00 01 00 02 00 00 00 00 00 ;Track 1 as audio <-- why that ???
01 00 02 02 37 44 00 00 00 00 ;Track 2 as audio
01 00 03 03 25 45 00 00 00 00 ;Track 3 as audio
41 00 01 00 02 01 00 00 02 00 ;Track 1 as data <-- listed last?
(remaining entries are zerofilled)
(weirdly, most MM:SS:FF values are stored in byte[3..5] instead [7..9])
(there are no point=A0h,A1h,A2h entries)
Example TOC (GOOGLE_AI_TTS.PBP):
01 00 01 00 02 00 00 00 00 00 ;Track 1 as audio
01 00 02 00 02 30 00 00 00 00 ;Track 2 as audio, but without pregap?
01 00 03 00 02 60 00 00 00 00 ;Track 3 as audio, but without pregap?
01 00 04 00 03 15 00 00 00 00 ;Track 4 as audio, but without pregap?
(remaining entries are zerofilled)
Sector List:
000h 4 Offset-110000h to Sector(N*10h)
004h 2 Compressed size of Sector(N*10h+(0..0Fh)) ;9300h=uncompressed?
006h 2 Zero (but, reportedly "usually 1... and 0 for the last entry")
008h 10h Zero (but, reportedly "first 10h bytes of SHA1 sum of 10h sectors")
018h 8 Zero (padding)
Data Compression is using raw Deflate (without any zlib headers or the like), and it's unfortunately just compressing the sectors as-is (without filtering out sector headers and ECC/EDC values). CDROM File Compression ZIP/GZIP/ZLIB (Inflate/Deflate) Audio Compression format is unknown:
?
Multi-disc format is unknown:
?
Retail files have "PGD" encryption:
?
CDROM Disk Images CHD (MAME)
All numbers are stored in Motorola (big-endian) byte ordering.
V1/V2 header (hdcomp):
V1/V2 contains harddisk related header entries (and apparently does't support cdroms).
000h 08h ID "MComprHD" (MAME Compressed Hunks of Data)
008h 4 Header size (4Ch=V1, 50h=V2)
00Ch 4 Header version (probably 01h=V1, 02h=V2)
010h 4 Flags (bit0=DriveHasParent, bit1=AllowWrites)
014h 4 Compression type (0=None, 1=ZLIB)
018h 4 Number of sectors per hunk
01Ch 4 Total number of hunks represented
020h 4 Number of cylinders on hard disk
024h 4 Number of heads on hard disk
028h 4 Number of sectors on hard disk
02Ch 10h MD5 checksum on raw data
03Ch 10h MD5 checksum on parent file
N/A - V1: Uses fixed 200h-byte Sector size
04Ch (4) V2: Number of bytes per sector
... ? Supposedly followed by map and/or data at whatever locations
V3/V4 header (chdman):
V3/V4 are inventing new "metadata" for info about harddisks or cdroms.
000h 08h ID "MComprHD" (MAME Compressed Hunks of Data)
008h 4 Header size (78h=V3, 6Ch=V4)
00Ch 4 Header version (03h=V3, 04h=V4)
010h 4 Flags (bit0=DriveHasParent, bit1=AllowWrites)
014h 4 Compression type (0=None, 1=ZLIB, 2=ZLIB_PLUS) (V4: 3=AV)
018h 4 Total number of hunks represented (N) (92h)
01Ch 08h Total size of all uncompressed hunks (N*2640h) (15D080h)
024h 08h Offset to the first blob of metadata
02Ch 10h V3: MD5 checksum on raw data ;\
03Ch 10h V3: MD5 checksum on parent file ;
04Ch 4 V3: Number of bytes per hunk (2640h=990h*4) ; V3
050h 14h V3: SHA1 checksum on raw data ;
064h 14h V3: SHA1 checksum on parent file ;/
02Ch 4 V4: Number of bytes per hunk (2640h=990h*4) ;\
030h 14h V4: SHA1 checksum on raw+meta ; V4
044h 14h V4: SHA1 checksum on raw+meta of parent ;
058h 14h V4: SHA1 checksum on raw data ;/
... N*10h Map entries (for each hunk)
... 10h Map end marker ("EndOfListCookie",00h)
... .. Metadata Chunk(s)
... .. Compressed Sectors (aka hunks)
V5 header (chdman):
000h 8 ID "MComprHD" (MAME Compressed Hunks of Data)
008h 4 Header size (7Ch=V5)
00Ch 4 Header version (05h=V5)
010h 4 Compressor 0 (usually "cdlz"=cdrom/lzma)
014h 4 Compressor 1 (usually "cdzl"=cdrom/zlib)
018h 4 Compressor 2 (usually "cdfl"=cdrom/flac)
01Ch 4 Compressor 3 (usually 0=none)
020h 8 Total size of all uncompressed hunks (N*4C80h-HunkPadding)
028h 8 Offset to Map (3D797h)
030h 8 Offset to first Metadata chunk (7Ch)
038h 4 Number of bytes per hunk (512k maximum) (990h*8) (4C80h)
03Ch 4 Number of bytes per sector (990h) (30h+60h)
040h 14h SHA1 on raw data
054h 14h SHA1 on raw+meta
068h 14h SHA1 on raw+meta of parent (0=No parent)
... .. Metadata Chunk(s)
... .. Padding to BytesPerHunk-boundary ;\when uncompressed
... .. Uncompressed Sectors (aka hunks) ;/
... .. Compressed Sectors (aka hunks) ;-when compressed
... .. Map
CHD Metadata
V3/V4/V5 Metadata
Overall Metadata chunk format:
000h 4 Chunk ID (aka Blob Tag) (eg. "CHT2" for each CDROM track)
004h 1 Flags (00h=V3, 01h=V4/V5) ;maybe some kind of flag/type/version?
005h 3 Chunk Data Size (24bit)
008h 8 Offset to next Chunk (or 0=Last chunk)
010h .. Chunk Data (eg. "TRACK:1 TYPE:MODE2_RAW ... POSTGAP:0",00h for CHT2)
There can be one or more chunks (eg. CHT2 chunk(s), one for each CDROM track).
Summary of Chunk IDs and corresponding Data entries:
ID_______Data_______________________________________________________
"GDDD" "CYLS,HEADS,SECS,BPS" ;-hard disk standard info ;\
"IDNT" ? ;-hard disk identify info ; HDD
"KEY " ? ;-hard disk key info ;/
"CIS " ? ;-pcmcia CIS info ;-PCMCIA
"CHCD" 94Ch-byte binary (4+99*24 bytes) ;\
"CHTR" "TRACK TYPE SUBTYPE FRAMES" ; CD-ROM
"CHT2" "TRACK TYPE SUBTYPE FRAMES PREGAP PGTYPE PGSUB POSTGAP" ;/
"CHGT" ? ;\Sega
"CHGD" "TRACK TYPE SUBTYPE FRAMES PAD PREGAP PGTYPE PGSUB POSTGAP" ;/GD-ROM
"AVAV" "FPS WIDTH HEIGHT INTERLACED CHANNELS SAMPLERATE" ;\AV
"AVLD" ? (A/V Laserdisc frame) ;/
V3/V4/V5 Metadata in ASCII format
The ASCII items are separated by spaces as shown above (or commas for GDDD). The last item in each chunk is terminated by 00h (at least so for CHTR/CHT2). Most items are followed by a colon and decimal string (eg. TRACK:1), except, TYPE,PGTYPE,SUBTYPE,PGSUB are followed by text strings (eg. TYPE:MODE2_RAW).
CYLS:# Hard disc number of cylinders
HEADS:# Hard disc number of heads
SECS:# Hard disc number of sectors
BPS:# Hard disc bytes per sector
TRACK:# CDROM current track number (1..99)
TYPE:string CDROM sector type/size
SUBTYPE:string CDROM subchannel info (usually "NONE")
FRAMES:# CDROM number of sectors per track (with/without pregap?)
PAD:# Sega GDROM only: whatever pad value?
PREGAP:# CDROM ... maybe number of pregap sectors? (can be HUGE !!??)
PGTYPE:string CDROM ... whatever type? (usually "MODE1"??)
PGSUB:string CDROM ... whatever subchannel (usually "RW"??)
POSTGAP:# CDROM ... maybe number of pstgap sectors? (usually 0)
FPS:#.###### AV Video(?)-frames per second? with 6-digit fraction? (.avi?)
WIDTH:# AV Width (maybe in pixels?)
HEIGHT:# AV Height (maybe in pixels?) (with/without interlace?)
INTERLACED:# AV Interlace (maybe a flag that might be maybe 0 or 1?)
CHANNELS:# AV Channels (maybe audio mono/stereo or so?)
SAMPLERATE:# AV Samplerate (maybe audio samplerate, maybe in Hertz?)
For SUBTYPE and PGSUB:
"RW" 60h-byte interleaved ;normal "cooked" 96 bytes per sector
"RW_RAW" 60h-byte uninterleaved ;raw uninterleaved 96 bytes per sector
"NONE" 0-byte ;no subcode data stored (default)
(unknown how RAW and RW_RAW differ, one format does probably store 8 bits
for 8 subchannels per byte... but unknown which format is doing so?)
For TYPE and PGTYPE (and CHCD numeric type 0..7):
"MODE1/2048" or "MODE1" CHCD=0 800h-byte ;\Data Mode1
"MODE1/2352" or "MODE1_RAW" CHCD=1 930h-byte ;/
"MODE2/2336" or "MODE2" ;\dupe? CHCD=2 920h-byte ;\
"MODE2/2336" or "MODE2_FORM_MIX" ;/ CHCD=5 920h-byte ;
"MODE2/2048" or "MODE2_FORM1" CHCD=3 800h-byte ; Data Mode2
"MODE2/2324" or "MODE2_FORM2" CHCD=4 914h-byte ;
"MODE2/2352" or "MODE2_RAW" or "CDI/2352" CHCD=6 930h-byte ;/
"AUDIO" (stored as big-endian samples!!!) CHCD=7 930h-byte ;-Audio CD-DA
Caution: AUDIO sectors are conventionally stored as 16bit little-endian samples, but CHD is storing them in big-endian (unlike formats like CUE/BIN). Caution: Older CHDMAN versions (eg. v0.146) did use nonsense "PGTYPE:MODE1" for all tracks (including audio tracks), later versions (eg. v0.246) did fix that issue; those newer files include a "V" prefix to indicate that the entry contains "valid" info (eg. "PGTYPE:VAUDIO") (except, Track 1 keeps using "PGTYPE:MODE1" without "V" and it's "MODE1" even on MODE2 discs).
CHCD Metadata (94Ch bytes, plus 10h-byte metadata header)
000h 4 Number of tracks (N) (1..99)
004h N*18h Track entries
... .. Zeropadding to 94Ch-byte size (when less than 99 tracks)
Track entries:
000h 4 Track Type (0..7, CHCD=# in above table) (eg. 6=MODE2_RAW)
004h 4 Subchannel Type (0=RW, 1=RW_RAW, 2=None)
008h 4 Sector Size (800h, 914h, 920h or 930h)
00Ch 4 Subchannel Size (0 or 60h)
010h 4 Number of Frames (aka number of sectors)
014h 4 Padding Frames (0..3) (to make Total Frames a multiple of 4)
CHD Maps
The Maps contain info (offset, size, compression method, etc.) for the separate compression blocks.
V1/V2 map format (64bit entries with 44bit+20bit):
44bit Offset to compressed data
20bit Size of compressed data (or uncompressed data when size=hunksize)
Unknown if offset is in upper or lower 44bit.
V3/V4 map entries (per hunk):
000h 8 Offset to compressed data (64bit big-endian)
008h 4 CRC32 on uncompressed data (32bit big-endian)
00Ch 3 Size of compressed data (24bit mixed-endian: Mid, Low, High)
00Fh 1 Flags, indicating compression info (=whut? maybe below V34 stuff?)
V34_MAP_ENTRY_FLAG_TYPE_MASK = 0x0f; // what type of hunk V34_MAP_ENTRY_FLAG_NO_CRC = 0x10; // no CRC is present (which CRC?) V3-V4 entry types
V34_MAP_ENTRY_TYPE_INVALID = 0 invalid type
V34_MAP_ENTRY_TYPE_COMPRESSED = 1 standard compression
V34_MAP_ENTRY_TYPE_UNCOMPRESSED = 2 uncompressed data
V34_MAP_ENTRY_TYPE_MINI = 3 mini: use offset as raw data
V34_MAP_ENTRY_TYPE_SELF_HUNK = 4 same as another hunk in this file
V34_MAP_ENTRY_TYPE_PARENT_HUNK = 5 same as a hunk in the parent file
V34_MAP_ENTRY_TYPE_2ND_COMPRESSED = 6 compressed with secondary algorithm
Note: Secondary algorithm is NEVER used (it seems to have been intended for FLAC CDDA, but that was apparently never actually implemented in V3/V4). Blurp: Secondary algorithm is "usually FLAC CDDA" (unknown where that is defined, and if one could also select other algorithms) ("usually FLAC" might mean "always FLAC" for cdroms, and "not used" elsewhere).
V5 Map Formats
V5 uncompressed map format (when [filehdr+10h]=00000000h):
000h N*4 Hunk List (32bit offsets: Offset/BytesPerHunk) (usually 1,2,3..)
V5 compressed map format (when [filehdr+10h]<>00000000h):
000h 4 Length of compressed map
004h 6 Offset of first block (48bit) (E4h, after meta)
00Ah 2 CRC16 on decompressed map entries
00Ch 1 bits used to encode complength
00Dh 1 bits used to encode self-refs
00Eh 1 bits used to encode parent unit refs
00Fh 1 Reserved for future use (probably zero)
010h .. Compressed Map entries (bitstream with Huffman/RLE encoding)
The decompressed map entries should look as shown below (one could store them
differently, eg. as 32bit little endian values; however, they must be stored
exactly as shown below when computing the CRC16 on decompressed map entries):
000h 1 Compression type (0..3=Codec0..3, 4=Uncompressed, 5=Self, 6=Parent)
001h 3 Compressed length (24bit big-endian)
004h 6 Offset to compressed data (48bit big-endian)
00Ah 2 CRC16 on decompressed data (big-endian)
V5 compression codecs:
0,0,0,0 = CHD_CODEC_NONE ;-unused (when using less than 4 codecs)
"zlib" = CHD_CODEC_ZLIB ;\
"lzma" = CHD_CODEC_LZMA ; general codecs
"huff" = CHD_CODEC_HUFFMAN ;
"flac" = CHD_CODEC_FLAC ;/
"cdzl" = CHD_CODEC_CD_ZLIB ;\
"cdlz" = CHD_CODEC_CD_LZMA ; general codecs with CD frontend
"cdfl" = CHD_CODEC_CD_FLAC ;/
"avhu" = CHD_CODEC_AVHUFF ;-A/V codecs
Uncompressed V5 Map loading (when [filehdr+10h]=00000000h)
readfile(src,NumberOfHunks*4) ;\
i=0 ; load uncomoressed
while i<NumberOfHunks ; map (needed only
ofs=bigendian32bit[src+i*4]*BytesPerHunk ; for uncompressed
byte[map+i*0Ch+00h]=04h ;typ=Uncompressed ; files, which can
bigendian24bit[map+i*0Ch+01h]=BytesPerHunk ; be created via
bigendian48bit[map+i*0Ch+04h]=ofs ; chdman commandline
bigendian16bit[map+i*0Ch+0Ah]=none ;no crc ; options)
ofs=ofs+len, i=i+1 ;/
Compressed V5 Map loading (when [filehdr+10h]<>00000000h)
readfile(hdr,10h) ;\read map hdr and
readfile(src,bigendian32bit[hdr+0]) ; compressed map
InitBitstream(src,BigEndianMsbFirst) ;/
i=0 ;\
while i<10h ;
val=GetBits(4), num=1 ;
if val=01h then ; read huffman tree
val=GetBits(4) ;
if val<>01h then num=GetBits(4)+3 ;
for j=1 to num, codesizes[i]=val, i=i+1 ;
nonlzh_explode_tree(codetree,codesizes,10h) ;/
i=0, typ=0, num=0 ;\
while i<NumberOfHunks ;
if num=0 ; load huffman coded
x=GetHuffCode(codetree) ; map type values
if x=07h then ;COMPRESSION_RLE_SMALL ;
num=GetHuffCode(codetree)+03h ;
elseif x=08h then ;COMPRESSION_RLE_LARGE ;
num=GetHuffCode(codetree)*10h ;
num=GetHuffCode(codetree)+num+13h ;
else typ=x, num=1 ;
byte[map+i*0Ch+0]=typ, i=i+1, num=num-1 ;/
i=0, s=0, p=0 ;index,self,parent ;\
o=bigendian48bit[hdr+4] ;offset ; load other
while i<NumberOfHunks ; map items
typ=byte[map+i*0Ch+00h], ofs=o, len=0, crc=0 ;
if typ<04h then len=GetBits([hdr+0Ch]), crc=GetBits(16); ;Met
*Truncated - read the full file at https://github.com/sadnescity/psx-spx-claude-plugin/blob/72f1dc0b8596ee0bdadeeb9128ad9cf4452dc6b0/skills/cdrom-file-disc-images/SKILL.md.*