cd: fix cycle overflow issue
[picodrive.git] / pico / cd / cd_sys.c
CommitLineData
6cadc2da 1/***********************************************************\r
2 * *\r
8b99ab90 3 * This source file was taken from the Gens project *\r
6cadc2da 4 * Written by Stéphane Dallongeville *\r
5 * Copyright (c) 2002 by Stéphane Dallongeville *\r
6 * Modified/adapted for PicoDrive by notaz, 2007 *\r
7 * *\r
8 ***********************************************************/\r
9\r
cc68a136 10#include <stdio.h>\r
cc68a136 11\r
efcba75f 12#include "../pico_int.h"\r
eff55556 13#include "cd_sys.h"\r
14#include "cd_file.h"\r
cc68a136 15\r
c459aefd 16#define DEBUG_CD\r
cc68a136 17\r
18#define TRAY_OPEN 0x0500 // TRAY OPEN CDD status\r
19#define NOCD 0x0000 // CD removed CDD status\r
20#define STOPPED 0x0900 // STOPPED CDD status (happen after stop or close tray command)\r
21#define READY 0x0400 // READY CDD status (also used for seeking)\r
22#define FAST_FOW 0x0300 // FAST FORWARD track CDD status\r
23#define FAST_REV 0x10300 // FAST REVERSE track CDD status\r
24#define PLAYING 0x0100 // PLAYING audio track CDD status\r
25\r
cc68a136 26\r
cc68a136 27static int CD_Present = 0;\r
cc68a136 28\r
29\r
30#define CHECK_TRAY_OPEN \\r
31if (Pico_mcd->scd.Status_CDD == TRAY_OPEN) \\r
32{ \\r
33 Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD; \\r
34 \\r
35 Pico_mcd->cdd.Minute = 0; \\r
36 Pico_mcd->cdd.Seconde = 0; \\r
37 Pico_mcd->cdd.Frame = 0; \\r
38 Pico_mcd->cdd.Ext = 0; \\r
39 \\r
51a902ae 40 Pico_mcd->scd.CDD_Complete = 1; \\r
cc68a136 41 \\r
42 return 2; \\r
43}\r
44\r
45\r
46#define CHECK_CD_PRESENT \\r
47if (!CD_Present) \\r
48{ \\r
49 Pico_mcd->scd.Status_CDD = NOCD; \\r
50 Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD; \\r
51 \\r
52 Pico_mcd->cdd.Minute = 0; \\r
53 Pico_mcd->cdd.Seconde = 0; \\r
54 Pico_mcd->cdd.Frame = 0; \\r
55 Pico_mcd->cdd.Ext = 0; \\r
56 \\r
51a902ae 57 Pico_mcd->scd.CDD_Complete = 1; \\r
cc68a136 58 \\r
59 return 3; \\r
60}\r
61\r
62\r
cc68a136 63static int MSF_to_LBA(_msf *MSF)\r
64{\r
65 return (MSF->M * 60 * 75) + (MSF->S * 75) + MSF->F - 150;\r
66}\r
67\r
68\r
eff55556 69PICO_INTERNAL void LBA_to_MSF(int lba, _msf *MSF)\r
cc68a136 70{\r
71 if (lba < -150) lba = 0;\r
72 else lba += 150;\r
73 MSF->M = lba / (60 * 75);\r
74 MSF->S = (lba / 75) % 60;\r
75 MSF->F = lba % 75;\r
76}\r
77\r
78\r
79static unsigned int MSF_to_Track(_msf *MSF)\r
80{\r
81 int i, Start, Cur;\r
82\r
83 Start = (MSF->M << 16) + (MSF->S << 8) + MSF->F;\r
84\r
75736070 85 for(i = 1; i <= (Pico_mcd->TOC.Last_Track + 1); i++)\r
cc68a136 86 {\r
75736070 87 Cur = Pico_mcd->TOC.Tracks[i - 1].MSF.M << 16;\r
88 Cur += Pico_mcd->TOC.Tracks[i - 1].MSF.S << 8;\r
89 Cur += Pico_mcd->TOC.Tracks[i - 1].MSF.F;\r
cc68a136 90\r
91 if (Cur > Start) break;\r
92 }\r
93\r
94 --i;\r
95\r
75736070 96 if (i > Pico_mcd->TOC.Last_Track) return 100;\r
97 else if (i < 1) i = 1;\r
cc68a136 98\r
99 return (unsigned) i;\r
100}\r
101\r
102\r
103static unsigned int LBA_to_Track(int lba)\r
104{\r
105 _msf MSF;\r
106\r
107 LBA_to_MSF(lba, &MSF);\r
108 return MSF_to_Track(&MSF);\r
109}\r
110\r
111\r
112static void Track_to_MSF(int track, _msf *MSF)\r
113{\r
75736070 114 if (track < 1) track = 1;\r
115 else if (track > Pico_mcd->TOC.Last_Track) track = Pico_mcd->TOC.Last_Track;\r
cc68a136 116\r
75736070 117 MSF->M = Pico_mcd->TOC.Tracks[track - 1].MSF.M;\r
118 MSF->S = Pico_mcd->TOC.Tracks[track - 1].MSF.S;\r
119 MSF->F = Pico_mcd->TOC.Tracks[track - 1].MSF.F;\r
cc68a136 120}\r
121\r
122\r
eff55556 123PICO_INTERNAL int Track_to_LBA(int track)\r
cc68a136 124{\r
125 _msf MSF;\r
126\r
127 Track_to_MSF(track, &MSF);\r
128 return MSF_to_LBA(&MSF);\r
129}\r
130\r
131\r
eff55556 132PICO_INTERNAL void Check_CD_Command(void)\r
cc68a136 133{\r
c459aefd 134 cdprintf("CHECK CD COMMAND");\r
cc68a136 135\r
cc68a136 136 // Check CDC\r
cc68a136 137 if (Pico_mcd->scd.Status_CDC & 1) // CDC is reading data ...\r
138 {\r
c459aefd 139 cdprintf("Got a read command");\r
cc68a136 140\r
141 // DATA ?\r
75736070 142 if (Pico_mcd->scd.Cur_Track == 1)\r
cc68a136 143 Pico_mcd->s68k_regs[0x36] |= 0x01;\r
144 else Pico_mcd->s68k_regs[0x36] &= ~0x01; // AUDIO\r
145\r
51a902ae 146 if (Pico_mcd->scd.File_Add_Delay == 0)\r
cc68a136 147 {\r
cc68a136 148 FILE_Read_One_LBA_CDC();\r
cc68a136 149 }\r
51a902ae 150 else Pico_mcd->scd.File_Add_Delay--;\r
cc68a136 151 }\r
152\r
1cd356a3 153 // Check CDD\r
154 if (Pico_mcd->scd.CDD_Complete)\r
155 {\r
156 Pico_mcd->scd.CDD_Complete = 0;\r
157\r
158 CDD_Export_Status();\r
159 }\r
160\r
cc68a136 161 if (Pico_mcd->scd.Status_CDD == FAST_FOW)\r
162 {\r
163 Pico_mcd->scd.Cur_LBA += 10;\r
164 CDC_Update_Header();\r
165\r
166 }\r
167 else if (Pico_mcd->scd.Status_CDD == FAST_REV)\r
168 {\r
169 Pico_mcd->scd.Cur_LBA -= 10;\r
170 if (Pico_mcd->scd.Cur_LBA < -150) Pico_mcd->scd.Cur_LBA = -150;\r
171 CDC_Update_Header();\r
172 }\r
173}\r
174\r
175\r
eff55556 176PICO_INTERNAL int Init_CD_Driver(void)\r
cc68a136 177{\r
cc68a136 178 return 0;\r
179}\r
180\r
181\r
eff55556 182PICO_INTERNAL void End_CD_Driver(void)\r
cc68a136 183{\r
eff55556 184 Unload_ISO();\r
cc68a136 185}\r
186\r
187\r
eff55556 188PICO_INTERNAL void Reset_CD(void)\r
cc68a136 189{\r
190 Pico_mcd->scd.Cur_Track = 0;\r
191 Pico_mcd->scd.Cur_LBA = -150;\r
5c69a605 192 Pico_mcd->scd.Status_CDC &= ~1;\r
d0132772 193 if (Pico_mcd->scd.Status_CDD != TRAY_OPEN)\r
194 Pico_mcd->scd.Status_CDD = CD_Present ? READY : NOCD;\r
51a902ae 195 Pico_mcd->scd.CDD_Complete = 0;\r
5c69a605 196 Pico_mcd->scd.File_Add_Delay = 0;\r
cc68a136 197}\r
198\r
199\r
35e3031a 200int Insert_CD(const char *cdimg_name, int type)\r
cc68a136 201{\r
b923ecbe 202 int ret = 1;\r
bf098bc5 203\r
bf098bc5 204 CD_Present = 0;\r
205\r
b923ecbe 206 if (cdimg_name != NULL && type != CIT_NOT_CD)\r
cc68a136 207 {\r
b923ecbe 208 ret = Load_CD_Image(cdimg_name, type);\r
721cd396 209 if (ret == 0) {\r
bf098bc5 210 CD_Present = 1;\r
d0132772 211\r
212 if (Pico_mcd->scd.Status_CDD == TRAY_OPEN)\r
213 {\r
214 if (Pico_mcd->bios[0x122 ^ 1] == '2')\r
215 Close_Tray_CDD_cC();\r
216 // else bios will issue it\r
217 }\r
218 else\r
219 {\r
d687ef50 220 Pico_mcd->scd.Status_CDD = READY;\r
d0132772 221 }\r
721cd396 222 }\r
cc68a136 223 }\r
224\r
d0132772 225 if (Pico_mcd->scd.Status_CDD != TRAY_OPEN && !CD_Present)\r
226 Pico_mcd->scd.Status_CDD = NOCD;\r
227\r
bf098bc5 228 return ret;\r
cc68a136 229}\r
230\r
231\r
d0132772 232int Stop_CD(void)\r
cc68a136 233{\r
d0132772 234 int ret = CD_Present;\r
235\r
cc68a136 236 Unload_ISO();\r
cc68a136 237 CD_Present = 0;\r
d0132772 238\r
239 return ret;\r
cc68a136 240}\r
241\r
242\r
eff55556 243/*\r
244PICO_INTERNAL void Change_CD(void)\r
cc68a136 245{\r
246 if (Pico_mcd->scd.Status_CDD == TRAY_OPEN) Close_Tray_CDD_cC();\r
247 else Open_Tray_CDD_cD();\r
248}\r
eff55556 249*/\r
cc68a136 250\r
eff55556 251PICO_INTERNAL int Get_Status_CDD_c0(void)\r
cc68a136 252{\r
c459aefd 253 cdprintf("Status command : Cur LBA = %d", Pico_mcd->scd.Cur_LBA);\r
cc68a136 254\r
255 // Clear immediat status\r
256 if ((Pico_mcd->cdd.Status & 0x0F00) == 0x0200)\r
257 Pico_mcd->cdd.Status = (Pico_mcd->scd.Status_CDD & 0xFF00) | (Pico_mcd->cdd.Status & 0x00FF);\r
258 else if ((Pico_mcd->cdd.Status & 0x0F00) == 0x0700)\r
259 Pico_mcd->cdd.Status = (Pico_mcd->scd.Status_CDD & 0xFF00) | (Pico_mcd->cdd.Status & 0x00FF);\r
260 else if ((Pico_mcd->cdd.Status & 0x0F00) == 0x0E00)\r
261 Pico_mcd->cdd.Status = (Pico_mcd->scd.Status_CDD & 0xFF00) | (Pico_mcd->cdd.Status & 0x00FF);\r
262\r
51a902ae 263 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 264\r
265 return 0;\r
266}\r
267\r
268\r
eff55556 269PICO_INTERNAL int Stop_CDD_c1(void)\r
cc68a136 270{\r
271 CHECK_TRAY_OPEN\r
272\r
273 Pico_mcd->scd.Status_CDC &= ~1; // Stop CDC read\r
274\r
275 if (CD_Present) Pico_mcd->scd.Status_CDD = STOPPED;\r
276 else Pico_mcd->scd.Status_CDD = NOCD;\r
277 Pico_mcd->cdd.Status = 0x0000;\r
278\r
279 Pico_mcd->s68k_regs[0x36] |= 0x01; // Data bit set because stopped\r
280\r
281 Pico_mcd->cdd.Minute = 0;\r
282 Pico_mcd->cdd.Seconde = 0;\r
283 Pico_mcd->cdd.Frame = 0;\r
284 Pico_mcd->cdd.Ext = 0;\r
285\r
51a902ae 286 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 287\r
288 return 0;\r
289}\r
290\r
291\r
eff55556 292PICO_INTERNAL int Get_Pos_CDD_c20(void)\r
cc68a136 293{\r
294 _msf MSF;\r
295\r
c459aefd 296 cdprintf("command 200 : Cur LBA = %d", Pico_mcd->scd.Cur_LBA);\r
cc68a136 297\r
298 CHECK_TRAY_OPEN\r
299\r
300 Pico_mcd->cdd.Status &= 0xFF;\r
301 if (!CD_Present)\r
302 {\r
303 Pico_mcd->scd.Status_CDD = NOCD;\r
304 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
305 }\r
306// else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
307 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
308\r
c459aefd 309 cdprintf("Status CDD = %.4X Status = %.4X", Pico_mcd->scd.Status_CDD, Pico_mcd->cdd.Status);\r
cc68a136 310\r
311 LBA_to_MSF(Pico_mcd->scd.Cur_LBA, &MSF);\r
312\r
313 Pico_mcd->cdd.Minute = INT_TO_BCDW(MSF.M);\r
314 Pico_mcd->cdd.Seconde = INT_TO_BCDW(MSF.S);\r
315 Pico_mcd->cdd.Frame = INT_TO_BCDW(MSF.F);\r
316 Pico_mcd->cdd.Ext = 0;\r
317\r
51a902ae 318 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 319\r
320 return 0;\r
321}\r
322\r
323\r
eff55556 324PICO_INTERNAL int Get_Track_Pos_CDD_c21(void)\r
cc68a136 325{\r
326 int elapsed_time;\r
327 _msf MSF;\r
328\r
329 cdprintf("command 201 : Cur LBA = %d", Pico_mcd->scd.Cur_LBA);\r
330\r
331 CHECK_TRAY_OPEN\r
332\r
333 Pico_mcd->cdd.Status &= 0xFF;\r
334 if (!CD_Present)\r
335 {\r
336 Pico_mcd->scd.Status_CDD = NOCD;\r
337 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
338 }\r
339// else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
340 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
341\r
342 elapsed_time = Pico_mcd->scd.Cur_LBA - Track_to_LBA(LBA_to_Track(Pico_mcd->scd.Cur_LBA));\r
343 LBA_to_MSF(elapsed_time - 150, &MSF);\r
344\r
c459aefd 345 cdprintf(" elapsed = %d", elapsed_time);\r
cc68a136 346\r
347 Pico_mcd->cdd.Minute = INT_TO_BCDW(MSF.M);\r
348 Pico_mcd->cdd.Seconde = INT_TO_BCDW(MSF.S);\r
349 Pico_mcd->cdd.Frame = INT_TO_BCDW(MSF.F);\r
350 Pico_mcd->cdd.Ext = 0;\r
351\r
51a902ae 352 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 353\r
354 return 0;\r
355}\r
356\r
357\r
eff55556 358PICO_INTERNAL int Get_Current_Track_CDD_c22(void)\r
cc68a136 359{\r
c459aefd 360 cdprintf("Status CDD = %.4X Status = %.4X", Pico_mcd->scd.Status_CDD, Pico_mcd->cdd.Status);\r
cc68a136 361\r
362 CHECK_TRAY_OPEN\r
363\r
364 Pico_mcd->cdd.Status &= 0xFF;\r
365 if (!CD_Present)\r
366 {\r
367 Pico_mcd->scd.Status_CDD = NOCD;\r
368 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
369 }\r
370// else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
371 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
372\r
373 Pico_mcd->scd.Cur_Track = LBA_to_Track(Pico_mcd->scd.Cur_LBA);\r
374\r
375 if (Pico_mcd->scd.Cur_Track == 100) Pico_mcd->cdd.Minute = 0x0A02;\r
376 else Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
377 Pico_mcd->cdd.Seconde = 0;\r
378 Pico_mcd->cdd.Frame = 0;\r
379 Pico_mcd->cdd.Ext = 0;\r
380\r
51a902ae 381 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 382\r
383 return 0;\r
384}\r
385\r
386\r
eff55556 387PICO_INTERNAL int Get_Total_Lenght_CDD_c23(void)\r
cc68a136 388{\r
389 CHECK_TRAY_OPEN\r
390\r
391 Pico_mcd->cdd.Status &= 0xFF;\r
392 if (!CD_Present)\r
393 {\r
394 Pico_mcd->scd.Status_CDD = NOCD;\r
395 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
396 }\r
397// else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
398 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
399\r
75736070 400 Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->TOC.Tracks[Pico_mcd->TOC.Last_Track].MSF.M);\r
401 Pico_mcd->cdd.Seconde = INT_TO_BCDW(Pico_mcd->TOC.Tracks[Pico_mcd->TOC.Last_Track].MSF.S);\r
402 Pico_mcd->cdd.Frame = INT_TO_BCDW(Pico_mcd->TOC.Tracks[Pico_mcd->TOC.Last_Track].MSF.F);\r
cc68a136 403 Pico_mcd->cdd.Ext = 0;\r
404\r
51a902ae 405 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 406\r
407 return 0;\r
408}\r
409\r
410\r
eff55556 411PICO_INTERNAL int Get_First_Last_Track_CDD_c24(void)\r
cc68a136 412{\r
413 CHECK_TRAY_OPEN\r
414\r
415 Pico_mcd->cdd.Status &= 0xFF;\r
416 if (!CD_Present)\r
417 {\r
418 Pico_mcd->scd.Status_CDD = NOCD;\r
419 }\r
420// else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
421 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
422\r
75736070 423 Pico_mcd->cdd.Minute = INT_TO_BCDW(1);\r
424 Pico_mcd->cdd.Seconde = INT_TO_BCDW(Pico_mcd->TOC.Last_Track);\r
cc68a136 425 Pico_mcd->cdd.Frame = 0;\r
426 Pico_mcd->cdd.Ext = 0;\r
427\r
51a902ae 428 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 429\r
430 return 0;\r
431}\r
432\r
433\r
eff55556 434PICO_INTERNAL int Get_Track_Adr_CDD_c25(void)\r
cc68a136 435{\r
436 int track_number;\r
437\r
438 CHECK_TRAY_OPEN\r
439\r
440 // track number in TC4 & TC5\r
441\r
442 track_number = (Pico_mcd->s68k_regs[0x38+10+4] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+5] & 0xF);\r
443\r
444 Pico_mcd->cdd.Status &= 0xFF;\r
445 if (!CD_Present)\r
446 {\r
447 Pico_mcd->scd.Status_CDD = NOCD;\r
448 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
449 }\r
450// else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
451 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
452\r
75736070 453 if (track_number > Pico_mcd->TOC.Last_Track) track_number = Pico_mcd->TOC.Last_Track;\r
454 else if (track_number < 1) track_number = 1;\r
cc68a136 455\r
75736070 456 Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->TOC.Tracks[track_number - 1].MSF.M);\r
457 Pico_mcd->cdd.Seconde = INT_TO_BCDW(Pico_mcd->TOC.Tracks[track_number - 1].MSF.S);\r
458 Pico_mcd->cdd.Frame = INT_TO_BCDW(Pico_mcd->TOC.Tracks[track_number - 1].MSF.F);\r
cc68a136 459 Pico_mcd->cdd.Ext = track_number % 10;\r
460\r
75736070 461 if (track_number == 1) Pico_mcd->cdd.Frame |= 0x0800; // data track\r
cc68a136 462\r
51a902ae 463 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 464 return 0;\r
465}\r
466\r
467\r
eff55556 468PICO_INTERNAL int Play_CDD_c3(void)\r
cc68a136 469{\r
470 _msf MSF;\r
471 int delay, new_lba;\r
472\r
473 CHECK_TRAY_OPEN\r
474 CHECK_CD_PRESENT\r
475\r
476 // MSF of the track to play in TC buffer\r
477\r
478 MSF.M = (Pico_mcd->s68k_regs[0x38+10+2] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+3] & 0xF);\r
479 MSF.S = (Pico_mcd->s68k_regs[0x38+10+4] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+5] & 0xF);\r
480 MSF.F = (Pico_mcd->s68k_regs[0x38+10+6] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+7] & 0xF);\r
481\r
482 Pico_mcd->scd.Cur_Track = MSF_to_Track(&MSF);\r
483\r
484 new_lba = MSF_to_LBA(&MSF);\r
485 delay = new_lba - Pico_mcd->scd.Cur_LBA;\r
486 if (delay < 0) delay = -delay;\r
487 delay >>= 12;\r
488\r
d0132772 489 if (Pico_mcd->scd.Cur_LBA > 0 && delay < 13)\r
490 // based on genplus GX\r
59991f11 491 delay = 13;\r
492\r
cc68a136 493 Pico_mcd->scd.Cur_LBA = new_lba;\r
494 CDC_Update_Header();\r
495\r
c459aefd 496 cdprintf("Read : Cur LBA = %d, M=%d, S=%d, F=%d", Pico_mcd->scd.Cur_LBA, MSF.M, MSF.S, MSF.F);\r
cc68a136 497\r
498 if (Pico_mcd->scd.Status_CDD != PLAYING) delay += 20;\r
499\r
500 Pico_mcd->scd.Status_CDD = PLAYING;\r
501 Pico_mcd->cdd.Status = 0x0102;\r
502// Pico_mcd->cdd.Status = COMM_OK;\r
503\r
51a902ae 504 if (Pico_mcd->scd.File_Add_Delay == 0) Pico_mcd->scd.File_Add_Delay = delay;\r
cc68a136 505\r
75736070 506 if (Pico_mcd->scd.Cur_Track == 1)\r
cc68a136 507 {\r
508 Pico_mcd->s68k_regs[0x36] |= 0x01; // DATA\r
509 }\r
510 else\r
511 {\r
512 Pico_mcd->s68k_regs[0x36] &= ~0x01; // AUDIO\r
c9e1affc 513 cdda_start_play();\r
cc68a136 514 }\r
515\r
516 if (Pico_mcd->scd.Cur_Track == 100) Pico_mcd->cdd.Minute = 0x0A02;\r
517 else Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
518 Pico_mcd->cdd.Seconde = 0;\r
519 Pico_mcd->cdd.Frame = 0;\r
520 Pico_mcd->cdd.Ext = 0;\r
521\r
522 Pico_mcd->scd.Status_CDC |= 1; // Read data with CDC\r
523\r
51a902ae 524 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 525 return 0;\r
526}\r
527\r
528\r
eff55556 529PICO_INTERNAL int Seek_CDD_c4(void)\r
cc68a136 530{\r
531 _msf MSF;\r
532\r
533 CHECK_TRAY_OPEN\r
534 CHECK_CD_PRESENT\r
535\r
536 // MSF to seek in TC buffer\r
537\r
538 MSF.M = (Pico_mcd->s68k_regs[0x38+10+2] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+3] & 0xF);\r
539 MSF.S = (Pico_mcd->s68k_regs[0x38+10+4] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+5] & 0xF);\r
540 MSF.F = (Pico_mcd->s68k_regs[0x38+10+6] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+7] & 0xF);\r
541\r
542 Pico_mcd->scd.Cur_Track = MSF_to_Track(&MSF);\r
543 Pico_mcd->scd.Cur_LBA = MSF_to_LBA(&MSF);\r
544 CDC_Update_Header();\r
545\r
546 Pico_mcd->scd.Status_CDC &= ~1; // Stop CDC read\r
547\r
548 Pico_mcd->scd.Status_CDD = READY;\r
549 Pico_mcd->cdd.Status = 0x0200;\r
550\r
551 // DATA ?\r
75736070 552 if (Pico_mcd->scd.Cur_Track == 1)\r
cc68a136 553 Pico_mcd->s68k_regs[0x36] |= 0x01;\r
554 else Pico_mcd->s68k_regs[0x36] &= ~0x01; // AUDIO\r
555\r
556 Pico_mcd->cdd.Minute = 0;\r
557 Pico_mcd->cdd.Seconde = 0;\r
558 Pico_mcd->cdd.Frame = 0;\r
559 Pico_mcd->cdd.Ext = 0;\r
560\r
51a902ae 561 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 562\r
563 return 0;\r
564}\r
565\r
566\r
eff55556 567PICO_INTERNAL int Pause_CDD_c6(void)\r
cc68a136 568{\r
569 CHECK_TRAY_OPEN\r
570 CHECK_CD_PRESENT\r
571\r
572 Pico_mcd->scd.Status_CDC &= ~1; // Stop CDC read to start a new one if raw data\r
573\r
574 Pico_mcd->scd.Status_CDD = READY;\r
575 Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;\r
576\r
577 Pico_mcd->s68k_regs[0x36] |= 0x01; // Data bit set because stopped\r
578\r
579 Pico_mcd->cdd.Minute = 0;\r
580 Pico_mcd->cdd.Seconde = 0;\r
581 Pico_mcd->cdd.Frame = 0;\r
582 Pico_mcd->cdd.Ext = 0;\r
583\r
51a902ae 584 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 585\r
586 return 0;\r
587}\r
588\r
589\r
eff55556 590PICO_INTERNAL int Resume_CDD_c7(void)\r
cc68a136 591{\r
592 CHECK_TRAY_OPEN\r
593 CHECK_CD_PRESENT\r
594\r
595 Pico_mcd->scd.Cur_Track = LBA_to_Track(Pico_mcd->scd.Cur_LBA);\r
596\r
597#ifdef DEBUG_CD\r
598 {\r
599 _msf MSF;\r
600 LBA_to_MSF(Pico_mcd->scd.Cur_LBA, &MSF);\r
c459aefd 601 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 602 }\r
603#endif\r
604\r
605 Pico_mcd->scd.Status_CDD = PLAYING;\r
606 Pico_mcd->cdd.Status = 0x0102;\r
607\r
75736070 608 if (Pico_mcd->scd.Cur_Track == 1)\r
cc68a136 609 {\r
610 Pico_mcd->s68k_regs[0x36] |= 0x01; // DATA\r
611 }\r
612 else\r
613 {\r
614 Pico_mcd->s68k_regs[0x36] &= ~0x01; // AUDIO\r
c9e1affc 615 cdda_start_play();\r
cc68a136 616 }\r
617\r
618 if (Pico_mcd->scd.Cur_Track == 100) Pico_mcd->cdd.Minute = 0x0A02;\r
619 else Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
620 Pico_mcd->cdd.Seconde = 0;\r
621 Pico_mcd->cdd.Frame = 0;\r
622 Pico_mcd->cdd.Ext = 0;\r
623\r
624 Pico_mcd->scd.Status_CDC |= 1; // Read data with CDC\r
625\r
51a902ae 626 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 627 return 0;\r
628}\r
629\r
630\r
eff55556 631PICO_INTERNAL int Fast_Foward_CDD_c8(void)\r
cc68a136 632{\r
633 CHECK_TRAY_OPEN\r
634 CHECK_CD_PRESENT\r
635\r
636 Pico_mcd->scd.Status_CDC &= ~1; // Stop CDC read\r
637\r
638 Pico_mcd->scd.Status_CDD = FAST_FOW;\r
639 Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD | 2;\r
640\r
641 Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
642 Pico_mcd->cdd.Seconde = 0;\r
643 Pico_mcd->cdd.Frame = 0;\r
644 Pico_mcd->cdd.Ext = 0;\r
645\r
51a902ae 646 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 647\r
648 return 0;\r
649}\r
650\r
651\r
eff55556 652PICO_INTERNAL int Fast_Rewind_CDD_c9(void)\r
cc68a136 653{\r
654 CHECK_TRAY_OPEN\r
655 CHECK_CD_PRESENT\r
656\r
657 Pico_mcd->scd.Status_CDC &= ~1; // Stop CDC read\r
658\r
659 Pico_mcd->scd.Status_CDD = FAST_REV;\r
660 Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD | 2;\r
661\r
662 Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
663 Pico_mcd->cdd.Seconde = 0;\r
664 Pico_mcd->cdd.Frame = 0;\r
665 Pico_mcd->cdd.Ext = 0;\r
666\r
51a902ae 667 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 668\r
669 return 0;\r
670}\r
671\r
672\r
eff55556 673PICO_INTERNAL int Close_Tray_CDD_cC(void)\r
cc68a136 674{\r
cc68a136 675 Pico_mcd->scd.Status_CDC &= ~1; // Stop CDC read\r
676\r
c6196c0f 677 elprintf(EL_STATUS, "tray close\n");\r
cc68a136 678\r
721cd396 679 if (PicoMCDcloseTray != NULL)\r
d687ef50 680 PicoMCDcloseTray();\r
cc68a136 681\r
721cd396 682 Pico_mcd->scd.Status_CDD = CD_Present ? STOPPED : NOCD;\r
683 Pico_mcd->cdd.Status = 0x0000;\r
cc68a136 684\r
721cd396 685 Pico_mcd->cdd.Minute = 0;\r
686 Pico_mcd->cdd.Seconde = 0;\r
687 Pico_mcd->cdd.Frame = 0;\r
688 Pico_mcd->cdd.Ext = 0;\r
cc68a136 689\r
51a902ae 690 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 691\r
692 return 0;\r
693}\r
694\r
695\r
eff55556 696PICO_INTERNAL int Open_Tray_CDD_cD(void)\r
cc68a136 697{\r
698 CHECK_TRAY_OPEN\r
699\r
700 Pico_mcd->scd.Status_CDC &= ~1; // Stop CDC read\r
701\r
c6196c0f 702 elprintf(EL_STATUS, "tray open\n");\r
721cd396 703\r
cc68a136 704 Unload_ISO();\r
cc68a136 705 CD_Present = 0;\r
706\r
721cd396 707 if (PicoMCDopenTray != NULL)\r
708 PicoMCDopenTray();\r
709\r
cc68a136 710 Pico_mcd->scd.Status_CDD = TRAY_OPEN;\r
711 Pico_mcd->cdd.Status = 0x0E00;\r
712\r
713 Pico_mcd->cdd.Minute = 0;\r
714 Pico_mcd->cdd.Seconde = 0;\r
715 Pico_mcd->cdd.Frame = 0;\r
716 Pico_mcd->cdd.Ext = 0;\r
717\r
51a902ae 718 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 719\r
720 return 0;\r
721}\r
722\r
723\r
eff55556 724PICO_INTERNAL int CDD_cA(void)\r
cc68a136 725{\r
726 CHECK_TRAY_OPEN\r
727 CHECK_CD_PRESENT\r
728\r
729 Pico_mcd->scd.Status_CDC &= ~1;\r
730\r
731 Pico_mcd->scd.Status_CDD = READY;\r
732 Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;\r
733\r
734 Pico_mcd->cdd.Minute = 0;\r
735 Pico_mcd->cdd.Seconde = INT_TO_BCDW(1);\r
736 Pico_mcd->cdd.Frame = INT_TO_BCDW(1);\r
737 Pico_mcd->cdd.Ext = 0;\r
738\r
51a902ae 739 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 740\r
741 return 0;\r
742}\r
743\r
744\r
eff55556 745PICO_INTERNAL int CDD_Def(void)\r
cc68a136 746{\r
747 Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;\r
748\r
749 Pico_mcd->cdd.Minute = 0;\r
750 Pico_mcd->cdd.Seconde = 0;\r
751 Pico_mcd->cdd.Frame = 0;\r
752 Pico_mcd->cdd.Ext = 0;\r
753\r
754 return 0;\r
755}\r
756\r
757\r