2 // CD Interface handler
5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Cleanups by James L. Hammons
11 /* Added by SDLEMU (http://sdlemu.ngemu.com) */
12 /* Added for GCC UNIX compatibility */
15 #include <sys/types.h>
21 #define CDI_V2 0x80000004
22 #define CDI_V3 0x80000005
23 #define CDI_V35 0x80000006
25 static uint8 cdi_track_start_mark[10] =
26 { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF };
29 uint32 cdi_load_address;
30 uint32 cdi_code_length;
31 s_cdi_descriptor * cdi_descriptor;
32 s_cdi_track ** cdi_tracks;
33 uint32 cdi_tracks_count;
36 int cdi_open(char * path)
38 WriteLog("CDI: Opening %s\n", path);
39 return open(path, O_BINARY | O_RDONLY);
42 void cdi_close(int fp)
44 WriteLog("CDI: Closing\n");
51 return lseek(fd, 0LL, SEEK_CUR);
55 s_cdi_descriptor * cdi_get_descriptor(int fp, FILE * stdfp)
57 s_cdi_descriptor * descriptor;
58 uint32 previous_position = 0;
63 descriptor = (s_cdi_descriptor *)malloc(sizeof(s_cdi_descriptor));
65 if (descriptor == NULL)
68 lseek(fp, 0, SEEK_END);
69 //Why??? descriptor->length=tell(fp);
70 descriptor->length = lseek(fp, 0LL, SEEK_CUR);
72 if (descriptor->length < 8)
75 fprintf(stdfp, "CDI: Image is too short (%i bytes)\n", (int)descriptor->length);
80 lseek(fp, descriptor->length - 8, SEEK_SET);
81 read(fp, &descriptor->version, 4);
82 read(fp, &descriptor->header_offset, 4);
83 lseek(fp, descriptor->header_offset, SEEK_SET);
84 read(fp, &descriptor->nb_of_sessions, 2);
86 descriptor->sessions=(s_cdi_session *)malloc(descriptor->nb_of_sessions * sizeof(s_cdi_session));
88 if (descriptor->sessions == NULL)
95 fprintf(stdfp, "CDI: %i sessions\n", descriptor->nb_of_sessions);
97 uint32 track_position = 0;
98 for(uint16 session=0; session<descriptor->nb_of_sessions; session++)
100 read(fp, &descriptor->sessions[session].nb_of_tracks, 2);
101 descriptor->sessions[session].tracks = (s_cdi_track *)malloc(descriptor->sessions[session].nb_of_tracks * sizeof(s_cdi_track));
104 fprintf(stdfp, "CDI:\nCDI: Reading session %i (%i tracks)\n", session, descriptor->sessions[session].nb_of_tracks);
106 for (uint16 track=0; track<descriptor->sessions[session].nb_of_tracks; track++)
108 static char current_start_mark[10];
109 s_cdi_track * current_track=&descriptor->sessions[session].tracks[track];
111 fprintf(stdfp, "CDI:\nCDI: \t\tReading track %i\n",track);
115 read(fp, &temp_value, 4);
118 lseek(fp, 8, SEEK_CUR); // extra data (DJ 3.00.780 and up)
120 read(fp, current_start_mark, 10);
122 if (memcmp(cdi_track_start_mark, current_start_mark, 10))
125 fprintf(stdfp, "CDI: Could not find the track start mark\n");
129 read(fp, current_start_mark, 10);
131 if (memcmp(cdi_track_start_mark, current_start_mark, 10))
134 fprintf(stdfp, "CDI: Could not find the track start mark\n");
138 lseek(fp, 4, SEEK_CUR);
139 read(fp, ¤t_track->filename_length, 1);
140 lseek(fp, current_track->filename_length, SEEK_CUR);
142 lseek(fp, 11, SEEK_CUR);
143 lseek(fp, 4, SEEK_CUR);
144 lseek(fp, 4, SEEK_CUR);
145 read(fp, &temp_value, 4);
147 if (temp_value == 0x80000000)
148 lseek(fp, 8, SEEK_CUR); // DJ4
150 lseek(fp, 2, SEEK_CUR);
152 read(fp, ¤t_track->pregap_length, 4);
154 if (current_track->pregap_length != 150)
155 WriteLog("CDI: Warning: Pregap different than 150\n");
157 read(fp, ¤t_track->length, 4);
160 fprintf(stdfp, "CDI: \t\t\tPregap length: %i\n", (int)current_track->pregap_length);
162 fprintf(stdfp, "CDI: \t\t\tLength: %i\n", (int)current_track->length);
164 lseek(fp, 6, SEEK_CUR);
166 read(fp, ¤t_track->mode, 4);
169 fprintf(stdfp, "CDI: \t\t\tMode: %i\n", (int)current_track->mode);
171 lseek(fp, 12, SEEK_CUR);
172 read(fp, ¤t_track->start_lba, 4);
175 fprintf(stdfp, "CDI: \t\t\tStart LBA: %i\n", (int)current_track->start_lba);
177 read(fp, ¤t_track->total_length, 4);
180 fprintf(stdfp, "CDI: \t\t\tTotal length: %i\n", (int)current_track->total_length);
182 lseek(fp, 16, SEEK_CUR);
183 read(fp, ¤t_track->sector_size_value, 4);
186 fprintf(stdfp, "CDI: \t\t\tSector size: %i\n", (int)current_track->sector_size_value);
188 switch(current_track->sector_size_value)
190 case 0: current_track->sector_size = 2048; break;
191 case 1: current_track->sector_size = 2336; break;
192 case 2: current_track->sector_size = 2352; break;
196 fprintf(stdfp, "CDI: \t\t\tUnsupported %i bytes sector\n", (int)current_track->sector_size_value);
201 if (current_track->mode > 2)
203 fprintf(stdfp, "CDI: \t\t\tTrack mode %i not supported\n", (int)current_track->mode);
205 lseek(fp, 29, SEEK_CUR);
207 if (descriptor->version != CDI_V2)
209 lseek(fp, 5, SEEK_CUR);
210 read(fp, &temp_value, 4);
212 if (temp_value == 0xFFFFFFFF)
213 lseek(fp, 78, SEEK_CUR); // extra data (DJ 3.00.780 and up)
216 current_track->position = track_position;
217 track_position += (current_track->pregap_length+current_track->length) * current_track->sector_size;
218 previous_position = track_position;
221 lseek(fp, 4, SEEK_CUR);
222 lseek(fp, 8, SEEK_CUR);
224 if (descriptor->version != CDI_V2)
225 lseek(fp, 1, SEEK_CUR);
229 if (descriptor->header_offset == 0)
235 void cdi_dump_descriptor(FILE * fp, s_cdi_descriptor * cdi_descriptor)
237 fprintf(fp, "CDI: %i Mb\n", (int)(cdi_descriptor->length >> 20));
238 fprintf(fp, "CDI: Format version ");
239 switch(cdi_descriptor->version)
248 fprintf(fp, "3.5\n");
251 fprintf(fp, "unknown\n");
253 fprintf(fp, "CDI: %i sessions\n", cdi_descriptor->nb_of_sessions);
256 uint8 * cdi_extract_boot_code(int fp, s_cdi_descriptor * cdi_descriptor)
258 s_cdi_track * boot_track = &cdi_descriptor->sessions[1].tracks[0];
259 uint32 boot_track_size = boot_track->length * boot_track->sector_size;
261 uint8 * boot_track_data = (uint8 *)malloc(boot_track_size);
262 lseek(fp, 2 + (boot_track->position), SEEK_SET);
263 read(fp, boot_track_data, boot_track_size);
265 uint32 * boot_track_data_32 = (uint32 *)boot_track_data;
267 while (offset < (boot_track_size >> 2))
269 if (boot_track_data_32[offset] == 0x49205452)
273 if (offset == (boot_track_size >> 2))
275 WriteLog("CDI: Cannot find the boot code\n");
279 //This is likely wrong, but won't get a chance to fix it until I can get a CD image
281 offset = (offset << 2) + 4;
282 uint16 * data16 = (uint16 *)&boot_track_data[offset];
283 cdi_load_address = *data16++;
284 cdi_load_address <<= 16;
285 cdi_load_address |= *data16++;
286 cdi_code_length = *data16++;
287 cdi_code_length <<= 16;
288 cdi_code_length |= *data16++;
289 WriteLog("CDI: Load address: %08X\n", cdi_load_address);
290 WriteLog("CDI: Length: %08X\n", cdi_code_length);
291 //No need for byte swapping any more...
292 /* WriteLog("cdi: byte swapping boot code\n");
294 for(uint32 i=0; i<(cdi_code_length >> 1); i++)
296 uint16 sdata = data16[i];
297 sdata = (sdata >> 8) | (sdata << 8);
301 return (uint8 *)data16;
304 void cdi_load_sector(uint32 sector, uint8 * buffer)
306 if (sector == 0xFFFFFFFF)
308 memset(buffer, 0x00, 2352);
314 lseek(cdi_fp, 2+sector, SEEK_SET);
315 read(cdi_fp, buffer, 2352);
317 //This is probably not needed any more...
319 for (uint32 i=0;i<2352;i+=2)
321 uint8 sdata=buffer[i+0];
322 buffer[i+0]=buffer[i+1];