Eric Woudenberg
December, 1999
In light of this I thought it would be interesting to describe what I learned recently while working with a Sony MDH-10 Data drive. These drives were developed for use with special MD-Data discs but can also be used to read and write an MD-Audio disc's UTOC. Using this capability, Wolfgang Buresch (see references) investigated much of the basic information in the UTOC, though without detailing specific fields. Following his lead, I was able to get a reasonably accurate idea of the MD's on-disc data structures, which I describe below. Please note that my experiments were conducted chiefly by examining the UTOC manipulations made by a Sony MZ-R50 portable recorder, and so I make no claim that all MD units behave in precisely the ways I describe.
In the discussion that follows, it is important to understand the difference between what I term tracks and fragments. A track is the normal CD-like audio track that MD users see when playing, recording, and editing MDs. A fragment refers to a contiguous segment of audio data on the disc. Each MD track is made up of one or more individual fragments, and fragments are not generally visible to MD users (though some Sony decks allow you to see them from retry cause display mode). Fragments are typically created each time a recording begins and through editing operations (see editing operations, below).
The UTOC can be read and written by all MD recorders, and read by all MD players. It occupies several disc sectors, each 2336 bytes long. UTOC sector #0 describes the disc addresses of each track's audio information, sector #1 holds the characters in the track titles, and sector #2 holds track timestamp information. According to other documentation I've read, sector #3 contains the Barcode for the disc and ISRC for the music, and sector #4 contains Disk title, music titles and artist in ISO-8895-1 format.
On the Sony MDH-10 data drive, the UTOC is read one sector at a time with a group 1 SCSI command (ReadUTOC opcode is 0xD1). The block address given in the ReadUTOC command is 0, 1, or 2, corresponding to the 0th, 1st or 2nd UTOC sector. The data length is 2336 bytes.
The disc start and end addresses each consist of a cluster, sector, and sound group, all packed into 3 bytes. The sound group is the MiniDisc's smallest addressable unit, representing 11.6ms of mono audio (212 bytes). A sector contains 11 sound groups (2332 bytes). A cluster is an aggregate of 32 sectors (352 sound groups) representing 2.03 seconds of stereo audio; it is the smallest unit of data that can be written to a MiniDisc. In the 3 byte packing, there are 14 bits allocated to the cluster number, 6 bits to the sector, and 4 bits to the soundgroup; this arrangement allows addressing of up to 9.2 hours of stereo audio.
Since the freelist is intended to hold disc space that can be re-used for new recordings, short fragments (those less than 12 stereo seconds long) are not added to it. This 12 second restriction compensates for the long seek times typical in MD equipment by allowing the shock memory to fill after each seek (see fragmentation question in the FAQ).
These short, freelist ineligible bits of space are apparently not kept
track of in the UTOC. Using an MZ-R50 I found that, for example, tiny
sections of unused space left at the end of a cluster appeared nowhere
in the UTOC. Subsequent disc editing demonstrated that the MZ-R50 had
not lost track of this unused space and would coalesce it with other
unused space whenever possible. This led me to understand that the
freelist is not strictly necessary; its information can be recreated
by subtracting the allocated fragments from the space of the whole
disc. I believe this is how modern Sony MD decks are able to
circumvent "hacked" MDs with special freelists that extend their
recording time (see the Miyadisc compatibility tables); the decks are
able to independently validate the freelist and reject ones that are
out of bounds.
Data Structures
The UTOC Address Sector's C structures are as follows:
/* UTOC sector #0 (Address info). 2336 bytes */ typedef struct { uchar unknown_0[0xc]; /* ? */ short sign; /* signature of last UTOC updater */ uchar nonempty; /* ?flag indicating disc is not blank */ uchar ntracks; /* number of tracks on disc */ uchar unknown_1[0xf]; /* ? */ uchar free_track_slot; /* next empty track slot */ uchar trackmap[256]; /* map track no. to slot in fraglist, entry 0 represents freelist */ fragment fraglist[256]; } UTOC_0; /* * Fragment definition -- * contains start and end addresses for one contiguous region of audio. * 8 bytes. */ typedef struct { discaddr start; uchar mode; /* track mode */ # define F_PREEMPH 0x1 # define F_STEREO 0x2 /* 1 for SP stereo/LP2 mode, 0 for SP mono/LP4 mode audio tracks */ # define F_SP_MODE 0x4 /* 1 for SP mode, 0 for LP mode audio tracks */ # define F_UNK1 0x8 /* value always 0 for normal audio tracks */ # define F_AUDIO 0x10 /* 0 for audio track (1 for non-audio?) */ # define F_SCMS_CPY 0x20 /* SCMS: digital copy (original if clear) */ # define F_SCMS_UNR 0x40 /* SCMS: unrestricted i.e. no copyright (copyrighted if clear) */ # define F_WRTENB 0x80 /* writeable (fragment is readonly when clear) */ /* SCMS shorthand */ # define F_SCMSBITS 0x60 /* mask for extracting SCMS bits */ # define F_SCMS00 (F_SCMS_CPY|F_SCMS_UNR) /* unlimited copies allowed */ # define F_SCMS10 (F_SCMS_CPY) /* no copies allowed (recording source was digital) */ # define F_SCMS11 0 /* allow 1 generation (recording source was analog) */ discaddr end; uchar link; /* if non-zero, gives next fragment */ } fragment;See also page 10 of the JE520 Service Manual for the above bit definitions./* * Cluster, Sector, Group; 3 bytes, packed as follows: * c = cluster, s = sector, g = sound group. * byte 0 byte 1 byte 2 * cccc.cccc cccc.ccss ssss.gggg */ typedef struct { uchar csg[3]; } discaddr;
/* UTOC sector #1 (Title info). 2336 bytes */ typedef struct { uchar unknown[0x1f]; uchar free_title_slot; /* next free titlelist slot */ uchar titlemap[256]; /* map track no. to slot in titlelist */ titlecell titlelist[256]; } UTOC_1; /* Title cell -- up to 7 characters of a title */ typedef struct { char title[7]; /* ASCII title info */ uchar link; /* if non-zero, title continues at this titlelist entry */ } titlecell;
Note that a timestamp is associated with a track, not a fragment. Although there is space in the UTOC to place a timestamp on each fragment (thereby making it an indelible record of when each fragment was recorded), this approach was not taken. (Perhaps the bookkeeping operations necessary for that would have been too complex.)
One unusual member of the timestamp structure is the 16 bit signature value. This value is apparently unique to every MiniDisc recorder, and through experimentation we have determined a few of its values:
Make & Model Signature Aiwa AM-F70 D0A Sharp MD-MS701 A11 Sony MZ-R3 124 Sony MZ-R30 126 Sony MZ-R50 127 Sony MDS-303 144 Sony MDS-503 145 Sony MDS-JE500/JE510 146 Sony MDS-B5 (pro deck) 147 Sony MDS-JE520 14A Sony MDS-JB920/JB730/JE530/JE330 14D Sony MDS-JB940 154 Sony MDS-JE440 14D Sony MDS-W1 14C
/* UTOC sector #2 (Date and Time info). 2336 bytes */ typedef struct { uchar unknown[0x1f]; uchar free_time_slot; /* next free timelist slot */ uchar timemap[256]; /* map track no. to slot in timelist */ timestamp timelist[256]; } UTOC_2; /* Timestamp */ typedef struct { uchar y, mo, d, h, m, s; /* values are printed correctly in hex! */ short signature; /* "signature" of machine that wrote this track */ } timestamp;
DIVIDE (a.k.a. TRACK MARK) creates a new track and (usually) a new fragment. The new fragment is made by splitting an existing one such that the two resulting fragments point at disc regions that abut each other at the divide point. The preceeding fragment remains in the existing track, the succeeding fragment (and all the fragments it links to) become the new track. A special case occurs when a track is split exactly at a fragment boundary, in this case no fragment splitting need occur. The timestamp information is also split, and the second track's timestamp is updated to reflect the new offset.
JOIN (a.k.a. REMOVE TRACK MARK) links the fragments of the succeeding track onto the last fragment of the preceeding track and then removes the succeeding track. A special case occurs when the fragments at the join point are for abutting disc regions, in this case it is possible to coalesce the two fragments into one.
MOVE simply shuffles entries in the trackmap, titlemap, and timemap; no fragment manipulation is necessary.
DELETE removes a track and all the fragments associated with it. The removed fragments are placed on the freelist.
RECORD creates a new track and takes fragments from the freelist. When a freelist fragment is not fully consumed, a fragment consisting of the remainder (if sufficiently long) is placed on the freelist. Recorders can only start a recording on a cluster boundary, since a cluster is the smallest writable unit on an MD.
The UTOC title structure limits MD track titling to a total of 1785 characters (255 cells * 7 chars/cell) and 255 titles. A disc with 255 titled tracks illustrates these limitations; there would be no room on such a disc for the disc title, and there could be no more than 7 characters in any title.