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