390c3094d3a279fbad106e174e3ddd3ba7f02438
[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 #include "cd_sys.h"\r
12 #include "cd_file.h"\r
13 \r
14 #include "../PicoInt.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 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 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 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 int Init_CD_Driver(void)\r
179 {\r
180         return 0;\r
181 }\r
182 \r
183 \r
184 void End_CD_Driver(void)\r
185 {\r
186         FILE_End();\r
187 }\r
188 \r
189 \r
190 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 //      memset(CD_Audio_Buffer_L, 0, 4096 * 4);\r
206 //      memset(CD_Audio_Buffer_R, 0, 4096 * 4);\r
207 \r
208         CD_Present = 0;\r
209         Pico_mcd->scd.Status_CDD = NOCD;\r
210 \r
211         if (iso_name != NULL)\r
212         {\r
213                 ret = Load_ISO(iso_name, is_bin);\r
214                 if (ret == 0) {\r
215                         CD_Present = 1;\r
216                         Pico_mcd->scd.Status_CDD = READY;\r
217                 }\r
218         }\r
219 \r
220         return ret;\r
221 }\r
222 \r
223 \r
224 void Stop_CD(void)\r
225 {\r
226         Unload_ISO();\r
227         CD_Present = 0;\r
228 }\r
229 \r
230 \r
231 void Change_CD(void)\r
232 {\r
233         if (Pico_mcd->scd.Status_CDD == TRAY_OPEN) Close_Tray_CDD_cC();\r
234         else Open_Tray_CDD_cD();\r
235 }\r
236 \r
237 \r
238 int Get_Status_CDD_c0(void)\r
239 {\r
240         cdprintf("Status command : Cur LBA = %d", Pico_mcd->scd.Cur_LBA);\r
241 \r
242         // Clear immediat status\r
243         if ((Pico_mcd->cdd.Status & 0x0F00) == 0x0200)\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) == 0x0700)\r
246                 Pico_mcd->cdd.Status = (Pico_mcd->scd.Status_CDD & 0xFF00) | (Pico_mcd->cdd.Status & 0x00FF);\r
247         else if ((Pico_mcd->cdd.Status & 0x0F00) == 0x0E00)\r
248                 Pico_mcd->cdd.Status = (Pico_mcd->scd.Status_CDD & 0xFF00) | (Pico_mcd->cdd.Status & 0x00FF);\r
249 \r
250         Pico_mcd->scd.CDD_Complete = 1;\r
251 \r
252         return 0;\r
253 }\r
254 \r
255 \r
256 int Stop_CDD_c1(void)\r
257 {\r
258         CHECK_TRAY_OPEN\r
259 \r
260         Pico_mcd->scd.Status_CDC &= ~1;                         // Stop CDC read\r
261 \r
262         if (CD_Present) Pico_mcd->scd.Status_CDD = STOPPED;\r
263         else Pico_mcd->scd.Status_CDD = NOCD;\r
264         Pico_mcd->cdd.Status = 0x0000;\r
265 \r
266         Pico_mcd->s68k_regs[0x36] |= 0x01;                      // Data bit set because stopped\r
267 \r
268         Pico_mcd->cdd.Minute = 0;\r
269         Pico_mcd->cdd.Seconde = 0;\r
270         Pico_mcd->cdd.Frame = 0;\r
271         Pico_mcd->cdd.Ext = 0;\r
272 \r
273         Pico_mcd->scd.CDD_Complete = 1;\r
274 \r
275         return 0;\r
276 }\r
277 \r
278 \r
279 int Get_Pos_CDD_c20(void)\r
280 {\r
281         _msf MSF;\r
282 \r
283         cdprintf("command 200 : Cur LBA = %d", Pico_mcd->scd.Cur_LBA);\r
284 \r
285         CHECK_TRAY_OPEN\r
286 \r
287         Pico_mcd->cdd.Status &= 0xFF;\r
288         if (!CD_Present)\r
289         {\r
290                 Pico_mcd->scd.Status_CDD = NOCD;\r
291                 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
292         }\r
293 //      else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
294         Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
295 \r
296         cdprintf("Status CDD = %.4X  Status = %.4X", Pico_mcd->scd.Status_CDD, Pico_mcd->cdd.Status);\r
297 \r
298         LBA_to_MSF(Pico_mcd->scd.Cur_LBA, &MSF);\r
299 \r
300         Pico_mcd->cdd.Minute = INT_TO_BCDW(MSF.M);\r
301         Pico_mcd->cdd.Seconde = INT_TO_BCDW(MSF.S);\r
302         Pico_mcd->cdd.Frame = INT_TO_BCDW(MSF.F);\r
303         Pico_mcd->cdd.Ext = 0;\r
304 \r
305         Pico_mcd->scd.CDD_Complete = 1;\r
306 \r
307         return 0;\r
308 }\r
309 \r
310 \r
311 int Get_Track_Pos_CDD_c21(void)\r
312 {\r
313         int elapsed_time;\r
314         _msf MSF;\r
315 \r
316         cdprintf("command 201 : Cur LBA = %d", Pico_mcd->scd.Cur_LBA);\r
317 \r
318         CHECK_TRAY_OPEN\r
319 \r
320         Pico_mcd->cdd.Status &= 0xFF;\r
321         if (!CD_Present)\r
322         {\r
323                 Pico_mcd->scd.Status_CDD = NOCD;\r
324                 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
325         }\r
326 //      else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
327         Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
328 \r
329         elapsed_time = Pico_mcd->scd.Cur_LBA - Track_to_LBA(LBA_to_Track(Pico_mcd->scd.Cur_LBA));\r
330         LBA_to_MSF(elapsed_time - 150, &MSF);\r
331 \r
332         cdprintf("   elapsed = %d", elapsed_time);\r
333 \r
334         Pico_mcd->cdd.Minute = INT_TO_BCDW(MSF.M);\r
335         Pico_mcd->cdd.Seconde = INT_TO_BCDW(MSF.S);\r
336         Pico_mcd->cdd.Frame = INT_TO_BCDW(MSF.F);\r
337         Pico_mcd->cdd.Ext = 0;\r
338 \r
339         Pico_mcd->scd.CDD_Complete = 1;\r
340 \r
341         return 0;\r
342 }\r
343 \r
344 \r
345 int Get_Current_Track_CDD_c22(void)\r
346 {\r
347         cdprintf("Status CDD = %.4X  Status = %.4X", Pico_mcd->scd.Status_CDD, Pico_mcd->cdd.Status);\r
348 \r
349         CHECK_TRAY_OPEN\r
350 \r
351         Pico_mcd->cdd.Status &= 0xFF;\r
352         if (!CD_Present)\r
353         {\r
354                 Pico_mcd->scd.Status_CDD = NOCD;\r
355                 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
356         }\r
357 //      else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
358         Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
359 \r
360         Pico_mcd->scd.Cur_Track = LBA_to_Track(Pico_mcd->scd.Cur_LBA);\r
361 \r
362         if (Pico_mcd->scd.Cur_Track == 100) Pico_mcd->cdd.Minute = 0x0A02;\r
363         else Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
364         Pico_mcd->cdd.Seconde = 0;\r
365         Pico_mcd->cdd.Frame = 0;\r
366         Pico_mcd->cdd.Ext = 0;\r
367 \r
368         Pico_mcd->scd.CDD_Complete = 1;\r
369 \r
370         return 0;\r
371 }\r
372 \r
373 \r
374 int Get_Total_Lenght_CDD_c23(void)\r
375 {\r
376         CHECK_TRAY_OPEN\r
377 \r
378         Pico_mcd->cdd.Status &= 0xFF;\r
379         if (!CD_Present)\r
380         {\r
381                 Pico_mcd->scd.Status_CDD = NOCD;\r
382                 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
383         }\r
384 //      else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
385         Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
386 \r
387         Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->TOC.Tracks[Pico_mcd->TOC.Last_Track].MSF.M);\r
388         Pico_mcd->cdd.Seconde = INT_TO_BCDW(Pico_mcd->TOC.Tracks[Pico_mcd->TOC.Last_Track].MSF.S);\r
389         Pico_mcd->cdd.Frame = INT_TO_BCDW(Pico_mcd->TOC.Tracks[Pico_mcd->TOC.Last_Track].MSF.F);\r
390         Pico_mcd->cdd.Ext = 0;\r
391 \r
392         Pico_mcd->scd.CDD_Complete = 1;\r
393 \r
394         return 0;\r
395 }\r
396 \r
397 \r
398 int Get_First_Last_Track_CDD_c24(void)\r
399 {\r
400         CHECK_TRAY_OPEN\r
401 \r
402         Pico_mcd->cdd.Status &= 0xFF;\r
403         if (!CD_Present)\r
404         {\r
405                 Pico_mcd->scd.Status_CDD = NOCD;\r
406         }\r
407 //      else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
408         Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
409 \r
410         Pico_mcd->cdd.Minute = INT_TO_BCDW(1);\r
411         Pico_mcd->cdd.Seconde = INT_TO_BCDW(Pico_mcd->TOC.Last_Track);\r
412         Pico_mcd->cdd.Frame = 0;\r
413         Pico_mcd->cdd.Ext = 0;\r
414 \r
415         Pico_mcd->scd.CDD_Complete = 1;\r
416 \r
417         return 0;\r
418 }\r
419 \r
420 \r
421 int Get_Track_Adr_CDD_c25(void)\r
422 {\r
423         int track_number;\r
424 \r
425         CHECK_TRAY_OPEN\r
426 \r
427         // track number in TC4 & TC5\r
428 \r
429         track_number = (Pico_mcd->s68k_regs[0x38+10+4] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+5] & 0xF);\r
430 \r
431         Pico_mcd->cdd.Status &= 0xFF;\r
432         if (!CD_Present)\r
433         {\r
434                 Pico_mcd->scd.Status_CDD = NOCD;\r
435                 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
436         }\r
437 //      else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
438         Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
439 \r
440         if (track_number > Pico_mcd->TOC.Last_Track) track_number = Pico_mcd->TOC.Last_Track;\r
441         else if (track_number < 1) track_number = 1;\r
442 \r
443         Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->TOC.Tracks[track_number - 1].MSF.M);\r
444         Pico_mcd->cdd.Seconde = INT_TO_BCDW(Pico_mcd->TOC.Tracks[track_number - 1].MSF.S);\r
445         Pico_mcd->cdd.Frame = INT_TO_BCDW(Pico_mcd->TOC.Tracks[track_number - 1].MSF.F);\r
446         Pico_mcd->cdd.Ext = track_number % 10;\r
447 \r
448         if (track_number == 1) Pico_mcd->cdd.Frame |= 0x0800; // data track\r
449 \r
450         Pico_mcd->scd.CDD_Complete = 1;\r
451         return 0;\r
452 }\r
453 \r
454 \r
455 int Play_CDD_c3(void)\r
456 {\r
457         _msf MSF;\r
458         int delay, new_lba;\r
459 \r
460         CHECK_TRAY_OPEN\r
461         CHECK_CD_PRESENT\r
462 \r
463         // MSF of the track to play in TC buffer\r
464 \r
465         MSF.M = (Pico_mcd->s68k_regs[0x38+10+2] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+3] & 0xF);\r
466         MSF.S = (Pico_mcd->s68k_regs[0x38+10+4] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+5] & 0xF);\r
467         MSF.F = (Pico_mcd->s68k_regs[0x38+10+6] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+7] & 0xF);\r
468 \r
469         Pico_mcd->scd.Cur_Track = MSF_to_Track(&MSF);\r
470 \r
471         new_lba = MSF_to_LBA(&MSF);\r
472         delay = new_lba - Pico_mcd->scd.Cur_LBA;\r
473         if (delay < 0) delay = -delay;\r
474         delay >>= 12;\r
475 \r
476         Pico_mcd->scd.Cur_LBA = new_lba;\r
477         CDC_Update_Header();\r
478 \r
479         cdprintf("Read : Cur LBA = %d, M=%d, S=%d, F=%d", Pico_mcd->scd.Cur_LBA, MSF.M, MSF.S, MSF.F);\r
480 \r
481         if (Pico_mcd->scd.Status_CDD != PLAYING) delay += 20;\r
482 \r
483         Pico_mcd->scd.Status_CDD = PLAYING;\r
484         Pico_mcd->cdd.Status = 0x0102;\r
485 //      Pico_mcd->cdd.Status = COMM_OK;\r
486 \r
487         if (Pico_mcd->scd.File_Add_Delay == 0) Pico_mcd->scd.File_Add_Delay = delay;\r
488 \r
489         if (Pico_mcd->scd.Cur_Track == 1)\r
490         {\r
491                 Pico_mcd->s68k_regs[0x36] |=  0x01;                             // DATA\r
492         }\r
493         else\r
494         {\r
495                 Pico_mcd->s68k_regs[0x36] &= ~0x01;                             // AUDIO\r
496                 //CD_Audio_Starting = 1;\r
497                 FILE_Play_CD_LBA();\r
498         }\r
499 \r
500         if (Pico_mcd->scd.Cur_Track == 100) Pico_mcd->cdd.Minute = 0x0A02;\r
501         else Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
502         Pico_mcd->cdd.Seconde = 0;\r
503         Pico_mcd->cdd.Frame = 0;\r
504         Pico_mcd->cdd.Ext = 0;\r
505 \r
506         Pico_mcd->scd.Status_CDC |= 1;                  // Read data with CDC\r
507 \r
508         Pico_mcd->scd.CDD_Complete = 1;\r
509         return 0;\r
510 }\r
511 \r
512 \r
513 int Seek_CDD_c4(void)\r
514 {\r
515         _msf MSF;\r
516 \r
517         CHECK_TRAY_OPEN\r
518         CHECK_CD_PRESENT\r
519 \r
520         // MSF to seek in TC buffer\r
521 \r
522         MSF.M = (Pico_mcd->s68k_regs[0x38+10+2] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+3] & 0xF);\r
523         MSF.S = (Pico_mcd->s68k_regs[0x38+10+4] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+5] & 0xF);\r
524         MSF.F = (Pico_mcd->s68k_regs[0x38+10+6] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+7] & 0xF);\r
525 \r
526         Pico_mcd->scd.Cur_Track = MSF_to_Track(&MSF);\r
527         Pico_mcd->scd.Cur_LBA = MSF_to_LBA(&MSF);\r
528         CDC_Update_Header();\r
529 \r
530         Pico_mcd->scd.Status_CDC &= ~1;                         // Stop CDC read\r
531 \r
532         Pico_mcd->scd.Status_CDD = READY;\r
533         Pico_mcd->cdd.Status = 0x0200;\r
534 \r
535         // DATA ?\r
536         if (Pico_mcd->scd.Cur_Track == 1)\r
537              Pico_mcd->s68k_regs[0x36] |=  0x01;\r
538         else Pico_mcd->s68k_regs[0x36] &= ~0x01;                // AUDIO\r
539 \r
540         Pico_mcd->cdd.Minute = 0;\r
541         Pico_mcd->cdd.Seconde = 0;\r
542         Pico_mcd->cdd.Frame = 0;\r
543         Pico_mcd->cdd.Ext = 0;\r
544 \r
545         Pico_mcd->scd.CDD_Complete = 1;\r
546 \r
547         return 0;\r
548 }\r
549 \r
550 \r
551 int Pause_CDD_c6(void)\r
552 {\r
553         CHECK_TRAY_OPEN\r
554         CHECK_CD_PRESENT\r
555 \r
556         Pico_mcd->scd.Status_CDC &= ~1;                 // Stop CDC read to start a new one if raw data\r
557 \r
558         Pico_mcd->scd.Status_CDD = READY;\r
559         Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;\r
560 \r
561         Pico_mcd->s68k_regs[0x36] |= 0x01;              // Data bit set because stopped\r
562 \r
563         Pico_mcd->cdd.Minute = 0;\r
564         Pico_mcd->cdd.Seconde = 0;\r
565         Pico_mcd->cdd.Frame = 0;\r
566         Pico_mcd->cdd.Ext = 0;\r
567 \r
568         Pico_mcd->scd.CDD_Complete = 1;\r
569 \r
570         return 0;\r
571 }\r
572 \r
573 \r
574 int Resume_CDD_c7(void)\r
575 {\r
576         CHECK_TRAY_OPEN\r
577         CHECK_CD_PRESENT\r
578 \r
579         Pico_mcd->scd.Cur_Track = LBA_to_Track(Pico_mcd->scd.Cur_LBA);\r
580 \r
581 #ifdef DEBUG_CD\r
582         {\r
583                 _msf MSF;\r
584                 LBA_to_MSF(Pico_mcd->scd.Cur_LBA, &MSF);\r
585                 cdprintf("Resume read : Cur LBA = %d, M=%d, S=%d, F=%d", Pico_mcd->scd.Cur_LBA, MSF.M, MSF.S, MSF.F);\r
586         }\r
587 #endif\r
588 \r
589         Pico_mcd->scd.Status_CDD = PLAYING;\r
590         Pico_mcd->cdd.Status = 0x0102;\r
591 \r
592         if (Pico_mcd->scd.Cur_Track == 1)\r
593         {\r
594                 Pico_mcd->s68k_regs[0x36] |=  0x01;                             // DATA\r
595         }\r
596         else\r
597         {\r
598                 Pico_mcd->s68k_regs[0x36] &= ~0x01;                             // AUDIO\r
599                 //CD_Audio_Starting = 1;\r
600                 FILE_Play_CD_LBA();\r
601         }\r
602 \r
603         if (Pico_mcd->scd.Cur_Track == 100) Pico_mcd->cdd.Minute = 0x0A02;\r
604         else Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
605         Pico_mcd->cdd.Seconde = 0;\r
606         Pico_mcd->cdd.Frame = 0;\r
607         Pico_mcd->cdd.Ext = 0;\r
608 \r
609         Pico_mcd->scd.Status_CDC |= 1;                  // Read data with CDC\r
610 \r
611         Pico_mcd->scd.CDD_Complete = 1;\r
612         return 0;\r
613 }\r
614 \r
615 \r
616 int Fast_Foward_CDD_c8(void)\r
617 {\r
618         CHECK_TRAY_OPEN\r
619         CHECK_CD_PRESENT\r
620 \r
621         Pico_mcd->scd.Status_CDC &= ~1;                         // Stop CDC read\r
622 \r
623         Pico_mcd->scd.Status_CDD = FAST_FOW;\r
624         Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD | 2;\r
625 \r
626         Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
627         Pico_mcd->cdd.Seconde = 0;\r
628         Pico_mcd->cdd.Frame = 0;\r
629         Pico_mcd->cdd.Ext = 0;\r
630 \r
631         Pico_mcd->scd.CDD_Complete = 1;\r
632 \r
633         return 0;\r
634 }\r
635 \r
636 \r
637 int Fast_Rewind_CDD_c9(void)\r
638 {\r
639         CHECK_TRAY_OPEN\r
640         CHECK_CD_PRESENT\r
641 \r
642         Pico_mcd->scd.Status_CDC &= ~1;                         // Stop CDC read\r
643 \r
644         Pico_mcd->scd.Status_CDD = FAST_REV;\r
645         Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD | 2;\r
646 \r
647         Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
648         Pico_mcd->cdd.Seconde = 0;\r
649         Pico_mcd->cdd.Frame = 0;\r
650         Pico_mcd->cdd.Ext = 0;\r
651 \r
652         Pico_mcd->scd.CDD_Complete = 1;\r
653 \r
654         return 0;\r
655 }\r
656 \r
657 \r
658 int Close_Tray_CDD_cC(void)\r
659 {\r
660         CD_Present = 0;\r
661         //Clear_Sound_Buffer();\r
662 \r
663         Pico_mcd->scd.Status_CDC &= ~1;                 // Stop CDC read\r
664 \r
665         printf("tray close\n");\r
666 \r
667         if (PicoMCDcloseTray != NULL)\r
668                 CD_Present = PicoMCDcloseTray();\r
669 \r
670         Pico_mcd->scd.Status_CDD = CD_Present ? STOPPED : NOCD;\r
671         Pico_mcd->cdd.Status = 0x0000;\r
672 \r
673         Pico_mcd->cdd.Minute = 0;\r
674         Pico_mcd->cdd.Seconde = 0;\r
675         Pico_mcd->cdd.Frame = 0;\r
676         Pico_mcd->cdd.Ext = 0;\r
677 \r
678         Pico_mcd->scd.CDD_Complete = 1;\r
679 \r
680         return 0;\r
681 }\r
682 \r
683 \r
684 int Open_Tray_CDD_cD(void)\r
685 {\r
686         CHECK_TRAY_OPEN\r
687 \r
688         Pico_mcd->scd.Status_CDC &= ~1;                 // Stop CDC read\r
689 \r
690         printf("tray open\n");\r
691 \r
692         Unload_ISO();\r
693         CD_Present = 0;\r
694 \r
695         if (PicoMCDopenTray != NULL)\r
696                 PicoMCDopenTray();\r
697 \r
698         Pico_mcd->scd.Status_CDD = TRAY_OPEN;\r
699         Pico_mcd->cdd.Status = 0x0E00;\r
700 \r
701         Pico_mcd->cdd.Minute = 0;\r
702         Pico_mcd->cdd.Seconde = 0;\r
703         Pico_mcd->cdd.Frame = 0;\r
704         Pico_mcd->cdd.Ext = 0;\r
705 \r
706         Pico_mcd->scd.CDD_Complete = 1;\r
707 \r
708         return 0;\r
709 }\r
710 \r
711 \r
712 int CDD_cA(void)\r
713 {\r
714         CHECK_TRAY_OPEN\r
715         CHECK_CD_PRESENT\r
716 \r
717         Pico_mcd->scd.Status_CDC &= ~1;\r
718 \r
719         Pico_mcd->scd.Status_CDD = READY;\r
720         Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;\r
721 \r
722         Pico_mcd->cdd.Minute = 0;\r
723         Pico_mcd->cdd.Seconde = INT_TO_BCDW(1);\r
724         Pico_mcd->cdd.Frame = INT_TO_BCDW(1);\r
725         Pico_mcd->cdd.Ext = 0;\r
726 \r
727         Pico_mcd->scd.CDD_Complete = 1;\r
728 \r
729         return 0;\r
730 }\r
731 \r
732 \r
733 int CDD_Def(void)\r
734 {\r
735         Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;\r
736 \r
737         Pico_mcd->cdd.Minute = 0;\r
738         Pico_mcd->cdd.Seconde = 0;\r
739         Pico_mcd->cdd.Frame = 0;\r
740         Pico_mcd->cdd.Ext = 0;\r
741 \r
742         return 0;\r
743 }\r
744 \r
745 \r