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