cd: switch to CD controller code from genplus
[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
3f23709e 26//#undef cdprintf\r
27//#define cdprintf(x, ...) elprintf(EL_STATUS, x, ##__VA_ARGS__)\r
28\r
29#define CDC_Update_Header()\r
cc68a136 30\r
cc68a136 31static int CD_Present = 0;\r
cc68a136 32\r
33\r
34#define CHECK_TRAY_OPEN \\r
35if (Pico_mcd->scd.Status_CDD == TRAY_OPEN) \\r
36{ \\r
37 Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD; \\r
38 \\r
39 Pico_mcd->cdd.Minute = 0; \\r
40 Pico_mcd->cdd.Seconde = 0; \\r
41 Pico_mcd->cdd.Frame = 0; \\r
42 Pico_mcd->cdd.Ext = 0; \\r
43 \\r
51a902ae 44 Pico_mcd->scd.CDD_Complete = 1; \\r
cc68a136 45 \\r
46 return 2; \\r
47}\r
48\r
49\r
50#define CHECK_CD_PRESENT \\r
51if (!CD_Present) \\r
52{ \\r
53 Pico_mcd->scd.Status_CDD = NOCD; \\r
54 Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD; \\r
55 \\r
56 Pico_mcd->cdd.Minute = 0; \\r
57 Pico_mcd->cdd.Seconde = 0; \\r
58 Pico_mcd->cdd.Frame = 0; \\r
59 Pico_mcd->cdd.Ext = 0; \\r
60 \\r
51a902ae 61 Pico_mcd->scd.CDD_Complete = 1; \\r
cc68a136 62 \\r
63 return 3; \\r
64}\r
65\r
66\r
cc68a136 67static int MSF_to_LBA(_msf *MSF)\r
68{\r
69 return (MSF->M * 60 * 75) + (MSF->S * 75) + MSF->F - 150;\r
70}\r
71\r
72\r
eff55556 73PICO_INTERNAL void LBA_to_MSF(int lba, _msf *MSF)\r
cc68a136 74{\r
75 if (lba < -150) lba = 0;\r
76 else lba += 150;\r
77 MSF->M = lba / (60 * 75);\r
78 MSF->S = (lba / 75) % 60;\r
79 MSF->F = lba % 75;\r
80}\r
81\r
82\r
83static unsigned int MSF_to_Track(_msf *MSF)\r
84{\r
85 int i, Start, Cur;\r
86\r
87 Start = (MSF->M << 16) + (MSF->S << 8) + MSF->F;\r
88\r
75736070 89 for(i = 1; i <= (Pico_mcd->TOC.Last_Track + 1); i++)\r
cc68a136 90 {\r
75736070 91 Cur = Pico_mcd->TOC.Tracks[i - 1].MSF.M << 16;\r
92 Cur += Pico_mcd->TOC.Tracks[i - 1].MSF.S << 8;\r
93 Cur += Pico_mcd->TOC.Tracks[i - 1].MSF.F;\r
cc68a136 94\r
95 if (Cur > Start) break;\r
96 }\r
97\r
98 --i;\r
99\r
75736070 100 if (i > Pico_mcd->TOC.Last_Track) return 100;\r
101 else if (i < 1) i = 1;\r
cc68a136 102\r
103 return (unsigned) i;\r
104}\r
105\r
106\r
107static unsigned int LBA_to_Track(int lba)\r
108{\r
109 _msf MSF;\r
110\r
111 LBA_to_MSF(lba, &MSF);\r
112 return MSF_to_Track(&MSF);\r
113}\r
114\r
115\r
116static void Track_to_MSF(int track, _msf *MSF)\r
117{\r
75736070 118 if (track < 1) track = 1;\r
119 else if (track > Pico_mcd->TOC.Last_Track) track = Pico_mcd->TOC.Last_Track;\r
cc68a136 120\r
75736070 121 MSF->M = Pico_mcd->TOC.Tracks[track - 1].MSF.M;\r
122 MSF->S = Pico_mcd->TOC.Tracks[track - 1].MSF.S;\r
123 MSF->F = Pico_mcd->TOC.Tracks[track - 1].MSF.F;\r
cc68a136 124}\r
125\r
126\r
eff55556 127PICO_INTERNAL int Track_to_LBA(int track)\r
cc68a136 128{\r
129 _msf MSF;\r
130\r
131 Track_to_MSF(track, &MSF);\r
132 return MSF_to_LBA(&MSF);\r
133}\r
134\r
135\r
eff55556 136PICO_INTERNAL void Check_CD_Command(void)\r
cc68a136 137{\r
c459aefd 138 cdprintf("CHECK CD COMMAND");\r
cc68a136 139\r
cc68a136 140 // Check CDC\r
cc68a136 141 if (Pico_mcd->scd.Status_CDC & 1) // CDC is reading data ...\r
142 {\r
c459aefd 143 cdprintf("Got a read command");\r
cc68a136 144\r
145 // DATA ?\r
3f23709e 146 if (Pico_mcd->scd.Cur_Track == 1) {\r
cc68a136 147 Pico_mcd->s68k_regs[0x36] |= 0x01;\r
cc68a136 148\r
3f23709e 149 if (Pico_mcd->scd.File_Add_Delay == 0)\r
150 {\r
151 unsigned char header[4];\r
152 _msf MSF;\r
153\r
154 LBA_to_MSF(Pico_mcd->scd.Cur_LBA, &MSF);\r
155\r
156 header[0] = INT_TO_BCDB(MSF.M);\r
157 header[1] = INT_TO_BCDB(MSF.S);\r
158 header[2] = INT_TO_BCDB(MSF.F);\r
159 header[3] = 0x01;\r
160\r
161 //FILE_Read_One_LBA_CDC();\r
162 Pico_mcd->scd.Cur_LBA +=\r
163 cdc_decoder_update(header);\r
164 }\r
165 else Pico_mcd->scd.File_Add_Delay--;\r
166 }\r
167 else {\r
168 Pico_mcd->s68k_regs[0x36] &= ~0x01; // AUDIO\r
169 unsigned char header[4] = { 0, };\r
170 cdc_decoder_update(header);\r
cc68a136 171 }\r
cc68a136 172 }\r
173\r
1cd356a3 174 // Check CDD\r
175 if (Pico_mcd->scd.CDD_Complete)\r
176 {\r
177 Pico_mcd->scd.CDD_Complete = 0;\r
178\r
179 CDD_Export_Status();\r
180 }\r
181\r
cc68a136 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
eff55556 197PICO_INTERNAL int Init_CD_Driver(void)\r
cc68a136 198{\r
cc68a136 199 return 0;\r
200}\r
201\r
202\r
eff55556 203PICO_INTERNAL void End_CD_Driver(void)\r
cc68a136 204{\r
eff55556 205 Unload_ISO();\r
cc68a136 206}\r
207\r
208\r
eff55556 209PICO_INTERNAL void Reset_CD(void)\r
cc68a136 210{\r
211 Pico_mcd->scd.Cur_Track = 0;\r
212 Pico_mcd->scd.Cur_LBA = -150;\r
5c69a605 213 Pico_mcd->scd.Status_CDC &= ~1;\r
d0132772 214 if (Pico_mcd->scd.Status_CDD != TRAY_OPEN)\r
215 Pico_mcd->scd.Status_CDD = CD_Present ? READY : NOCD;\r
51a902ae 216 Pico_mcd->scd.CDD_Complete = 0;\r
5c69a605 217 Pico_mcd->scd.File_Add_Delay = 0;\r
cc68a136 218}\r
219\r
220\r
35e3031a 221int Insert_CD(const char *cdimg_name, int type)\r
cc68a136 222{\r
b923ecbe 223 int ret = 1;\r
bf098bc5 224\r
bf098bc5 225 CD_Present = 0;\r
226\r
b923ecbe 227 if (cdimg_name != NULL && type != CIT_NOT_CD)\r
cc68a136 228 {\r
b923ecbe 229 ret = Load_CD_Image(cdimg_name, type);\r
721cd396 230 if (ret == 0) {\r
bf098bc5 231 CD_Present = 1;\r
d0132772 232\r
233 if (Pico_mcd->scd.Status_CDD == TRAY_OPEN)\r
234 {\r
235 if (Pico_mcd->bios[0x122 ^ 1] == '2')\r
236 Close_Tray_CDD_cC();\r
237 // else bios will issue it\r
238 }\r
239 else\r
240 {\r
d687ef50 241 Pico_mcd->scd.Status_CDD = READY;\r
d0132772 242 }\r
721cd396 243 }\r
cc68a136 244 }\r
245\r
d0132772 246 if (Pico_mcd->scd.Status_CDD != TRAY_OPEN && !CD_Present)\r
247 Pico_mcd->scd.Status_CDD = NOCD;\r
248\r
bf098bc5 249 return ret;\r
cc68a136 250}\r
251\r
252\r
d0132772 253int Stop_CD(void)\r
cc68a136 254{\r
d0132772 255 int ret = CD_Present;\r
256\r
cc68a136 257 Unload_ISO();\r
cc68a136 258 CD_Present = 0;\r
d0132772 259\r
260 return ret;\r
cc68a136 261}\r
262\r
263\r
eff55556 264/*\r
265PICO_INTERNAL void Change_CD(void)\r
cc68a136 266{\r
267 if (Pico_mcd->scd.Status_CDD == TRAY_OPEN) Close_Tray_CDD_cC();\r
268 else Open_Tray_CDD_cD();\r
269}\r
eff55556 270*/\r
cc68a136 271\r
eff55556 272PICO_INTERNAL int Get_Status_CDD_c0(void)\r
cc68a136 273{\r
c459aefd 274 cdprintf("Status command : Cur LBA = %d", Pico_mcd->scd.Cur_LBA);\r
cc68a136 275\r
276 // Clear immediat status\r
277 if ((Pico_mcd->cdd.Status & 0x0F00) == 0x0200)\r
278 Pico_mcd->cdd.Status = (Pico_mcd->scd.Status_CDD & 0xFF00) | (Pico_mcd->cdd.Status & 0x00FF);\r
279 else if ((Pico_mcd->cdd.Status & 0x0F00) == 0x0700)\r
280 Pico_mcd->cdd.Status = (Pico_mcd->scd.Status_CDD & 0xFF00) | (Pico_mcd->cdd.Status & 0x00FF);\r
281 else if ((Pico_mcd->cdd.Status & 0x0F00) == 0x0E00)\r
282 Pico_mcd->cdd.Status = (Pico_mcd->scd.Status_CDD & 0xFF00) | (Pico_mcd->cdd.Status & 0x00FF);\r
283\r
51a902ae 284 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 285\r
286 return 0;\r
287}\r
288\r
289\r
eff55556 290PICO_INTERNAL int Stop_CDD_c1(void)\r
cc68a136 291{\r
292 CHECK_TRAY_OPEN\r
293\r
294 Pico_mcd->scd.Status_CDC &= ~1; // Stop CDC read\r
295\r
296 if (CD_Present) Pico_mcd->scd.Status_CDD = STOPPED;\r
297 else Pico_mcd->scd.Status_CDD = NOCD;\r
298 Pico_mcd->cdd.Status = 0x0000;\r
299\r
300 Pico_mcd->s68k_regs[0x36] |= 0x01; // Data bit set because stopped\r
301\r
302 Pico_mcd->cdd.Minute = 0;\r
303 Pico_mcd->cdd.Seconde = 0;\r
304 Pico_mcd->cdd.Frame = 0;\r
305 Pico_mcd->cdd.Ext = 0;\r
306\r
51a902ae 307 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 308\r
309 return 0;\r
310}\r
311\r
312\r
eff55556 313PICO_INTERNAL int Get_Pos_CDD_c20(void)\r
cc68a136 314{\r
315 _msf MSF;\r
316\r
c459aefd 317 cdprintf("command 200 : Cur LBA = %d", Pico_mcd->scd.Cur_LBA);\r
cc68a136 318\r
319 CHECK_TRAY_OPEN\r
320\r
321 Pico_mcd->cdd.Status &= 0xFF;\r
322 if (!CD_Present)\r
323 {\r
324 Pico_mcd->scd.Status_CDD = NOCD;\r
325 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
326 }\r
327// else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
328 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
329\r
c459aefd 330 cdprintf("Status CDD = %.4X Status = %.4X", Pico_mcd->scd.Status_CDD, Pico_mcd->cdd.Status);\r
cc68a136 331\r
332 LBA_to_MSF(Pico_mcd->scd.Cur_LBA, &MSF);\r
333\r
334 Pico_mcd->cdd.Minute = INT_TO_BCDW(MSF.M);\r
335 Pico_mcd->cdd.Seconde = INT_TO_BCDW(MSF.S);\r
336 Pico_mcd->cdd.Frame = INT_TO_BCDW(MSF.F);\r
337 Pico_mcd->cdd.Ext = 0;\r
338\r
51a902ae 339 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 340\r
341 return 0;\r
342}\r
343\r
344\r
eff55556 345PICO_INTERNAL int Get_Track_Pos_CDD_c21(void)\r
cc68a136 346{\r
347 int elapsed_time;\r
348 _msf MSF;\r
349\r
350 cdprintf("command 201 : Cur LBA = %d", Pico_mcd->scd.Cur_LBA);\r
351\r
352 CHECK_TRAY_OPEN\r
353\r
354 Pico_mcd->cdd.Status &= 0xFF;\r
355 if (!CD_Present)\r
356 {\r
357 Pico_mcd->scd.Status_CDD = NOCD;\r
358 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
359 }\r
360// else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
361 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
362\r
363 elapsed_time = Pico_mcd->scd.Cur_LBA - Track_to_LBA(LBA_to_Track(Pico_mcd->scd.Cur_LBA));\r
364 LBA_to_MSF(elapsed_time - 150, &MSF);\r
365\r
c459aefd 366 cdprintf(" elapsed = %d", elapsed_time);\r
cc68a136 367\r
368 Pico_mcd->cdd.Minute = INT_TO_BCDW(MSF.M);\r
369 Pico_mcd->cdd.Seconde = INT_TO_BCDW(MSF.S);\r
370 Pico_mcd->cdd.Frame = INT_TO_BCDW(MSF.F);\r
371 Pico_mcd->cdd.Ext = 0;\r
372\r
51a902ae 373 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 374\r
375 return 0;\r
376}\r
377\r
378\r
eff55556 379PICO_INTERNAL int Get_Current_Track_CDD_c22(void)\r
cc68a136 380{\r
c459aefd 381 cdprintf("Status CDD = %.4X Status = %.4X", Pico_mcd->scd.Status_CDD, Pico_mcd->cdd.Status);\r
cc68a136 382\r
383 CHECK_TRAY_OPEN\r
384\r
385 Pico_mcd->cdd.Status &= 0xFF;\r
386 if (!CD_Present)\r
387 {\r
388 Pico_mcd->scd.Status_CDD = NOCD;\r
389 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
390 }\r
391// else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
392 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
393\r
394 Pico_mcd->scd.Cur_Track = LBA_to_Track(Pico_mcd->scd.Cur_LBA);\r
395\r
396 if (Pico_mcd->scd.Cur_Track == 100) Pico_mcd->cdd.Minute = 0x0A02;\r
397 else Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
398 Pico_mcd->cdd.Seconde = 0;\r
399 Pico_mcd->cdd.Frame = 0;\r
400 Pico_mcd->cdd.Ext = 0;\r
401\r
51a902ae 402 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 403\r
404 return 0;\r
405}\r
406\r
407\r
eff55556 408PICO_INTERNAL int Get_Total_Lenght_CDD_c23(void)\r
cc68a136 409{\r
410 CHECK_TRAY_OPEN\r
411\r
412 Pico_mcd->cdd.Status &= 0xFF;\r
413 if (!CD_Present)\r
414 {\r
415 Pico_mcd->scd.Status_CDD = NOCD;\r
416 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
417 }\r
418// else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
419 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
420\r
75736070 421 Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->TOC.Tracks[Pico_mcd->TOC.Last_Track].MSF.M);\r
422 Pico_mcd->cdd.Seconde = INT_TO_BCDW(Pico_mcd->TOC.Tracks[Pico_mcd->TOC.Last_Track].MSF.S);\r
423 Pico_mcd->cdd.Frame = INT_TO_BCDW(Pico_mcd->TOC.Tracks[Pico_mcd->TOC.Last_Track].MSF.F);\r
cc68a136 424 Pico_mcd->cdd.Ext = 0;\r
425\r
51a902ae 426 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 427\r
428 return 0;\r
429}\r
430\r
431\r
eff55556 432PICO_INTERNAL int Get_First_Last_Track_CDD_c24(void)\r
cc68a136 433{\r
434 CHECK_TRAY_OPEN\r
435\r
436 Pico_mcd->cdd.Status &= 0xFF;\r
437 if (!CD_Present)\r
438 {\r
439 Pico_mcd->scd.Status_CDD = NOCD;\r
440 }\r
441// else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
442 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
443\r
75736070 444 Pico_mcd->cdd.Minute = INT_TO_BCDW(1);\r
445 Pico_mcd->cdd.Seconde = INT_TO_BCDW(Pico_mcd->TOC.Last_Track);\r
cc68a136 446 Pico_mcd->cdd.Frame = 0;\r
447 Pico_mcd->cdd.Ext = 0;\r
448\r
51a902ae 449 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 450\r
451 return 0;\r
452}\r
453\r
454\r
eff55556 455PICO_INTERNAL int Get_Track_Adr_CDD_c25(void)\r
cc68a136 456{\r
457 int track_number;\r
458\r
459 CHECK_TRAY_OPEN\r
460\r
461 // track number in TC4 & TC5\r
462\r
463 track_number = (Pico_mcd->s68k_regs[0x38+10+4] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+5] & 0xF);\r
464\r
465 Pico_mcd->cdd.Status &= 0xFF;\r
466 if (!CD_Present)\r
467 {\r
468 Pico_mcd->scd.Status_CDD = NOCD;\r
469 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
470 }\r
471// else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
472 Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;\r
473\r
75736070 474 if (track_number > Pico_mcd->TOC.Last_Track) track_number = Pico_mcd->TOC.Last_Track;\r
475 else if (track_number < 1) track_number = 1;\r
cc68a136 476\r
75736070 477 Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->TOC.Tracks[track_number - 1].MSF.M);\r
478 Pico_mcd->cdd.Seconde = INT_TO_BCDW(Pico_mcd->TOC.Tracks[track_number - 1].MSF.S);\r
479 Pico_mcd->cdd.Frame = INT_TO_BCDW(Pico_mcd->TOC.Tracks[track_number - 1].MSF.F);\r
cc68a136 480 Pico_mcd->cdd.Ext = track_number % 10;\r
481\r
75736070 482 if (track_number == 1) Pico_mcd->cdd.Frame |= 0x0800; // data track\r
cc68a136 483\r
51a902ae 484 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 485 return 0;\r
486}\r
487\r
488\r
eff55556 489PICO_INTERNAL int Play_CDD_c3(void)\r
cc68a136 490{\r
491 _msf MSF;\r
492 int delay, new_lba;\r
493\r
494 CHECK_TRAY_OPEN\r
495 CHECK_CD_PRESENT\r
496\r
497 // MSF of the track to play in TC buffer\r
498\r
499 MSF.M = (Pico_mcd->s68k_regs[0x38+10+2] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+3] & 0xF);\r
500 MSF.S = (Pico_mcd->s68k_regs[0x38+10+4] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+5] & 0xF);\r
501 MSF.F = (Pico_mcd->s68k_regs[0x38+10+6] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+7] & 0xF);\r
502\r
503 Pico_mcd->scd.Cur_Track = MSF_to_Track(&MSF);\r
504\r
505 new_lba = MSF_to_LBA(&MSF);\r
506 delay = new_lba - Pico_mcd->scd.Cur_LBA;\r
507 if (delay < 0) delay = -delay;\r
508 delay >>= 12;\r
509\r
d0132772 510 if (Pico_mcd->scd.Cur_LBA > 0 && delay < 13)\r
511 // based on genplus GX\r
59991f11 512 delay = 13;\r
513\r
cc68a136 514 Pico_mcd->scd.Cur_LBA = new_lba;\r
515 CDC_Update_Header();\r
516\r
c459aefd 517 cdprintf("Read : Cur LBA = %d, M=%d, S=%d, F=%d", Pico_mcd->scd.Cur_LBA, MSF.M, MSF.S, MSF.F);\r
cc68a136 518\r
519 if (Pico_mcd->scd.Status_CDD != PLAYING) delay += 20;\r
520\r
521 Pico_mcd->scd.Status_CDD = PLAYING;\r
522 Pico_mcd->cdd.Status = 0x0102;\r
523// Pico_mcd->cdd.Status = COMM_OK;\r
524\r
51a902ae 525 if (Pico_mcd->scd.File_Add_Delay == 0) Pico_mcd->scd.File_Add_Delay = delay;\r
cc68a136 526\r
75736070 527 if (Pico_mcd->scd.Cur_Track == 1)\r
cc68a136 528 {\r
529 Pico_mcd->s68k_regs[0x36] |= 0x01; // DATA\r
530 }\r
531 else\r
532 {\r
533 Pico_mcd->s68k_regs[0x36] &= ~0x01; // AUDIO\r
c9e1affc 534 cdda_start_play();\r
cc68a136 535 }\r
536\r
537 if (Pico_mcd->scd.Cur_Track == 100) Pico_mcd->cdd.Minute = 0x0A02;\r
538 else Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
539 Pico_mcd->cdd.Seconde = 0;\r
540 Pico_mcd->cdd.Frame = 0;\r
541 Pico_mcd->cdd.Ext = 0;\r
542\r
543 Pico_mcd->scd.Status_CDC |= 1; // Read data with CDC\r
544\r
51a902ae 545 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 546 return 0;\r
547}\r
548\r
549\r
eff55556 550PICO_INTERNAL int Seek_CDD_c4(void)\r
cc68a136 551{\r
552 _msf MSF;\r
553\r
554 CHECK_TRAY_OPEN\r
555 CHECK_CD_PRESENT\r
556\r
557 // MSF to seek in TC buffer\r
558\r
559 MSF.M = (Pico_mcd->s68k_regs[0x38+10+2] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+3] & 0xF);\r
560 MSF.S = (Pico_mcd->s68k_regs[0x38+10+4] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+5] & 0xF);\r
561 MSF.F = (Pico_mcd->s68k_regs[0x38+10+6] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+7] & 0xF);\r
562\r
563 Pico_mcd->scd.Cur_Track = MSF_to_Track(&MSF);\r
564 Pico_mcd->scd.Cur_LBA = MSF_to_LBA(&MSF);\r
565 CDC_Update_Header();\r
566\r
567 Pico_mcd->scd.Status_CDC &= ~1; // Stop CDC read\r
568\r
569 Pico_mcd->scd.Status_CDD = READY;\r
570 Pico_mcd->cdd.Status = 0x0200;\r
571\r
572 // DATA ?\r
75736070 573 if (Pico_mcd->scd.Cur_Track == 1)\r
cc68a136 574 Pico_mcd->s68k_regs[0x36] |= 0x01;\r
575 else Pico_mcd->s68k_regs[0x36] &= ~0x01; // AUDIO\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
eff55556 588PICO_INTERNAL int Pause_CDD_c6(void)\r
cc68a136 589{\r
590 CHECK_TRAY_OPEN\r
591 CHECK_CD_PRESENT\r
592\r
593 Pico_mcd->scd.Status_CDC &= ~1; // Stop CDC read to start a new one if raw data\r
594\r
595 Pico_mcd->scd.Status_CDD = READY;\r
596 Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;\r
597\r
598 Pico_mcd->s68k_regs[0x36] |= 0x01; // Data bit set because stopped\r
599\r
600 Pico_mcd->cdd.Minute = 0;\r
601 Pico_mcd->cdd.Seconde = 0;\r
602 Pico_mcd->cdd.Frame = 0;\r
603 Pico_mcd->cdd.Ext = 0;\r
604\r
51a902ae 605 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 606\r
607 return 0;\r
608}\r
609\r
610\r
eff55556 611PICO_INTERNAL int Resume_CDD_c7(void)\r
cc68a136 612{\r
613 CHECK_TRAY_OPEN\r
614 CHECK_CD_PRESENT\r
615\r
616 Pico_mcd->scd.Cur_Track = LBA_to_Track(Pico_mcd->scd.Cur_LBA);\r
617\r
618#ifdef DEBUG_CD\r
619 {\r
620 _msf MSF;\r
621 LBA_to_MSF(Pico_mcd->scd.Cur_LBA, &MSF);\r
c459aefd 622 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 623 }\r
624#endif\r
625\r
626 Pico_mcd->scd.Status_CDD = PLAYING;\r
627 Pico_mcd->cdd.Status = 0x0102;\r
628\r
75736070 629 if (Pico_mcd->scd.Cur_Track == 1)\r
cc68a136 630 {\r
631 Pico_mcd->s68k_regs[0x36] |= 0x01; // DATA\r
632 }\r
633 else\r
634 {\r
635 Pico_mcd->s68k_regs[0x36] &= ~0x01; // AUDIO\r
c9e1affc 636 cdda_start_play();\r
cc68a136 637 }\r
638\r
639 if (Pico_mcd->scd.Cur_Track == 100) Pico_mcd->cdd.Minute = 0x0A02;\r
640 else 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
645 Pico_mcd->scd.Status_CDC |= 1; // Read data with CDC\r
646\r
51a902ae 647 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 648 return 0;\r
649}\r
650\r
651\r
eff55556 652PICO_INTERNAL int Fast_Foward_CDD_c8(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_FOW;\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 Fast_Rewind_CDD_c9(void)\r
cc68a136 674{\r
675 CHECK_TRAY_OPEN\r
676 CHECK_CD_PRESENT\r
677\r
678 Pico_mcd->scd.Status_CDC &= ~1; // Stop CDC read\r
679\r
680 Pico_mcd->scd.Status_CDD = FAST_REV;\r
681 Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD | 2;\r
682\r
683 Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);\r
684 Pico_mcd->cdd.Seconde = 0;\r
685 Pico_mcd->cdd.Frame = 0;\r
686 Pico_mcd->cdd.Ext = 0;\r
687\r
51a902ae 688 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 689\r
690 return 0;\r
691}\r
692\r
693\r
eff55556 694PICO_INTERNAL int Close_Tray_CDD_cC(void)\r
cc68a136 695{\r
cc68a136 696 Pico_mcd->scd.Status_CDC &= ~1; // Stop CDC read\r
697\r
c6196c0f 698 elprintf(EL_STATUS, "tray close\n");\r
cc68a136 699\r
721cd396 700 if (PicoMCDcloseTray != NULL)\r
d687ef50 701 PicoMCDcloseTray();\r
cc68a136 702\r
721cd396 703 Pico_mcd->scd.Status_CDD = CD_Present ? STOPPED : NOCD;\r
704 Pico_mcd->cdd.Status = 0x0000;\r
cc68a136 705\r
721cd396 706 Pico_mcd->cdd.Minute = 0;\r
707 Pico_mcd->cdd.Seconde = 0;\r
708 Pico_mcd->cdd.Frame = 0;\r
709 Pico_mcd->cdd.Ext = 0;\r
cc68a136 710\r
51a902ae 711 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 712\r
713 return 0;\r
714}\r
715\r
716\r
eff55556 717PICO_INTERNAL int Open_Tray_CDD_cD(void)\r
cc68a136 718{\r
719 CHECK_TRAY_OPEN\r
720\r
721 Pico_mcd->scd.Status_CDC &= ~1; // Stop CDC read\r
722\r
c6196c0f 723 elprintf(EL_STATUS, "tray open\n");\r
721cd396 724\r
cc68a136 725 Unload_ISO();\r
cc68a136 726 CD_Present = 0;\r
727\r
721cd396 728 if (PicoMCDopenTray != NULL)\r
729 PicoMCDopenTray();\r
730\r
cc68a136 731 Pico_mcd->scd.Status_CDD = TRAY_OPEN;\r
732 Pico_mcd->cdd.Status = 0x0E00;\r
733\r
734 Pico_mcd->cdd.Minute = 0;\r
735 Pico_mcd->cdd.Seconde = 0;\r
736 Pico_mcd->cdd.Frame = 0;\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_cA(void)\r
cc68a136 746{\r
747 CHECK_TRAY_OPEN\r
748 CHECK_CD_PRESENT\r
749\r
750 Pico_mcd->scd.Status_CDC &= ~1;\r
751\r
752 Pico_mcd->scd.Status_CDD = READY;\r
753 Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;\r
754\r
755 Pico_mcd->cdd.Minute = 0;\r
756 Pico_mcd->cdd.Seconde = INT_TO_BCDW(1);\r
757 Pico_mcd->cdd.Frame = INT_TO_BCDW(1);\r
758 Pico_mcd->cdd.Ext = 0;\r
759\r
51a902ae 760 Pico_mcd->scd.CDD_Complete = 1;\r
cc68a136 761\r
762 return 0;\r
763}\r
764\r
765\r
eff55556 766PICO_INTERNAL int CDD_Def(void)\r
cc68a136 767{\r
768 Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;\r
769\r
770 Pico_mcd->cdd.Minute = 0;\r
771 Pico_mcd->cdd.Seconde = 0;\r
772 Pico_mcd->cdd.Frame = 0;\r
773 Pico_mcd->cdd.Ext = 0;\r
774\r
775 return 0;\r
776}\r
777\r
778\r
3f23709e 779static int bswapwrite(int a, unsigned short d)\r
780{\r
781 *(unsigned short *)(Pico_mcd->s68k_regs + a) = (d>>8)|(d<<8);\r
782 return d + (d >> 8);\r
783}\r
784\r
785PICO_INTERNAL void CDD_Export_Status(void)\r
786{\r
787 unsigned int csum;\r
788\r
789 csum = bswapwrite( 0x38+0, Pico_mcd->cdd.Status);\r
790 csum += bswapwrite( 0x38+2, Pico_mcd->cdd.Minute);\r
791 csum += bswapwrite( 0x38+4, Pico_mcd->cdd.Seconde);\r
792 csum += bswapwrite( 0x38+6, Pico_mcd->cdd.Frame);\r
793 Pico_mcd->s68k_regs[0x38+8] = Pico_mcd->cdd.Ext;\r
794 csum += Pico_mcd->cdd.Ext;\r
795 Pico_mcd->s68k_regs[0x38+9] = ~csum & 0xf;\r
796\r
797 Pico_mcd->s68k_regs[0x37] &= 3; // CDD.Control\r
798\r
799 if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN4)\r
800 {\r
801 elprintf(EL_INTS, "cdd export irq 4");\r
802 SekInterruptS68k(4);\r
803 }\r
804\r
805// cdprintf("CDD exported status\n");\r
806 cdprintf("out: Status=%.4X, Minute=%.4X, Second=%.4X, Frame=%.4X Checksum=%.4X",\r
807 (Pico_mcd->s68k_regs[0x38+0] << 8) | Pico_mcd->s68k_regs[0x38+1],\r
808 (Pico_mcd->s68k_regs[0x38+2] << 8) | Pico_mcd->s68k_regs[0x38+3],\r
809 (Pico_mcd->s68k_regs[0x38+4] << 8) | Pico_mcd->s68k_regs[0x38+5],\r
810 (Pico_mcd->s68k_regs[0x38+6] << 8) | Pico_mcd->s68k_regs[0x38+7],\r
811 (Pico_mcd->s68k_regs[0x38+8] << 8) | Pico_mcd->s68k_regs[0x38+9]);\r
812}\r
813\r
814\r
815PICO_INTERNAL void CDD_Import_Command(void)\r
816{\r
817// cdprintf("CDD importing command\n");\r
818 cdprintf("in: Command=%.4X, Minute=%.4X, Second=%.4X, Frame=%.4X Checksum=%.4X",\r
819 (Pico_mcd->s68k_regs[0x38+10+0] << 8) | Pico_mcd->s68k_regs[0x38+10+1],\r
820 (Pico_mcd->s68k_regs[0x38+10+2] << 8) | Pico_mcd->s68k_regs[0x38+10+3],\r
821 (Pico_mcd->s68k_regs[0x38+10+4] << 8) | Pico_mcd->s68k_regs[0x38+10+5],\r
822 (Pico_mcd->s68k_regs[0x38+10+6] << 8) | Pico_mcd->s68k_regs[0x38+10+7],\r
823 (Pico_mcd->s68k_regs[0x38+10+8] << 8) | Pico_mcd->s68k_regs[0x38+10+9]);\r
824\r
825 switch (Pico_mcd->s68k_regs[0x38+10+0])\r
826 {\r
827 case 0x0: // STATUS (?)\r
828 Get_Status_CDD_c0();\r
829 break;\r
830\r
831 case 0x1: // STOP ALL (?)\r
832 Stop_CDD_c1();\r
833 break;\r
834\r
835 case 0x2: // GET TOC INFORMATIONS\r
836 switch(Pico_mcd->s68k_regs[0x38+10+3])\r
837 {\r
838 case 0x0: // get current position (MSF format)\r
839 Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00);\r
840 Get_Pos_CDD_c20();\r
841 break;\r
842\r
843 case 0x1: // get elapsed time of current track played/scanned (relative MSF format)\r
844 Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 1;\r
845 Get_Track_Pos_CDD_c21();\r
846 break;\r
847\r
848 case 0x2: // get current track in RS2-RS3\r
849 Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 2;\r
850 Get_Current_Track_CDD_c22();\r
851 break;\r
852\r
853 case 0x3: // get total length (MSF format)\r
854 Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 3;\r
855 Get_Total_Lenght_CDD_c23();\r
856 break;\r
857\r
858 case 0x4: // first & last track number\r
859 Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 4;\r
860 Get_First_Last_Track_CDD_c24();\r
861 break;\r
862\r
863 case 0x5: // get track addresse (MSF format)\r
864 Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 5;\r
865 Get_Track_Adr_CDD_c25();\r
866 break;\r
867\r
868 default : // invalid, then we return status\r
869 Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 0xF;\r
870 Get_Status_CDD_c0();\r
871 break;\r
872 }\r
873 break;\r
874\r
875 case 0x3: // READ\r
876 Play_CDD_c3();\r
877 break;\r
878\r
879 case 0x4: // SEEK\r
880 Seek_CDD_c4();\r
881 break;\r
882\r
883 case 0x6: // PAUSE/STOP\r
884 Pause_CDD_c6();\r
885 break;\r
886\r
887 case 0x7: // RESUME\r
888 Resume_CDD_c7();\r
889 break;\r
890\r
891 case 0x8: // FAST FOWARD\r
892 Fast_Foward_CDD_c8();\r
893 break;\r
894\r
895 case 0x9: // FAST REWIND\r
896 Fast_Rewind_CDD_c9();\r
897 break;\r
898\r
899 case 0xA: // RECOVER INITIAL STATE (?)\r
900 CDD_cA();\r
901 break;\r
902\r
903 case 0xC: // CLOSE TRAY\r
904 Close_Tray_CDD_cC();\r
905 break;\r
906\r
907 case 0xD: // OPEN TRAY\r
908 Open_Tray_CDD_cD();\r
909 break;\r
910\r
911 default: // UNKNOWN\r
912 CDD_Def();\r
913 break;\r
914 }\r
915}\r
916\r
917void CDD_Reset(void)\r
918{\r
919 // Reseting CDD\r
920\r
921 memset(Pico_mcd->s68k_regs+0x34, 0, 2*2); // CDD.Fader, CDD.Control\r
922 Pico_mcd->cdd.Status = 0;\r
923 Pico_mcd->cdd.Minute = 0;\r
924 Pico_mcd->cdd.Seconde = 0;\r
925 Pico_mcd->cdd.Frame = 0;\r
926 Pico_mcd->cdd.Ext = 0;\r
927\r
928 // clear receive status and transfer command\r
929 memset(Pico_mcd->s68k_regs+0x38, 0, 20);\r
930 Pico_mcd->s68k_regs[0x38+9] = 0xF; // Default checksum\r
931}\r
932\r
933\r