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 fprintf(log_get(), "CDI: Opening %s\n", path);
39 return open(path, O_BINARY | O_RDONLY);
42 void cdi_close(int fp)
44 fprintf(log_get(), "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;
59 uint32 previous_position=0;
64 descriptor=(s_cdi_descriptor *)malloc(sizeof(s_cdi_descriptor));
69 descriptor->length=tell(fp);
70 if (descriptor->length<8)
72 if (stdfp) fprintf(stdfp,"cdi: image is too short (%i bytes)\n",descriptor->length);
76 lseek(fp,descriptor->length-8,SEEK_SET);
77 read(fp,&descriptor->version,4);
78 read(fp,&descriptor->header_offset,4);
79 lseek(fp,descriptor->header_offset,SEEK_SET);
80 read(fp,&descriptor->nb_of_sessions,2);
82 descriptor->sessions=(s_cdi_session *)malloc(descriptor->nb_of_sessions*sizeof(s_cdi_session));
83 if (descriptor->sessions==0)
88 if (stdfp) fprintf(stdfp,"cdi: %i sessions\n",descriptor->nb_of_sessions);
89 uint32 track_position=0;
90 for (uint16 session=0;session<descriptor->nb_of_sessions;session++)
92 read(fp,&descriptor->sessions[session].nb_of_tracks,2);
93 descriptor->sessions[session].tracks=(s_cdi_track*)malloc(descriptor->sessions[session].nb_of_tracks*sizeof(s_cdi_track));
95 if (stdfp) fprintf(stdfp,"cdi:\ncdi: reading session %i (%i tracks)\n",session,descriptor->sessions[session].nb_of_tracks);
97 for (uint16 track=0;track<descriptor->sessions[session].nb_of_tracks;track++)
99 static char current_start_mark[10];
100 s_cdi_track *current_track=&descriptor->sessions[session].tracks[track];
101 if (stdfp) fprintf(stdfp,"cdi:\ncdi: \t\treading track %i\n",track);
105 read(fp,&temp_value, 4);
107 lseek(fp, 8, SEEK_CUR); // extra data (DJ 3.00.780 and up)
109 read(fp,current_start_mark, 10);
110 if (memcmp(cdi_track_start_mark, current_start_mark, 10))
112 if (stdfp) fprintf(stdfp,"cdi: could not find the track start mark");
115 read(fp,current_start_mark, 10);
116 if (memcmp(cdi_track_start_mark, current_start_mark, 10))
118 if (stdfp) fprintf(stdfp,"cdi: could not find the track start mark");
122 lseek(fp, 4, SEEK_CUR);
123 read(fp,¤t_track->filename_length, 1);
124 lseek(fp, current_track->filename_length, SEEK_CUR);
126 lseek(fp, 11, SEEK_CUR);
127 lseek(fp, 4, SEEK_CUR);
128 lseek(fp, 4, SEEK_CUR);
129 read(fp,&temp_value, 4);
130 if (temp_value == 0x80000000)
131 lseek(fp, 8, SEEK_CUR); // DJ4
132 lseek(fp, 2, SEEK_CUR);
134 read(fp, ¤t_track->pregap_length, 4);
135 if (current_track->pregap_length!=150)
137 fprintf(log_get(),"cdi: warning: pregap different than 150\n");
139 read(fp, ¤t_track->length, 4);
140 if (stdfp) fprintf(stdfp,"cdi: \t\t\tpregap length : %i\n", current_track->pregap_length);
141 if (stdfp) fprintf(stdfp,"cdi: \t\t\tlength : %i\n", current_track->length);
143 lseek(fp, 6, SEEK_CUR);
145 read(fp, ¤t_track->mode, 4);
146 if (stdfp) fprintf(stdfp,"cdi: \t\t\tmode : %i\n", current_track->mode);
148 lseek(fp, 12, SEEK_CUR);
149 read(fp, ¤t_track->start_lba, 4);
150 if (stdfp) fprintf(stdfp,"cdi: \t\t\tstart lba : %i\n", current_track->start_lba);
151 read(fp, ¤t_track->total_length, 4);
152 if (stdfp) fprintf(stdfp,"cdi: \t\t\ttotal length : %i\n", current_track->total_length);
153 lseek(fp, 16, SEEK_CUR);
154 read(fp, ¤t_track->sector_size_value, 4);
155 if (stdfp) fprintf(stdfp,"cdi: \t\t\tsector size : %i\n", current_track->sector_size_value);
157 switch(current_track->sector_size_value)
159 case 0 : current_track->sector_size = 2048; break;
160 case 1 : current_track->sector_size = 2336; break;
161 case 2 : current_track->sector_size = 2352; break;
163 if (stdfp) fprintf(stdfp,"cdi: \t\t\tunsupported %i bytes sector",current_track->sector_size_value);
168 if (current_track->mode > 2)
169 if (stdfp) fprintf(stdfp,"cdi: \t\t\ttrack mode %i not supported",current_track->mode);
171 lseek(fp, 29, SEEK_CUR);
172 if (descriptor->version != CDI_V2)
174 lseek(fp, 5, SEEK_CUR);
175 read(fp,&temp_value, 4);
176 if (temp_value == 0xffffffff)
177 lseek(fp, 78, SEEK_CUR); // extra data (DJ 3.00.780 and up)
179 current_track->position=track_position;
180 track_position+=(current_track->pregap_length+current_track->length)*current_track->sector_size;
181 previous_position=track_position;
183 lseek(fp, 4, SEEK_CUR);
184 lseek(fp, 8, SEEK_CUR);
185 if (descriptor->version != CDI_V2)
186 lseek(fp, 1, SEEK_CUR);
189 if (descriptor->header_offset == 0)
195 void cdi_dump_descriptor(FILE *fp,s_cdi_descriptor *cdi_descriptor)
197 fprintf(fp,"cdi: %i Mb\n",cdi_descriptor->length>>20);
198 fprintf(fp,"cdi: format version ");
199 switch(cdi_descriptor->version)
201 case CDI_V2: fprintf(fp,"2\n"); break;
202 case CDI_V3: fprintf(fp,"3\n"); break;
203 case CDI_V35: fprintf(fp,"3.5\n"); break;
204 default: fprintf(fp,"unknown\n"); break;
206 fprintf(fp,"cdi: %i sessions\n",cdi_descriptor->nb_of_sessions);
209 uint8 * cdi_extract_boot_code(int fp, s_cdi_descriptor * cdi_descriptor)
211 s_cdi_track * boot_track = &cdi_descriptor->sessions[1].tracks[0];
212 uint32 boot_track_size = boot_track->length * boot_track->sector_size;
214 uint8 * boot_track_data = (uint8 *)malloc(boot_track_size);
215 lseek(fp, 2 + (boot_track->position), SEEK_SET);
216 read(fp, boot_track_data, boot_track_size);
218 uint32 * boot_track_data_32 = (uint32 *)boot_track_data;
220 while (offset < (boot_track_size >> 2))
222 if (boot_track_data_32[offset] == 0x49205452)
226 if (offset == (boot_track_size >> 2))
228 fprintf(log_get(), "CDI: Cannot find the boot code\n");
232 offset = (offset << 2) + 4;
233 uint16 * data16 = (uint16 *)&boot_track_data[offset];
234 cdi_load_address = *data16++;
235 cdi_load_address <<= 16;
236 cdi_load_address |= *data16++;
237 cdi_code_length = *data16++;
238 cdi_code_length <<= 16;
239 cdi_code_length |= *data16++;
240 fprintf(log_get(), "CDI: Load address: %08X\n", cdi_load_address);
241 fprintf(log_get(), "CDI: Length: %08X\n", cdi_code_length);
242 //No need for byte swapping any more...
243 /* fprintf(log_get(), "cdi: byte swapping boot code\n");
245 for(uint32 i=0; i<(cdi_code_length >> 1); i++)
247 uint16 sdata = data16[i];
248 sdata = (sdata >> 8) | (sdata << 8);
252 return (uint8 *)data16;
255 void cdi_load_sector(uint32 sector, uint8 * buffer)
257 if (sector == 0xFFFFFFFF)
259 memset(buffer, 0x00, 2352);
265 lseek(cdi_fp, 2+sector, SEEK_SET);
266 read(cdi_fp, buffer, 2352);
268 //This is probably not needed any more...
270 for (uint32 i=0;i<2352;i+=2)
272 uint8 sdata=buffer[i+0];
273 buffer[i+0]=buffer[i+1];