2c70ea2685f20b6f8a0ed77af5dc421f5d74f68f
[picodrive.git] / Pico / cd / cd_sys.c
1 #include <stdio.h>\r
2 #include "cd_sys.h"\r
3 #include "cd_file.h"\r
4 \r
5 #include "../PicoInt.h"\r
6 \r
7 #define cdprintf dprintf\r
8 //#define cdprintf(x...)\r
9 #define DEBUG_CD\r
10 \r
11 #define TRAY_OPEN       0x0500          // TRAY OPEN CDD status\r
12 #define NOCD            0x0000          // CD removed CDD status\r
13 #define STOPPED         0x0900          // STOPPED CDD status (happen after stop or close tray command)\r
14 #define READY           0x0400          // READY CDD status (also used for seeking)\r
15 #define FAST_FOW        0x0300          // FAST FORWARD track CDD status\r
16 #define FAST_REV        0x10300         // FAST REVERSE track CDD status\r
17 #define PLAYING         0x0100          // PLAYING audio track CDD status\r
18 \r
19 \r
20 /*\r
21 int CDDA_Enable;\r
22 \r
23 int CD_Audio_Buffer_L[8192];\r
24 int CD_Audio_Buffer_R[8192];\r
25 int CD_Audio_Buffer_Read_Pos = 0;\r
26 int CD_Audio_Buffer_Write_Pos = 2000;\r
27 int CD_Audio_Starting;\r
28 */\r
29 \r
30 static int CD_Present = 0;\r
31 int CD_Timer_Counter = 0; // TODO: check refs\r
32 \r
33 static int CDD_Complete;\r
34 \r
35 static int File_Add_Delay = 0;\r
36 \r
37 \r
38 \r
39 #define CHECK_TRAY_OPEN                         \\r
40 if (Pico_mcd->scd.Status_CDD == TRAY_OPEN)      \\r
41 {                                                                       \\r
42         Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;        \\r
43                                                                         \\r
44         Pico_mcd->cdd.Minute = 0;                                       \\r
45         Pico_mcd->cdd.Seconde = 0;                              \\r
46         Pico_mcd->cdd.Frame = 0;                                        \\r
47         Pico_mcd->cdd.Ext = 0;                                  \\r
48                                                                         \\r
49         CDD_Complete = 1;                               \\r
50                                                                         \\r
51         return 2;                                               \\r
52 }\r
53 \r
54 \r
55 #define CHECK_CD_PRESENT                        \\r
56 if (!CD_Present)                                        \\r
57 {                                                                       \\r
58         Pico_mcd->scd.Status_CDD = NOCD;                        \\r
59         Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;        \\r
60                                                                         \\r
61         Pico_mcd->cdd.Minute = 0;                                       \\r
62         Pico_mcd->cdd.Seconde = 0;                              \\r
63         Pico_mcd->cdd.Frame = 0;                                        \\r
64         Pico_mcd->cdd.Ext = 0;                                  \\r
65                                                                         \\r
66         CDD_Complete = 1;                               \\r
67                                                                         \\r
68         return 3;                                               \\r
69 }\r
70 \r
71 \r
72 #if 0\r
73 static void MSB2DWORD(unsigned int *d, unsigned char *b)\r
74 {\r
75         unsigned int  retVal;\r
76 \r
77         retVal = (unsigned int )b[0];\r
78         retVal = (retVal<<8) + (unsigned int )b[1];\r
79         retVal = (retVal<<8) + (unsigned int )b[2];\r
80         retVal = (retVal<<8) + (unsigned int )b[3];\r
81 \r
82         *d = retVal;\r
83 }\r
84 #endif\r
85 \r
86 static int MSF_to_LBA(_msf *MSF)\r
87 {\r
88         return (MSF->M * 60 * 75) + (MSF->S * 75) + MSF->F - 150;\r
89 }\r
90 \r
91 \r
92 void LBA_to_MSF(int lba, _msf *MSF)\r
93 {\r
94         if (lba < -150) lba = 0;\r
95         else lba += 150;\r
96         MSF->M = lba / (60 * 75);\r
97         MSF->S = (lba / 75) % 60;\r
98         MSF->F = lba % 75;\r
99 }\r
100 \r
101 \r
102 static unsigned int MSF_to_Track(_msf *MSF)\r
103 {\r
104         int i, Start, Cur;\r
105 \r
106         Start = (MSF->M << 16) + (MSF->S << 8) + MSF->F;\r
107 \r
108         for(i = Pico_mcd->scd.TOC.First_Track; i <= (Pico_mcd->scd.TOC.Last_Track + 1); i++)\r
109         {\r
110                 Cur = Pico_mcd->scd.TOC.Tracks[i - Pico_mcd->scd.TOC.First_Track].MSF.M << 16;\r
111                 Cur += Pico_mcd->scd.TOC.Tracks[i - Pico_mcd->scd.TOC.First_Track].MSF.S << 8;\r
112                 Cur += Pico_mcd->scd.TOC.Tracks[i - Pico_mcd->scd.TOC.First_Track].MSF.F;\r
113 \r
114                 if (Cur > Start) break;\r
115         }\r
116 \r
117         --i;\r
118 \r
119         if (i > Pico_mcd->scd.TOC.Last_Track) return 100;\r
120         if (i < Pico_mcd->scd.TOC.First_Track) i = Pico_mcd->scd.TOC.First_Track;\r
121 \r
122         return (unsigned) i;\r
123 }\r
124 \r
125 \r
126 static unsigned int LBA_to_Track(int lba)\r
127 {\r
128         _msf MSF;\r
129 \r
130         LBA_to_MSF(lba, &MSF);\r
131         return MSF_to_Track(&MSF);\r
132 }\r
133 \r
134 \r
135 static void Track_to_MSF(int track, _msf *MSF)\r
136 {\r
137         if (track < Pico_mcd->scd.TOC.First_Track) track = Pico_mcd->scd.TOC.First_Track;\r
138         else if (track > Pico_mcd->scd.TOC.Last_Track) track = Pico_mcd->scd.TOC.Last_Track;\r
139 \r
140         MSF->M = Pico_mcd->scd.TOC.Tracks[track - Pico_mcd->scd.TOC.First_Track].MSF.M;\r
141         MSF->S = Pico_mcd->scd.TOC.Tracks[track - Pico_mcd->scd.TOC.First_Track].MSF.S;\r
142         MSF->F = Pico_mcd->scd.TOC.Tracks[track - Pico_mcd->scd.TOC.First_Track].MSF.F;\r
143 }\r
144 \r
145 \r
146 int Track_to_LBA(int track)\r
147 {\r
148         _msf MSF;\r
149 \r
150         Track_to_MSF(track, &MSF);\r
151         return MSF_to_LBA(&MSF);\r
152 }\r
153 \r
154 \r
155 void Check_CD_Command(void)\r
156 {\r
157         cdprintf("CHECK CD COMMAND");\r
158 \r
159         // Check CDD\r
160 \r
161         if (CDD_Complete)\r
162         {\r
163                 CDD_Complete = 0;\r
164 \r
165                 CDD_Export_Status();\r
166         }\r
167 \r
168         // Check CDC\r
169 \r
170         if (Pico_mcd->scd.Status_CDC & 1)                       // CDC is reading data ...\r
171         {\r
172                 cdprintf("Got a read command");\r
173 \r
174                 // DATA ?\r
175                 if (Pico_mcd->scd.TOC.Tracks[Pico_mcd->scd.Cur_Track - Pico_mcd->scd.TOC.First_Track].Type)\r
176                      Pico_mcd->s68k_regs[0x36] |=  0x01;\r
177                 else Pico_mcd->s68k_regs[0x36] &= ~0x01;                        // AUDIO\r
178 \r
179                 if (File_Add_Delay == 0)\r
180                 {\r
181                         FILE_Read_One_LBA_CDC();\r
182                 }\r
183                 else File_Add_Delay--;\r
184         }\r
185 \r
186         if (Pico_mcd->scd.Status_CDD == FAST_FOW)\r
187         {\r
188                 Pico_mcd->scd.Cur_LBA += 10;\r
189                 CDC_Update_Header();\r
190 \r
191         }\r
192         else if (Pico_mcd->scd.Status_CDD == FAST_REV)\r
193         {\r
194                 Pico_mcd->scd.Cur_LBA -= 10;\r
195                 if (Pico_mcd->scd.Cur_LBA < -150) Pico_mcd->scd.Cur_LBA = -150;\r
196                 CDC_Update_Header();\r
197         }\r
198 }\r
199 \r
200 \r
201 int Init_CD_Driver(void)\r
202 {\r
203         FILE_Init();\r
204 \r
205         return 0;\r
206 }\r
207 \r
208 \r
209 void End_CD_Driver(void)\r
210 {\r
211         FILE_End();\r
212 }\r
213 \r
214 \r
215 void Reset_CD(void)\r
216 {\r
217         Pico_mcd->scd.Cur_Track = 0;\r
218         Pico_mcd->scd.Cur_LBA = -150;\r
219         Pico_mcd->scd.Status_CDD = READY;\r
220         CDD_Complete = 0;\r
221 }\r
222 \r
223 \r
224 int Insert_CD(char *iso_name, int is_bin)\r
225 {\r
226         int ret = 0;\r
227 \r
228 //      memset(CD_Audio_Buffer_L, 0, 4096 * 4);\r
229 //      memset(CD_Audio_Buffer_R, 0, 4096 * 4);\r
230 \r
231         CD_Present = 0;\r
232 \r
233         if (iso_name != NULL)\r
234         {\r
235                 ret = Load_ISO(iso_name, is_bin);\r
236                 if (ret == 0)\r
237                         CD_Present = 1;\r
238         }\r
239 \r
240         return ret;\r
241 }\r
242 \r
243 \r
244 void Stop_CD(void)\r
245 {\r
246         Unload_ISO();\r
247         CD_Present = 0;\r
248 }\r
249 \r
250 \r
251 void Change_CD(void)\r
252 {\r
253         if (Pico_mcd->scd.Status_CDD == TRAY_OPEN) Close_Tray_CDD_cC();\r
254         else Open_Tray_CDD_cD();\r
255 }\r
256 \r
257 \r
258 int Get_Status_CDD_c0(void)\r
259 {\r
260         cdprintf("Status command : Cur LBA = %d", Pico_mcd->scd.Cur_LBA);\r
261 \r
262         // Clear immediat status\r
263         if ((Pico_mcd->cdd.Status & 0x0F00) == 0x0200)\r
264                 Pico_mcd->cdd.Status = (Pico_mcd->scd.Status_CDD & 0xFF00) | (Pico_mcd->cdd.Status & 0x00FF);\r
265         else if ((Pico_mcd->cdd.Status & 0x0F00) == 0x0700)\r
266                 Pico_mcd->cdd.Status = (Pico_mcd->scd.Status_CDD & 0xFF00) | (Pico_mcd->cdd.Status & 0x00FF);\r
267         else if ((Pico_mcd->cdd.Status & 0x0F00) == 0x0E00)\r
268                 Pico_mcd->cdd.Status = (Pico_mcd->scd.Status_CDD & 0xFF00) | (Pico_mcd->cdd.Status & 0x00FF);\r
269 \r
270         CDD_Complete = 1;\r
271 \r
272         return 0;\r
273 }\r
274 \r
275 \r
276 int Stop_CDD_c1(void)\r
277 {\r
278         CHECK_TRAY_OPEN\r
279 \r
280         Pico_mcd->scd.Status_CDC &= ~1;                         // Stop CDC read\r
281 \r
282         if (CD_Present) Pico_mcd->scd.Status_CDD = STOPPED;\r
283         else Pico_mcd->scd.Status_CDD = NOCD;\r
284         Pico_mcd->cdd.Status = 0x0000;\r
285 \r
286         Pico_mcd->s68k_regs[0x36] |= 0x01;                      // Data bit set because stopped\r
287 \r
288         Pico_mcd->cdd.Minute = 0;\r
289         Pico_mcd->cdd.Seconde = 0;\r
290         Pico_mcd->cdd.Frame = 0;\r
291         Pico_mcd->cdd.Ext = 0;\r
292 \r
293         CDD_Complete = 1;\r
294 \r
295         return 0;\r
296 }\r
297 \r
298 \r
299 int Get_Pos_CDD_c20(void)\r
300 {\r
301         _msf MSF;\r
302 \r
303         cdprintf("command 200 : Cur LBA = %d", Pico_mcd->scd.Cur_LBA);\r
304 \r
305         CHECK_TRAY_OPEN\r
306 \r
307         Pico_mcd->cdd.Status &= 0xFF;\r
308         if (!CD_Present)\r
309         {\r
310                 Pico_mcd->scd.Status_CDD = NOCD;\r
311                 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
312         }\r
313 //      else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
314         Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
315 \r
316         cdprintf("Status CDD = %.4X  Status = %.4X", Pico_mcd->scd.Status_CDD, Pico_mcd->cdd.Status);\r
317 \r
318         LBA_to_MSF(Pico_mcd->scd.Cur_LBA, &MSF);\r
319 \r
320         Pico_mcd->cdd.Minute = INT_TO_BCDW(MSF.M);\r
321         Pico_mcd->cdd.Seconde = INT_TO_BCDW(MSF.S);\r
322         Pico_mcd->cdd.Frame = INT_TO_BCDW(MSF.F);\r
323         Pico_mcd->cdd.Ext = 0;\r
324 \r
325         CDD_Complete = 1;\r
326 \r
327         return 0;\r
328 }\r
329 \r
330 \r
331 int Get_Track_Pos_CDD_c21(void)\r
332 {\r
333         int elapsed_time;\r
334         _msf MSF;\r
335 \r
336         cdprintf("command 201 : Cur LBA = %d", Pico_mcd->scd.Cur_LBA);\r
337 \r
338         CHECK_TRAY_OPEN\r
339 \r
340         Pico_mcd->cdd.Status &= 0xFF;\r
341         if (!CD_Present)\r
342         {\r
343                 Pico_mcd->scd.Status_CDD = NOCD;\r
344                 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
345         }\r
346 //      else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
347         Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
348 \r
349         elapsed_time = Pico_mcd->scd.Cur_LBA - Track_to_LBA(LBA_to_Track(Pico_mcd->scd.Cur_LBA));\r
350         LBA_to_MSF(elapsed_time - 150, &MSF);\r
351 \r
352         cdprintf("   elapsed = %d", elapsed_time);\r
353 \r
354         Pico_mcd->cdd.Minute = INT_TO_BCDW(MSF.M);\r
355         Pico_mcd->cdd.Seconde = INT_TO_BCDW(MSF.S);\r
356         Pico_mcd->cdd.Frame = INT_TO_BCDW(MSF.F);\r
357         Pico_mcd->cdd.Ext = 0;\r
358 \r
359         CDD_Complete = 1;\r
360 \r
361         return 0;\r
362 }\r
363 \r
364 \r
365 int Get_Current_Track_CDD_c22(void)\r
366 {\r
367         cdprintf("Status CDD = %.4X  Status = %.4X", Pico_mcd->scd.Status_CDD, Pico_mcd->cdd.Status);\r
368 \r
369         CHECK_TRAY_OPEN\r
370 \r
371         Pico_mcd->cdd.Status &= 0xFF;\r
372         if (!CD_Present)\r
373         {\r
374                 Pico_mcd->scd.Status_CDD = NOCD;\r
375                 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
376         }\r
377 //      else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
378         Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
379 \r
380         Pico_mcd->scd.Cur_Track = LBA_to_Track(Pico_mcd->scd.Cur_LBA);\r
381 \r
382         if (Pico_mcd->scd.Cur_Track == 100) Pico_mcd->cdd.Minute = 0x0A02;\r
383         else Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
384         Pico_mcd->cdd.Seconde = 0;\r
385         Pico_mcd->cdd.Frame = 0;\r
386         Pico_mcd->cdd.Ext = 0;\r
387 \r
388         CDD_Complete = 1;\r
389 \r
390         return 0;\r
391 }\r
392 \r
393 \r
394 int Get_Total_Lenght_CDD_c23(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                 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
403         }\r
404 //      else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
405         Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
406 \r
407         Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.TOC.Tracks[Pico_mcd->scd.TOC.Last_Track -\r
408                                 Pico_mcd->scd.TOC.First_Track + 1].MSF.M);\r
409         Pico_mcd->cdd.Seconde = INT_TO_BCDW(Pico_mcd->scd.TOC.Tracks[Pico_mcd->scd.TOC.Last_Track -\r
410                                 Pico_mcd->scd.TOC.First_Track + 1].MSF.S);\r
411         Pico_mcd->cdd.Frame = INT_TO_BCDW(Pico_mcd->scd.TOC.Tracks[Pico_mcd->scd.TOC.Last_Track -\r
412                                 Pico_mcd->scd.TOC.First_Track + 1].MSF.F);\r
413         Pico_mcd->cdd.Ext = 0;\r
414 \r
415 // FIXME: remove\r
416 //Pico_mcd->cdd.Seconde = 2;\r
417 \r
418         CDD_Complete = 1;\r
419 \r
420         return 0;\r
421 }\r
422 \r
423 \r
424 int Get_First_Last_Track_CDD_c24(void)\r
425 {\r
426         CHECK_TRAY_OPEN\r
427 \r
428         Pico_mcd->cdd.Status &= 0xFF;\r
429         if (!CD_Present)\r
430         {\r
431                 Pico_mcd->scd.Status_CDD = NOCD;\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         Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.TOC.First_Track);\r
437         Pico_mcd->cdd.Seconde = INT_TO_BCDW(Pico_mcd->scd.TOC.Last_Track);\r
438         Pico_mcd->cdd.Frame = 0;\r
439         Pico_mcd->cdd.Ext = 0;\r
440 \r
441 // FIXME: remove\r
442 //Pico_mcd->cdd.Minute = Pico_mcd->cdd.Seconde = 1;\r
443 \r
444         CDD_Complete = 1;\r
445 \r
446         return 0;\r
447 }\r
448 \r
449 \r
450 int Get_Track_Adr_CDD_c25(void)\r
451 {\r
452         int track_number;\r
453 \r
454         CHECK_TRAY_OPEN\r
455 \r
456         // track number in TC4 & TC5\r
457 \r
458         track_number = (Pico_mcd->s68k_regs[0x38+10+4] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+5] & 0xF);\r
459 \r
460         Pico_mcd->cdd.Status &= 0xFF;\r
461         if (!CD_Present)\r
462         {\r
463                 Pico_mcd->scd.Status_CDD = NOCD;\r
464                 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
465         }\r
466 //      else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
467         Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
468 \r
469         if (track_number > Pico_mcd->scd.TOC.Last_Track) track_number = Pico_mcd->scd.TOC.Last_Track;\r
470         else if (track_number < Pico_mcd->scd.TOC.First_Track) track_number = Pico_mcd->scd.TOC.First_Track;\r
471 \r
472         Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.TOC.Tracks[track_number - Pico_mcd->scd.TOC.First_Track].MSF.M);\r
473         Pico_mcd->cdd.Seconde = INT_TO_BCDW(Pico_mcd->scd.TOC.Tracks[track_number - Pico_mcd->scd.TOC.First_Track].MSF.S);\r
474         Pico_mcd->cdd.Frame = INT_TO_BCDW(Pico_mcd->scd.TOC.Tracks[track_number - Pico_mcd->scd.TOC.First_Track].MSF.F);\r
475         Pico_mcd->cdd.Ext = track_number % 10;\r
476 \r
477         if (Pico_mcd->scd.TOC.Tracks[track_number - Pico_mcd->scd.TOC.First_Track].Type) Pico_mcd->cdd.Frame |= 0x0800;\r
478 \r
479         CDD_Complete = 1;\r
480         return 0;\r
481 }\r
482 \r
483 \r
484 int Play_CDD_c3(void)\r
485 {\r
486         _msf MSF;\r
487         int delay, new_lba;\r
488 \r
489         CHECK_TRAY_OPEN\r
490         CHECK_CD_PRESENT\r
491 \r
492         // MSF of the track to play in TC buffer\r
493 \r
494         MSF.M = (Pico_mcd->s68k_regs[0x38+10+2] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+3] & 0xF);\r
495         MSF.S = (Pico_mcd->s68k_regs[0x38+10+4] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+5] & 0xF);\r
496         MSF.F = (Pico_mcd->s68k_regs[0x38+10+6] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+7] & 0xF);\r
497 \r
498         Pico_mcd->scd.Cur_Track = MSF_to_Track(&MSF);\r
499 \r
500         new_lba = MSF_to_LBA(&MSF);\r
501         delay = new_lba - Pico_mcd->scd.Cur_LBA;\r
502         if (delay < 0) delay = -delay;\r
503         delay >>= 12;\r
504 \r
505         Pico_mcd->scd.Cur_LBA = new_lba;\r
506         CDC_Update_Header();\r
507 \r
508         cdprintf("Read : Cur LBA = %d, M=%d, S=%d, F=%d", Pico_mcd->scd.Cur_LBA, MSF.M, MSF.S, MSF.F);\r
509 \r
510         if (Pico_mcd->scd.Status_CDD != PLAYING) delay += 20;\r
511 \r
512         Pico_mcd->scd.Status_CDD = PLAYING;\r
513         Pico_mcd->cdd.Status = 0x0102;\r
514 //      Pico_mcd->cdd.Status = COMM_OK;\r
515 \r
516         if (File_Add_Delay == 0) File_Add_Delay = delay;\r
517 \r
518         if (Pico_mcd->scd.TOC.Tracks[Pico_mcd->scd.Cur_Track - Pico_mcd->scd.TOC.First_Track].Type)\r
519         {\r
520                 Pico_mcd->s68k_regs[0x36] |=  0x01;                             // DATA\r
521         }\r
522         else\r
523         {\r
524                 Pico_mcd->s68k_regs[0x36] &= ~0x01;                             // AUDIO\r
525                 //CD_Audio_Starting = 1;\r
526                 FILE_Play_CD_LBA();\r
527         }\r
528 \r
529         if (Pico_mcd->scd.Cur_Track == 100) Pico_mcd->cdd.Minute = 0x0A02;\r
530         else Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
531         Pico_mcd->cdd.Seconde = 0;\r
532         Pico_mcd->cdd.Frame = 0;\r
533         Pico_mcd->cdd.Ext = 0;\r
534 \r
535         Pico_mcd->scd.Status_CDC |= 1;                  // Read data with CDC\r
536 \r
537         CDD_Complete = 1;\r
538         return 0;\r
539 }\r
540 \r
541 \r
542 int Seek_CDD_c4(void)\r
543 {\r
544         _msf MSF;\r
545 \r
546         CHECK_TRAY_OPEN\r
547         CHECK_CD_PRESENT\r
548 \r
549         // MSF to seek in TC buffer\r
550 \r
551         MSF.M = (Pico_mcd->s68k_regs[0x38+10+2] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+3] & 0xF);\r
552         MSF.S = (Pico_mcd->s68k_regs[0x38+10+4] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+5] & 0xF);\r
553         MSF.F = (Pico_mcd->s68k_regs[0x38+10+6] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+7] & 0xF);\r
554 \r
555         Pico_mcd->scd.Cur_Track = MSF_to_Track(&MSF);\r
556         Pico_mcd->scd.Cur_LBA = MSF_to_LBA(&MSF);\r
557         CDC_Update_Header();\r
558 \r
559         Pico_mcd->scd.Status_CDC &= ~1;                         // Stop CDC read\r
560 \r
561         Pico_mcd->scd.Status_CDD = READY;\r
562         Pico_mcd->cdd.Status = 0x0200;\r
563 \r
564         // DATA ?\r
565         if (Pico_mcd->scd.TOC.Tracks[Pico_mcd->scd.Cur_Track - Pico_mcd->scd.TOC.First_Track].Type)\r
566              Pico_mcd->s68k_regs[0x36] |=  0x01;\r
567         else Pico_mcd->s68k_regs[0x36] &= ~0x01;                // AUDIO\r
568 \r
569         Pico_mcd->cdd.Minute = 0;\r
570         Pico_mcd->cdd.Seconde = 0;\r
571         Pico_mcd->cdd.Frame = 0;\r
572         Pico_mcd->cdd.Ext = 0;\r
573 \r
574         CDD_Complete = 1;\r
575 \r
576         return 0;\r
577 }\r
578 \r
579 \r
580 int Pause_CDD_c6(void)\r
581 {\r
582         CHECK_TRAY_OPEN\r
583         CHECK_CD_PRESENT\r
584 \r
585         Pico_mcd->scd.Status_CDC &= ~1;                 // Stop CDC read to start a new one if raw data\r
586 \r
587         Pico_mcd->scd.Status_CDD = READY;\r
588         Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;\r
589 \r
590         Pico_mcd->s68k_regs[0x36] |= 0x01;              // Data bit set because stopped\r
591 \r
592         Pico_mcd->cdd.Minute = 0;\r
593         Pico_mcd->cdd.Seconde = 0;\r
594         Pico_mcd->cdd.Frame = 0;\r
595         Pico_mcd->cdd.Ext = 0;\r
596 \r
597         CDD_Complete = 1;\r
598 \r
599         return 0;\r
600 }\r
601 \r
602 \r
603 int Resume_CDD_c7(void)\r
604 {\r
605         CHECK_TRAY_OPEN\r
606         CHECK_CD_PRESENT\r
607 \r
608         Pico_mcd->scd.Cur_Track = LBA_to_Track(Pico_mcd->scd.Cur_LBA);\r
609 \r
610 #ifdef DEBUG_CD\r
611         {\r
612                 _msf MSF;\r
613                 LBA_to_MSF(Pico_mcd->scd.Cur_LBA, &MSF);\r
614                 cdprintf("Resume read : Cur LBA = %d, M=%d, S=%d, F=%d", Pico_mcd->scd.Cur_LBA, MSF.M, MSF.S, MSF.F);\r
615         }\r
616 #endif\r
617 \r
618         Pico_mcd->scd.Status_CDD = PLAYING;\r
619         Pico_mcd->cdd.Status = 0x0102;\r
620 \r
621         if (Pico_mcd->scd.TOC.Tracks[Pico_mcd->scd.Cur_Track - Pico_mcd->scd.TOC.First_Track].Type)\r
622         {\r
623                 Pico_mcd->s68k_regs[0x36] |=  0x01;                             // DATA\r
624         }\r
625         else\r
626         {\r
627                 Pico_mcd->s68k_regs[0x36] &= ~0x01;                             // AUDIO\r
628                 //CD_Audio_Starting = 1;\r
629                 FILE_Play_CD_LBA();\r
630         }\r
631 \r
632         if (Pico_mcd->scd.Cur_Track == 100) Pico_mcd->cdd.Minute = 0x0A02;\r
633         else Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
634         Pico_mcd->cdd.Seconde = 0;\r
635         Pico_mcd->cdd.Frame = 0;\r
636         Pico_mcd->cdd.Ext = 0;\r
637 \r
638         Pico_mcd->scd.Status_CDC |= 1;                  // Read data with CDC\r
639 \r
640         CDD_Complete = 1;\r
641         return 0;\r
642 }\r
643 \r
644 \r
645 int Fast_Foward_CDD_c8(void)\r
646 {\r
647         CHECK_TRAY_OPEN\r
648         CHECK_CD_PRESENT\r
649 \r
650         Pico_mcd->scd.Status_CDC &= ~1;                         // Stop CDC read\r
651 \r
652         Pico_mcd->scd.Status_CDD = FAST_FOW;\r
653         Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD | 2;\r
654 \r
655         Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
656         Pico_mcd->cdd.Seconde = 0;\r
657         Pico_mcd->cdd.Frame = 0;\r
658         Pico_mcd->cdd.Ext = 0;\r
659 \r
660         CDD_Complete = 1;\r
661 \r
662         return 0;\r
663 }\r
664 \r
665 \r
666 int Fast_Rewind_CDD_c9(void)\r
667 {\r
668         CHECK_TRAY_OPEN\r
669         CHECK_CD_PRESENT\r
670 \r
671         Pico_mcd->scd.Status_CDC &= ~1;                         // Stop CDC read\r
672 \r
673         Pico_mcd->scd.Status_CDD = FAST_REV;\r
674         Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD | 2;\r
675 \r
676         Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
677         Pico_mcd->cdd.Seconde = 0;\r
678         Pico_mcd->cdd.Frame = 0;\r
679         Pico_mcd->cdd.Ext = 0;\r
680 \r
681         CDD_Complete = 1;\r
682 \r
683         return 0;\r
684 }\r
685 \r
686 \r
687 int Close_Tray_CDD_cC(void)\r
688 {\r
689         //Clear_Sound_Buffer();\r
690 \r
691         Pico_mcd->scd.Status_CDC &= ~1;                 // Stop CDC read\r
692 \r
693         {\r
694 #if 0 // TODO\r
695                 char new_iso[1024];\r
696 \r
697                 memset(new_iso, 0, 1024);\r
698 \r
699                 while (!Change_File_L(new_iso, Rom_Dir, "Load SegaCD image file", "SegaCD image file\0*.bin;*.iso;*.raw\0All files\0*.*\0\0", ""));\r
700                 Reload_SegaCD(new_iso);\r
701 \r
702                 CD_Present = 1;\r
703 #else\r
704                 CD_Present = 0;\r
705 #endif\r
706                 Pico_mcd->scd.Status_CDD = STOPPED;\r
707                 Pico_mcd->cdd.Status = 0x0000;\r
708 \r
709                 Pico_mcd->cdd.Minute = 0;\r
710                 Pico_mcd->cdd.Seconde = 0;\r
711                 Pico_mcd->cdd.Frame = 0;\r
712                 Pico_mcd->cdd.Ext = 0;\r
713         }\r
714 \r
715         CDD_Complete = 1;\r
716 \r
717         return 0;\r
718 }\r
719 \r
720 \r
721 int Open_Tray_CDD_cD(void)\r
722 {\r
723         CHECK_TRAY_OPEN\r
724 \r
725         Pico_mcd->scd.Status_CDC &= ~1;                 // Stop CDC read\r
726 \r
727         Unload_ISO();\r
728         CD_Present = 0;\r
729 \r
730         Pico_mcd->scd.Status_CDD = TRAY_OPEN;\r
731         Pico_mcd->cdd.Status = 0x0E00;\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         CDD_Complete = 1;\r
739 \r
740         return 0;\r
741 }\r
742 \r
743 \r
744 int CDD_cA(void)\r
745 {\r
746         CHECK_TRAY_OPEN\r
747         CHECK_CD_PRESENT\r
748 \r
749         Pico_mcd->scd.Status_CDC &= ~1;\r
750 \r
751         Pico_mcd->scd.Status_CDD = READY;\r
752         Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;\r
753 \r
754         Pico_mcd->cdd.Minute = 0;\r
755         Pico_mcd->cdd.Seconde = INT_TO_BCDW(1);\r
756         Pico_mcd->cdd.Frame = INT_TO_BCDW(1);\r
757         Pico_mcd->cdd.Ext = 0;\r
758 \r
759         CDD_Complete = 1;\r
760 \r
761         return 0;\r
762 }\r
763 \r
764 \r
765 int CDD_Def(void)\r
766 {\r
767         Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;\r
768 \r
769         Pico_mcd->cdd.Minute = 0;\r
770         Pico_mcd->cdd.Seconde = 0;\r
771         Pico_mcd->cdd.Frame = 0;\r
772         Pico_mcd->cdd.Ext = 0;\r
773 \r
774         return 0;\r
775 }\r
776 \r
777 \r
778 \r
779 \r
780 /***************************\r
781  *   Others CD functions   *\r
782  **************************/\r
783 \r
784 \r
785 // do we need them?\r
786 #if 0\r
787 void Write_CD_Audio(short *Buf, int rate, int channel, int lenght)\r
788 {\r
789         unsigned int lenght_src, lenght_dst;\r
790         unsigned int pos_src, pas_src;\r
791 \r
792         if (rate == 0) return;\r
793         if (Sound_Rate == 0) return;\r
794 \r
795         if (CD_Audio_Starting)\r
796         {\r
797                 CD_Audio_Starting = 0;\r
798                 memset(CD_Audio_Buffer_L, 0, 4096 * 4);\r
799                 memset(CD_Audio_Buffer_R, 0, 4096 * 4);\r
800                 CD_Audio_Buffer_Write_Pos = (CD_Audio_Buffer_Read_Pos + 2000) & 0xFFF;\r
801         }\r
802 \r
803         lenght_src = rate / 75;                         // 75th of a second\r
804         lenght_dst = Sound_Rate / 75;           // 75th of a second\r
805 \r
806         pas_src = (lenght_src << 16) / lenght_dst;\r
807         pos_src = 0;\r
808 \r
809 #ifdef DEBUG_CD\r
810         fprintf(debug_SCD_file, "\n*********  Write Pos = %d    ", CD_Audio_Buffer_Write_Pos);\r
811 #endif\r
812 \r
813         if (channel == 2)\r
814         {\r
815                 __asm\r
816                 {\r
817                         mov edi, CD_Audio_Buffer_Write_Pos\r
818                         mov ebx, Buf\r
819                         xor esi, esi\r
820                         mov ecx, lenght_dst\r
821                         xor eax, eax\r
822                         mov edx, pas_src\r
823                         dec ecx\r
824                         jmp short loop_stereo\r
825 \r
826 align 16\r
827 \r
828 loop_stereo:\r
829                         movsx eax, word ptr [ebx + esi * 4]\r
830                         mov CD_Audio_Buffer_L[edi * 4], eax\r
831                         movsx eax, word ptr [ebx + esi * 4 + 2]\r
832                         mov CD_Audio_Buffer_R[edi * 4], eax\r
833                         mov esi, dword ptr pos_src\r
834                         inc edi\r
835                         add esi, edx\r
836                         and edi, 0xFFF\r
837                         mov dword ptr pos_src, esi\r
838                         shr esi, 16\r
839                         dec ecx\r
840                         jns short loop_stereo\r
841 \r
842                         mov CD_Audio_Buffer_Write_Pos, edi\r
843                 }\r
844         }\r
845         else\r
846         {\r
847                 __asm\r
848                 {\r
849                         mov edi, CD_Audio_Buffer_Write_Pos\r
850                         mov ebx, Buf\r
851                         xor esi, esi\r
852                         mov ecx, lenght_dst\r
853                         xor eax, eax\r
854                         mov edx, pas_src\r
855                         dec ecx\r
856                         jmp short loop_mono\r
857 \r
858 align 16\r
859 \r
860 loop_mono:\r
861                         movsx eax, word ptr [ebx + esi * 2]\r
862                         mov CD_Audio_Buffer_L[edi * 4], eax\r
863                         mov CD_Audio_Buffer_R[edi * 4], eax\r
864                         mov esi, dword ptr pos_src\r
865                         inc edi\r
866                         add esi, edx\r
867                         and edi, 0xFFF\r
868                         mov dword ptr pos_src, esi\r
869                         shr esi, 16\r
870                         dec ecx\r
871                         jns short loop_mono\r
872 \r
873                         mov CD_Audio_Buffer_Write_Pos, edi\r
874                 }\r
875         }\r
876 \r
877 #ifdef DEBUG_CD\r
878         fprintf(debug_SCD_file, "Write Pos 2 = %d\n\n", CD_Audio_Buffer_Write_Pos);\r
879 #endif\r
880 }\r
881 \r
882 \r
883 void Update_CD_Audio(int **buf, int lenght)\r
884 {\r
885         int *Buf_L, *Buf_R;\r
886         int diff;\r
887 \r
888         Buf_L = buf[0];\r
889         Buf_R = buf[1];\r
890 \r
891         if (Pico_mcd->s68k_regs[0x36] & 0x01) return;\r
892         if (!(Pico_mcd->scd.Status_CDC & 1))  return;\r
893         if (CD_Audio_Starting) return;\r
894 \r
895 #ifdef DEBUG_CD\r
896         fprintf(debug_SCD_file, "\n*********  Read Pos Normal = %d     ", CD_Audio_Buffer_Read_Pos);\r
897 #endif\r
898 \r
899         if (CD_Audio_Buffer_Write_Pos < CD_Audio_Buffer_Read_Pos)\r
900         {\r
901                 diff = CD_Audio_Buffer_Write_Pos + (4096) - CD_Audio_Buffer_Read_Pos;\r
902         }\r
903         else\r
904         {\r
905                 diff = CD_Audio_Buffer_Write_Pos - CD_Audio_Buffer_Read_Pos;\r
906         }\r
907 \r
908         if (diff < 500) CD_Audio_Buffer_Read_Pos -= 2000;\r
909         else if (diff > 3500) CD_Audio_Buffer_Read_Pos += 2000;\r
910 \r
911 #ifdef DEBUG_CD\r
912         else fprintf(debug_SCD_file, " pas de modifs   ");\r
913 #endif\r
914 \r
915         CD_Audio_Buffer_Read_Pos &= 0xFFF;\r
916 \r
917 #ifdef DEBUG_CD\r
918         fprintf(debug_SCD_file, "Read Pos = %d   ", CD_Audio_Buffer_Read_Pos);\r
919 #endif\r
920 \r
921         if (CDDA_Enable)\r
922         {\r
923                 __asm\r
924                 {\r
925                         mov ecx, lenght\r
926                         mov esi, CD_Audio_Buffer_Read_Pos\r
927                         mov edi, Buf_L\r
928                         dec ecx\r
929 \r
930 loop_L:\r
931                         mov eax, CD_Audio_Buffer_L[esi * 4]\r
932                         add [edi], eax\r
933                         inc esi\r
934                         add edi, 4\r
935                         and esi, 0xFFF\r
936                         dec ecx\r
937                         jns short loop_L\r
938 \r
939                         mov ecx, lenght\r
940                         mov esi, CD_Audio_Buffer_Read_Pos\r
941                         mov edi, Buf_R\r
942                         dec ecx\r
943 \r
944 loop_R:\r
945                         mov eax, CD_Audio_Buffer_R[esi * 4]\r
946                         add [edi], eax\r
947                         inc esi\r
948                         add edi, 4\r
949                         and esi, 0xFFF\r
950                         dec ecx\r
951                         jns short loop_R\r
952 \r
953                         mov CD_Audio_Buffer_Read_Pos, esi\r
954                 }\r
955         }\r
956         else\r
957         {\r
958                 CD_Audio_Buffer_Read_Pos += lenght;\r
959                 CD_Audio_Buffer_Read_Pos &= 0xFFF;\r
960         }\r
961 \r
962 #ifdef DEBUG_CD\r
963         fprintf(debug_SCD_file, "Read Pos 2 = %d\n\n", CD_Audio_Buffer_Read_Pos);\r
964 #endif\r
965 }\r
966 #endif\r
967 \r