2 * This file has been modified for the cdrkit suite.
4 * The behaviour and appearence of the program code below can differ to a major
5 * extent from the version distributed by the original author(s).
7 * For details, see Changelog file distributed with the cdrkit package. If you
8 * received this file from another source then ask the distributing person for
9 * a log of modifications.
13 /* @(#)cd_extra.c 1.8 02/11/21 Copyright 2000-2001 Heiko Eissfeldt */
15 /* This is an include file! */
16 /**************** CD-Extra special treatment *********************************/
20 static unsigned long Read_CD_Extra_File(unsigned char *Extra_buf, unsigned long sector);
23 Read_CD_Extra_File(unsigned char *Extra_buf, unsigned long sector)
28 ReadCdRomData(get_scsi_p(), Extra_buf, sector+16, 1);
30 /* check ISO signature */
31 if (memcmp(Extra_buf, "\001CD001", 6) != 0) return 0;
34 mysec = Extra_buf[148] << 24;
35 mysec |= Extra_buf[149] << 16;
36 mysec |= Extra_buf[150] << 8;
37 mysec |= Extra_buf[151];
39 if (mysec <= sector) return 0;
42 ReadCdRomData(get_scsi_p(), Extra_buf, mysec, 1);
44 /* find cdplus subdirectory */
45 { unsigned char * p = Extra_buf;
46 while (p+8 < Extra_buf + CD_FRAMESIZE_RAW) {
49 namelength = p[0] | (p[1] << 8);
50 if (namelength == 6 &&
51 !memcmp(p+8, "CDPLUS", 6)) break;
53 p += 8 + namelength + (namelength & 1);
55 if (p+8 >= Extra_buf + CD_FRAMESIZE_RAW) return 0;
64 if (mysec <= sector) return 0;
66 ReadCdRomData(get_scsi_p(), Extra_buf, mysec, 1);
68 /* find file info.cdp */
69 { unsigned char * p = Extra_buf;
70 while (p+33 < Extra_buf + CD_FRAMESIZE_RAW) {
74 if (namelength == 10 &&
75 !memcmp(p+33, "INFO.CDP;1", 10)) break;
79 if (p+33 >= Extra_buf + CD_FRAMESIZE_RAW) return 0;
88 if (mysec <= sector) return 0;
90 /* read file info.cdp */
91 ReadCdRomData(get_scsi_p(), Extra_buf, mysec, 1);
93 return mysec - sector;
96 static unsigned char Extra_buffer[CD_FRAMESIZE_RAW];
99 * Read the file cdplus/info.cdp from the cd extra disc.
100 * This file has to reside at exactly 75 sectors after start of
101 * the last session (according to Blue Book).
102 * Of course, there are a lot dubious cd extras, which don't care :-(((
103 * As an alternative method, we try reading through the iso9660 file system...
105 static int Read_CD_Extra_Info(unsigned long sector);
106 static int Read_CD_Extra_Info(unsigned long sector)
109 static int offsets[] = {
110 75 /* this is what blue book says */
113 for (i = 0; i < sizeof(offsets)/sizeof(int); i++) {
115 fprintf(stderr, "debug: Read_CD_Extra_Info at sector %lu\n", sector+offsets[i]);
117 ReadCdRomData(get_scsi_p(), Extra_buffer, sector+offsets[i], 1);
119 /* If we are unlucky the drive cannot handle XA sectors by default.
120 We try to compensate by ignoring the first eight bytes.
121 Of course then we lack the last 8 bytes of the sector...
124 if (Extra_buffer[0] == 0)
125 memmove(Extra_buffer, Extra_buffer +8, CD_FRAMESIZE - 8);
127 /* check for cd extra */
128 if (Extra_buffer[0] == 'C' && Extra_buffer[1] == 'D')
129 return sector+offsets[i];
132 * CD is not conforming to BlueBook!
133 * Read the file through ISO9660 file system.
136 unsigned long offset = Read_CD_Extra_File(Extra_buffer, sector);
138 if (offset == 0) return 0;
140 if (Extra_buffer[0] == 0)
141 memmove(Extra_buffer, Extra_buffer +8, CD_FRAMESIZE - 8);
143 /* check for cd extra */
144 if (Extra_buffer[0] == 'C' && Extra_buffer[1] == 'D')
145 return sector+offset;
152 static void Read_Subinfo(unsigned pos, unsigned length);
153 static void Read_Subinfo(unsigned pos, unsigned length)
155 unsigned num_infos, num;
156 unsigned char *Subp, *orgSubp;
157 unsigned this_track = 0xff;
166 length = (length + CD_FRAMESIZE_RAW-1) / CD_FRAMESIZE_RAW;
167 length *= CD_FRAMESIZE_RAW;
168 orgSubp = Subp = malloc(length);
171 fprintf(stderr, "Read_Subinfo no memory(%d)\n",length);
175 ReadCdRomData(get_scsi_p(), Subp, pos, 1);
177 num_infos = Subp[45]+(Subp[44] << 8);
179 fprintf(stderr, "subinfo version %c%c.%c%c, %d info packets\n",
188 for (num = 0; num < num_infos && length > 0; num++) {
190 unsigned len = *(Subp +1);
191 #define INFOPACKETTYPES 0x44
192 #ifdef INFOPACKETSTRINGS
193 static const char *infopacketID[INFOPACKETTYPES] = { "0",
196 "universal product code",
197 "international standard book number",
202 "secondary interpret",
213 "14", "15", "16", "17", "18", "19",
214 "copyright state SUB_INFO",
215 "copyright state intro lyrics",
216 "copyright state lyrics",
217 "copyright state MIDI data",
220 "pointer to lyrics text file and length",
221 "22", "23", "24", "25", "26", "27", "28",
222 "29", "2a", "2b", "2c", "2d", "2e", "2f",
223 "still picture descriptor",
225 "32", "33", "34", "35", "36", "37", "38",
226 "39", "3a", "3b", "3c", "3d", "3e", "3f",
227 "MIDI file descriptor",
234 if (id >= INFOPACKETTYPES) {
235 fprintf(stderr, "Off=%4d, ind=%2d/%2d, unknown Id=%2u, len=%2u ",
236 /* this pointer difference is assumed to be small enough for an int. */
237 (int)(Subp - orgSubp)
238 , num, num_infos, id, len);
244 fprintf(stderr, "info packet %d\n", id);
248 case 1: /* track nummer or 0 */
249 this_track = 10 * (*(Subp + 2) - '0') + (*(Subp + 3) - '0');
252 case 0x02: /* album title */
253 if (global.disctitle == NULL) {
254 global.disctitle = malloc(len + 1);
255 if (global.disctitle != NULL) {
256 memcpy(global.disctitle, Subp + 2, len);
257 global.disctitle[len] = '\0';
261 case 0x03: /* media catalog number */
262 if (Get_MCN()[0] == '\0' && Subp[2] != '\0' && len >= 13) {
266 case 0x06: /* track title */
267 if (this_track > 0 && this_track < 100
268 && global.tracktitle[this_track] == NULL) {
269 global.tracktitle[this_track] = malloc(len + 1);
270 if (global.tracktitle[this_track] != NULL) {
271 memcpy(global.tracktitle[this_track], Subp + 2, len);
272 global.tracktitle[this_track][len] = '\0';
276 case 0x05: /* copyright message */
277 if (global.copyright_message == NULL) {
278 global.copyright_message = malloc(len + 1);
279 if (global.copyright_message != NULL) {
280 memcpy(global.copyright_message, Subp + 2, len);
281 global.copyright_message[len] = '\0';
285 case 0x08: /* creator */
286 if (global.creator == NULL) {
287 global.creator = malloc(len + 1);
288 if (global.creator != NULL) {
289 memcpy(global.creator, Subp + 2, len);
290 global.creator[len] = '\0';
294 case 0x10: /* isrc */
295 if (this_track > 0 && this_track < 100
296 && Get_ISRC(this_track)[0] == '\0' && Subp[2] != '\0'
298 Set_ISRC(this_track, Subp + 2);
311 #ifdef INFOPACKETSTRINGS
312 fprintf(stderr, "%s: %*.*s\n",infopacketID[id], (int) len, (int) len, (Subp +2));
320 #ifdef INFOPACKETSTRINGS
321 fprintf(stderr, "%s %scopyrighted\n", infopacketID[id], *(Subp + 2) == 0 ? "not " : "");
326 fprintf(stderr, "lyrics file beginning at sector %u",
327 (unsigned) GET_BE_UINT_FROM_CHARP(Subp + 2));
329 fprintf(stderr, ", having length: %u\n",
330 (unsigned) GET_BE_UINT_FROM_CHARP(Subp + 6));
337 while (sp < Subp + 2 + len) {
338 /*while (len >= 10) {*/
339 s = be16_to_cpu((*(sp)) | (*(sp) << 8));
340 fprintf(stderr, "%04x, ", s);
353 u = GET_BE_UINT_FROM_CHARP(up);
354 fprintf(stderr, "%04lx, ", (long) u);
356 u = GET_BE_UINT_FROM_CHARP(up);
357 fprintf(stderr, "%04lx, ", (long) u);
365 fprintf(stderr, "MIDI file beginning at sector %u",
366 (unsigned) GET_BE_UINT_FROM_CHARP(Subp + 2));
368 fprintf(stderr, ", having length: %u\n",
369 (unsigned) GET_BE_UINT_FROM_CHARP(Subp + 6));
374 #ifdef INFOPACKETSTRINGS
376 fprintf(stderr, "%s: %d beats per minute\n",infopacketID[id], *(Subp + 2));
380 fprintf(stderr, "%s: %x, %x, %x, %x, %x, %x, %x, %x\n",
392 fprintf(stderr, "%s:\n",infopacketID[id]);
395 fprintf(stderr, "%s: %x\n",infopacketID[id], *(Subp + 2));
398 fprintf(stderr, "%s: %*.*s\n",infopacketID[id], (int) len, (int) len, (Subp +2));