amalgamation
[picodrive.git] / Pico / cd / cd_sys.c
1 /***********************************************************\r
2  *                                                         *\r
3  * This source was taken from the Gens project             *\r
4  * Written by Stéphane Dallongeville                       *\r
5  * Copyright (c) 2002 by Stéphane Dallongeville            *\r
6  * Modified/adapted for PicoDrive by notaz, 2007           *\r
7  *                                                         *\r
8  ***********************************************************/\r
9 \r
10 #include <stdio.h>\r
11 \r
12 #include "../PicoInt.h"\r
13 #include "cd_sys.h"\r
14 #include "cd_file.h"\r
15 \r
16 #define cdprintf dprintf\r
17 //#define cdprintf(x...)\r
18 #define DEBUG_CD\r
19 \r
20 #define TRAY_OPEN       0x0500          // TRAY OPEN CDD status\r
21 #define NOCD            0x0000          // CD removed CDD status\r
22 #define STOPPED         0x0900          // STOPPED CDD status (happen after stop or close tray command)\r
23 #define READY           0x0400          // READY CDD status (also used for seeking)\r
24 #define FAST_FOW        0x0300          // FAST FORWARD track CDD status\r
25 #define FAST_REV        0x10300         // FAST REVERSE track CDD status\r
26 #define PLAYING         0x0100          // PLAYING audio track CDD status\r
27 \r
28 \r
29 static int CD_Present = 0;\r
30 \r
31 \r
32 #define CHECK_TRAY_OPEN                         \\r
33 if (Pico_mcd->scd.Status_CDD == TRAY_OPEN)      \\r
34 {                                                                       \\r
35         Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;        \\r
36                                                                         \\r
37         Pico_mcd->cdd.Minute = 0;                                       \\r
38         Pico_mcd->cdd.Seconde = 0;                              \\r
39         Pico_mcd->cdd.Frame = 0;                                        \\r
40         Pico_mcd->cdd.Ext = 0;                                  \\r
41                                                                         \\r
42         Pico_mcd->scd.CDD_Complete = 1;                         \\r
43                                                                         \\r
44         return 2;                                               \\r
45 }\r
46 \r
47 \r
48 #define CHECK_CD_PRESENT                        \\r
49 if (!CD_Present)                                        \\r
50 {                                                                       \\r
51         Pico_mcd->scd.Status_CDD = NOCD;                        \\r
52         Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;        \\r
53                                                                         \\r
54         Pico_mcd->cdd.Minute = 0;                                       \\r
55         Pico_mcd->cdd.Seconde = 0;                              \\r
56         Pico_mcd->cdd.Frame = 0;                                        \\r
57         Pico_mcd->cdd.Ext = 0;                                  \\r
58                                                                         \\r
59         Pico_mcd->scd.CDD_Complete = 1;                         \\r
60                                                                         \\r
61         return 3;                                               \\r
62 }\r
63 \r
64 \r
65 static int MSF_to_LBA(_msf *MSF)\r
66 {\r
67         return (MSF->M * 60 * 75) + (MSF->S * 75) + MSF->F - 150;\r
68 }\r
69 \r
70 \r
71 PICO_INTERNAL void LBA_to_MSF(int lba, _msf *MSF)\r
72 {\r
73         if (lba < -150) lba = 0;\r
74         else lba += 150;\r
75         MSF->M = lba / (60 * 75);\r
76         MSF->S = (lba / 75) % 60;\r
77         MSF->F = lba % 75;\r
78 }\r
79 \r
80 \r
81 static unsigned int MSF_to_Track(_msf *MSF)\r
82 {\r
83         int i, Start, Cur;\r
84 \r
85         Start = (MSF->M << 16) + (MSF->S << 8) + MSF->F;\r
86 \r
87         for(i = 1; i <= (Pico_mcd->TOC.Last_Track + 1); i++)\r
88         {\r
89                 Cur = Pico_mcd->TOC.Tracks[i - 1].MSF.M << 16;\r
90                 Cur += Pico_mcd->TOC.Tracks[i - 1].MSF.S << 8;\r
91                 Cur += Pico_mcd->TOC.Tracks[i - 1].MSF.F;\r
92 \r
93                 if (Cur > Start) break;\r
94         }\r
95 \r
96         --i;\r
97 \r
98         if (i > Pico_mcd->TOC.Last_Track) return 100;\r
99         else if (i < 1) i = 1;\r
100 \r
101         return (unsigned) i;\r
102 }\r
103 \r
104 \r
105 static unsigned int LBA_to_Track(int lba)\r
106 {\r
107         _msf MSF;\r
108 \r
109         LBA_to_MSF(lba, &MSF);\r
110         return MSF_to_Track(&MSF);\r
111 }\r
112 \r
113 \r
114 static void Track_to_MSF(int track, _msf *MSF)\r
115 {\r
116         if (track < 1) track = 1;\r
117         else if (track > Pico_mcd->TOC.Last_Track) track = Pico_mcd->TOC.Last_Track;\r
118 \r
119         MSF->M = Pico_mcd->TOC.Tracks[track - 1].MSF.M;\r
120         MSF->S = Pico_mcd->TOC.Tracks[track - 1].MSF.S;\r
121         MSF->F = Pico_mcd->TOC.Tracks[track - 1].MSF.F;\r
122 }\r
123 \r
124 \r
125 PICO_INTERNAL int Track_to_LBA(int track)\r
126 {\r
127         _msf MSF;\r
128 \r
129         Track_to_MSF(track, &MSF);\r
130         return MSF_to_LBA(&MSF);\r
131 }\r
132 \r
133 \r
134 PICO_INTERNAL void Check_CD_Command(void)\r
135 {\r
136         cdprintf("CHECK CD COMMAND");\r
137 \r
138         // Check CDC\r
139         if (Pico_mcd->scd.Status_CDC & 1)                       // CDC is reading data ...\r
140         {\r
141                 cdprintf("Got a read command");\r
142 \r
143                 // DATA ?\r
144                 if (Pico_mcd->scd.Cur_Track == 1)\r
145                      Pico_mcd->s68k_regs[0x36] |=  0x01;\r
146                 else Pico_mcd->s68k_regs[0x36] &= ~0x01;                        // AUDIO\r
147 \r
148                 if (Pico_mcd->scd.File_Add_Delay == 0)\r
149                 {\r
150                         FILE_Read_One_LBA_CDC();\r
151                 }\r
152                 else Pico_mcd->scd.File_Add_Delay--;\r
153         }\r
154 \r
155         // Check CDD\r
156         if (Pico_mcd->scd.CDD_Complete)\r
157         {\r
158                 Pico_mcd->scd.CDD_Complete = 0;\r
159 \r
160                 CDD_Export_Status();\r
161         }\r
162 \r
163         if (Pico_mcd->scd.Status_CDD == FAST_FOW)\r
164         {\r
165                 Pico_mcd->scd.Cur_LBA += 10;\r
166                 CDC_Update_Header();\r
167 \r
168         }\r
169         else if (Pico_mcd->scd.Status_CDD == FAST_REV)\r
170         {\r
171                 Pico_mcd->scd.Cur_LBA -= 10;\r
172                 if (Pico_mcd->scd.Cur_LBA < -150) Pico_mcd->scd.Cur_LBA = -150;\r
173                 CDC_Update_Header();\r
174         }\r
175 }\r
176 \r
177 \r
178 PICO_INTERNAL int Init_CD_Driver(void)\r
179 {\r
180         return 0;\r
181 }\r
182 \r
183 \r
184 PICO_INTERNAL void End_CD_Driver(void)\r
185 {\r
186         Unload_ISO();\r
187 }\r
188 \r
189 \r
190 PICO_INTERNAL void Reset_CD(void)\r
191 {\r
192         Pico_mcd->scd.Cur_Track = 0;\r
193         Pico_mcd->scd.Cur_LBA = -150;\r
194         Pico_mcd->scd.Status_CDC &= ~1;\r
195         Pico_mcd->scd.Status_CDD = CD_Present ? READY : NOCD;\r
196         Pico_mcd->scd.CDD_Complete = 0;\r
197         Pico_mcd->scd.File_Add_Delay = 0;\r
198 }\r
199 \r
200 \r
201 int Insert_CD(char *iso_name, int is_bin)\r
202 {\r
203         int ret = 0;\r
204 \r
205         CD_Present = 0;\r
206         Pico_mcd->scd.Status_CDD = NOCD;\r
207 \r
208         if (iso_name != NULL)\r
209         {\r
210                 ret = Load_ISO(iso_name, is_bin);\r
211                 if (ret == 0) {\r
212                         CD_Present = 1;\r
213                         Pico_mcd->scd.Status_CDD = READY;\r
214                 }\r
215         }\r
216 \r
217         return ret;\r
218 }\r
219 \r
220 \r
221 void Stop_CD(void)\r
222 {\r
223         Unload_ISO();\r
224         CD_Present = 0;\r
225 }\r
226 \r
227 \r
228 /*\r
229 PICO_INTERNAL void Change_CD(void)\r
230 {\r
231         if (Pico_mcd->scd.Status_CDD == TRAY_OPEN) Close_Tray_CDD_cC();\r
232         else Open_Tray_CDD_cD();\r
233 }\r
234 */\r
235 \r
236 PICO_INTERNAL int Get_Status_CDD_c0(void)\r
237 {\r
238         cdprintf("Status command : Cur LBA = %d", Pico_mcd->scd.Cur_LBA);\r
239 \r
240         // Clear immediat status\r
241         if ((Pico_mcd->cdd.Status & 0x0F00) == 0x0200)\r
242                 Pico_mcd->cdd.Status = (Pico_mcd->scd.Status_CDD & 0xFF00) | (Pico_mcd->cdd.Status & 0x00FF);\r
243         else if ((Pico_mcd->cdd.Status & 0x0F00) == 0x0700)\r
244                 Pico_mcd->cdd.Status = (Pico_mcd->scd.Status_CDD & 0xFF00) | (Pico_mcd->cdd.Status & 0x00FF);\r
245         else if ((Pico_mcd->cdd.Status & 0x0F00) == 0x0E00)\r
246                 Pico_mcd->cdd.Status = (Pico_mcd->scd.Status_CDD & 0xFF00) | (Pico_mcd->cdd.Status & 0x00FF);\r
247 \r
248         Pico_mcd->scd.CDD_Complete = 1;\r
249 \r
250         return 0;\r
251 }\r
252 \r
253 \r
254 PICO_INTERNAL int Stop_CDD_c1(void)\r
255 {\r
256         CHECK_TRAY_OPEN\r
257 \r
258         Pico_mcd->scd.Status_CDC &= ~1;                         // Stop CDC read\r
259 \r
260         if (CD_Present) Pico_mcd->scd.Status_CDD = STOPPED;\r
261         else Pico_mcd->scd.Status_CDD = NOCD;\r
262         Pico_mcd->cdd.Status = 0x0000;\r
263 \r
264         Pico_mcd->s68k_regs[0x36] |= 0x01;                      // Data bit set because stopped\r
265 \r
266         Pico_mcd->cdd.Minute = 0;\r
267         Pico_mcd->cdd.Seconde = 0;\r
268         Pico_mcd->cdd.Frame = 0;\r
269         Pico_mcd->cdd.Ext = 0;\r
270 \r
271         Pico_mcd->scd.CDD_Complete = 1;\r
272 \r
273         return 0;\r
274 }\r
275 \r
276 \r
277 PICO_INTERNAL int Get_Pos_CDD_c20(void)\r
278 {\r
279         _msf MSF;\r
280 \r
281         cdprintf("command 200 : Cur LBA = %d", Pico_mcd->scd.Cur_LBA);\r
282 \r
283         CHECK_TRAY_OPEN\r
284 \r
285         Pico_mcd->cdd.Status &= 0xFF;\r
286         if (!CD_Present)\r
287         {\r
288                 Pico_mcd->scd.Status_CDD = NOCD;\r
289                 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
290         }\r
291 //      else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
292         Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
293 \r
294         cdprintf("Status CDD = %.4X  Status = %.4X", Pico_mcd->scd.Status_CDD, Pico_mcd->cdd.Status);\r
295 \r
296         LBA_to_MSF(Pico_mcd->scd.Cur_LBA, &MSF);\r
297 \r
298         Pico_mcd->cdd.Minute = INT_TO_BCDW(MSF.M);\r
299         Pico_mcd->cdd.Seconde = INT_TO_BCDW(MSF.S);\r
300         Pico_mcd->cdd.Frame = INT_TO_BCDW(MSF.F);\r
301         Pico_mcd->cdd.Ext = 0;\r
302 \r
303         Pico_mcd->scd.CDD_Complete = 1;\r
304 \r
305         return 0;\r
306 }\r
307 \r
308 \r
309 PICO_INTERNAL int Get_Track_Pos_CDD_c21(void)\r
310 {\r
311         int elapsed_time;\r
312         _msf MSF;\r
313 \r
314         cdprintf("command 201 : Cur LBA = %d", Pico_mcd->scd.Cur_LBA);\r
315 \r
316         CHECK_TRAY_OPEN\r
317 \r
318         Pico_mcd->cdd.Status &= 0xFF;\r
319         if (!CD_Present)\r
320         {\r
321                 Pico_mcd->scd.Status_CDD = NOCD;\r
322                 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
323         }\r
324 //      else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
325         Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
326 \r
327         elapsed_time = Pico_mcd->scd.Cur_LBA - Track_to_LBA(LBA_to_Track(Pico_mcd->scd.Cur_LBA));\r
328         LBA_to_MSF(elapsed_time - 150, &MSF);\r
329 \r
330         cdprintf("   elapsed = %d", elapsed_time);\r
331 \r
332         Pico_mcd->cdd.Minute = INT_TO_BCDW(MSF.M);\r
333         Pico_mcd->cdd.Seconde = INT_TO_BCDW(MSF.S);\r
334         Pico_mcd->cdd.Frame = INT_TO_BCDW(MSF.F);\r
335         Pico_mcd->cdd.Ext = 0;\r
336 \r
337         Pico_mcd->scd.CDD_Complete = 1;\r
338 \r
339         return 0;\r
340 }\r
341 \r
342 \r
343 PICO_INTERNAL int Get_Current_Track_CDD_c22(void)\r
344 {\r
345         cdprintf("Status CDD = %.4X  Status = %.4X", Pico_mcd->scd.Status_CDD, Pico_mcd->cdd.Status);\r
346 \r
347         CHECK_TRAY_OPEN\r
348 \r
349         Pico_mcd->cdd.Status &= 0xFF;\r
350         if (!CD_Present)\r
351         {\r
352                 Pico_mcd->scd.Status_CDD = NOCD;\r
353                 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
354         }\r
355 //      else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
356         Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
357 \r
358         Pico_mcd->scd.Cur_Track = LBA_to_Track(Pico_mcd->scd.Cur_LBA);\r
359 \r
360         if (Pico_mcd->scd.Cur_Track == 100) Pico_mcd->cdd.Minute = 0x0A02;\r
361         else Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
362         Pico_mcd->cdd.Seconde = 0;\r
363         Pico_mcd->cdd.Frame = 0;\r
364         Pico_mcd->cdd.Ext = 0;\r
365 \r
366         Pico_mcd->scd.CDD_Complete = 1;\r
367 \r
368         return 0;\r
369 }\r
370 \r
371 \r
372 PICO_INTERNAL int Get_Total_Lenght_CDD_c23(void)\r
373 {\r
374         CHECK_TRAY_OPEN\r
375 \r
376         Pico_mcd->cdd.Status &= 0xFF;\r
377         if (!CD_Present)\r
378         {\r
379                 Pico_mcd->scd.Status_CDD = NOCD;\r
380                 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
381         }\r
382 //      else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
383         Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
384 \r
385         Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->TOC.Tracks[Pico_mcd->TOC.Last_Track].MSF.M);\r
386         Pico_mcd->cdd.Seconde = INT_TO_BCDW(Pico_mcd->TOC.Tracks[Pico_mcd->TOC.Last_Track].MSF.S);\r
387         Pico_mcd->cdd.Frame = INT_TO_BCDW(Pico_mcd->TOC.Tracks[Pico_mcd->TOC.Last_Track].MSF.F);\r
388         Pico_mcd->cdd.Ext = 0;\r
389 \r
390         Pico_mcd->scd.CDD_Complete = 1;\r
391 \r
392         return 0;\r
393 }\r
394 \r
395 \r
396 PICO_INTERNAL int Get_First_Last_Track_CDD_c24(void)\r
397 {\r
398         CHECK_TRAY_OPEN\r
399 \r
400         Pico_mcd->cdd.Status &= 0xFF;\r
401         if (!CD_Present)\r
402         {\r
403                 Pico_mcd->scd.Status_CDD = NOCD;\r
404         }\r
405 //      else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
406         Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
407 \r
408         Pico_mcd->cdd.Minute = INT_TO_BCDW(1);\r
409         Pico_mcd->cdd.Seconde = INT_TO_BCDW(Pico_mcd->TOC.Last_Track);\r
410         Pico_mcd->cdd.Frame = 0;\r
411         Pico_mcd->cdd.Ext = 0;\r
412 \r
413         Pico_mcd->scd.CDD_Complete = 1;\r
414 \r
415         return 0;\r
416 }\r
417 \r
418 \r
419 PICO_INTERNAL int Get_Track_Adr_CDD_c25(void)\r
420 {\r
421         int track_number;\r
422 \r
423         CHECK_TRAY_OPEN\r
424 \r
425         // track number in TC4 & TC5\r
426 \r
427         track_number = (Pico_mcd->s68k_regs[0x38+10+4] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+5] & 0xF);\r
428 \r
429         Pico_mcd->cdd.Status &= 0xFF;\r
430         if (!CD_Present)\r
431         {\r
432                 Pico_mcd->scd.Status_CDD = NOCD;\r
433                 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
434         }\r
435 //      else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
436         Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
437 \r
438         if (track_number > Pico_mcd->TOC.Last_Track) track_number = Pico_mcd->TOC.Last_Track;\r
439         else if (track_number < 1) track_number = 1;\r
440 \r
441         Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->TOC.Tracks[track_number - 1].MSF.M);\r
442         Pico_mcd->cdd.Seconde = INT_TO_BCDW(Pico_mcd->TOC.Tracks[track_number - 1].MSF.S);\r
443         Pico_mcd->cdd.Frame = INT_TO_BCDW(Pico_mcd->TOC.Tracks[track_number - 1].MSF.F);\r
444         Pico_mcd->cdd.Ext = track_number % 10;\r
445 \r
446         if (track_number == 1) Pico_mcd->cdd.Frame |= 0x0800; // data track\r
447 \r
448         Pico_mcd->scd.CDD_Complete = 1;\r
449         return 0;\r
450 }\r
451 \r
452 \r
453 PICO_INTERNAL int Play_CDD_c3(void)\r
454 {\r
455         _msf MSF;\r
456         int delay, new_lba;\r
457 \r
458         CHECK_TRAY_OPEN\r
459         CHECK_CD_PRESENT\r
460 \r
461         // MSF of the track to play in TC buffer\r
462 \r
463         MSF.M = (Pico_mcd->s68k_regs[0x38+10+2] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+3] & 0xF);\r
464         MSF.S = (Pico_mcd->s68k_regs[0x38+10+4] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+5] & 0xF);\r
465         MSF.F = (Pico_mcd->s68k_regs[0x38+10+6] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+7] & 0xF);\r
466 \r
467         Pico_mcd->scd.Cur_Track = MSF_to_Track(&MSF);\r
468 \r
469         new_lba = MSF_to_LBA(&MSF);\r
470         delay = new_lba - Pico_mcd->scd.Cur_LBA;\r
471         if (delay < 0) delay = -delay;\r
472         delay >>= 12;\r
473 \r
474         Pico_mcd->scd.Cur_LBA = new_lba;\r
475         CDC_Update_Header();\r
476 \r
477         cdprintf("Read : Cur LBA = %d, M=%d, S=%d, F=%d", Pico_mcd->scd.Cur_LBA, MSF.M, MSF.S, MSF.F);\r
478 \r
479         if (Pico_mcd->scd.Status_CDD != PLAYING) delay += 20;\r
480 \r
481         Pico_mcd->scd.Status_CDD = PLAYING;\r
482         Pico_mcd->cdd.Status = 0x0102;\r
483 //      Pico_mcd->cdd.Status = COMM_OK;\r
484 \r
485         if (Pico_mcd->scd.File_Add_Delay == 0) Pico_mcd->scd.File_Add_Delay = delay;\r
486 \r
487         if (Pico_mcd->scd.Cur_Track == 1)\r
488         {\r
489                 Pico_mcd->s68k_regs[0x36] |=  0x01;                             // DATA\r
490         }\r
491         else\r
492         {\r
493                 Pico_mcd->s68k_regs[0x36] &= ~0x01;                             // AUDIO\r
494                 //CD_Audio_Starting = 1;\r
495                 FILE_Play_CD_LBA();\r
496         }\r
497 \r
498         if (Pico_mcd->scd.Cur_Track == 100) Pico_mcd->cdd.Minute = 0x0A02;\r
499         else Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
500         Pico_mcd->cdd.Seconde = 0;\r
501         Pico_mcd->cdd.Frame = 0;\r
502         Pico_mcd->cdd.Ext = 0;\r
503 \r
504         Pico_mcd->scd.Status_CDC |= 1;                  // Read data with CDC\r
505 \r
506         Pico_mcd->scd.CDD_Complete = 1;\r
507         return 0;\r
508 }\r
509 \r
510 \r
511 PICO_INTERNAL int Seek_CDD_c4(void)\r
512 {\r
513         _msf MSF;\r
514 \r
515         CHECK_TRAY_OPEN\r
516         CHECK_CD_PRESENT\r
517 \r
518         // MSF to seek in TC buffer\r
519 \r
520         MSF.M = (Pico_mcd->s68k_regs[0x38+10+2] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+3] & 0xF);\r
521         MSF.S = (Pico_mcd->s68k_regs[0x38+10+4] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+5] & 0xF);\r
522         MSF.F = (Pico_mcd->s68k_regs[0x38+10+6] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+7] & 0xF);\r
523 \r
524         Pico_mcd->scd.Cur_Track = MSF_to_Track(&MSF);\r
525         Pico_mcd->scd.Cur_LBA = MSF_to_LBA(&MSF);\r
526         CDC_Update_Header();\r
527 \r
528         Pico_mcd->scd.Status_CDC &= ~1;                         // Stop CDC read\r
529 \r
530         Pico_mcd->scd.Status_CDD = READY;\r
531         Pico_mcd->cdd.Status = 0x0200;\r
532 \r
533         // DATA ?\r
534         if (Pico_mcd->scd.Cur_Track == 1)\r
535              Pico_mcd->s68k_regs[0x36] |=  0x01;\r
536         else Pico_mcd->s68k_regs[0x36] &= ~0x01;                // AUDIO\r
537 \r
538         Pico_mcd->cdd.Minute = 0;\r
539         Pico_mcd->cdd.Seconde = 0;\r
540         Pico_mcd->cdd.Frame = 0;\r
541         Pico_mcd->cdd.Ext = 0;\r
542 \r
543         Pico_mcd->scd.CDD_Complete = 1;\r
544 \r
545         return 0;\r
546 }\r
547 \r
548 \r
549 PICO_INTERNAL int Pause_CDD_c6(void)\r
550 {\r
551         CHECK_TRAY_OPEN\r
552         CHECK_CD_PRESENT\r
553 \r
554         Pico_mcd->scd.Status_CDC &= ~1;                 // Stop CDC read to start a new one if raw data\r
555 \r
556         Pico_mcd->scd.Status_CDD = READY;\r
557         Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;\r
558 \r
559         Pico_mcd->s68k_regs[0x36] |= 0x01;              // Data bit set because stopped\r
560 \r
561         Pico_mcd->cdd.Minute = 0;\r
562         Pico_mcd->cdd.Seconde = 0;\r
563         Pico_mcd->cdd.Frame = 0;\r
564         Pico_mcd->cdd.Ext = 0;\r
565 \r
566         Pico_mcd->scd.CDD_Complete = 1;\r
567 \r
568         return 0;\r
569 }\r
570 \r
571 \r
572 PICO_INTERNAL int Resume_CDD_c7(void)\r
573 {\r
574         CHECK_TRAY_OPEN\r
575         CHECK_CD_PRESENT\r
576 \r
577         Pico_mcd->scd.Cur_Track = LBA_to_Track(Pico_mcd->scd.Cur_LBA);\r
578 \r
579 #ifdef DEBUG_CD\r
580         {\r
581                 _msf MSF;\r
582                 LBA_to_MSF(Pico_mcd->scd.Cur_LBA, &MSF);\r
583                 cdprintf("Resume read : Cur LBA = %d, M=%d, S=%d, F=%d", Pico_mcd->scd.Cur_LBA, MSF.M, MSF.S, MSF.F);\r
584         }\r
585 #endif\r
586 \r
587         Pico_mcd->scd.Status_CDD = PLAYING;\r
588         Pico_mcd->cdd.Status = 0x0102;\r
589 \r
590         if (Pico_mcd->scd.Cur_Track == 1)\r
591         {\r
592                 Pico_mcd->s68k_regs[0x36] |=  0x01;                             // DATA\r
593         }\r
594         else\r
595         {\r
596                 Pico_mcd->s68k_regs[0x36] &= ~0x01;                             // AUDIO\r
597                 //CD_Audio_Starting = 1;\r
598                 FILE_Play_CD_LBA();\r
599         }\r
600 \r
601         if (Pico_mcd->scd.Cur_Track == 100) Pico_mcd->cdd.Minute = 0x0A02;\r
602         else Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
603         Pico_mcd->cdd.Seconde = 0;\r
604         Pico_mcd->cdd.Frame = 0;\r
605         Pico_mcd->cdd.Ext = 0;\r
606 \r
607         Pico_mcd->scd.Status_CDC |= 1;                  // Read data with CDC\r
608 \r
609         Pico_mcd->scd.CDD_Complete = 1;\r
610         return 0;\r
611 }\r
612 \r
613 \r
614 PICO_INTERNAL int Fast_Foward_CDD_c8(void)\r
615 {\r
616         CHECK_TRAY_OPEN\r
617         CHECK_CD_PRESENT\r
618 \r
619         Pico_mcd->scd.Status_CDC &= ~1;                         // Stop CDC read\r
620 \r
621         Pico_mcd->scd.Status_CDD = FAST_FOW;\r
622         Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD | 2;\r
623 \r
624         Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
625         Pico_mcd->cdd.Seconde = 0;\r
626         Pico_mcd->cdd.Frame = 0;\r
627         Pico_mcd->cdd.Ext = 0;\r
628 \r
629         Pico_mcd->scd.CDD_Complete = 1;\r
630 \r
631         return 0;\r
632 }\r
633 \r
634 \r
635 PICO_INTERNAL int Fast_Rewind_CDD_c9(void)\r
636 {\r
637         CHECK_TRAY_OPEN\r
638         CHECK_CD_PRESENT\r
639 \r
640         Pico_mcd->scd.Status_CDC &= ~1;                         // Stop CDC read\r
641 \r
642         Pico_mcd->scd.Status_CDD = FAST_REV;\r
643         Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD | 2;\r
644 \r
645         Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
646         Pico_mcd->cdd.Seconde = 0;\r
647         Pico_mcd->cdd.Frame = 0;\r
648         Pico_mcd->cdd.Ext = 0;\r
649 \r
650         Pico_mcd->scd.CDD_Complete = 1;\r
651 \r
652         return 0;\r
653 }\r
654 \r
655 \r
656 PICO_INTERNAL int Close_Tray_CDD_cC(void)\r
657 {\r
658         CD_Present = 0;\r
659         //Clear_Sound_Buffer();\r
660 \r
661         Pico_mcd->scd.Status_CDC &= ~1;                 // Stop CDC read\r
662 \r
663         printf("tray close\n");\r
664 \r
665         if (PicoMCDcloseTray != NULL)\r
666                 CD_Present = PicoMCDcloseTray();\r
667 \r
668         Pico_mcd->scd.Status_CDD = CD_Present ? STOPPED : NOCD;\r
669         Pico_mcd->cdd.Status = 0x0000;\r
670 \r
671         Pico_mcd->cdd.Minute = 0;\r
672         Pico_mcd->cdd.Seconde = 0;\r
673         Pico_mcd->cdd.Frame = 0;\r
674         Pico_mcd->cdd.Ext = 0;\r
675 \r
676         Pico_mcd->scd.CDD_Complete = 1;\r
677 \r
678         return 0;\r
679 }\r
680 \r
681 \r
682 PICO_INTERNAL int Open_Tray_CDD_cD(void)\r
683 {\r
684         CHECK_TRAY_OPEN\r
685 \r
686         Pico_mcd->scd.Status_CDC &= ~1;                 // Stop CDC read\r
687 \r
688         printf("tray open\n");\r
689 \r
690         Unload_ISO();\r
691         CD_Present = 0;\r
692 \r
693         if (PicoMCDopenTray != NULL)\r
694                 PicoMCDopenTray();\r
695 \r
696         Pico_mcd->scd.Status_CDD = TRAY_OPEN;\r
697         Pico_mcd->cdd.Status = 0x0E00;\r
698 \r
699         Pico_mcd->cdd.Minute = 0;\r
700         Pico_mcd->cdd.Seconde = 0;\r
701         Pico_mcd->cdd.Frame = 0;\r
702         Pico_mcd->cdd.Ext = 0;\r
703 \r
704         Pico_mcd->scd.CDD_Complete = 1;\r
705 \r
706         return 0;\r
707 }\r
708 \r
709 \r
710 PICO_INTERNAL int CDD_cA(void)\r
711 {\r
712         CHECK_TRAY_OPEN\r
713         CHECK_CD_PRESENT\r
714 \r
715         Pico_mcd->scd.Status_CDC &= ~1;\r
716 \r
717         Pico_mcd->scd.Status_CDD = READY;\r
718         Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;\r
719 \r
720         Pico_mcd->cdd.Minute = 0;\r
721         Pico_mcd->cdd.Seconde = INT_TO_BCDW(1);\r
722         Pico_mcd->cdd.Frame = INT_TO_BCDW(1);\r
723         Pico_mcd->cdd.Ext = 0;\r
724 \r
725         Pico_mcd->scd.CDD_Complete = 1;\r
726 \r
727         return 0;\r
728 }\r
729 \r
730 \r
731 PICO_INTERNAL int CDD_Def(void)\r
732 {\r
733         Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;\r
734 \r
735         Pico_mcd->cdd.Minute = 0;\r
736         Pico_mcd->cdd.Seconde = 0;\r
737         Pico_mcd->cdd.Frame = 0;\r
738         Pico_mcd->cdd.Ext = 0;\r
739 \r
740         return 0;\r
741 }\r
742 \r
743 \r