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