Sonic CD shows Sega logo
[picodrive.git] / Pico / cd / LC89510.c
CommitLineData
bf098bc5 1/***********************************************************\r
2 * *\r
3 * This source is taken from the Gens project *\r
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
cc68a136 9\r
10#include "../PicoInt.h"\r
11\r
c459aefd 12#define cdprintf dprintf\r
cc68a136 13//#define cdprintf(x...)\r
14\r
15\r
16#define CDC_DMA_SPEED 256\r
17\r
c459aefd 18int CDC_Decode_Reg_Read; // 2 context?\r
cc68a136 19\r
20\r
21static void CDD_Reset(void)\r
22{\r
23 // Reseting CDD\r
24\r
25 memset(Pico_mcd->s68k_regs+0x34, 0, 2*2); // CDD.Fader, CDD.Control\r
26 Pico_mcd->cdd.Status = 0;\r
27 Pico_mcd->cdd.Minute = 0;\r
28 Pico_mcd->cdd.Seconde = 0;\r
29 Pico_mcd->cdd.Frame = 0;\r
30 Pico_mcd->cdd.Ext = 0;\r
31\r
32 // clear receive status and transfer command\r
33 memset(Pico_mcd->s68k_regs+0x38, 0, 20);\r
34 Pico_mcd->s68k_regs[0x38+9] = 0xF; // Default checksum\r
35}\r
36\r
37\r
38static void CDC_Reset(void)\r
39{\r
40 // Reseting CDC\r
41\r
42 memset(Pico_mcd->cdc.Buffer, 0, (16 * 1024 * 2) + 2352);\r
43\r
44 CDC_Update_Header();\r
45\r
46 Pico_mcd->cdc.COMIN = 0;\r
47 Pico_mcd->cdc.IFSTAT = 0xFF;\r
48 Pico_mcd->cdc.DAC.N = 0;\r
49 Pico_mcd->cdc.DBC.N = 0;\r
50 Pico_mcd->cdc.HEAD.N = 0x01000000;\r
51 Pico_mcd->cdc.PT.N = 0;\r
52 Pico_mcd->cdc.WA.N = 2352 * 2;\r
53 Pico_mcd->cdc.STAT.N = 0x00000080;\r
54 Pico_mcd->cdc.SBOUT = 0;\r
55 Pico_mcd->cdc.IFCTRL = 0;\r
56 Pico_mcd->cdc.CTRL.N = 0;\r
57\r
58 CDC_Decode_Reg_Read = 0;\r
c459aefd 59 Pico_mcd->scd.Status_CDC &= ~0x08;\r
cc68a136 60}\r
61\r
62\r
63void LC89510_Reset(void)\r
64{\r
65 CDD_Reset();\r
66 CDC_Reset();\r
67\r
cb4a513a 68 // clear DMA_Adr & Stop_Watch\r
69 memset(Pico_mcd->s68k_regs + 0xA, 0, 4);\r
cc68a136 70}\r
71\r
cc68a136 72\r
bf098bc5 73void Update_CDC_TRansfer(int which)\r
74{\r
cb4a513a 75 unsigned int DMA_Adr, dep, length, len;\r
bf098bc5 76 unsigned short *dest;\r
77 unsigned char *src;\r
cc68a136 78\r
79 if (Pico_mcd->cdc.DBC.N <= (CDC_DMA_SPEED * 2))\r
80 {\r
bf098bc5 81 length = (Pico_mcd->cdc.DBC.N + 1) >> 1;\r
c459aefd 82 Pico_mcd->scd.Status_CDC &= ~0x08; // Last transfer\r
bf098bc5 83 Pico_mcd->s68k_regs[4] |= 0x80; // End data transfer\r
84 Pico_mcd->s68k_regs[4] &= ~0x40; // no more data ready\r
85 Pico_mcd->cdc.IFSTAT |= 0x08; // No more data transfer in progress\r
cc68a136 86\r
bf098bc5 87 if (Pico_mcd->cdc.IFCTRL & 0x40) // DTEIEN = Data Trasnfer End Interrupt Enable ?\r
cc68a136 88 {\r
89 Pico_mcd->cdc.IFSTAT &= ~0x40;\r
90\r
bf098bc5 91 if (Pico_mcd->s68k_regs[0x33] & (1<<5))\r
92 {\r
93 dprintf("cdc DTE irq 5");\r
94 SekInterruptS68k(5);\r
95 }\r
cc68a136 96 }\r
97 }\r
bf098bc5 98 else length = CDC_DMA_SPEED;\r
99\r
cc68a136 100\r
bf098bc5 101 // TODO: dst bounds checking? DAC.N alignment?\r
102 src = Pico_mcd->cdc.Buffer + Pico_mcd->cdc.DAC.N;\r
cb4a513a 103 DMA_Adr = (Pico_mcd->s68k_regs[0xA]<<8) | Pico_mcd->s68k_regs[0xB];\r
cc68a136 104\r
bf098bc5 105 if (which == 7) // WORD RAM\r
cc68a136 106 {\r
bf098bc5 107 if (Pico_mcd->s68k_regs[3] & 4)\r
cc68a136 108 {\r
cb4a513a 109 dep = ((DMA_Adr & 0x3FFF) << 3);\r
bf098bc5 110 cdprintf("CD DMA # %04x -> word_ram1M # %06x, len=%i",\r
111 Pico_mcd->cdc.DAC.N, dep, length);\r
112\r
cb4a513a 113 dep = ((DMA_Adr & 0x3FFF) << 4);\r
bf098bc5 114 if (!(Pico_mcd->s68k_regs[3]&1)) dep += 2;\r
115 dest = (unsigned short *) (Pico_mcd->word_ram + dep);\r
116\r
117 for (len = length; len > 0; len--, src+=2, dest+=2)\r
118 *dest = (src[0]<<8) | src[1];\r
cc68a136 119 }\r
bf098bc5 120 else\r
121 {\r
cb4a513a 122 dep = ((DMA_Adr & 0x7FFF) << 3);\r
bf098bc5 123 cdprintf("CD DMA # %04x -> word_ram2M # %06x, len=%i",\r
124 Pico_mcd->cdc.DAC.N, dep, length);\r
125 dest = (unsigned short *) (Pico_mcd->word_ram + dep);\r
cc68a136 126\r
bf098bc5 127 for (len = length; len > 0; len--, src+=2, dest++)\r
128 *dest = (src[0]<<8) | src[1];\r
129 }\r
cc68a136 130 }\r
bf098bc5 131 else if (which == 4) // PCM RAM\r
cc68a136 132 {\r
bf098bc5 133#if 0\r
134 dest = (unsigned char *) Ram_PCM;\r
cb4a513a 135 dep = ((DMA_Adr & 0x03FF) << 2) + PCM_Chip.Bank;\r
bf098bc5 136#else\r
cb4a513a 137 cdprintf("CD DMA # %04x -> PCD TODO", Pico_mcd->cdc.DAC.N);\r
bf098bc5 138#endif\r
139 }\r
140 else if (which == 5) // PRG RAM\r
141 {\r
cb4a513a 142 dep = DMA_Adr << 3;\r
bf098bc5 143 dest = (unsigned short *) (Pico_mcd->prg_ram + dep);\r
144 cdprintf("CD DMA # %04x -> prg_ram # %06x, len=%i",\r
145 Pico_mcd->cdc.DAC.N, dep, length);\r
cc68a136 146\r
bf098bc5 147 for (len = length; len > 0; len--, src+=2, dest++)\r
148 *dest = (src[0]<<8) | src[1];\r
cc68a136 149 }\r
150\r
bf098bc5 151 length <<= 1;\r
152 Pico_mcd->cdc.DAC.N = (Pico_mcd->cdc.DAC.N + length) & 0xFFFF;\r
c459aefd 153 if (Pico_mcd->scd.Status_CDC & 0x08) Pico_mcd->cdc.DBC.N -= length;\r
cc68a136 154 else Pico_mcd->cdc.DBC.N = 0;\r
155}\r
cc68a136 156\r
157\r
158unsigned short Read_CDC_Host(int is_sub)\r
159{\r
160 int addr;\r
161\r
c459aefd 162 if (!(Pico_mcd->scd.Status_CDC & 0x08))\r
cc68a136 163 {\r
164 // Transfer data disabled\r
c459aefd 165 cdprintf("Read_CDC_Host: Transfer data disabled");\r
cc68a136 166 return 0;\r
167 }\r
168\r
169 if ((is_sub && (Pico_mcd->s68k_regs[4] & 7) != 3) ||\r
170 (!is_sub && (Pico_mcd->s68k_regs[4] & 7) != 2))\r
171 {\r
172 // Wrong setting\r
c459aefd 173 cdprintf("Read_CDC_Host: Wrong setting");\r
cc68a136 174 return 0;\r
175 }\r
176\r
177 Pico_mcd->cdc.DBC.N -= 2;\r
178\r
179 if (Pico_mcd->cdc.DBC.N <= 0)\r
180 {\r
181 Pico_mcd->cdc.DBC.N = 0;\r
c459aefd 182 Pico_mcd->scd.Status_CDC &= ~0x08; // Last transfer\r
cc68a136 183 Pico_mcd->s68k_regs[4] |= 0x80; // End data transfer\r
184 Pico_mcd->s68k_regs[4] &= ~0x40; // no more data ready\r
185 Pico_mcd->cdc.IFSTAT |= 0x08; // No more data transfer in progress\r
186\r
187 if (Pico_mcd->cdc.IFCTRL & 0x40) // DTEIEN = Data Transfer End Interrupt Enable ?\r
188 {\r
189 Pico_mcd->cdc.IFSTAT &= ~0x40;\r
190\r
191 if (Pico_mcd->s68k_regs[0x33]&(1<<5)) {\r
192 dprintf("m68k: s68k irq 5");\r
193 SekInterruptS68k(5);\r
194 }\r
195\r
c459aefd 196 cdprintf("CDC - DTE interrupt");\r
cc68a136 197 }\r
198 }\r
199\r
200 addr = Pico_mcd->cdc.DAC.N;\r
201 Pico_mcd->cdc.DAC.N += 2;\r
c459aefd 202\r
203 cdprintf("Read_CDC_Host sub=%i d=%04x dac=%04x dbc=%04x", is_sub,\r
204 (Pico_mcd->cdc.Buffer[addr]<<8) | Pico_mcd->cdc.Buffer[addr+1], Pico_mcd->cdc.DAC.N, Pico_mcd->cdc.DBC.N);\r
205\r
cc68a136 206 return (Pico_mcd->cdc.Buffer[addr]<<8) | Pico_mcd->cdc.Buffer[addr+1];\r
207\r
208#if 0\r
209 __asm\r
210 {\r
211 mov esi, Pico_mcd->cdc.DAC.N\r
212 lea ebx, Pico_mcd->cdc.Buffer\r
213// and esi, 0x3FFF\r
214 mov ax, [ebx + esi]\r
215 add esi, 2\r
216 rol ax, 8\r
217 mov Pico_mcd->cdc.DAC.N, esi\r
218 mov val, ax\r
219 }\r
220#endif\r
221}\r
222\r
223\r
224void CDC_Update_Header(void)\r
225{\r
226 if (Pico_mcd->cdc.CTRL.B.B1 & 0x01) // Sub-Header wanted ?\r
227 {\r
228 Pico_mcd->cdc.HEAD.B.B0 = 0;\r
229 Pico_mcd->cdc.HEAD.B.B1 = 0;\r
230 Pico_mcd->cdc.HEAD.B.B2 = 0;\r
231 Pico_mcd->cdc.HEAD.B.B3 = 0;\r
232 }\r
233 else\r
234 {\r
235 _msf MSF;\r
236\r
237 LBA_to_MSF(Pico_mcd->scd.Cur_LBA, &MSF);\r
238\r
239 Pico_mcd->cdc.HEAD.B.B0 = INT_TO_BCDB(MSF.M);\r
240 Pico_mcd->cdc.HEAD.B.B1 = INT_TO_BCDB(MSF.S);\r
241 Pico_mcd->cdc.HEAD.B.B2 = INT_TO_BCDB(MSF.F);\r
242 Pico_mcd->cdc.HEAD.B.B3 = 0x01;\r
243 }\r
244}\r
245\r
246\r
247unsigned char CDC_Read_Reg(void)\r
248{\r
249 unsigned char ret;\r
250\r
cc68a136 251 switch(Pico_mcd->s68k_regs[5] & 0xF)\r
252 {\r
253 case 0x0: // COMIN\r
c459aefd 254 cdprintf("CDC read reg 00 = %.2X", Pico_mcd->cdc.COMIN);\r
cc68a136 255\r
256 Pico_mcd->s68k_regs[5] = 0x1;\r
257 return Pico_mcd->cdc.COMIN;\r
258\r
259 case 0x1: // IFSTAT\r
c459aefd 260 cdprintf("CDC read reg 01 = %.2X", Pico_mcd->cdc.IFSTAT);\r
cc68a136 261\r
262 CDC_Decode_Reg_Read |= (1 << 1); // Reg 1 (decoding)\r
263 Pico_mcd->s68k_regs[5] = 0x2;\r
264 return Pico_mcd->cdc.IFSTAT;\r
265\r
266 case 0x2: // DBCL\r
c459aefd 267 cdprintf("CDC read reg 02 = %.2X", Pico_mcd->cdc.DBC.B.L);\r
cc68a136 268\r
269 Pico_mcd->s68k_regs[5] = 0x3;\r
270 return Pico_mcd->cdc.DBC.B.L;\r
271\r
272 case 0x3: // DBCH\r
c459aefd 273 cdprintf("CDC read reg 03 = %.2X", Pico_mcd->cdc.DBC.B.H);\r
cc68a136 274\r
275 Pico_mcd->s68k_regs[5] = 0x4;\r
276 return Pico_mcd->cdc.DBC.B.H;\r
277\r
278 case 0x4: // HEAD0\r
c459aefd 279 cdprintf("CDC read reg 04 = %.2X", Pico_mcd->cdc.HEAD.B.B0);\r
cc68a136 280\r
281 CDC_Decode_Reg_Read |= (1 << 4); // Reg 4 (decoding)\r
282 Pico_mcd->s68k_regs[5] = 0x5;\r
283 return Pico_mcd->cdc.HEAD.B.B0;\r
284\r
285 case 0x5: // HEAD1\r
c459aefd 286 cdprintf("CDC read reg 05 = %.2X", Pico_mcd->cdc.HEAD.B.B1);\r
cc68a136 287\r
288 CDC_Decode_Reg_Read |= (1 << 5); // Reg 5 (decoding)\r
289 Pico_mcd->s68k_regs[5] = 0x6;\r
290 return Pico_mcd->cdc.HEAD.B.B1;\r
291\r
292 case 0x6: // HEAD2\r
c459aefd 293 cdprintf("CDC read reg 06 = %.2X", Pico_mcd->cdc.HEAD.B.B2);\r
cc68a136 294\r
295 CDC_Decode_Reg_Read |= (1 << 6); // Reg 6 (decoding)\r
296 Pico_mcd->s68k_regs[5] = 0x7;\r
297 return Pico_mcd->cdc.HEAD.B.B2;\r
298\r
299 case 0x7: // HEAD3\r
c459aefd 300 cdprintf("CDC read reg 07 = %.2X", Pico_mcd->cdc.HEAD.B.B3);\r
cc68a136 301\r
302 CDC_Decode_Reg_Read |= (1 << 7); // Reg 7 (decoding)\r
303 Pico_mcd->s68k_regs[5] = 0x8;\r
304 return Pico_mcd->cdc.HEAD.B.B3;\r
305\r
306 case 0x8: // PTL\r
c459aefd 307 cdprintf("CDC read reg 08 = %.2X", Pico_mcd->cdc.PT.B.L);\r
cc68a136 308\r
309 CDC_Decode_Reg_Read |= (1 << 8); // Reg 8 (decoding)\r
310 Pico_mcd->s68k_regs[5] = 0x9;\r
311 return Pico_mcd->cdc.PT.B.L;\r
312\r
313 case 0x9: // PTH\r
c459aefd 314 cdprintf("CDC read reg 09 = %.2X", Pico_mcd->cdc.PT.B.H);\r
cc68a136 315\r
316 CDC_Decode_Reg_Read |= (1 << 9); // Reg 9 (decoding)\r
317 Pico_mcd->s68k_regs[5] = 0xA;\r
318 return Pico_mcd->cdc.PT.B.H;\r
319\r
320 case 0xA: // WAL\r
c459aefd 321 cdprintf("CDC read reg 10 = %.2X", Pico_mcd->cdc.WA.B.L);\r
cc68a136 322\r
323 Pico_mcd->s68k_regs[5] = 0xB;\r
324 return Pico_mcd->cdc.WA.B.L;\r
325\r
326 case 0xB: // WAH\r
c459aefd 327 cdprintf("CDC read reg 11 = %.2X", Pico_mcd->cdc.WA.B.H);\r
cc68a136 328\r
329 Pico_mcd->s68k_regs[5] = 0xC;\r
330 return Pico_mcd->cdc.WA.B.H;\r
331\r
332 case 0xC: // STAT0\r
c459aefd 333 cdprintf("CDC read reg 12 = %.2X", Pico_mcd->cdc.STAT.B.B0);\r
cc68a136 334\r
335 CDC_Decode_Reg_Read |= (1 << 12); // Reg 12 (decoding)\r
336 Pico_mcd->s68k_regs[5] = 0xD;\r
337 return Pico_mcd->cdc.STAT.B.B0;\r
338\r
339 case 0xD: // STAT1\r
c459aefd 340 cdprintf("CDC read reg 13 = %.2X", Pico_mcd->cdc.STAT.B.B1);\r
cc68a136 341\r
342 CDC_Decode_Reg_Read |= (1 << 13); // Reg 13 (decoding)\r
343 Pico_mcd->s68k_regs[5] = 0xE;\r
344 return Pico_mcd->cdc.STAT.B.B1;\r
345\r
346 case 0xE: // STAT2\r
c459aefd 347 cdprintf("CDC read reg 14 = %.2X", Pico_mcd->cdc.STAT.B.B2);\r
cc68a136 348\r
349 CDC_Decode_Reg_Read |= (1 << 14); // Reg 14 (decoding)\r
350 Pico_mcd->s68k_regs[5] = 0xF;\r
351 return Pico_mcd->cdc.STAT.B.B2;\r
352\r
353 case 0xF: // STAT3\r
c459aefd 354 cdprintf("CDC read reg 15 = %.2X", Pico_mcd->cdc.STAT.B.B3);\r
cc68a136 355\r
356 ret = Pico_mcd->cdc.STAT.B.B3;\r
357 Pico_mcd->cdc.IFSTAT |= 0x20; // decoding interrupt flag cleared\r
358 if ((Pico_mcd->cdc.CTRL.B.B0 & 0x80) && (Pico_mcd->cdc.IFCTRL & 0x20))\r
359 {\r
360 if ((CDC_Decode_Reg_Read & 0x73F2) == 0x73F2)\r
361 Pico_mcd->cdc.STAT.B.B3 = 0x80;\r
362 }\r
363 return ret;\r
364 }\r
365\r
366 return 0;\r
367}\r
368\r
369\r
370void CDC_Write_Reg(unsigned char Data)\r
371{\r
c459aefd 372 cdprintf("CDC write reg%02d = %.2X", Pico_mcd->s68k_regs[5] & 0xF, Data);\r
cc68a136 373\r
374 switch (Pico_mcd->s68k_regs[5] & 0xF)\r
375 {\r
376 case 0x0: // SBOUT\r
377 Pico_mcd->s68k_regs[5] = 0x1;\r
378 Pico_mcd->cdc.SBOUT = Data;\r
379\r
380 break;\r
381\r
382 case 0x1: // IFCTRL\r
383 Pico_mcd->s68k_regs[5] = 0x2;\r
384 Pico_mcd->cdc.IFCTRL = Data;\r
385\r
386 if ((Pico_mcd->cdc.IFCTRL & 0x02) == 0) // Stop data transfer\r
387 {\r
388 Pico_mcd->cdc.DBC.N = 0;\r
c459aefd 389 Pico_mcd->scd.Status_CDC &= ~0x08;\r
cc68a136 390 Pico_mcd->cdc.IFSTAT |= 0x08; // No more data transfer in progress\r
391 }\r
392 break;\r
393\r
394 case 0x2: // DBCL\r
395 Pico_mcd->s68k_regs[5] = 0x3;\r
396 Pico_mcd->cdc.DBC.B.L = Data;\r
397\r
398 break;\r
399\r
400 case 0x3: // DBCH\r
401 Pico_mcd->s68k_regs[5] = 0x4;\r
402 Pico_mcd->cdc.DBC.B.H = Data;\r
403\r
404 break;\r
405\r
406 case 0x4: // DACL\r
407 Pico_mcd->s68k_regs[5] = 0x5;\r
408 Pico_mcd->cdc.DAC.B.L = Data;\r
409\r
410 break;\r
411\r
412 case 0x5: // DACH\r
413 Pico_mcd->s68k_regs[5] = 0x6;\r
414 Pico_mcd->cdc.DAC.B.H = Data;\r
415\r
416 break;\r
417\r
418 case 0x6: // DTTRG\r
419 if (Pico_mcd->cdc.IFCTRL & 0x02) // Data transfer enable ?\r
420 {\r
421 Pico_mcd->cdc.IFSTAT &= ~0x08; // Data transfer in progress\r
c459aefd 422 Pico_mcd->scd.Status_CDC |= 0x08; // Data transfer in progress\r
cc68a136 423 Pico_mcd->s68k_regs[4] &= 0x7F; // A data transfer start\r
424\r
c459aefd 425 cdprintf("************** Starting Data Transfer ***********");\r
cc68a136 426 cdprintf("RS0 = %.4X DAC = %.4X DBC = %.4X DMA adr = %.4X\n\n", Pico_mcd->s68k_regs[4]<<8,\r
cb4a513a 427 Pico_mcd->cdc.DAC.N, Pico_mcd->cdc.DBC.N, (Pico_mcd->s68k_regs[0xA]<<8) | Pico_mcd->s68k_regs[0xB]);\r
cc68a136 428 }\r
429 break;\r
430\r
431 case 0x7: // DTACK\r
432 Pico_mcd->cdc.IFSTAT |= 0x40; // end data transfer interrupt flag cleared\r
433 break;\r
434\r
435 case 0x8: // WAL\r
436 Pico_mcd->s68k_regs[5] = 0x9;\r
437 Pico_mcd->cdc.WA.B.L = Data;\r
438\r
439 break;\r
440\r
441 case 0x9: // WAH\r
442 Pico_mcd->s68k_regs[5] = 0xA;\r
443 Pico_mcd->cdc.WA.B.H = Data;\r
444\r
445 break;\r
446\r
447 case 0xA: // CTRL0\r
448 Pico_mcd->s68k_regs[5] = 0xB;\r
449 Pico_mcd->cdc.CTRL.B.B0 = Data;\r
450\r
451 break;\r
452\r
453 case 0xB: // CTRL1\r
454 Pico_mcd->s68k_regs[5] = 0xC;\r
455 Pico_mcd->cdc.CTRL.B.B1 = Data;\r
456\r
457 break;\r
458\r
459 case 0xC: // PTL\r
460 Pico_mcd->s68k_regs[5] = 0xD;\r
461 Pico_mcd->cdc.PT.B.L = Data;\r
462\r
463 break;\r
464\r
465 case 0xD: // PTH\r
466 Pico_mcd->s68k_regs[5] = 0xE;\r
467 Pico_mcd->cdc.PT.B.H = Data;\r
468\r
469 break;\r
470\r
471 case 0xE: // CTRL2\r
472 Pico_mcd->cdc.CTRL.B.B2 = Data;\r
473 break;\r
474\r
475 case 0xF: // RESET\r
476 CDC_Reset();\r
477 break;\r
478 }\r
479}\r
480\r
481\r
482static int bswapwrite(int a, unsigned short d)\r
483{\r
484 *(unsigned short *)(Pico_mcd->s68k_regs + a) = (d>>8)|(d<<8);\r
485 return d + (d >> 8);\r
486}\r
487\r
488void CDD_Export_Status(void)\r
489{\r
490 unsigned int csum;\r
491\r
492 csum = bswapwrite( 0x38+0, Pico_mcd->cdd.Status);\r
493 csum += bswapwrite( 0x38+2, Pico_mcd->cdd.Minute);\r
494 csum += bswapwrite( 0x38+4, Pico_mcd->cdd.Seconde);\r
495 csum += bswapwrite( 0x38+6, Pico_mcd->cdd.Frame);\r
496 Pico_mcd->s68k_regs[0x38+8] = Pico_mcd->cdd.Ext;\r
497 csum += Pico_mcd->cdd.Ext;\r
498 Pico_mcd->s68k_regs[0x38+9] = ~csum & 0xf;\r
499\r
672ad671 500 Pico_mcd->s68k_regs[0x37] &= 3; // CDD.Control\r
cc68a136 501\r
502 if (Pico_mcd->s68k_regs[0x33] & (1<<4))\r
503 {\r
504 dprintf("cdd export irq 4");\r
505 SekInterruptS68k(4);\r
506 }\r
507\r
c459aefd 508// cdprintf("CDD exported status\n");\r
509 cdprintf("out: Status=%.4X, Minute=%.4X, Second=%.4X, Frame=%.4X Checksum=%.4X",\r
cc68a136 510 (Pico_mcd->s68k_regs[0x38+0] << 8) | Pico_mcd->s68k_regs[0x38+1],\r
511 (Pico_mcd->s68k_regs[0x38+2] << 8) | Pico_mcd->s68k_regs[0x38+3],\r
512 (Pico_mcd->s68k_regs[0x38+4] << 8) | Pico_mcd->s68k_regs[0x38+5],\r
513 (Pico_mcd->s68k_regs[0x38+6] << 8) | Pico_mcd->s68k_regs[0x38+7],\r
514 (Pico_mcd->s68k_regs[0x38+8] << 8) | Pico_mcd->s68k_regs[0x38+9]);\r
515}\r
516\r
517\r
518void CDD_Import_Command(void)\r
519{\r
c459aefd 520// cdprintf("CDD importing command\n");\r
521 cdprintf("in: Command=%.4X, Minute=%.4X, Second=%.4X, Frame=%.4X Checksum=%.4X",\r
cc68a136 522 (Pico_mcd->s68k_regs[0x38+10+0] << 8) | Pico_mcd->s68k_regs[0x38+10+1],\r
523 (Pico_mcd->s68k_regs[0x38+10+2] << 8) | Pico_mcd->s68k_regs[0x38+10+3],\r
524 (Pico_mcd->s68k_regs[0x38+10+4] << 8) | Pico_mcd->s68k_regs[0x38+10+5],\r
525 (Pico_mcd->s68k_regs[0x38+10+6] << 8) | Pico_mcd->s68k_regs[0x38+10+7],\r
526 (Pico_mcd->s68k_regs[0x38+10+8] << 8) | Pico_mcd->s68k_regs[0x38+10+9]);\r
527\r
528 switch (Pico_mcd->s68k_regs[0x38+10+0])\r
529 {\r
530 case 0x0: // STATUS (?)\r
531 Get_Status_CDD_c0();\r
532 break;\r
533\r
534 case 0x1: // STOP ALL (?)\r
535 Stop_CDD_c1();\r
536 break;\r
537\r
538 case 0x2: // GET TOC INFORMATIONS\r
539 switch(Pico_mcd->s68k_regs[0x38+10+3])\r
540 {\r
541 case 0x0: // get current position (MSF format)\r
542 Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00);\r
543 Get_Pos_CDD_c20();\r
544 break;\r
545\r
546 case 0x1: // get elapsed time of current track played/scanned (relative MSF format)\r
547 Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 1;\r
548 Get_Track_Pos_CDD_c21();\r
549 break;\r
550\r
551 case 0x2: // get current track in RS2-RS3\r
552 Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 2;\r
553 Get_Current_Track_CDD_c22();\r
554 break;\r
555\r
bf098bc5 556 case 0x3: // get total length (MSF format)\r
cc68a136 557 Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 3;\r
558 Get_Total_Lenght_CDD_c23();\r
559 break;\r
560\r
561 case 0x4: // first & last track number\r
562 Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 4;\r
563 Get_First_Last_Track_CDD_c24();\r
564 break;\r
565\r
566 case 0x5: // get track addresse (MSF format)\r
567 Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 5;\r
568 Get_Track_Adr_CDD_c25();\r
569 break;\r
570\r
571 default : // invalid, then we return status\r
572 Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 0xF;\r
573 Get_Status_CDD_c0();\r
574 break;\r
575 }\r
576 break;\r
577\r
578 case 0x3: // READ\r
579 Play_CDD_c3();\r
580 break;\r
581\r
582 case 0x4: // SEEK\r
583 Seek_CDD_c4();\r
584 break;\r
585\r
586 case 0x6: // PAUSE/STOP\r
587 Pause_CDD_c6();\r
588 break;\r
589\r
590 case 0x7: // RESUME\r
591 Resume_CDD_c7();\r
592 break;\r
593\r
594 case 0x8: // FAST FOWARD\r
595 Fast_Foward_CDD_c8();\r
596 break;\r
597\r
598 case 0x9: // FAST REWIND\r
599 Fast_Rewind_CDD_c9();\r
600 break;\r
601\r
602 case 0xA: // RECOVER INITIAL STATE (?)\r
603 CDD_cA();\r
604 break;\r
605\r
606 case 0xC: // CLOSE TRAY\r
607 Close_Tray_CDD_cC();\r
608 break;\r
609\r
610 case 0xD: // OPEN TRAY\r
611 Open_Tray_CDD_cD();\r
612 break;\r
613\r
614 default: // UNKNOWN\r
615 CDD_Def();\r
616 break;\r
617 }\r
618}\r
619\r