Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/genplus-gx/core/cd_hw/cdc.c
2 views
1
/***************************************************************************************
2
* Genesis Plus
3
* CD data controller (LC89510 compatible)
4
*
5
* Copyright (C) 2012 Eke-Eke (Genesis Plus GX)
6
*
7
* Redistribution and use of this code or any derivative works are permitted
8
* provided that the following conditions are met:
9
*
10
* - Redistributions may not be sold, nor may they be used in a commercial
11
* product or activity.
12
*
13
* - Redistributions that are modified from the original source must include the
14
* complete source code, including the source code for all components used by a
15
* binary built from the modified sources. However, as a special exception, the
16
* source code distributed need not include anything that is normally distributed
17
* (in either source or binary form) with the major components (compiler, kernel,
18
* and so on) of the operating system on which the executable runs, unless that
19
* component itself accompanies the executable.
20
*
21
* - Redistributions must reproduce the above copyright notice, this list of
22
* conditions and the following disclaimer in the documentation and/or other
23
* materials provided with the distribution.
24
*
25
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35
* POSSIBILITY OF SUCH DAMAGE.
36
*
37
****************************************************************************************/
38
39
#include "shared.h"
40
41
/* IFSTAT register bitmasks */
42
#define BIT_DTEI 0x40
43
#define BIT_DECI 0x20
44
#define BIT_DTBSY 0x08
45
#define BIT_DTEN 0x02
46
47
/* IFCTRL register bitmasks */
48
#define BIT_DTEIEN 0x40
49
#define BIT_DECIEN 0x20
50
#define BIT_DOUTEN 0x02
51
52
/* CTRL0 register bitmasks */
53
#define BIT_DECEN 0x80
54
#define BIT_E01RQ 0x20
55
#define BIT_AUTORQ 0x10
56
#define BIT_WRRQ 0x04
57
58
/* CTRL1 register bitmasks */
59
#define BIT_MODRQ 0x08
60
#define BIT_FORMRQ 0x04
61
#define BIT_SHDREN 0x01
62
63
/* CTRL2 register bitmask */
64
#define BIT_VALST 0x80
65
66
/* TODO: figure exact DMA transfer rate */
67
#define DMA_BYTES_PER_LINE 512
68
69
void cdc_init(void)
70
{
71
memset(&cdc, 0, sizeof(cdc_t));
72
}
73
74
void cdc_reset(void)
75
{
76
/* reset CDC register index */
77
scd.regs[0x04>>1].byte.l = 0x00;
78
79
/* reset CDC registers */
80
cdc.ifstat = 0xff;
81
cdc.ifctrl = 0x00;
82
cdc.ctrl[0] = 0x00;
83
cdc.ctrl[1] = 0x00;
84
cdc.stat[0] = 0x00;
85
cdc.stat[1] = 0x00;
86
cdc.stat[2] = 0x00;
87
cdc.stat[3] = 0x80;
88
cdc.head[0][0] = 0x00;
89
cdc.head[0][1] = 0x00;
90
cdc.head[0][2] = 0x00;
91
cdc.head[0][3] = 0x01;
92
cdc.head[1][0] = 0x00;
93
cdc.head[1][1] = 0x00;
94
cdc.head[1][2] = 0x00;
95
cdc.head[1][3] = 0x00;
96
97
/* reset CDC cycle counter */
98
cdc.cycles = 0;
99
100
/* DMA transfer disabled */
101
cdc.dma_w = 0;
102
103
/* clear any pending IRQ */
104
if (scd.pending & (1 << 5))
105
{
106
/* clear any pending interrupt level 5 */
107
scd.pending &= ~(1 << 5);
108
109
/* update IRQ level */
110
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
111
}
112
}
113
114
int cdc_context_save(uint8 *state)
115
{
116
uint8 tmp8;
117
int bufferptr = 0;
118
119
if (cdc.dma_w == pcm_ram_dma_w)
120
{
121
tmp8 = 1;
122
}
123
else if (cdc.dma_w == prg_ram_dma_w)
124
{
125
tmp8 = 2;
126
}
127
else if (cdc.dma_w == word_ram_0_dma_w)
128
{
129
tmp8 = 3;
130
}
131
else if (cdc.dma_w == word_ram_1_dma_w)
132
{
133
tmp8 = 4;
134
}
135
else if (cdc.dma_w == word_ram_2M_dma_w)
136
{
137
tmp8 = 5;
138
}
139
else
140
{
141
tmp8 = 0;
142
}
143
144
save_param(&cdc, sizeof(cdc));
145
save_param(&tmp8, 1);
146
147
return bufferptr;
148
}
149
150
int cdc_context_load(uint8 *state)
151
{
152
uint8 tmp8;
153
int bufferptr = 0;
154
155
load_param(&cdc, sizeof(cdc));
156
load_param(&tmp8, 1);
157
158
switch (tmp8)
159
{
160
case 1:
161
cdc.dma_w = pcm_ram_dma_w;
162
break;
163
case 2:
164
cdc.dma_w = prg_ram_dma_w;
165
break;
166
case 3:
167
cdc.dma_w = word_ram_0_dma_w;
168
break;
169
case 4:
170
cdc.dma_w = word_ram_1_dma_w;
171
break;
172
case 5:
173
cdc.dma_w = word_ram_2M_dma_w;
174
break;
175
default:
176
cdc.dma_w = 0;
177
break;
178
}
179
180
return bufferptr;
181
}
182
183
void cdc_dma_update(void)
184
{
185
/* maximal transfer length */
186
int length = DMA_BYTES_PER_LINE;
187
188
/* end of DMA transfer ? */
189
if (cdc.dbc.w < DMA_BYTES_PER_LINE)
190
{
191
/* transfer remaining words using 16-bit DMA */
192
cdc.dma_w((cdc.dbc.w + 1) >> 1);
193
194
/* reset data byte counter (DBCH bits 4-7 should be set to 1) */
195
cdc.dbc.w = 0xf000;
196
197
/* clear !DTEN and !DTBSY */
198
cdc.ifstat |= (BIT_DTBSY | BIT_DTEN);
199
200
/* pending Data Transfer End interrupt */
201
cdc.ifstat &= ~BIT_DTEI;
202
203
/* Data Transfer End interrupt enabled ? */
204
if (cdc.ifctrl & BIT_DTEIEN)
205
{
206
/* pending level 5 interrupt */
207
scd.pending |= (1 << 5);
208
209
/* level 5 interrupt enabled ? */
210
if (scd.regs[0x32>>1].byte.l & 0x20)
211
{
212
/* update IRQ level */
213
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
214
}
215
}
216
217
/* clear DSR bit & set EDT bit (CD register $04) */
218
scd.regs[0x04>>1].byte.h = (scd.regs[0x04>>1].byte.h & 0x07) | 0x80;
219
220
/* SUB-CPU idle on register $04 polling ? */
221
if (s68k.stopped & (1<<0x04))
222
{
223
/* sync SUB-CPU with CDC */
224
s68k.cycles = scd.cycles;
225
226
/* restart SUB-CPU */
227
s68k.stopped = 0;
228
#ifdef LOG_SCD
229
error("s68k started from %d cycles\n", s68k.cycles);
230
#endif
231
}
232
233
/* disable DMA transfer */
234
cdc.dma_w = 0;
235
}
236
else
237
{
238
/* transfer all words using 16-bit DMA */
239
cdc.dma_w(DMA_BYTES_PER_LINE >> 1);
240
241
/* decrement data byte counter */
242
cdc.dbc.w -= length;
243
}
244
}
245
246
int cdc_decoder_update(uint32 header)
247
{
248
/* data decoding enabled ? */
249
if (cdc.ctrl[0] & BIT_DECEN)
250
{
251
/* update HEAD registers */
252
*(uint32 *)(cdc.head[0]) = header;
253
254
/* set !VALST */
255
cdc.stat[3] = 0x00;
256
257
/* pending decoder interrupt */
258
cdc.ifstat &= ~BIT_DECI;
259
260
/* decoder interrupt enabled ? */
261
if (cdc.ifctrl & BIT_DECIEN)
262
{
263
/* pending level 5 interrupt */
264
scd.pending |= (1 << 5);
265
266
/* level 5 interrupt enabled ? */
267
if (scd.regs[0x32>>1].byte.l & 0x20)
268
{
269
/* update IRQ level */
270
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
271
}
272
}
273
274
/* buffer RAM write enabled ? */
275
if (cdc.ctrl[0] & BIT_WRRQ)
276
{
277
uint16 offset;
278
279
/* increment block pointer */
280
cdc.pt.w += 2352;
281
282
/* increment write address */
283
cdc.wa.w += 2352;
284
285
/* CDC buffer address */
286
offset = cdc.pt.w & 0x3fff;
287
288
/* write CDD block header (4 bytes) */
289
*(uint32 *)(cdc.ram + offset) = header;
290
291
/* write CDD block data (2048 bytes) */
292
cdd_read_data(cdc.ram + 4 + offset);
293
294
/* take care of buffer overrun */
295
if (offset > (0x4000 - 2048 - 4))
296
{
297
/* data should be written at the start of buffer */
298
memcpy(cdc.ram, cdc.ram + 0x4000, offset + 2048 + 4 - 0x4000);
299
}
300
301
/* read next data block */
302
return 1;
303
}
304
}
305
306
/* keep decoding same data block if Buffer Write is disabled */
307
return 0;
308
}
309
310
void cdc_reg_w(unsigned char data)
311
{
312
#ifdef LOG_CDC
313
error("CDC register %X write 0x%04x (%X)\n", scd.regs[0x04>>1].byte.l & 0x0F, data, s68k.pc);
314
#endif
315
switch (scd.regs[0x04>>1].byte.l & 0x0F)
316
{
317
case 0x01: /* IFCTRL */
318
{
319
/* pending interrupts ? */
320
if (((data & BIT_DTEIEN) && !(cdc.ifstat & BIT_DTEI)) ||
321
((data & BIT_DECIEN) && !(cdc.ifstat & BIT_DECI)))
322
{
323
/* pending level 5 interrupt */
324
scd.pending |= (1 << 5);
325
326
/* level 5 interrupt enabled ? */
327
if (scd.regs[0x32>>1].byte.l & 0x20)
328
{
329
/* update IRQ level */
330
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
331
}
332
}
333
else if (scd.pending & (1 << 5))
334
{
335
/* clear pending level 5 interrupts */
336
scd.pending &= ~(1 << 5);
337
338
/* update IRQ level */
339
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
340
}
341
342
/* abort any data transfer if data output is disabled */
343
if (!(data & BIT_DOUTEN))
344
{
345
/* clear !DTBSY and !DTEN */
346
cdc.ifstat |= (BIT_DTBSY | BIT_DTEN);
347
}
348
349
cdc.ifctrl = data;
350
scd.regs[0x04>>1].byte.l = 0x02;
351
break;
352
}
353
354
case 0x02: /* DBCL */
355
cdc.dbc.byte.l = data;
356
scd.regs[0x04>>1].byte.l = 0x03;
357
break;
358
359
case 0x03: /* DBCH */
360
cdc.dbc.byte.h = data;
361
scd.regs[0x04>>1].byte.l = 0x04;
362
break;
363
364
case 0x04: /* DACL */
365
cdc.dac.byte.l = data;
366
scd.regs[0x04>>1].byte.l = 0x05;
367
break;
368
369
case 0x05: /* DACH */
370
cdc.dac.byte.h = data;
371
scd.regs[0x04>>1].byte.l = 0x06;
372
break;
373
374
case 0x06: /* DTRG */
375
{
376
/* start data transfer if data output is enabled */
377
if (cdc.ifctrl & BIT_DOUTEN)
378
{
379
/* set !DTBSY */
380
cdc.ifstat &= ~BIT_DTBSY;
381
382
/* clear DBCH bits 4-7 */
383
cdc.dbc.byte.h &= 0x0f;
384
385
/* clear EDT & DSR bits (SCD register $04) */
386
scd.regs[0x04>>1].byte.h &= 0x07;
387
388
/* setup data transfer destination */
389
switch (scd.regs[0x04>>1].byte.h & 0x07)
390
{
391
case 2: /* MAIN-CPU host read */
392
case 3: /* SUB-CPU host read */
393
{
394
/* set !DTEN */
395
cdc.ifstat &= ~BIT_DTEN;
396
397
/* set DSR bit (register $04) */
398
scd.regs[0x04>>1].byte.h |= 0x40;
399
break;
400
}
401
402
case 4: /* PCM RAM DMA */
403
{
404
cdc.dma_w = pcm_ram_dma_w;
405
break;
406
}
407
408
case 5: /* PRG-RAM DMA */
409
{
410
cdc.dma_w = prg_ram_dma_w;
411
break;
412
}
413
414
case 7: /* WORD-RAM DMA */
415
{
416
/* check memory mode */
417
if (scd.regs[0x02 >> 1].byte.l & 0x04)
418
{
419
/* 1M mode */
420
if (scd.regs[0x02 >> 1].byte.l & 0x01)
421
{
422
/* Word-RAM bank 0 is assigned to SUB-CPU */
423
cdc.dma_w = word_ram_0_dma_w;
424
}
425
else
426
{
427
/* Word-RAM bank 1 is assigned to SUB-CPU */
428
cdc.dma_w = word_ram_1_dma_w;
429
}
430
}
431
else
432
{
433
/* 2M mode */
434
if (scd.regs[0x02 >> 1].byte.l & 0x02)
435
{
436
/* only process DMA if Word-RAM is assigned to SUB-CPU */
437
cdc.dma_w = word_ram_2M_dma_w;
438
}
439
}
440
break;
441
}
442
443
default: /* invalid */
444
{
445
#ifdef LOG_CDC
446
error("invalid CDC tranfer destination (%d)\n", scd.regs[0x04>>1].byte.h & 0x07);
447
#endif
448
break;
449
}
450
}
451
}
452
453
scd.regs[0x04>>1].byte.l = 0x07;
454
break;
455
}
456
457
case 0x07: /* DTACK */
458
{
459
/* clear pending data transfer end interrupt */
460
cdc.ifstat |= BIT_DTEI;
461
462
/* clear DBCH bits 4-7 */
463
cdc.dbc.byte.h &= 0x0f;
464
465
#if 0
466
/* no pending decoder interrupt ? */
467
if ((cdc.ifstat | BIT_DECI) || !(cdc.ifctrl & BIT_DECIEN))
468
{
469
/* clear pending level 5 interrupt */
470
scd.pending &= ~(1 << 5);
471
472
/* update IRQ level */
473
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
474
}
475
#endif
476
scd.regs[0x04>>1].byte.l = 0x08;
477
break;
478
}
479
480
case 0x08: /* WAL */
481
cdc.wa.byte.l = data;
482
scd.regs[0x04>>1].byte.l = 0x09;
483
break;
484
485
case 0x09: /* WAH */
486
cdc.wa.byte.h = data;
487
scd.regs[0x04>>1].byte.l = 0x0a;
488
break;
489
490
case 0x0a: /* CTRL0 */
491
{
492
/* set CRCOK bit only if decoding is enabled */
493
cdc.stat[0] = data & BIT_DECEN;
494
495
/* update decoding mode */
496
if (data & BIT_AUTORQ)
497
{
498
/* set MODE bit according to CTRL1 register & clear FORM bit */
499
cdc.stat[2] = cdc.ctrl[1] & BIT_MODRQ;
500
}
501
else
502
{
503
/* set MODE & FORM bits according to CTRL1 register */
504
cdc.stat[2] = cdc.ctrl[1] & (BIT_MODRQ | BIT_FORMRQ);
505
}
506
507
cdc.ctrl[0] = data;
508
scd.regs[0x04>>1].byte.l = 0x0b;
509
break;
510
}
511
512
case 0x0b: /* CTRL1 */
513
{
514
/* update decoding mode */
515
if (cdc.ctrl[0] & BIT_AUTORQ)
516
{
517
/* set MODE bit according to CTRL1 register & clear FORM bit */
518
cdc.stat[2] = data & BIT_MODRQ;
519
}
520
else
521
{
522
/* set MODE & FORM bits according to CTRL1 register */
523
cdc.stat[2] = data & (BIT_MODRQ | BIT_FORMRQ);
524
}
525
526
cdc.ctrl[1] = data;
527
scd.regs[0x04>>1].byte.l = 0x0c;
528
break;
529
}
530
531
case 0x0c: /* PTL */
532
cdc.pt.byte.l = data;
533
scd.regs[0x04>>1].byte.l = 0x0d;
534
break;
535
536
case 0x0d: /* PTH */
537
cdc.pt.byte.h = data;
538
scd.regs[0x04>>1].byte.l = 0x0e;
539
break;
540
541
case 0x0e: /* CTRL2 (unused) */
542
scd.regs[0x04>>1].byte.l = 0x0f;
543
break;
544
545
case 0x0f: /* RESET */
546
cdc_reset();
547
break;
548
549
default: /* by default, SBOUT is not used */
550
break;
551
}
552
}
553
554
unsigned char cdc_reg_r(void)
555
{
556
switch (scd.regs[0x04>>1].byte.l & 0x0F)
557
{
558
case 0x01: /* IFSTAT */
559
scd.regs[0x04>>1].byte.l = 0x02;
560
return cdc.ifstat;
561
562
case 0x02: /* DBCL */
563
scd.regs[0x04>>1].byte.l = 0x03;
564
return cdc.dbc.byte.l;
565
566
case 0x03: /* DBCH */
567
scd.regs[0x04>>1].byte.l = 0x04;
568
return cdc.dbc.byte.h;
569
570
case 0x04: /* HEAD0 */
571
scd.regs[0x04>>1].byte.l = 0x05;
572
return cdc.head[cdc.ctrl[1] & BIT_SHDREN][0];
573
574
case 0x05: /* HEAD1 */
575
scd.regs[0x04>>1].byte.l = 0x06;
576
return cdc.head[cdc.ctrl[1] & BIT_SHDREN][1];
577
578
case 0x06: /* HEAD2 */
579
scd.regs[0x04>>1].byte.l = 0x07;
580
return cdc.head[cdc.ctrl[1] & BIT_SHDREN][2];
581
582
case 0x07: /* HEAD3 */
583
scd.regs[0x04>>1].byte.l = 0x08;
584
return cdc.head[cdc.ctrl[1] & BIT_SHDREN][3];
585
586
case 0x08: /* PTL */
587
scd.regs[0x04>>1].byte.l = 0x09;
588
return cdc.pt.byte.l;
589
590
case 0x09: /* PTH */
591
scd.regs[0x04>>1].byte.l = 0x0a;
592
return cdc.pt.byte.h;
593
594
case 0x0a: /* WAL */
595
scd.regs[0x04>>1].byte.l = 0x0b;
596
return cdc.wa.byte.l;
597
598
case 0x0b: /* WAH */
599
scd.regs[0x04>>1].byte.l = 0x0c;
600
return cdc.wa.byte.h;
601
602
case 0x0c: /* STAT0 */
603
scd.regs[0x04>>1].byte.l = 0x0d;
604
return cdc.stat[0];
605
606
case 0x0d: /* STAT1 (always return 0) */
607
scd.regs[0x04>>1].byte.l = 0x0e;
608
return 0x00;
609
610
case 0x0e: /* STAT2 */
611
scd.regs[0x04>>1].byte.l = 0x0f;
612
return cdc.stat[2];
613
614
case 0x0f: /* STAT3 */
615
{
616
uint8 data = cdc.stat[3];
617
618
/* clear !VALST (note: this is not 100% correct but BIOS do not seem to care) */
619
cdc.stat[3] = BIT_VALST;
620
621
/* clear pending decoder interrupt */
622
cdc.ifstat |= BIT_DECI;
623
624
#if 0
625
/* no pending data transfer end interrupt */
626
if ((cdc.ifstat | BIT_DTEI) || !(cdc.ifctrl & BIT_DTEIEN))
627
{
628
/* clear pending level 5 interrupt */
629
scd.pending &= ~(1 << 5);
630
631
/* update IRQ level */
632
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
633
}
634
#endif
635
636
scd.regs[0x04>>1].byte.l = 0x00;
637
return data;
638
}
639
640
default: /* by default, COMIN is always empty */
641
return 0xff;
642
}
643
}
644
645
unsigned short cdc_host_r(void)
646
{
647
/* check if data is available */
648
if (!(cdc.ifstat & BIT_DTEN))
649
{
650
/* read data word from CDC RAM buffer */
651
uint16 data = *(uint16 *)(cdc.ram + (cdc.dac.w & 0x3ffe));
652
653
#ifdef LSB_FIRST
654
/* source data is stored in big endian format */
655
data = ((data >> 8) | (data << 8)) & 0xffff;
656
#endif
657
658
#ifdef LOG_CDC
659
error("CDC host read 0x%04x -> 0x%04x (dbc=0x%x) (%X)\n", cdc.dac.w, data, cdc.dbc.w, s68k.pc);
660
#endif
661
662
/* increment data address counter */
663
cdc.dac.w += 2;
664
665
/* decrement data byte counter */
666
cdc.dbc.w -= 2;
667
668
/* end of transfer ? */
669
if ((int16)cdc.dbc.w <= 0)
670
{
671
/* reset data byte counter (DBCH bits 4-7 should be set to 1) */
672
cdc.dbc.w = 0xf000;
673
674
/* clear !DTEN and !DTBSY */
675
cdc.ifstat |= (BIT_DTBSY | BIT_DTEN);
676
677
/* pending Data Transfer End interrupt */
678
cdc.ifstat &= ~BIT_DTEI;
679
680
/* Data Transfer End interrupt enabled ? */
681
if (cdc.ifctrl & BIT_DTEIEN)
682
{
683
/* pending level 5 interrupt */
684
scd.pending |= (1 << 5);
685
686
/* level 5 interrupt enabled ? */
687
if (scd.regs[0x32>>1].byte.l & 0x20)
688
{
689
/* update IRQ level */
690
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
691
}
692
}
693
694
/* clear DSR bit & set EDT bit (SCD register $04) */
695
scd.regs[0x04>>1].byte.h = (scd.regs[0x04>>1].byte.h & 0x07) | 0x80;
696
}
697
698
return data;
699
}
700
701
#ifdef LOG_CDC
702
error("error reading CDC host (data transfer disabled)\n");
703
#endif
704
return 0xffff;
705
}
706
707