TOC description


PJBTOC -- PJB TOC description

PJB TOC description

This is the original toc.txt documentation, that comes with the SDK, as provided by COMPAQ Research.

A TOC has the following structure

      Version Record (V)
      Root Record (R)
      Set Record (S)
          Disc Record (D)
                 Track Record (T)       (T, B, I repeated for
		 Track Location (B)	each track on a disc)
		 Track ID (I)
          Disc Record (D)
                 Track Record (T)       (T, B, I repeated for
		 Track Location (B)	each track on a disc)
		 Track ID (I)
      Set Record (S)
          Disc Record (D)
          Disc Record (D)
      ... (additional SET records)
      UID Records (U)
      End of file record (.)
      Allocation map records (+)

typedef struct fs_blkaddr {
    u8 addr[3];

typedef struct fs_allocblock {
	union {
	    struct {
		FS_BLKADDR h_next;            /* Next block in chain */
		FS_BLKADDR h_prev;            /* Previous block in chain */
		u8 userdata[1020];            /* Data not used by player */
		FS_BLKADDR h_next2;           /* Copy of "next block in chain" */
		FS_BLKADDR h_prev2;           /* Copy of "previous block in chain" */
	    } h;
	    u8 head[1032];
	} h;
        u8 body[130032];                      /* Body (mp3 data) */
	union {
	    struct {
		FS_BLKADDR t_next;            /* next block in chain */
		u8 t_chksum[4];               /* checksum of block */
		u8 t_unused;
	    } t;
	    u8 tail[8];
	} t;


Conceptual format of an allocation block---these are the parts of the allocation block known to the device.

A byte_t is a densely packed 8-bit quantity.

        struct fs_allocblock {
                byte_t head[1032];
                byte_t body[130032]
                byte_t tail[8]

The body is the MP3 data to play.

The number of the next allocation block to play after this allocation block

is head[0]*65536 + head[1]*256 + head[2] and tail[0]*65536 + tail[1]*256 + tail[2] where the bytes here are assumed to be unsigned.

That is, the number is stored twice, once at the start of the head, and once at the start of the tail, and in both cases the byte order is big-endian.

The number of the previous allocation block to access on rewind is head[3]*65536 + head[4]*256 + head[5] where the bytes here are assumed to be unsigned. These numbers are repeated at offset 1026. That is forall i = 1 .. 6: head[1026+i] = head[i]

The CRC of all bytes in the head, body and the first 3 bytes of the tail is stored in tail[4, .., 7]. The bytes should be bytes returned by the cksum() call (see the cksum interface).

There is an additional header section that the PC program maintains for its own purposes. The header starts at head[100] and also contains the following information (multi-byte quantities are big-endian):

the header version number (1 byte);

the content origin (1 byte) ... see AB_Origin_*;

the track number of the first sample in the block, byte value is 255 if not AB_Origin_CD (1 byte);

the "track offset" (in bytes) from the beginning of buffer of the beginning of a track (if this block contains a beginning of track); -1 otherwise;

the ordinal block number of this AB within a track, starting at zero (4 bytes);

the encoding type (1 byte)

the encoding bit rate (3 bytes)

the number of bytes in this track in this block (new as of hdr-version 2)

the CD-ID of the track's CD (null-terminated string) (AB_Origin_CD only);

the ID3 tags from an MP3 file (null-terminated string) (AB_Origin_ID3 only);

a checksum over the entire header (4 bytes)

Header bytes [6..99] are unused.

Note that for header version = 0, the AB checksum is erroneously computed over [0..AB_PayloadSize-4) rather than [0..AB_Size-5). Also, there is no encoding bit rate value or header checksum.

Note also that as of header version 2, if there are two tracks sharing a block, the header refers to the second of the two tracks. There cannot be more than 2 track in a block.


#define AB_ClickSize	1024
#define	AB_NClicks		128

#define AB_Size			(AB_ClickSize * AB_NClicks)
#define AB_HeaderSize	(1032) // so that PayloadSize is multiple of 12
#define AB_TrailerSize	(8)
#define	AB_TrailerStart	(AB_Size - AB_TrailerSize)
#define	AB_PayloadStart	(AB_HeaderSize)
#define	AB_PayloadSize	(AB_Size - AB_PayloadStart - AB_TrailerSize)

#define AB_NextLink		0
#define AB_PrevLink		3
#define AB_NextLink1	1026
#define AB_PrevLink1	1029

#define AB_PrivateHdr	(100)
#define AB_HdrVersion	(AB_PrivateHdr)
#define AB_Origin		(AB_PrivateHdr + 1)
#define AB_TrackNumber	(AB_PrivateHdr + 3)
#define AB_TrackOffset	(AB_PrivateHdr + 4)
#define AB_BlockInTrack	(AB_PrivateHdr + 8)
#define AB_Encoding		(AB_PrivateHdr + 12)
#define AB_Bitrate		(AB_PrivateHdr + 13)
#define AB_BytesInBlock	(AB_PrivateHdr + 16)
#define AB_CDID			(AB_PrivateHdr + 60)
#define AB_ID3_TAG		(AB_PrivateHdr + 60)

#define AB_HdrCRC		(1020)  // so that header+CRC can fit in 1024
#define AB_HdrCRCSize	(AB_HdrCRC)  // so that header+CRC can fit in 1024

#define	AB_AltNextLink	(AB_TrailerStart)
#define AB_CRC			(AB_TrailerStart + 4)
#define AB_CRCSize		(AB_AltNextLink + 3)

//#define AB_Origin_CD	(0)		// audio CD capture
//#define AB_Origin_ID3	(1)     // ID3 tagged MP3 file
//#define AB_Origin_Unk	(2)     // untagged MP3 file

#define AB_CURR_HDR_VERSION		(2)