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