]> Shamusworld >> Repos - virtualjaguar/blob - src/cdi.cpp
Initial revision
[virtualjaguar] / src / cdi.cpp
1 #include "cdi.h"
2
3 /* Added by SDLEMU (http://sdlemu.ngemu.com) */
4 /* Added for GCC UNIX compatibility          */
5 #ifdef __GCCUNIX__
6         #include <unistd.h>
7         #include <sys/types.h>
8         #include <fcntl.h>
9
10         #define O_BINARY (0)
11 #endif
12
13 #define CDI_V2  0x80000004
14 #define CDI_V3  0x80000005
15 #define CDI_V35 0x80000006
16
17 static uint8 cdi_track_start_mark[10] = { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF };
18
19
20
21 int cdi_fp;
22 uint32 cdi_load_address;
23 uint32 cdi_code_length;
24 s_cdi_descriptor        *cdi_descriptor;
25 s_cdi_track                     **cdi_tracks;
26 uint32                          cdi_tracks_count;
27
28
29 //////////////////////////////////////////////////////////////////////////////
30 //
31 //////////////////////////////////////////////////////////////////////////////
32 //
33 //
34 //
35 //
36 //
37 //
38 //////////////////////////////////////////////////////////////////////////////
39 int cdi_open(char *path)
40 {
41         fprintf(log_get(),"cdi: opening %s\n",path);
42         return(open(path,O_BINARY|O_RDONLY));
43 }
44 //////////////////////////////////////////////////////////////////////////////
45 //
46 //////////////////////////////////////////////////////////////////////////////
47 //
48 //
49 //
50 //
51 //
52 //
53 //////////////////////////////////////////////////////////////////////////////
54 void cdi_close(int fp)
55 {
56         fprintf(log_get(),"cdi: closing\n");
57         close(fp);
58 }
59 //////////////////////////////////////////////////////////////////////////////
60 //
61 //////////////////////////////////////////////////////////////////////////////
62 //
63 //
64 //
65 //
66 //
67 //
68 //////////////////////////////////////////////////////////////////////////////
69 #ifdef __PORT__
70 long tell(int fd)
71 {
72         return lseek(fd, 0LL, SEEK_CUR);
73 }
74 #endif
75 s_cdi_descriptor *cdi_get_descriptor(int fp, FILE *stdfp)
76 {
77         s_cdi_descriptor *descriptor;
78         
79         uint32 previous_position=0;
80
81         if (fp==-1)
82                 return(0);
83
84         descriptor=(s_cdi_descriptor *)malloc(sizeof(s_cdi_descriptor));
85         if (descriptor==0)
86                 return(0);
87
88         lseek(fp,0,SEEK_END);
89         descriptor->length=tell(fp);
90         if (descriptor->length<8)
91         {
92                 if (stdfp) fprintf(stdfp,"cdi: image is too short (%i bytes)\n",descriptor->length);
93                 free(descriptor);
94                 return(0);
95         }
96         lseek(fp,descriptor->length-8,SEEK_SET);
97         read(fp,&descriptor->version,4);
98         read(fp,&descriptor->header_offset,4);
99         lseek(fp,descriptor->header_offset,SEEK_SET);
100         read(fp,&descriptor->nb_of_sessions,2);
101
102         descriptor->sessions=(s_cdi_session *)malloc(descriptor->nb_of_sessions*sizeof(s_cdi_session));
103         if (descriptor->sessions==0)
104         {
105                 free(descriptor);
106                 return(0);
107         }
108         if (stdfp) fprintf(stdfp,"cdi: %i sessions\n",descriptor->nb_of_sessions);
109         uint32 track_position=0;
110         for (uint16 session=0;session<descriptor->nb_of_sessions;session++)
111         {
112                 read(fp,&descriptor->sessions[session].nb_of_tracks,2);
113                 descriptor->sessions[session].tracks=(s_cdi_track*)malloc(descriptor->sessions[session].nb_of_tracks*sizeof(s_cdi_track));
114
115                 if (stdfp) fprintf(stdfp,"cdi:\ncdi: reading session %i (%i tracks)\n",session,descriptor->sessions[session].nb_of_tracks);
116
117                 for (uint16 track=0;track<descriptor->sessions[session].nb_of_tracks;track++)
118                 {
119                         static char current_start_mark[10];
120                         s_cdi_track *current_track=&descriptor->sessions[session].tracks[track];
121                         if (stdfp) fprintf(stdfp,"cdi:\ncdi: \t\treading track %i\n",track);
122
123                         uint32 temp_value;
124
125                         read(fp,&temp_value, 4);
126                         if (temp_value != 0)
127                                 lseek(fp, 8, SEEK_CUR); // extra data (DJ 3.00.780 and up)
128         
129                         read(fp,current_start_mark, 10);
130                         if (memcmp(cdi_track_start_mark, current_start_mark, 10)) 
131                         {
132                                 if (stdfp) fprintf(stdfp,"cdi: could not find the track start mark");
133                                 return(0);
134                         }
135                         read(fp,current_start_mark, 10);
136                         if (memcmp(cdi_track_start_mark, current_start_mark, 10)) 
137                         {
138                                 if (stdfp) fprintf(stdfp,"cdi: could not find the track start mark");
139                                 return(0);
140                         }
141
142                         lseek(fp, 4, SEEK_CUR);
143                         read(fp,&current_track->filename_length, 1);
144                         lseek(fp, current_track->filename_length, SEEK_CUR);
145
146                         lseek(fp, 11, SEEK_CUR);
147                         lseek(fp, 4, SEEK_CUR);
148                         lseek(fp, 4, SEEK_CUR);
149                         read(fp,&temp_value, 4);
150                         if (temp_value == 0x80000000)
151                                 lseek(fp, 8, SEEK_CUR); // DJ4
152                         lseek(fp, 2, SEEK_CUR);
153                         
154                         read(fp, &current_track->pregap_length, 4);
155                         if (current_track->pregap_length!=150)
156                         {
157                                 fprintf(log_get(),"cdi: warning: pregap different than 150\n");
158                         }
159                         read(fp, &current_track->length, 4);
160                         if (stdfp) fprintf(stdfp,"cdi: \t\t\tpregap length : %i\n", current_track->pregap_length);
161                         if (stdfp) fprintf(stdfp,"cdi: \t\t\tlength : %i\n", current_track->length);
162
163                         lseek(fp, 6, SEEK_CUR);
164                         
165                         read(fp, &current_track->mode, 4);
166                         if (stdfp) fprintf(stdfp,"cdi: \t\t\tmode : %i\n", current_track->mode);
167
168                         lseek(fp, 12, SEEK_CUR);
169                         read(fp, &current_track->start_lba, 4);
170                         if (stdfp) fprintf(stdfp,"cdi: \t\t\tstart lba : %i\n", current_track->start_lba);
171                         read(fp, &current_track->total_length, 4);
172                         if (stdfp) fprintf(stdfp,"cdi: \t\t\ttotal length : %i\n", current_track->total_length);
173                         lseek(fp, 16, SEEK_CUR);
174                         read(fp, &current_track->sector_size_value, 4);
175                         if (stdfp) fprintf(stdfp,"cdi: \t\t\tsector size : %i\n", current_track->sector_size_value);
176
177                         switch(current_track->sector_size_value)
178                         {
179                         case 0 : current_track->sector_size = 2048; break;
180                         case 1 : current_track->sector_size = 2336; break;
181                         case 2 : current_track->sector_size = 2352; break;
182                         default: {
183                                                 if (stdfp) fprintf(stdfp,"cdi: \t\t\tunsupported %i bytes sector",current_track->sector_size_value);
184                                                 return(0);
185                                         }
186                         }
187                         
188                         if (current_track->mode > 2) 
189                                 if (stdfp) fprintf(stdfp,"cdi: \t\t\ttrack mode %i not supported",current_track->mode);
190
191                         lseek(fp, 29, SEEK_CUR);
192                         if (descriptor->version != CDI_V2)
193                         {
194                                 lseek(fp, 5, SEEK_CUR);
195                                 read(fp,&temp_value, 4);
196                                 if (temp_value == 0xffffffff)
197                                         lseek(fp, 78, SEEK_CUR); // extra data (DJ 3.00.780 and up)
198                         }
199                         current_track->position=track_position;
200                         track_position+=(current_track->pregap_length+current_track->length)*current_track->sector_size;
201                         previous_position=track_position;
202                 }
203                 lseek(fp, 4, SEEK_CUR);
204                 lseek(fp, 8, SEEK_CUR);
205                 if (descriptor->version != CDI_V2)
206                         lseek(fp, 1, SEEK_CUR);
207
208         }
209     if (descriptor->header_offset == 0) 
210                 return(0);
211
212         return(descriptor);
213 }
214 //////////////////////////////////////////////////////////////////////////////
215 //
216 //////////////////////////////////////////////////////////////////////////////
217 //
218 //
219 //
220 //
221 //
222 //
223 //////////////////////////////////////////////////////////////////////////////
224 void cdi_dump_descriptor(FILE *fp,s_cdi_descriptor *cdi_descriptor)
225 {
226         fprintf(fp,"cdi: %i Mb\n",cdi_descriptor->length>>20);
227         fprintf(fp,"cdi: format version ");
228         switch(cdi_descriptor->version)
229         {
230         case CDI_V2:    fprintf(fp,"2\n"); break;
231         case CDI_V3:    fprintf(fp,"3\n"); break;
232         case CDI_V35:   fprintf(fp,"3.5\n"); break;
233         default:                fprintf(fp,"unknown\n"); break;
234         }
235         fprintf(fp,"cdi: %i sessions\n",cdi_descriptor->nb_of_sessions);
236 }
237 //////////////////////////////////////////////////////////////////////////////
238 //
239 //////////////////////////////////////////////////////////////////////////////
240 //
241 //
242 //
243 //
244 //
245 //
246 //////////////////////////////////////////////////////////////////////////////
247 uint8 *cdi_extract_boot_code(int fp, s_cdi_descriptor *cdi_descriptor)
248 {
249         s_cdi_track *boot_track=&cdi_descriptor->sessions[1].tracks[0];
250         uint32 boot_track_size=boot_track->length*boot_track->sector_size;
251
252         uint8 *boot_track_data=(uint8*)malloc(boot_track_size);
253         lseek(fp,2+(boot_track->position), SEEK_SET);
254         read(fp,boot_track_data,boot_track_size);
255         
256         uint32 *boot_track_data_32=(uint32*)boot_track_data;
257         uint32 offset=0;
258         while (offset<(boot_track_size>>2))
259         {
260                 if (boot_track_data_32[offset]==0x49205452)
261                         break;
262                 offset++;
263         }
264         if (offset==(boot_track_size>>2))
265         {
266                 fprintf(log_get(),"cdi: cannot find the boot code\n");
267                 return(NULL);
268         }
269         offset=(offset<<2)+4;
270         uint16 *data16=(uint16*)&boot_track_data[offset];
271         cdi_load_address=*data16++; cdi_load_address<<=16; cdi_load_address|=*data16++;
272         cdi_code_length=*data16++; cdi_code_length<<=16; cdi_code_length|=*data16++;
273         fprintf(log_get(),"cdi: load address: 0x%.8x\n",cdi_load_address);
274         fprintf(log_get(),"cdi: length: 0x%.8x\n",cdi_code_length);
275         fprintf(log_get(),"cdi: byte swapping boot code\n");
276
277         for (uint32 i=0;i<(cdi_code_length>>1);i++)
278         {
279                 uint16 sdata=data16[i];
280                 sdata=(sdata>>8)|(sdata<<8);
281                 data16[i]=sdata;
282         }
283         return((uint8*)data16);
284 }
285 //////////////////////////////////////////////////////////////////////////////
286 //
287 //////////////////////////////////////////////////////////////////////////////
288 //
289 //
290 //
291 //
292 //
293 //
294 //////////////////////////////////////////////////////////////////////////////
295 void cdi_load_sector(uint32 sector, uint8 *buffer)
296 {
297         if (sector==0xffffffff)
298         {
299                 memset(buffer,0x00,2352);
300                 return;
301         }
302
303         sector*=2352;
304
305         lseek(cdi_fp,2+sector,SEEK_SET);
306         read(cdi_fp,buffer,2352);
307
308         // byte swap
309         for (uint32 i=0;i<2352;i+=2)
310         {
311                 uint8 sdata=buffer[i+0];
312                 buffer[i+0]=buffer[i+1];
313                 buffer[i+1]=sdata;
314         }
315
316 }