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