ISO loading, menus, LEDs
[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
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
cc68a136 18\r
19/*\r
20int CDDA_Enable;\r
21\r
22int CD_Audio_Buffer_L[8192];\r
23int CD_Audio_Buffer_R[8192];\r
24int CD_Audio_Buffer_Read_Pos = 0;\r
25int CD_Audio_Buffer_Write_Pos = 2000;\r
26int CD_Audio_Starting;\r
27*/\r
28\r
29static int CD_Present = 0;\r
30int CD_Timer_Counter = 0; // TODO: check refs\r
31\r
32static int CDD_Complete;\r
33\r
34static int File_Add_Delay = 0;\r
35\r
cc68a136 36\r
37\r
38#define CHECK_TRAY_OPEN \\r
39if (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
55if (!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
72static 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
85static 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
91void 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
101static 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
125static 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
134static 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
145int 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
154void 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
cc68a136 180 FILE_Read_One_LBA_CDC();\r
cc68a136 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
200int Init_CD_Driver(void)\r
201{\r
cc68a136 202 FILE_Init();\r
cc68a136 203\r
204 return 0;\r
205}\r
206\r
207\r
208void End_CD_Driver(void)\r
209{\r
cc68a136 210 FILE_End();\r
cc68a136 211}\r
212\r
213\r
214void 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
bf098bc5 223int Insert_CD(char *iso_name, int is_bin)\r
cc68a136 224{\r
bf098bc5 225 int ret = 0;\r
226\r
cc68a136 227// memset(CD_Audio_Buffer_L, 0, 4096 * 4);\r
228// memset(CD_Audio_Buffer_R, 0, 4096 * 4);\r
229\r
bf098bc5 230 CD_Present = 0;\r
231\r
232 if (iso_name != NULL)\r
cc68a136 233 {\r
bf098bc5 234 ret = Load_ISO(iso_name, is_bin);\r
235 if (ret == 0)\r
236 CD_Present = 1;\r
cc68a136 237 }\r
238\r
bf098bc5 239 return ret;\r
cc68a136 240}\r
241\r
242\r
243void Stop_CD(void)\r
244{\r
cc68a136 245 Unload_ISO();\r
cc68a136 246 CD_Present = 0;\r
247}\r
248\r
249\r
250void 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
257int 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
275int 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
298int 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
330int 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
364int 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
393int 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
bf098bc5 415//Pico_mcd->cdd.Seconde = 2;\r
cc68a136 416\r
417 CDD_Complete = 1;\r
418\r
419 return 0;\r
420}\r
421\r
422\r
423int 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
bf098bc5 441//Pico_mcd->cdd.Minute = Pico_mcd->cdd.Seconde = 1;\r
cc68a136 442\r
443 CDD_Complete = 1;\r
444\r
445 return 0;\r
446}\r
447\r
448\r
449int 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
483int 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
cc68a136 525 FILE_Play_CD_LBA();\r
cc68a136 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
541int 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
579int 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
602int 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
cc68a136 628 FILE_Play_CD_LBA();\r
cc68a136 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
bf098bc5 644int Fast_Foward_CDD_c8(void)\r
cc68a136 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
bf098bc5 665int Fast_Rewind_CDD_c9(void)\r
cc68a136 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
686int 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
720int 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
cc68a136 726 Unload_ISO();\r
cc68a136 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
743int 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
764int 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
786void 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
825align 16\r
826\r
827loop_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
857align 16\r
858\r
859loop_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
882void 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
929loop_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
943loop_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