1.10 release
[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
31int CD_Timer_Counter = 0; // TODO: check refs\r
32\r
33static int CDD_Complete;\r
34\r
35static int File_Add_Delay = 0;\r
36\r
cc68a136 37\r
38\r
39#define CHECK_TRAY_OPEN \\r
40if (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
56if (!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
73static 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
86static 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
92void 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
102static 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
126static 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
135static 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
146int 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
155void Check_CD_Command(void)\r
156{\r
c459aefd 157 cdprintf("CHECK CD COMMAND");\r
cc68a136 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
c459aefd 172 cdprintf("Got a read command");\r
cc68a136 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
cc68a136 181 FILE_Read_One_LBA_CDC();\r
cc68a136 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
201int Init_CD_Driver(void)\r
202{\r
cc68a136 203 FILE_Init();\r
cc68a136 204\r
205 return 0;\r
206}\r
207\r
208\r
209void End_CD_Driver(void)\r
210{\r
cc68a136 211 FILE_End();\r
cc68a136 212}\r
213\r
214\r
215void 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
bf098bc5 224int Insert_CD(char *iso_name, int is_bin)\r
cc68a136 225{\r
bf098bc5 226 int ret = 0;\r
227\r
cc68a136 228// memset(CD_Audio_Buffer_L, 0, 4096 * 4);\r
229// memset(CD_Audio_Buffer_R, 0, 4096 * 4);\r
230\r
bf098bc5 231 CD_Present = 0;\r
232\r
233 if (iso_name != NULL)\r
cc68a136 234 {\r
bf098bc5 235 ret = Load_ISO(iso_name, is_bin);\r
236 if (ret == 0)\r
237 CD_Present = 1;\r
cc68a136 238 }\r
239\r
bf098bc5 240 return ret;\r
cc68a136 241}\r
242\r
243\r
244void Stop_CD(void)\r
245{\r
cc68a136 246 Unload_ISO();\r
cc68a136 247 CD_Present = 0;\r
248}\r
249\r
250\r
251void 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
258int Get_Status_CDD_c0(void)\r
259{\r
c459aefd 260 cdprintf("Status command : Cur LBA = %d", Pico_mcd->scd.Cur_LBA);\r
cc68a136 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
276int 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
299int Get_Pos_CDD_c20(void)\r
300{\r
301 _msf MSF;\r
302\r
c459aefd 303 cdprintf("command 200 : Cur LBA = %d", Pico_mcd->scd.Cur_LBA);\r
cc68a136 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
c459aefd 316 cdprintf("Status CDD = %.4X Status = %.4X", Pico_mcd->scd.Status_CDD, Pico_mcd->cdd.Status);\r
cc68a136 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
331int 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
c459aefd 352 cdprintf(" elapsed = %d", elapsed_time);\r
cc68a136 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
365int Get_Current_Track_CDD_c22(void)\r
366{\r
c459aefd 367 cdprintf("Status CDD = %.4X Status = %.4X", Pico_mcd->scd.Status_CDD, Pico_mcd->cdd.Status);\r
cc68a136 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
394int 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
bf098bc5 416//Pico_mcd->cdd.Seconde = 2;\r
cc68a136 417\r
418 CDD_Complete = 1;\r
419\r
420 return 0;\r
421}\r
422\r
423\r
424int 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
bf098bc5 442//Pico_mcd->cdd.Minute = Pico_mcd->cdd.Seconde = 1;\r
cc68a136 443\r
444 CDD_Complete = 1;\r
445\r
446 return 0;\r
447}\r
448\r
449\r
450int 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
484int 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
c459aefd 508 cdprintf("Read : Cur LBA = %d, M=%d, S=%d, F=%d", Pico_mcd->scd.Cur_LBA, MSF.M, MSF.S, MSF.F);\r
cc68a136 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
cc68a136 526 FILE_Play_CD_LBA();\r
cc68a136 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
542int 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
580int 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
603int 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
c459aefd 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
cc68a136 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
cc68a136 629 FILE_Play_CD_LBA();\r
cc68a136 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
bf098bc5 645int Fast_Foward_CDD_c8(void)\r
cc68a136 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
bf098bc5 666int Fast_Rewind_CDD_c9(void)\r
cc68a136 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
687int 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
721int 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
cc68a136 727 Unload_ISO();\r
cc68a136 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
744int 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
765int 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
787void 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
826align 16\r
827\r
828loop_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
858align 16\r
859\r
860loop_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
883void 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
930loop_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
944loop_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