31efd0e4c23714b45a5d1e89449dc927653fdf6a
[picodrive.git] / cd_file.c
1 /***********************************************************
2  *                                                         *
3  * This source was taken from the Gens project             *
4  * Written by Stéphane Dallongeville                       *
5  * Copyright (c) 2002 by Stéphane Dallongeville            *
6  * Modified/adapted for PicoDrive by notaz, 2007           *
7  *                                                         *
8  ***********************************************************/
9
10 #include "../pico_int.h"
11 #include "cd_file.h"
12 #include "cue.h"
13
14 //#define cdprintf(f,...) printf(f "\n",##__VA_ARGS__) // tmp
15
16 static int audio_track_mp3(const char *fname, int index)
17 {
18         _scd_track *Tracks = Pico_mcd->TOC.Tracks;
19         FILE *tmp_file;
20         int fs, ret;
21
22         tmp_file = fopen(fname, "rb");
23         if (tmp_file == NULL)
24                 return -1;
25
26         ret = fseek(tmp_file, 0, SEEK_END);
27         fs = ftell(tmp_file);                           // used to calculate length
28         fseek(tmp_file, 0, SEEK_SET);
29
30 #if DONT_OPEN_MANY_FILES
31         // some systems (like PSP) can't have many open files at a time,
32         // so we work with their names instead.
33         fclose(tmp_file);
34         tmp_file = (void *) strdup(fname);
35 #endif
36         Tracks[index].KBtps = (short) mp3_get_bitrate(tmp_file, fs);
37         Tracks[index].KBtps >>= 3;
38         if (ret != 0 || Tracks[index].KBtps <= 0)
39         {
40                 elprintf(EL_STATUS, "track %2i: mp3 bitrate %i", index+1, Tracks[index].KBtps);
41 #if !DONT_OPEN_MANY_FILES
42                 fclose(tmp_file);
43 #else
44                 free(tmp_file);
45 #endif
46                 return -1;
47         }
48
49         Tracks[index].F = tmp_file;
50
51         // MP3 File
52         Tracks[index].ftype = TYPE_MP3;
53         fs *= 75;
54         fs /= Tracks[index].KBtps * 1000;
55         Tracks[index].Length = fs;
56         Tracks[index].Offset = 0;
57
58         return 0;
59 }
60
61 PICO_INTERNAL int Load_CD_Image(const char *cd_img_name, cd_img_type type)
62 {
63         int i, j, num_track, Cur_LBA, index, ret, iso_name_len, missed, cd_img_sectors;
64         _scd_track *Tracks = Pico_mcd->TOC.Tracks;
65         char tmp_name[1024], tmp_ext[10];
66         cue_data_t *cue_data = NULL;
67         pm_file *pmf;
68         static char *exts[] = {
69                 "%02d.mp3", " %02d.mp3", "-%02d.mp3", "_%02d.mp3", " - %02d.mp3",
70                 "%d.mp3", " %d.mp3", "-%d.mp3", "_%d.mp3", " - %d.mp3",
71 #if CASE_SENSITIVE_FS
72                 "%02d.MP3", " %02d.MP3", "-%02d.MP3", "_%02d.MP3", " - %02d.MP3",
73 #endif
74         };
75
76         if (PicoCDLoadProgressCB != NULL)
77                 PicoCDLoadProgressCB(cd_img_name, 1);
78
79         Unload_ISO();
80
81         /* is this .cue? */
82         ret = strlen(cd_img_name);
83         if (ret >= 3 && strcasecmp(cd_img_name + ret - 3, "cue") == 0)
84                 cue_data = cue_parse(cd_img_name);
85         if (cue_data != NULL)
86                 cd_img_name = cue_data->tracks[1].fname;
87
88         Tracks[0].ftype = type == CIT_BIN ? TYPE_BIN : TYPE_ISO;
89
90         Tracks[0].F = pmf = pm_open(cd_img_name);
91         if (Tracks[0].F == NULL)
92         {
93                 Tracks[0].ftype = 0;
94                 Tracks[0].Length = 0;
95                 if (cue_data != NULL)
96                         cue_destroy(cue_data);
97                 return -1;
98         }
99
100         if (Tracks[0].ftype == TYPE_ISO)
101              cd_img_sectors = pmf->size >>= 11; // size in sectors
102         else cd_img_sectors = pmf->size /= 2352;
103         Tracks[0].Offset = 0;
104
105         Tracks[0].MSF.M = 0; // minutes
106         Tracks[0].MSF.S = 2; // seconds
107         Tracks[0].MSF.F = 0; // frames
108
109         elprintf(EL_STATUS, "Track  1: %02d:%02d:%02d %9i DATA",
110                 Tracks[0].MSF.M, Tracks[0].MSF.S, Tracks[0].MSF.F, Tracks[0].Length);
111
112         Cur_LBA = Tracks[0].Length = cd_img_sectors;
113
114         if (cue_data != NULL)
115         {
116                 if (cue_data->tracks[2].fname == NULL) { // NULL means track2 is in same file as track1
117                         Cur_LBA = Tracks[0].Length = cue_data->tracks[2].sector_offset;
118                 }
119                 i = 100 / cue_data->track_count+1;
120                 for (num_track = 2; num_track <= cue_data->track_count; num_track++)
121                 {
122                         if (PicoCDLoadProgressCB != NULL)
123                                 PicoCDLoadProgressCB(cd_img_name, i * num_track);
124                         index = num_track - 1;
125                         Cur_LBA += cue_data->tracks[num_track].pregap;
126                         if (cue_data->tracks[num_track].type == CT_MP3) {
127                                 ret = audio_track_mp3(cue_data->tracks[num_track].fname, index);
128                                 if (ret != 0) break;
129                         }
130                         else
131                         {
132                                 Tracks[index].ftype = cue_data->tracks[num_track].type;
133                                 if (cue_data->tracks[num_track].fname != NULL)
134                                 {
135                                         pm_file *pmfn = pm_open(cue_data->tracks[num_track].fname);
136                                         if (pmfn != NULL)
137                                         {
138                                                 // addume raw, ignore header for wav..
139                                                 Tracks[index].F = pmfn;
140                                                 Tracks[index].Length = pmfn->size / 2352;
141                                                 Tracks[index].Offset = cue_data->tracks[num_track].sector_offset;
142                                         }
143                                         else
144                                         {
145                                                 elprintf(EL_STATUS, "track %2i (%s): can't determine length",
146                                                         num_track, cue_data->tracks[num_track].fname);
147                                                 Tracks[index].Length = 2*75;
148                                                 Tracks[index].Offset = 0;
149                                         }
150                                 }
151                                 else
152                                 {
153                                         if (num_track < cue_data->track_count)
154                                                 Tracks[index].Length = cue_data->tracks[num_track+1].sector_offset -
155                                                         cue_data->tracks[num_track].sector_offset;
156                                         else
157                                                 Tracks[index].Length = cd_img_sectors - cue_data->tracks[num_track].sector_offset;
158                                         Tracks[index].Offset = cue_data->tracks[num_track].sector_offset;
159                                 }
160                         }
161
162                         if (cue_data->tracks[num_track].sector_xlength != 0)
163                                 // overriden by custom cue command
164                                 Tracks[index].Length = cue_data->tracks[num_track].sector_xlength;
165
166                         LBA_to_MSF(Cur_LBA, &Tracks[index].MSF);
167                         Cur_LBA += Tracks[index].Length;
168
169                         elprintf(EL_STATUS, "Track %2i: %02d:%02d:%02d %9i AUDIO - %s", num_track, Tracks[index].MSF.M,
170                                 Tracks[index].MSF.S, Tracks[index].MSF.F, Tracks[index].Length,
171                                 cue_data->tracks[num_track].fname);
172                 }
173                 cue_destroy(cue_data);
174                 goto finish;
175         }
176
177         /* mp3 track autosearch, Gens-like */
178         iso_name_len = strlen(cd_img_name);
179         if (iso_name_len >= sizeof(tmp_name))
180                 iso_name_len = sizeof(tmp_name) - 1;
181
182         for (num_track = 2, i = 0, missed = 0; i < 100 && missed < 4; i++)
183         {
184                 if (PicoCDLoadProgressCB != NULL && i > 1)
185                         PicoCDLoadProgressCB(cd_img_name, i + (100-i)*missed/4);
186
187                 for (j = 0; j < sizeof(exts)/sizeof(char *); j++)
188                 {
189                         int ext_len;
190                         sprintf(tmp_ext, exts[j], i);
191                         ext_len = strlen(tmp_ext);
192
193                         memcpy(tmp_name, cd_img_name, iso_name_len + 1);
194                         tmp_name[iso_name_len - 4] = 0;
195                         strcat(tmp_name, tmp_ext);
196
197                         index = num_track - 1;
198                         ret = audio_track_mp3(tmp_name, index);
199                         if (ret != 0 && i > 1 && iso_name_len > ext_len) {
200                                 tmp_name[iso_name_len - ext_len] = 0;
201                                 strcat(tmp_name, tmp_ext);
202                                 ret = audio_track_mp3(tmp_name, index);
203                         }
204
205                         if (ret == 0)
206                         {
207                                 LBA_to_MSF(Cur_LBA, &Tracks[index].MSF);
208                                 Cur_LBA += Tracks[index].Length;
209
210                                 elprintf(EL_STATUS, "Track %2i: %02d:%02d:%02d %9i AUDIO - %s", num_track, Tracks[index].MSF.M,
211                                         Tracks[index].MSF.S, Tracks[index].MSF.F, Tracks[index].Length, tmp_name);
212
213                                 num_track++;
214                                 missed = 0;
215                                 break;
216                         }
217                 }
218                 if (ret != 0 && i > 1) missed++;
219         }
220
221 finish:
222         Pico_mcd->TOC.Last_Track = num_track - 1;
223
224         index = num_track - 1;
225
226         LBA_to_MSF(Cur_LBA, &Tracks[index].MSF);
227
228         elprintf(EL_STATUS, "End CD -  %02d:%02d:%02d\n", Tracks[index].MSF.M,
229                 Tracks[index].MSF.S, Tracks[index].MSF.F);
230
231         if (PicoCDLoadProgressCB != NULL)
232                 PicoCDLoadProgressCB(cd_img_name, 100);
233
234         return 0;
235 }
236
237
238 PICO_INTERNAL void Unload_ISO(void)
239 {
240         int i;
241
242         if (Pico_mcd == NULL) return;
243
244         if (Pico_mcd->TOC.Tracks[0].F) pm_close(Pico_mcd->TOC.Tracks[0].F);
245
246         for(i = 1; i < 100; i++)
247         {
248                 if (Pico_mcd->TOC.Tracks[i].F != NULL)
249                 {
250                         if (Pico_mcd->TOC.Tracks[i].ftype == TYPE_MP3)
251 #if DONT_OPEN_MANY_FILES
252                                 free(Pico_mcd->TOC.Tracks[i].F);
253 #else
254                                 fclose(Pico_mcd->TOC.Tracks[i].F);
255 #endif
256                         else
257                                 pm_close(Pico_mcd->TOC.Tracks[i].F);
258                 }
259         }
260         memset(Pico_mcd->TOC.Tracks, 0, sizeof(Pico_mcd->TOC.Tracks));
261 }
262
263
264 PICO_INTERNAL int FILE_Read_One_LBA_CDC(void)
265 {
266         if (Pico_mcd->s68k_regs[0x36] & 1)                                      // DATA
267         {
268                 if (Pico_mcd->TOC.Tracks[0].F == NULL) return -1;
269
270                 // moved below..
271                 //fseek(Pico_mcd->TOC.Tracks[0].F, where_read, SEEK_SET);
272                 //fread(cp_buf, 1, 2048, Pico_mcd->TOC.Tracks[0].F);
273
274                 cdprintf("Read file CDC 1 data sector :\n");
275         }
276         else                                                                    // AUDIO
277         {
278                 cdprintf("Read file CDC 1 audio sector :\n");
279         }
280
281         // Update CDC stuff
282
283         CDC_Update_Header();
284
285         if (Pico_mcd->s68k_regs[0x36] & 1)              // DATA track
286         {
287                 if (Pico_mcd->cdc.CTRL.B.B0 & 0x80)             // DECEN = decoding enable
288                 {
289                         if (Pico_mcd->cdc.CTRL.B.B0 & 0x04)     // WRRQ : this bit enable write to buffer
290                         {
291                                 int where_read = 0;
292
293                                 // CAUTION : lookahead bit not implemented
294
295                                 if (Pico_mcd->scd.Cur_LBA < 0)
296                                         where_read = 0;
297                                 else if (Pico_mcd->scd.Cur_LBA >= Pico_mcd->TOC.Tracks[0].Length)
298                                         where_read = Pico_mcd->TOC.Tracks[0].Length - 1;
299                                 else where_read = Pico_mcd->scd.Cur_LBA;
300
301                                 Pico_mcd->scd.Cur_LBA++;
302
303                                 Pico_mcd->cdc.WA.N = (Pico_mcd->cdc.WA.N + 2352) & 0x7FFF;              // add one sector to WA
304                                 Pico_mcd->cdc.PT.N = (Pico_mcd->cdc.PT.N + 2352) & 0x7FFF;
305
306                                 *(unsigned int *)(Pico_mcd->cdc.Buffer + Pico_mcd->cdc.PT.N) = Pico_mcd->cdc.HEAD.N;
307                                 //memcpy(&Pico_mcd->cdc.Buffer[Pico_mcd->cdc.PT.N + 4], cp_buf, 2048);
308
309                                 //pm_seek(Pico_mcd->TOC.Tracks[0].F, where_read, SEEK_SET);
310                                 //pm_read(Pico_mcd->cdc.Buffer + Pico_mcd->cdc.PT.N + 4, 2048, Pico_mcd->TOC.Tracks[0].F);
311                                 PicoCDBufferRead(Pico_mcd->cdc.Buffer + Pico_mcd->cdc.PT.N + 4, where_read);
312
313                                 cdprintf("Read -> WA = %d  Buffer[%d] =", Pico_mcd->cdc.WA.N, Pico_mcd->cdc.PT.N & 0x3FFF);
314                                 cdprintf("Header 1 = %.2X %.2X %.2X %.2X", Pico_mcd->cdc.HEAD.B.B0,
315                                         Pico_mcd->cdc.HEAD.B.B1, Pico_mcd->cdc.HEAD.B.B2, Pico_mcd->cdc.HEAD.B.B3);
316                                 cdprintf("Header 2 = %.2X %.2X %.2X %.2X --- %.2X %.2X\n\n",
317                                         Pico_mcd->cdc.Buffer[(Pico_mcd->cdc.PT.N + 0) & 0x3FFF],
318                                         Pico_mcd->cdc.Buffer[(Pico_mcd->cdc.PT.N + 1) & 0x3FFF],
319                                         Pico_mcd->cdc.Buffer[(Pico_mcd->cdc.PT.N + 2) & 0x3FFF],
320                                         Pico_mcd->cdc.Buffer[(Pico_mcd->cdc.PT.N + 3) & 0x3FFF],
321                                         Pico_mcd->cdc.Buffer[(Pico_mcd->cdc.PT.N + 4) & 0x3FFF],
322                                         Pico_mcd->cdc.Buffer[(Pico_mcd->cdc.PT.N + 5) & 0x3FFF]);
323                         }
324
325                 }
326         }
327         else            // music track
328         {
329                 Pico_mcd->scd.Cur_LBA++;
330
331                 Pico_mcd->cdc.WA.N = (Pico_mcd->cdc.WA.N + 2352) & 0x7FFF;              // add one sector to WA
332                 Pico_mcd->cdc.PT.N = (Pico_mcd->cdc.PT.N + 2352) & 0x7FFF;
333
334                 if (Pico_mcd->cdc.CTRL.B.B0 & 0x80)             // DECEN = decoding enable
335                 {
336                         if (Pico_mcd->cdc.CTRL.B.B0 & 0x04)     // WRRQ : this bit enable write to buffer
337                         {
338                                 // CAUTION : lookahead bit not implemented
339
340                                 // this is pretty rough, but oh well - not much depends on this anyway
341                                 memcpy(&Pico_mcd->cdc.Buffer[Pico_mcd->cdc.PT.N], cdda_out_buffer, 2352);
342                         }
343                 }
344         }
345
346         if (Pico_mcd->cdc.CTRL.B.B0 & 0x80)             // DECEN = decoding enable
347         {
348                 Pico_mcd->cdc.STAT.B.B0 = 0x80;
349
350                 if (Pico_mcd->cdc.CTRL.B.B0 & 0x10)     // determine form bit form sub header ?
351                 {
352                         Pico_mcd->cdc.STAT.B.B2 = Pico_mcd->cdc.CTRL.B.B1 & 0x08;
353                 }
354                 else
355                 {
356                         Pico_mcd->cdc.STAT.B.B2 = Pico_mcd->cdc.CTRL.B.B1 & 0x0C;
357                 }
358
359                 if (Pico_mcd->cdc.CTRL.B.B0 & 0x02) Pico_mcd->cdc.STAT.B.B3 = 0x20;     // ECC done
360                 else Pico_mcd->cdc.STAT.B.B3 = 0x00;    // ECC not done
361
362                 if (Pico_mcd->cdc.IFCTRL & 0x20)
363                 {
364                         if (Pico_mcd->s68k_regs[0x33] & (1<<5))
365                         {
366                                 elprintf(EL_INTS, "cdc dec irq 5");
367                                 SekInterruptS68k(5);
368                         }
369
370                         Pico_mcd->cdc.IFSTAT &= ~0x20;          // DEC interrupt happen
371                         Pico_mcd->cdc.Decode_Reg_Read = 0;      // Reset read after DEC int
372                 }
373         }
374
375
376         return 0;
377 }
378