Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/genplus-gx32/core/cd_hw/scd.c
2 views
1
/***************************************************************************************
2
* Genesis Plus
3
* Mega CD / Sega CD hardware
4
*
5
* Copyright (C) 2012-2013 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
/*--------------------------------------------------------------------------*/
42
/* Unused area (return open bus data, i.e prefetched instruction word) */
43
/*--------------------------------------------------------------------------*/
44
static unsigned int s68k_read_bus_8(unsigned int address)
45
{
46
#ifdef LOGERROR
47
error("[SUB 68k] Unused read8 %08X (%08X)\n", address, s68k.pc);
48
#endif
49
address = s68k.pc | (address & 1);
50
return READ_BYTE(s68k.memory_map[((address)>>16)&0xff].base, (address) & 0xffff);
51
}
52
53
static unsigned int s68k_read_bus_16(unsigned int address)
54
{
55
#ifdef LOGERROR
56
error("[SUB 68k] Unused read16 %08X (%08X)\n", address, s68k.pc);
57
#endif
58
address = s68k.pc;
59
return *(uint16 *)(s68k.memory_map[((address)>>16)&0xff].base + ((address) & 0xffff));
60
}
61
62
static void s68k_unused_8_w(unsigned int address, unsigned int data)
63
{
64
#ifdef LOGERROR
65
error("[SUB 68k] Unused write8 %08X = %02X (%08X)\n", address, data, s68k.pc);
66
#endif
67
}
68
69
static void s68k_unused_16_w(unsigned int address, unsigned int data)
70
{
71
#ifdef LOGERROR
72
error("[SUB 68k] Unused write16 %08X = %04X (%08X)\n", address, data, s68k.pc);
73
#endif
74
}
75
76
/*--------------------------------------------------------------------------*/
77
/* PRG-RAM DMA access */
78
/*--------------------------------------------------------------------------*/
79
void prg_ram_dma_w(unsigned int words)
80
{
81
uint16 data;
82
83
/* CDC buffer source address */
84
uint16 src_index = cdc.dac.w & 0x3ffe;
85
86
/* PRG-RAM destination address*/
87
uint32 dst_index = (scd.regs[0x0a>>1].w << 3) & 0x7fffe;
88
89
/* update DMA destination address */
90
scd.regs[0x0a>>1].w += (words >> 2);
91
92
/* update DMA source address */
93
cdc.dac.w += (words << 1);
94
95
/* check PRG-RAM write protected area */
96
if (dst_index < (scd.regs[0x02>>1].byte.h << 9))
97
{
98
return;
99
}
100
101
/* DMA transfer */
102
while (words--)
103
{
104
/* read 16-bit word from CDC buffer */
105
data = *(uint16 *)(cdc.ram + src_index);
106
107
#ifdef LSB_FIRST
108
/* source data is stored in big endian format */
109
data = ((data >> 8) | (data << 8)) & 0xffff;
110
#endif
111
112
/* write 16-bit word to PRG-RAM */
113
*(uint16 *)(scd.prg_ram + dst_index) = data ;
114
115
/* increment CDC buffer source address */
116
src_index = (src_index + 2) & 0x3ffe;
117
118
/* increment PRG-RAM destination address */
119
dst_index = (dst_index + 2) & 0x7fffe;
120
}
121
}
122
123
/*--------------------------------------------------------------------------*/
124
/* PRG-RAM write protected area */
125
/*--------------------------------------------------------------------------*/
126
static void prg_ram_write_byte(unsigned int address, unsigned int data)
127
{
128
address &= 0x7ffff;
129
if (address >= (scd.regs[0x02>>1].byte.h << 9))
130
{
131
WRITE_BYTE(scd.prg_ram, address, data);
132
return;
133
}
134
#ifdef LOGERROR
135
error("[SUB 68k] PRG-RAM protected write8 %08X = %02X (%08X)\n", address, data, s68k.pc);
136
#endif
137
}
138
139
static void prg_ram_write_word(unsigned int address, unsigned int data)
140
{
141
address &= 0x7fffe;
142
if (address >= (scd.regs[0x02>>1].byte.h << 9))
143
{
144
*(uint16 *)(scd.prg_ram + address) = data;
145
return;
146
}
147
#ifdef LOGERROR
148
error("[SUB 68k] PRG-RAM protected write16 %08X = %02X (%08X)\n", address, data, s68k.pc);
149
#endif
150
}
151
152
/*--------------------------------------------------------------------------*/
153
/* internal backup RAM (8KB) */
154
/*--------------------------------------------------------------------------*/
155
static unsigned int bram_read_byte(unsigned int address)
156
{
157
/* LSB only */
158
if (address & 1)
159
{
160
return scd.bram[(address >> 1) & 0x1fff];
161
}
162
163
return 0xff;
164
}
165
166
static unsigned int bram_read_word(unsigned int address)
167
{
168
return (scd.bram[(address >> 1) & 0x1fff] | 0xff00);
169
}
170
171
static void bram_write_byte(unsigned int address, unsigned int data)
172
{
173
/* LSB only */
174
if (address & 1)
175
{
176
scd.bram[(address >> 1) & 0x1fff] = data;
177
}
178
}
179
180
static void bram_write_word(unsigned int address, unsigned int data)
181
{
182
scd.bram[(address >> 1) & 0x1fff] = data & 0xff;
183
}
184
185
/*--------------------------------------------------------------------------*/
186
/* PCM chip & Gate-Array area */
187
/*--------------------------------------------------------------------------*/
188
189
static void s68k_poll_detect(unsigned int reg_mask)
190
{
191
/* detect SUB-CPU register polling */
192
if (s68k.poll.detected & reg_mask)
193
{
194
if (s68k.cycles <= s68k.poll.cycle)
195
{
196
if (s68k.pc == s68k.poll.pc)
197
{
198
/* SUB-CPU polling confirmed ? */
199
if (s68k.poll.detected & 1)
200
{
201
/* idle SUB-CPU until register is modified */
202
s68k.cycles = s68k.cycle_end;
203
s68k.stopped = reg_mask;
204
#ifdef LOG_SCD
205
error("s68k stopped from %d cycles\n", s68k.cycles);
206
#endif
207
}
208
else
209
{
210
/* confirm SUB-CPU polling */
211
s68k.poll.detected |= 1;
212
s68k.poll.cycle = s68k.cycles + 392;
213
}
214
}
215
return;
216
}
217
}
218
else
219
{
220
/* set SUB-CPU register access flag */
221
s68k.poll.detected = reg_mask;
222
}
223
224
/* reset SUB-CPU polling detection */
225
s68k.poll.cycle = s68k.cycles + 392;
226
s68k.poll.pc = s68k.pc;
227
}
228
229
static void s68k_poll_sync(unsigned int reg_mask)
230
{
231
/* relative MAIN-CPU cycle counter */
232
unsigned int cycles = (s68k.cycles * MCYCLES_PER_LINE) / SCYCLES_PER_LINE;
233
234
/* sync MAIN-CPU with SUB-CPU */
235
if (!m68k.stopped)
236
{
237
m68k_run(cycles);
238
}
239
240
/* MAIN-CPU idle on register polling ? */
241
if (m68k.stopped & reg_mask)
242
{
243
/* sync MAIN-CPU with SUB-CPU */
244
m68k.cycles = cycles;
245
246
/* restart MAIN-CPU */
247
m68k.stopped = 0;
248
#ifdef LOG_SCD
249
error("m68k started from %d cycles\n", cycles);
250
#endif
251
}
252
253
/* clear CPU register access flags */
254
s68k.poll.detected &= ~reg_mask;
255
m68k.poll.detected &= ~reg_mask;
256
}
257
258
static unsigned int scd_read_byte(unsigned int address)
259
{
260
/* PCM area (8K) is mirrored into $FF0000-$FF7FFF */
261
if (address < 0xff8000)
262
{
263
/* get /LDS only */
264
if (address & 1)
265
{
266
return pcm_read((address >> 1) & 0x1fff);
267
}
268
269
return s68k_read_bus_8(address);
270
}
271
272
#ifdef LOG_SCD
273
error("[%d][%d]read byte CD register %X (%X)\n", v_counter, s68k.cycles, address, s68k.pc);
274
#endif
275
276
/* Memory Mode */
277
if (address == 0xff8003)
278
{
279
s68k_poll_detect(1<<0x03);
280
return scd.regs[0x03>>1].byte.l;
281
}
282
283
/* MAIN-CPU communication flags */
284
if (address == 0xff800e)
285
{
286
s68k_poll_detect(1<<0x0e);
287
return scd.regs[0x0e>>1].byte.h;
288
}
289
290
/* CDC transfer status */
291
if (address == 0xff8004)
292
{
293
s68k_poll_detect(1<<0x04);
294
return scd.regs[0x04>>1].byte.h;
295
}
296
297
/* GFX operation status */
298
if (address == 0xff8058)
299
{
300
s68k_poll_detect(1<<0x08);
301
return scd.regs[0x58>>1].byte.h;
302
}
303
304
/* CDC register data (controlled by BIOS, byte access only ?) */
305
if (address == 0xff8007)
306
{
307
unsigned int data = cdc_reg_r();
308
#ifdef LOG_CDC
309
error("CDC register %X read 0x%02X (%X)\n", scd.regs[0x04>>1].byte.l & 0x0F, data, s68k.pc);
310
#endif
311
return data;
312
}
313
314
/* LED status */
315
if (address == 0xff8000)
316
{
317
/* register $00 is reserved for MAIN-CPU, we use $06 instead */
318
return scd.regs[0x06>>1].byte.h;
319
}
320
321
/* RESET status */
322
if (address == 0xff8001)
323
{
324
/* always return 1 */
325
return 0x01;
326
}
327
328
/* Font data */
329
if ((address >= 0xff8050) && (address <= 0xff8056))
330
{
331
/* shifted 4-bit input (xxxx00) */
332
uint8 bits = (scd.regs[0x4e>>1].w >> (((address & 6) ^ 6) << 1)) << 2;
333
334
/* color code */
335
uint8 code = scd.regs[0x4c>>1].byte.l;
336
337
/* 16-bit font data (4 pixels = 16 bits) */
338
uint16 data = (code >> (bits & 4)) & 0x0f;
339
340
bits = bits >> 1;
341
data = data | (((code >> (bits & 4)) << 4) & 0xf0);
342
343
bits = bits >> 1;
344
data = data | (((code >> (bits & 4)) << 8) & 0xf00);
345
346
bits = bits >> 1;
347
data = data | (((code >> (bits & 4)) << 12) & 0xf000);
348
349
return (address & 1) ? (data & 0xff) : (data >> 8);
350
}
351
352
/* MAIN-CPU communication words */
353
if ((address & 0x1f0) == 0x10)
354
{
355
s68k_poll_detect(1 << (address & 0x1f));
356
}
357
358
/* default registers */
359
if (address & 1)
360
{
361
/* register LSB */
362
return scd.regs[(address >> 1) & 0xff].byte.l;
363
}
364
365
/* register MSB */
366
return scd.regs[(address >> 1) & 0xff].byte.h;
367
}
368
369
static unsigned int scd_read_word(unsigned int address)
370
{
371
/* PCM area (8K) is mirrored into $FF0000-$FF7FFF */
372
if (address < 0xff8000)
373
{
374
/* get /LDS only */
375
return pcm_read((address >> 1) & 0x1fff);
376
}
377
378
#ifdef LOG_SCD
379
error("[%d][%d]read word CD register %X (%X)\n", v_counter, s68k.cycles, address, s68k.pc);
380
#endif
381
382
/* Memory Mode */
383
if (address == 0xff8002)
384
{
385
s68k_poll_detect(1<<0x03);
386
return scd.regs[0x03>>1].w;
387
}
388
389
/* CDC host data (word access only ?) */
390
if (address == 0xff8008)
391
{
392
return cdc_host_r();
393
}
394
395
/* LED & RESET status */
396
if (address == 0xff8000)
397
{
398
/* register $00 is reserved for MAIN-CPU, we use $06 instead */
399
return scd.regs[0x06>>1].w;
400
}
401
402
/* Stopwatch counter (word access only ?) */
403
if (address == 0xff800c)
404
{
405
/* cycle-accurate counter value */
406
return (scd.regs[0x0c>>1].w + ((s68k.cycles - scd.stopwatch) / TIMERS_SCYCLES_RATIO)) & 0xfff;
407
}
408
409
/* Font data */
410
if ((address >= 0xff8050) && (address <= 0xff8056))
411
{
412
/* shifted 4-bit input (xxxx00) */
413
uint8 bits = (scd.regs[0x4e>>1].w >> (((address & 6) ^ 6) << 1)) << 2;
414
415
/* color code */
416
uint8 code = scd.regs[0x4c>>1].byte.l;
417
418
/* 16-bit font data (4 pixels = 16 bits) */
419
uint16 data = (code >> (bits & 4)) & 0x0f;
420
421
bits = bits >> 1;
422
data = data | (((code >> (bits & 4)) << 4) & 0xf0);
423
424
bits = bits >> 1;
425
data = data | (((code >> (bits & 4)) << 8) & 0xf00);
426
427
bits = bits >> 1;
428
data = data | (((code >> (bits & 4)) << 12) & 0xf000);
429
430
return data;
431
}
432
433
/* MAIN-CPU communication words */
434
if ((address & 0x1f0) == 0x10)
435
{
436
if (!m68k.stopped)
437
{
438
/* relative MAIN-CPU cycle counter */
439
unsigned int cycles = (s68k.cycles * MCYCLES_PER_LINE) / SCYCLES_PER_LINE;
440
441
/* sync MAIN-CPU with SUB-CPU (Mighty Morphin Power Rangers) */
442
m68k_run(cycles);
443
}
444
445
s68k_poll_detect(3 << (address & 0x1e));
446
}
447
448
/* default registers */
449
return scd.regs[(address >> 1) & 0xff].w;
450
}
451
452
INLINE void word_ram_switch(uint8 mode)
453
{
454
int i;
455
uint16 *ptr1 = (uint16 *)(scd.word_ram_2M);
456
uint16 *ptr2 = (uint16 *)(scd.word_ram[0]);
457
uint16 *ptr3 = (uint16 *)(scd.word_ram[1]);
458
459
if (mode & 0x04)
460
{
461
/* 2M -> 1M mode */
462
for (i=0; i<0x10000; i++)
463
{
464
*ptr2++=*ptr1++;
465
*ptr3++=*ptr1++;
466
}
467
}
468
else
469
{
470
/* 1M -> 2M mode */
471
for (i=0; i<0x10000; i++)
472
{
473
*ptr1++=*ptr2++;
474
*ptr1++=*ptr3++;
475
}
476
477
/* allow Word-RAM access from both CPU in 2M mode (fixes sync issues in Mortal Kombat) */
478
for (i=scd.cartridge.boot+0x20; i<scd.cartridge.boot+0x24; i++)
479
{
480
/* MAIN-CPU: $200000-$23FFFF is mapped to 256K Word-RAM */
481
m68k.memory_map[i].base = scd.word_ram_2M + ((i & 0x03) << 16);
482
m68k.memory_map[i].read8 = NULL;
483
m68k.memory_map[i].read16 = NULL;
484
m68k.memory_map[i].write8 = NULL;
485
m68k.memory_map[i].write16 = NULL;
486
zbank_memory_map[i].read = NULL;
487
zbank_memory_map[i].write = NULL;
488
}
489
490
for (i=0x08; i<0x0c; i++)
491
{
492
/* SUB-CPU: $080000-$0BFFFF is mapped to 256K Word-RAM */
493
s68k.memory_map[i].read8 = NULL;
494
s68k.memory_map[i].read16 = NULL;
495
s68k.memory_map[i].write8 = NULL;
496
s68k.memory_map[i].write16 = NULL;
497
}
498
499
for (i=0x0c; i<0x0e; i++)
500
{
501
/* SUB-CPU: $0C0000-$0DFFFF is unmapped */
502
s68k.memory_map[i].read8 = s68k_read_bus_8;
503
s68k.memory_map[i].read16 = s68k_read_bus_16;
504
s68k.memory_map[i].write8 = s68k_unused_8_w;
505
s68k.memory_map[i].write16 = s68k_unused_16_w;
506
}
507
}
508
}
509
510
static void scd_write_byte(unsigned int address, unsigned int data)
511
{
512
/* PCM area (8K) is mirrored into $FF0000-$FF7FFF */
513
if (address < 0xff8000)
514
{
515
/* get /LDS only */
516
if (address & 1)
517
{
518
pcm_write((address >> 1) & 0x1fff, data);
519
return;
520
}
521
522
s68k_unused_8_w(address, data);
523
return;
524
}
525
526
#ifdef LOG_SCD
527
error("[%d][%d]write byte CD register %X -> 0x%02x (%X)\n", v_counter, s68k.cycles, address, data, s68k.pc);
528
#endif
529
530
/* Gate-Array registers */
531
switch (address & 0x1ff)
532
{
533
case 0x00: /* LED status */
534
{
535
/* register $00 is reserved for MAIN-CPU, use $06 instead */
536
scd.regs[0x06 >> 1].byte.h = data;
537
return;
538
}
539
540
case 0x01: /* RESET status */
541
{
542
/* RESET bit cleared ? */
543
if (!(data & 0x01))
544
{
545
/* reset CD hardware */
546
scd_reset(0);
547
}
548
return;
549
}
550
551
case 0x03: /* Memory Mode */
552
{
553
s68k_poll_sync(1<<0x03);
554
555
/* detect MODE & RET bits modifications */
556
if ((data ^ scd.regs[0x03 >> 1].byte.l) & 0x05)
557
{
558
int i;
559
560
/* MODE bit */
561
if (data & 0x04)
562
{
563
/* 2M->1M mode switch */
564
if (!(scd.regs[0x03 >> 1].byte.l & 0x04))
565
{
566
/* re-arrange Word-RAM banks */
567
word_ram_switch(0x04);
568
}
569
570
/* RET bit in 1M Mode */
571
if (data & 0x01)
572
{
573
/* Word-RAM 1 assigned to MAIN-CPU */
574
for (i=scd.cartridge.boot+0x20; i<scd.cartridge.boot+0x22; i++)
575
{
576
/* Word-RAM 1 data mapped at $200000-$21FFFF */
577
m68k.memory_map[i].base = scd.word_ram[1] + ((i & 0x01) << 16);
578
}
579
580
for (i=scd.cartridge.boot+0x22; i<scd.cartridge.boot+0x24; i++)
581
{
582
/* VRAM cell image mapped at $220000-$23FFFF */
583
m68k.memory_map[i].read8 = cell_ram_1_read8;
584
m68k.memory_map[i].read16 = cell_ram_1_read16;
585
m68k.memory_map[i].write8 = cell_ram_1_write8;
586
m68k.memory_map[i].write16 = cell_ram_1_write16;
587
zbank_memory_map[i].read = cell_ram_1_read8;
588
zbank_memory_map[i].write = cell_ram_1_write8;
589
}
590
591
/* Word-RAM 0 assigned to SUB-CPU */
592
for (i=0x08; i<0x0c; i++)
593
{
594
/* DOT image mapped at $080000-$0BFFFF */
595
s68k.memory_map[i].read8 = dot_ram_0_read8;
596
s68k.memory_map[i].read16 = dot_ram_0_read16;
597
s68k.memory_map[i].write8 = dot_ram_0_write8;
598
s68k.memory_map[i].write16 = dot_ram_0_write16;
599
}
600
601
for (i=0x0c; i<0x0e; i++)
602
{
603
/* Word-RAM 0 data mapped at $0C0000-$0DFFFF */
604
s68k.memory_map[i].base = scd.word_ram[0] + ((i & 0x01) << 16);
605
s68k.memory_map[i].read8 = NULL;
606
s68k.memory_map[i].read16 = NULL;
607
s68k.memory_map[i].write8 = NULL;
608
s68k.memory_map[i].write16 = NULL;
609
}
610
611
/* writing 1 to RET bit in 1M mode returns Word-RAM to MAIN-CPU in 2M mode */
612
scd.dmna = 0;
613
}
614
else
615
{
616
/* Word-RAM 0 assigned to MAIN-CPU */
617
for (i=scd.cartridge.boot+0x20; i<scd.cartridge.boot+0x22; i++)
618
{
619
/* Word-RAM 0 data mapped at $200000-$21FFFF */
620
m68k.memory_map[i].base = scd.word_ram[0] + ((i & 0x01) << 16);
621
}
622
623
for (i=scd.cartridge.boot+0x22; i<scd.cartridge.boot+0x24; i++)
624
{
625
/* VRAM cell image mapped at $220000-$23FFFF */
626
m68k.memory_map[i].read8 = cell_ram_0_read8;
627
m68k.memory_map[i].read16 = cell_ram_0_read16;
628
m68k.memory_map[i].write8 = cell_ram_0_write8;
629
m68k.memory_map[i].write16 = cell_ram_0_write16;
630
zbank_memory_map[i].read = cell_ram_0_read8;
631
zbank_memory_map[i].write = cell_ram_0_write8;
632
}
633
634
/* Word-RAM 1 assigned to SUB-CPU */
635
for (i=0x08; i<0x0c; i++)
636
{
637
/* DOT image mapped at $080000-$0BFFFF */
638
s68k.memory_map[i].read8 = dot_ram_1_read8;
639
s68k.memory_map[i].read16 = dot_ram_1_read16;
640
s68k.memory_map[i].write8 = dot_ram_1_write8;
641
s68k.memory_map[i].write16 = dot_ram_1_write16;
642
}
643
644
for (i=0x0c; i<0x0e; i++)
645
{
646
/* Word-RAM 1 data mapped at $0C0000-$0DFFFF */
647
s68k.memory_map[i].base = scd.word_ram[1] + ((i & 0x01) << 16);
648
s68k.memory_map[i].read8 = NULL;
649
s68k.memory_map[i].read16 = NULL;
650
s68k.memory_map[i].write8 = NULL;
651
s68k.memory_map[i].write16 = NULL;
652
}
653
}
654
655
/* clear DMNA bit (swap completed) */
656
scd.regs[0x02 >> 1].byte.l = (scd.regs[0x02 >> 1].byte.l & ~0x1f) | (data & 0x1d);
657
return;
658
}
659
else
660
{
661
/* 1M->2M mode switch */
662
if (scd.regs[0x02 >> 1].byte.l & 0x04)
663
{
664
/* re-arrange Word-RAM banks */
665
word_ram_switch(0x00);
666
667
/* RET bit set during 1M mode ? */
668
data |= ~scd.dmna & 0x01;
669
670
/* check if RET bit is cleared */
671
if (!(data & 0x01))
672
{
673
/* set DMNA bit */
674
data |= 0x02;
675
676
/* mask BK0-1 bits (MAIN-CPU side only) */
677
scd.regs[0x02 >> 1].byte.l = (scd.regs[0x02 >> 1].byte.l & ~0x1f) | (data & 0x1f);
678
return;
679
}
680
}
681
682
/* RET bit set in 2M mode */
683
if (data & 0x01)
684
{
685
/* Word-RAM is returned to MAIN-CPU */
686
scd.dmna = 0;
687
688
/* clear DMNA bit */
689
scd.regs[0x02 >> 1].byte.l = (scd.regs[0x02 >> 1].byte.l & ~0x1f) | (data & 0x1d);
690
return;
691
}
692
}
693
}
694
695
/* update PM0-1 & MODE bits */
696
scd.regs[0x02 >> 1].byte.l = (scd.regs[0x02 >> 1].byte.l & ~0x1c) | (data & 0x1c);
697
return;
698
}
699
700
case 0x07: /* CDC register write */
701
{
702
cdc_reg_w(data);
703
return;
704
}
705
706
case 0x0e: /* SUB-CPU communication flags */
707
case 0x0f: /* !LWR is ignored (Space Ace, Dragon's Lair) */
708
{
709
s68k_poll_sync(1<<0x0f);
710
scd.regs[0x0f>>1].byte.l = data;
711
return;
712
}
713
714
case 0x31: /* Timer */
715
{
716
/* reload timer (one timer clock = 384 CPU cycles) */
717
scd.timer = data * TIMERS_SCYCLES_RATIO;
718
719
/* only non-zero data starts timer, writing zero stops it */
720
if (data)
721
{
722
/* adjust regarding current CPU cycle */
723
scd.timer += (s68k.cycles - scd.cycles);
724
}
725
726
scd.regs[0x30>>1].byte.l = data;
727
return;
728
}
729
730
case 0x33: /* Interrupts */
731
{
732
/* update register value before updating interrupts */
733
scd.regs[0x32>>1].byte.l = data;
734
735
/* update IEN2 flag */
736
scd.regs[0x00].byte.h = (scd.regs[0x00].byte.h & 0x7f) | ((data & 0x04) << 5);
737
738
/* clear level 1 interrupt if disabled ("Batman Returns" option menu) */
739
scd.pending &= ~(data & 0x02);
740
741
/* update IRQ level */
742
s68k_update_irq((scd.pending & data) >> 1);
743
return;
744
}
745
746
case 0x37: /* CDD control (controlled by BIOS, byte access only ?) */
747
{
748
/* CDD communication started ? */
749
if ((data & 0x04) && !(scd.regs[0x37>>1].byte.l & 0x04))
750
{
751
/* reset CDD cycle counter */
752
cdd.cycles = (scd.cycles - s68k.cycles) * 3;
753
754
/* set pending interrupt level 4 */
755
scd.pending |= (1 << 4);
756
757
/* update IRQ level if interrupt is enabled */
758
if (scd.regs[0x32>>1].byte.l & 0x10)
759
{
760
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
761
}
762
}
763
764
scd.regs[0x37>>1].byte.l = data;
765
return;
766
}
767
768
default:
769
{
770
/* SUB-CPU communication words */
771
if ((address & 0xf0) == 0x20)
772
{
773
s68k_poll_sync(1 << ((address - 0x10) & 0x1f));
774
}
775
776
/* default registers */
777
if (address & 1)
778
{
779
/* register LSB */
780
scd.regs[(address >> 1) & 0xff].byte.l = data;
781
return;
782
}
783
784
/* register MSB */
785
scd.regs[(address >> 1) & 0xff].byte.h = data;
786
return;
787
}
788
}
789
}
790
791
static void scd_write_word(unsigned int address, unsigned int data)
792
{
793
/* PCM area (8K) is mirrored into $FF0000-$FF7FFF */
794
if (address < 0xff8000)
795
{
796
/* get /LDS only */
797
pcm_write((address >> 1) & 0x1fff, data);
798
return;
799
}
800
801
#ifdef LOG_SCD
802
error("[%d][%d]write word CD register %X -> 0x%04x (%X)\n", v_counter, s68k.cycles, address, data, s68k.pc);
803
#endif
804
805
/* Gate-Array registers */
806
switch (address & 0x1fe)
807
{
808
case 0x00: /* LED status & RESET */
809
{
810
/* only update LED status (register $00 is reserved for MAIN-CPU, use $06 instead) */
811
scd.regs[0x06>>1].byte.h = data >> 8;
812
813
/* RESET bit cleared ? */
814
if (!(data & 0x01))
815
{
816
/* reset CD hardware */
817
scd_reset(0);
818
}
819
return;
820
}
821
822
case 0x02: /* Memory Mode */
823
{
824
s68k_poll_sync(1<<0x03);
825
826
/* detect MODE & RET bits modifications */
827
if ((data ^ scd.regs[0x03>>1].byte.l) & 0x05)
828
{
829
int i;
830
831
/* MODE bit */
832
if (data & 0x04)
833
{
834
/* 2M->1M mode switch */
835
if (!(scd.regs[0x03 >> 1].byte.l & 0x04))
836
{
837
/* re-arrange Word-RAM banks */
838
word_ram_switch(0x04);
839
}
840
841
/* RET bit in 1M Mode */
842
if (data & 0x01)
843
{
844
/* Word-RAM 1 assigned to MAIN-CPU */
845
for (i=scd.cartridge.boot+0x20; i<scd.cartridge.boot+0x22; i++)
846
{
847
/* Word-RAM 1 data mapped at $200000-$21FFFF */
848
m68k.memory_map[i].base = scd.word_ram[1] + ((i & 0x01) << 16);
849
}
850
851
for (i=scd.cartridge.boot+0x22; i<scd.cartridge.boot+0x24; i++)
852
{
853
/* VRAM cell image mapped at $220000-$23FFFF */
854
m68k.memory_map[i].read8 = cell_ram_1_read8;
855
m68k.memory_map[i].read16 = cell_ram_1_read16;
856
m68k.memory_map[i].write8 = cell_ram_1_write8;
857
m68k.memory_map[i].write16 = cell_ram_1_write16;
858
zbank_memory_map[i].read = cell_ram_1_read8;
859
zbank_memory_map[i].write = cell_ram_1_write8;
860
}
861
862
/* Word-RAM 0 assigned to SUB-CPU */
863
for (i=0x08; i<0x0c; i++)
864
{
865
/* DOT image mapped at $080000-$0BFFFF */
866
s68k.memory_map[i].read8 = dot_ram_0_read8;
867
s68k.memory_map[i].read16 = dot_ram_0_read16;
868
s68k.memory_map[i].write8 = dot_ram_0_write8;
869
s68k.memory_map[i].write16 = dot_ram_0_write16;
870
}
871
872
for (i=0x0c; i<0x0e; i++)
873
{
874
/* Word-RAM 0 data mapped at $0C0000-$0DFFFF */
875
s68k.memory_map[i].base = scd.word_ram[0] + ((i & 0x01) << 16);
876
s68k.memory_map[i].read8 = NULL;
877
s68k.memory_map[i].read16 = NULL;
878
s68k.memory_map[i].write8 = NULL;
879
s68k.memory_map[i].write16 = NULL;
880
}
881
882
/* writing 1 to RET bit in 1M mode returns Word-RAM to MAIN-CPU in 2M mode */
883
scd.dmna = 0;
884
}
885
else
886
{
887
/* Word-RAM 0 assigned to MAIN-CPU */
888
for (i=scd.cartridge.boot+0x20; i<scd.cartridge.boot+0x22; i++)
889
{
890
/* Word-RAM 0 data mapped at $200000-$21FFFF */
891
m68k.memory_map[i].base = scd.word_ram[0] + ((i & 0x01) << 16);
892
}
893
894
for (i=scd.cartridge.boot+0x22; i<scd.cartridge.boot+0x24; i++)
895
{
896
/* VRAM cell image mapped at $220000-$23FFFF */
897
m68k.memory_map[i].read8 = cell_ram_0_read8;
898
m68k.memory_map[i].read16 = cell_ram_0_read16;
899
m68k.memory_map[i].write8 = cell_ram_0_write8;
900
m68k.memory_map[i].write16 = cell_ram_0_write16;
901
zbank_memory_map[i].read = cell_ram_0_read8;
902
zbank_memory_map[i].write = cell_ram_0_write8;
903
}
904
905
/* Word-RAM 1 assigned to SUB-CPU */
906
for (i=0x08; i<0x0c; i++)
907
{
908
/* DOT image mapped at $080000-$0BFFFF */
909
s68k.memory_map[i].read8 = dot_ram_1_read8;
910
s68k.memory_map[i].read16 = dot_ram_1_read16;
911
s68k.memory_map[i].write8 = dot_ram_1_write8;
912
s68k.memory_map[i].write16 = dot_ram_1_write16;
913
}
914
915
for (i=0x0c; i<0x0e; i++)
916
{
917
/* Word-RAM 1 data mapped at $0C0000-$0DFFFF */
918
s68k.memory_map[i].base = scd.word_ram[1] + ((i & 0x01) << 16);
919
s68k.memory_map[i].read8 = NULL;
920
s68k.memory_map[i].read16 = NULL;
921
s68k.memory_map[i].write8 = NULL;
922
s68k.memory_map[i].write16 = NULL;
923
}
924
}
925
926
/* clear DMNA bit (swap completed) */
927
scd.regs[0x03>>1].byte.l = (scd.regs[0x03>>1].byte.l & ~0x1f) | (data & 0x1d);
928
return;
929
}
930
else
931
{
932
/* 1M->2M mode switch */
933
if (scd.regs[0x03>>1].byte.l & 0x04)
934
{
935
/* re-arrange Word-RAM banks */
936
word_ram_switch(0x00);
937
938
/* RET bit set during 1M mode ? */
939
data |= ~scd.dmna & 0x01;
940
941
/* check if RET bit is cleared */
942
if (!(data & 0x01))
943
{
944
/* set DMNA bit */
945
data |= 0x02;
946
947
/* mask BK0-1 bits (MAIN-CPU side only) */
948
scd.regs[0x03>>1].byte.l = (scd.regs[0x03>>1].byte.l & ~0x1f) | (data & 0x1f);
949
return;
950
}
951
}
952
953
/* RET bit set in 2M mode */
954
if (data & 0x01)
955
{
956
/* Word-RAM is returned to MAIN-CPU */
957
scd.dmna = 0;
958
959
/* clear DMNA bit */
960
scd.regs[0x03>>1].byte.l = (scd.regs[0x03>>1].byte.l & ~0x1f) | (data & 0x1d);
961
return;
962
}
963
}
964
}
965
966
/* update PM0-1 & MODE bits */
967
scd.regs[0x03>>1].byte.l = (scd.regs[0x03>>1].byte.l & ~0x1c) | (data & 0x1c);
968
return;
969
}
970
971
case 0x06: /* CDC register write */
972
{
973
cdc_reg_w(data);
974
return;
975
}
976
977
case 0x0c: /* Stopwatch (word access only) */
978
{
979
/* synchronize the counter with SUB-CPU */
980
int ticks = (s68k.cycles - scd.stopwatch) / TIMERS_SCYCLES_RATIO;
981
scd.stopwatch += (ticks * TIMERS_SCYCLES_RATIO);
982
983
/* any writes clear the counter */
984
scd.regs[0x0c>>1].w = 0;
985
return;
986
}
987
988
case 0x0e: /* CPU Communication flags */
989
{
990
s68k_poll_sync(1<<0x0f);
991
992
/* D8-D15 ignored -> only SUB-CPU flags are updated */
993
scd.regs[0x0f>>1].byte.l = data & 0xff;
994
return;
995
}
996
997
case 0x30: /* Timer */
998
{
999
/* LSB only */
1000
data &= 0xff;
1001
1002
/* reload timer (one timer clock = 384 CPU cycles) */
1003
scd.timer = data * TIMERS_SCYCLES_RATIO;
1004
1005
/* only non-zero data starts timer, writing zero stops it */
1006
if (data)
1007
{
1008
/* adjust regarding current CPU cycle */
1009
scd.timer += (s68k.cycles - scd.cycles);
1010
}
1011
1012
scd.regs[0x30>>1].byte.l = data;
1013
return;
1014
}
1015
1016
case 0x32: /* Interrupts */
1017
{
1018
/* LSB only */
1019
data &= 0xff;
1020
1021
/* update register value before updating interrupts */
1022
scd.regs[0x32>>1].byte.l = data;
1023
1024
/* update IEN2 flag */
1025
scd.regs[0x00].byte.h = (scd.regs[0x00].byte.h & 0x7f) | ((data & 0x04) << 5);
1026
1027
/* clear pending level 1 interrupt if disabled ("Batman Returns" option menu) */
1028
scd.pending &= ~(data & 0x02);
1029
1030
/* update IRQ level */
1031
s68k_update_irq((scd.pending & data) >> 1);
1032
return;
1033
}
1034
1035
case 0x4a: /* CDD command 9 (controlled by BIOS, word access only ?) */
1036
{
1037
scd.regs[0x4a>>1].w = 0;
1038
cdd_process();
1039
#ifdef LOG_CDD
1040
error("CDD command: %02x %02x %02x %02x %02x %02x %02x %02x\n",scd.regs[0x42>>1].byte.h, scd.regs[0x42>>1].byte.l, scd.regs[0x44>>1].byte.h, scd.regs[0x44>>1].byte.l, scd.regs[0x46>>1].byte.h, scd.regs[0x46>>1].byte.l, scd.regs[0x48>>1].byte.h, scd.regs[0x48>>1].byte.l);
1041
error("CDD status: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",scd.regs[0x38>>1].byte.h, scd.regs[0x38>>1].byte.l, scd.regs[0x3a>>1].byte.h, scd.regs[0x3a>>1].byte.l, scd.regs[0x3c>>1].byte.h, scd.regs[0x3c>>1].byte.l, scd.regs[0x3e>>1].byte.h, scd.regs[0x3e>>1].byte.l, scd.regs[0x40>>1].byte.h, scd.regs[0x40>>1].byte.l);
1042
#endif
1043
break;
1044
}
1045
1046
case 0x66: /* Trace vector base address */
1047
{
1048
scd.regs[0x66>>1].w = data;
1049
1050
/* start GFX operation */
1051
gfx_start(data, s68k.cycles);
1052
return;
1053
}
1054
1055
default:
1056
{
1057
/* SUB-CPU communication words */
1058
if ((address & 0xf0) == 0x20)
1059
{
1060
s68k_poll_sync(3 << ((address - 0x10) & 0x1e));
1061
}
1062
1063
/* default registers */
1064
scd.regs[(address >> 1) & 0xff].w = data;
1065
return;
1066
}
1067
}
1068
}
1069
1070
1071
void scd_init(void)
1072
{
1073
int i;
1074
1075
/****************************************************************/
1076
/* MAIN-CPU low memory map ($000000-$7FFFFF) */
1077
/****************************************************************/
1078
1079
/* 0x00: boot from CD (Mode 2), 0x40: boot from cartridge (Mode 1) */
1080
uint8 base = scd.cartridge.boot;
1081
1082
/* $400000-$7FFFFF (resp. $000000-$3FFFFF): cartridge area (4MB) */
1083
cd_cart_init();
1084
1085
/* $000000-$1FFFFF (resp. $400000-$5FFFFF): CD memory area */
1086
for (i=base; i<base+0x20; i++)
1087
{
1088
if (i & 2)
1089
{
1090
/* $020000-$03FFFF (resp. $420000-$43FFFF): PRG-RAM (first 128KB bank, mirrored each 256KB) */
1091
m68k.memory_map[i].base = scd.prg_ram + ((i & 1) << 16);
1092
m68k.memory_map[i].read8 = NULL;
1093
m68k.memory_map[i].read16 = NULL;
1094
m68k.memory_map[i].write8 = NULL;
1095
m68k.memory_map[i].write16 = NULL;
1096
zbank_memory_map[i].read = NULL;
1097
zbank_memory_map[i].write = NULL;
1098
1099
}
1100
else
1101
{
1102
/* $000000-$01FFFF (resp. $400000-$41FFFF): internal ROM (128KB, mirrored each 256KB) */
1103
/* NB: Flux expects it to be mapped at $440000-$45FFFF */
1104
m68k.memory_map[i].base = scd.bootrom + ((i & 1) << 16);
1105
m68k.memory_map[i].read8 = NULL;
1106
m68k.memory_map[i].read16 = NULL;
1107
m68k.memory_map[i].write8 = m68k_unused_8_w;
1108
m68k.memory_map[i].write16 = m68k_unused_16_w;
1109
zbank_memory_map[i].read = NULL;
1110
zbank_memory_map[i].write = zbank_unused_w;
1111
}
1112
}
1113
1114
/* $200000-$3FFFFF (resp. $600000-$7FFFFF): Word-RAM in 2M mode (256KB mirrored) */
1115
for (i=base+0x20; i<base+0x40; i++)
1116
{
1117
m68k.memory_map[i].base = scd.word_ram_2M + ((i & 3) << 16);
1118
m68k.memory_map[i].read8 = NULL;
1119
m68k.memory_map[i].read16 = NULL;
1120
m68k.memory_map[i].write8 = NULL;
1121
m68k.memory_map[i].write16 = NULL;
1122
zbank_memory_map[i].read = NULL;
1123
zbank_memory_map[i].write = NULL;
1124
}
1125
1126
/****************************************************************/
1127
/* SUB-CPU memory map ($000000-$FFFFFF) */
1128
/****************************************************************/
1129
1130
/* $000000-$07FFFF: PRG-RAM (512KB) */
1131
for (i=0x00; i<0x08; i++)
1132
{
1133
s68k.memory_map[i].base = scd.prg_ram + (i << 16);
1134
s68k.memory_map[i].read8 = NULL;
1135
s68k.memory_map[i].read16 = NULL;
1136
1137
/* first 128KB is write-protected */
1138
s68k.memory_map[i].write8 = (i < 0x02) ? prg_ram_write_byte : NULL;
1139
s68k.memory_map[i].write16 = (i < 0x02) ? prg_ram_write_word : NULL;
1140
}
1141
1142
/* $080000-$0BFFFF: Word-RAM in 2M mode (256KB)*/
1143
for (i=0x08; i<0x0c; i++)
1144
{
1145
s68k.memory_map[i].base = scd.word_ram_2M + ((i & 3) << 16);
1146
s68k.memory_map[i].read8 = NULL;
1147
s68k.memory_map[i].read16 = NULL;
1148
s68k.memory_map[i].write8 = NULL;
1149
s68k.memory_map[i].write16 = NULL;
1150
}
1151
1152
/* $0C0000-$FD0000: Unused area (Word-RAM mirrored ?) */
1153
for (i=0x0c; i<0xfd; i++)
1154
{
1155
s68k.memory_map[i].base = scd.word_ram_2M + ((i & 3) << 16);
1156
s68k.memory_map[i].read8 = s68k_read_bus_8;
1157
s68k.memory_map[i].read16 = s68k_read_bus_16;
1158
s68k.memory_map[i].write8 = s68k_unused_8_w;
1159
s68k.memory_map[i].write16 = s68k_unused_16_w;
1160
}
1161
1162
/* $FD0000-$FF0000 (odd address only): 8KB backup RAM, mirrored(Wonder Mega / X'Eye BIOS access it at $FD0000-$FD1FFF) */
1163
for (i=0xfd; i<0xff; i++)
1164
{
1165
s68k.memory_map[i].base = NULL;
1166
s68k.memory_map[i].read8 = bram_read_byte;
1167
s68k.memory_map[i].read16 = bram_read_word;
1168
s68k.memory_map[i].write8 = bram_write_byte;
1169
s68k.memory_map[i].write16 = bram_write_word;
1170
}
1171
1172
/* $FF0000-$FFFFFF: PCM hardware & SUB-CPU registers */
1173
s68k.memory_map[0xff].base = NULL;
1174
s68k.memory_map[0xff].read8 = scd_read_byte;
1175
s68k.memory_map[0xff].read16 = scd_read_word;
1176
s68k.memory_map[0xff].write8 = scd_write_byte;
1177
s68k.memory_map[0xff].write16 = scd_write_word;
1178
1179
/* Initialize CD hardware */
1180
cdc_init();
1181
gfx_init();
1182
1183
/* Clear RAM */
1184
memset(scd.prg_ram, 0x00, sizeof(scd.prg_ram));
1185
memset(scd.word_ram, 0x00, sizeof(scd.word_ram));
1186
memset(scd.word_ram_2M, 0x00, sizeof(scd.word_ram_2M));
1187
memset(scd.bram, 0x00, sizeof(scd.bram));
1188
}
1189
1190
void scd_reset(int hard)
1191
{
1192
/* TODO: figure what exactly is resetted when RESET bit is cleared by SUB-CPU */
1193
if (hard)
1194
{
1195
int i;
1196
1197
/* Clear all ASIC registers by default */
1198
memset(scd.regs, 0, sizeof(scd.regs));
1199
1200
/* Clear pending DMNA write status */
1201
scd.dmna = 0;
1202
1203
/* H-INT default vector */
1204
*(uint16 *)(m68k.memory_map[scd.cartridge.boot].base + 0x70) = 0x00FF;
1205
*(uint16 *)(m68k.memory_map[scd.cartridge.boot].base + 0x72) = 0xFFFF;
1206
1207
/* Power ON initial values (MAIN-CPU side) */
1208
scd.regs[0x00>>1].w = 0x0002;
1209
scd.regs[0x02>>1].w = 0x0001;
1210
1211
/* 2M mode */
1212
word_ram_switch(0);
1213
1214
/* reset PRG-RAM banking on MAIN-CPU side */
1215
for (i=scd.cartridge.boot+0x02; i<scd.cartridge.boot+0x20; i+=4)
1216
{
1217
/* MAIN-CPU: $020000-$03FFFF (resp. $420000-$43FFFF) mapped to first 128KB PRG-RAM bank (mirrored each 256KB) */
1218
m68k.memory_map[i].base = scd.prg_ram;
1219
m68k.memory_map[i+1].base = scd.prg_ram + 0x10000;
1220
}
1221
1222
/* reset & halt SUB-CPU */
1223
s68k.cycles = 0;
1224
s68k_pulse_reset();
1225
s68k_pulse_halt();
1226
}
1227
else
1228
{
1229
/* Clear only SUB-CPU side registers */
1230
memset(&scd.regs[0x04>>1], 0, sizeof(scd.regs) - 4);
1231
}
1232
1233
/* SUB-CPU side default values */
1234
scd.regs[0x08>>1].w = 0xffff;
1235
scd.regs[0x0a>>1].w = 0xffff;
1236
scd.regs[0x36>>1].w = 0x0100;
1237
scd.regs[0x40>>1].w = 0x000f;
1238
scd.regs[0x42>>1].w = 0xffff;
1239
scd.regs[0x44>>1].w = 0xffff;
1240
scd.regs[0x46>>1].w = 0xffff;
1241
scd.regs[0x48>>1].w = 0xffff;
1242
scd.regs[0x4a>>1].w = 0xffff;
1243
1244
/* RESET register always return 1 (register $06 is unused by both sides, it is used for SUB-CPU first register) */
1245
scd.regs[0x06>>1].byte.l = 0x01;
1246
1247
/* Reset Timer & Stopwatch counters */
1248
scd.timer = 0;
1249
scd.stopwatch = 0;
1250
1251
/* Reset frame cycle counter */
1252
scd.cycles = 0;
1253
1254
/* Clear pending interrupts */
1255
scd.pending = 0;
1256
1257
/* Clear CPU polling detection */
1258
memset(&m68k.poll, 0, sizeof(m68k.poll));
1259
memset(&s68k.poll, 0, sizeof(s68k.poll));
1260
1261
/* Reset CD hardware */
1262
cdd_reset();
1263
cdc_reset();
1264
gfx_reset();
1265
pcm_reset();
1266
}
1267
1268
void scd_update(unsigned int cycles)
1269
{
1270
/* update CDC DMA transfer */
1271
if (cdc.dma_w)
1272
{
1273
cdc_dma_update();
1274
}
1275
1276
/* run both CPU in sync until end of line */
1277
do
1278
{
1279
m68k_run(cycles);
1280
s68k_run(scd.cycles + SCYCLES_PER_LINE);
1281
}
1282
while ((m68k.cycles < cycles) || (s68k.cycles < (scd.cycles + SCYCLES_PER_LINE)));
1283
1284
/* increment CD hardware cycle counter */
1285
scd.cycles += SCYCLES_PER_LINE;
1286
1287
/* CDD processing at 75Hz (one clock = 12500000/75 = 500000/3 CPU clocks) */
1288
cdd.cycles += (SCYCLES_PER_LINE * 3);
1289
if (cdd.cycles >= (500000 * 4))
1290
{
1291
/* reload CDD cycle counter */
1292
cdd.cycles -= (500000 * 4);
1293
1294
/* update CDD sector */
1295
cdd_update();
1296
1297
/* check if a new CDD command has been processed */
1298
if (!(scd.regs[0x4a>>1].byte.l & 0xf0))
1299
{
1300
/* reset CDD command wait flag */
1301
scd.regs[0x4a>>1].byte.l = 0xf0;
1302
1303
/* pending level 4 interrupt */
1304
scd.pending |= (1 << 4);
1305
1306
/* level 4 interrupt enabled */
1307
if (scd.regs[0x32>>1].byte.l & 0x10)
1308
{
1309
/* update IRQ level */
1310
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
1311
}
1312
}
1313
}
1314
1315
/* Timer */
1316
if (scd.timer)
1317
{
1318
/* decrement timer */
1319
scd.timer -= SCYCLES_PER_LINE;
1320
if (scd.timer <= 0)
1321
{
1322
/* reload timer (one timer clock = 384 CPU cycles) */
1323
scd.timer += (scd.regs[0x30>>1].byte.l * TIMERS_SCYCLES_RATIO);
1324
1325
/* level 3 interrupt enabled ? */
1326
if (scd.regs[0x32>>1].byte.l & 0x08)
1327
{
1328
/* trigger level 3 interrupt */
1329
scd.pending |= (1 << 3);
1330
1331
/* update IRQ level */
1332
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
1333
}
1334
}
1335
}
1336
1337
/* GFX processing */
1338
if (scd.regs[0x58>>1].byte.h & 0x80)
1339
{
1340
/* update graphics operation if running */
1341
gfx_update(scd.cycles);
1342
}
1343
}
1344
1345
void scd_end_frame(unsigned int cycles)
1346
{
1347
/* run Stopwatch until end of frame */
1348
int ticks = (cycles - scd.stopwatch) / TIMERS_SCYCLES_RATIO;
1349
scd.regs[0x0c>>1].w = (scd.regs[0x0c>>1].w + ticks) & 0xfff;
1350
1351
/* adjust Stopwatch counter for next frame (can be negative) */
1352
scd.stopwatch += (ticks * TIMERS_SCYCLES_RATIO) - cycles;
1353
1354
/* adjust SUB-CPU & GPU cycle counters for next frame */
1355
s68k.cycles -= cycles;
1356
gfx.cycles -= cycles;
1357
1358
/* reset CPU registers polling */
1359
m68k.poll.cycle = 0;
1360
s68k.poll.cycle = 0;
1361
}
1362
1363
int scd_context_save(uint8 *state)
1364
{
1365
uint16 tmp16;
1366
uint32 tmp32;
1367
int bufferptr = 0;
1368
1369
/* internal harware */
1370
save_param(scd.regs, sizeof(scd.regs));
1371
save_param(&scd.cycles, sizeof(scd.cycles));
1372
save_param(&scd.timer, sizeof(scd.timer));
1373
save_param(&scd.pending, sizeof(scd.pending));
1374
save_param(&scd.dmna, sizeof(scd.dmna));
1375
1376
/* GFX processor */
1377
bufferptr += gfx_context_save(&state[bufferptr]);
1378
1379
/* CD Data controller */
1380
bufferptr += cdc_context_save(&state[bufferptr]);
1381
1382
/* CD Drive processor */
1383
bufferptr += cdd_context_save(&state[bufferptr]);
1384
1385
/* PCM chip */
1386
bufferptr += pcm_context_save(&state[bufferptr]);
1387
1388
/* PRG-RAM */
1389
save_param(scd.prg_ram, sizeof(scd.prg_ram));
1390
1391
/* Word-RAM */
1392
if (scd.regs[0x03>>1].byte.l & 0x04)
1393
{
1394
/* 1M mode */
1395
save_param(scd.word_ram, sizeof(scd.word_ram));
1396
}
1397
else
1398
{
1399
/* 2M mode */
1400
save_param(scd.word_ram_2M, sizeof(scd.word_ram_2M));
1401
}
1402
1403
/* MAIN-CPU & SUB-CPU polling */
1404
save_param(&m68k.poll, sizeof(m68k.poll));
1405
save_param(&s68k.poll, sizeof(s68k.poll));
1406
1407
/* H-INT default vector */
1408
tmp16 = *(uint16 *)(m68k.memory_map[scd.cartridge.boot].base + 0x72);
1409
save_param(&tmp16, 2);
1410
1411
/* SUB-CPU internal state */
1412
save_param(&s68k.cycles, sizeof(s68k.cycles));
1413
save_param(&s68k.int_level, sizeof(s68k.int_level));
1414
save_param(&s68k.stopped, sizeof(s68k.stopped));
1415
1416
/* SUB-CPU registers */
1417
tmp32 = s68k_get_reg(M68K_REG_D0); save_param(&tmp32, 4);
1418
tmp32 = s68k_get_reg(M68K_REG_D1); save_param(&tmp32, 4);
1419
tmp32 = s68k_get_reg(M68K_REG_D2); save_param(&tmp32, 4);
1420
tmp32 = s68k_get_reg(M68K_REG_D3); save_param(&tmp32, 4);
1421
tmp32 = s68k_get_reg(M68K_REG_D4); save_param(&tmp32, 4);
1422
tmp32 = s68k_get_reg(M68K_REG_D5); save_param(&tmp32, 4);
1423
tmp32 = s68k_get_reg(M68K_REG_D6); save_param(&tmp32, 4);
1424
tmp32 = s68k_get_reg(M68K_REG_D7); save_param(&tmp32, 4);
1425
tmp32 = s68k_get_reg(M68K_REG_A0); save_param(&tmp32, 4);
1426
tmp32 = s68k_get_reg(M68K_REG_A1); save_param(&tmp32, 4);
1427
tmp32 = s68k_get_reg(M68K_REG_A2); save_param(&tmp32, 4);
1428
tmp32 = s68k_get_reg(M68K_REG_A3); save_param(&tmp32, 4);
1429
tmp32 = s68k_get_reg(M68K_REG_A4); save_param(&tmp32, 4);
1430
tmp32 = s68k_get_reg(M68K_REG_A5); save_param(&tmp32, 4);
1431
tmp32 = s68k_get_reg(M68K_REG_A6); save_param(&tmp32, 4);
1432
tmp32 = s68k_get_reg(M68K_REG_A7); save_param(&tmp32, 4);
1433
tmp32 = s68k_get_reg(M68K_REG_PC); save_param(&tmp32, 4);
1434
tmp16 = s68k_get_reg(M68K_REG_SR); save_param(&tmp16, 2);
1435
tmp32 = s68k_get_reg(M68K_REG_USP); save_param(&tmp32, 4);
1436
tmp32 = s68k_get_reg(M68K_REG_ISP); save_param(&tmp32, 4);
1437
1438
/* bootable MD cartridge */
1439
if (scd.cartridge.boot)
1440
{
1441
bufferptr += md_cart_context_save(&state[bufferptr]);
1442
}
1443
1444
save_param(scd.bram, 0x2000);
1445
// we don't save scd.cartridge.id separately, so it must be non-changing!
1446
if (scd.cartridge.id)
1447
save_param(scd.cartridge.area, scd.cartridge.mask + 1);
1448
1449
return bufferptr;
1450
}
1451
1452
int scd_context_load(uint8 *state)
1453
{
1454
int i;
1455
uint16 tmp16;
1456
uint32 tmp32;
1457
int bufferptr = 0;
1458
1459
/* internal harware */
1460
load_param(scd.regs, sizeof(scd.regs));
1461
load_param(&scd.cycles, sizeof(scd.cycles));
1462
load_param(&scd.timer, sizeof(scd.timer));
1463
load_param(&scd.pending, sizeof(scd.pending));
1464
load_param(&scd.dmna, sizeof(scd.dmna));
1465
1466
/* GFX processor */
1467
bufferptr += gfx_context_load(&state[bufferptr]);
1468
1469
/* CD Data controller */
1470
bufferptr += cdc_context_load(&state[bufferptr]);
1471
1472
/* CD Drive processor */
1473
bufferptr += cdd_context_load(&state[bufferptr]);
1474
1475
/* PCM chip */
1476
bufferptr += pcm_context_load(&state[bufferptr]);
1477
1478
/* PRG-RAM */
1479
load_param(scd.prg_ram, sizeof(scd.prg_ram));
1480
1481
/* PRG-RAM 128k bank mapped to $020000-$03FFFF (resp. $420000-$43FFFF) */
1482
m68k.memory_map[scd.cartridge.boot + 0x02].base = scd.prg_ram + ((scd.regs[0x03>>1].byte.l & 0xc0) << 11);
1483
m68k.memory_map[scd.cartridge.boot + 0x03].base = m68k.memory_map[scd.cartridge.boot + 0x02].base + 0x10000;
1484
1485
/* Word-RAM */
1486
if (scd.regs[0x03>>1].byte.l & 0x04)
1487
{
1488
/* 1M Mode */
1489
load_param(scd.word_ram, sizeof(scd.word_ram));
1490
1491
if (scd.regs[0x03>>1].byte.l & 0x01)
1492
{
1493
/* Word-RAM 1 assigned to MAIN-CPU */
1494
for (i=scd.cartridge.boot+0x20; i<scd.cartridge.boot+0x22; i++)
1495
{
1496
/* Word-RAM 1 data mapped at $200000-$21FFFF */
1497
m68k.memory_map[i].base = scd.word_ram[1] + ((i & 0x01) << 16);
1498
}
1499
1500
for (i=scd.cartridge.boot+0x22; i<scd.cartridge.boot+0x24; i++)
1501
{
1502
/* VRAM cell image mapped at $220000-$23FFFF */
1503
m68k.memory_map[i].read8 = cell_ram_1_read8;
1504
m68k.memory_map[i].read16 = cell_ram_1_read16;
1505
m68k.memory_map[i].write8 = cell_ram_1_write8;
1506
m68k.memory_map[i].write16 = cell_ram_1_write16;
1507
zbank_memory_map[i].read = cell_ram_1_read8;
1508
zbank_memory_map[i].write = cell_ram_1_write8;
1509
}
1510
1511
/* Word-RAM 0 assigned to SUB-CPU */
1512
for (i=0x08; i<0x0c; i++)
1513
{
1514
/* DOT image mapped at $080000-$0BFFFF */
1515
s68k.memory_map[i].read8 = dot_ram_0_read8;
1516
s68k.memory_map[i].read16 = dot_ram_0_read16;
1517
s68k.memory_map[i].write8 = dot_ram_0_write8;
1518
s68k.memory_map[i].write16 = dot_ram_0_write16;
1519
}
1520
1521
for (i=0x0c; i<0x0e; i++)
1522
{
1523
/* Word-RAM 0 data mapped at $0C0000-$0DFFFF */
1524
s68k.memory_map[i].base = scd.word_ram[0] + ((i & 0x01) << 16);
1525
s68k.memory_map[i].read8 = NULL;
1526
s68k.memory_map[i].read16 = NULL;
1527
s68k.memory_map[i].write8 = NULL;
1528
s68k.memory_map[i].write16 = NULL;
1529
}
1530
}
1531
else
1532
{
1533
/* Word-RAM 0 assigned to MAIN-CPU */
1534
for (i=scd.cartridge.boot+0x20; i<scd.cartridge.boot+0x22; i++)
1535
{
1536
/* Word-RAM 0 data mapped at $200000-$21FFFF */
1537
m68k.memory_map[i].base = scd.word_ram[0] + ((i & 0x01) << 16);
1538
}
1539
1540
for (i=scd.cartridge.boot+0x22; i<scd.cartridge.boot+0x24; i++)
1541
{
1542
/* VRAM cell image mapped at $220000-$23FFFF */
1543
m68k.memory_map[i].read8 = cell_ram_0_read8;
1544
m68k.memory_map[i].read16 = cell_ram_0_read16;
1545
m68k.memory_map[i].write8 = cell_ram_0_write8;
1546
m68k.memory_map[i].write16 = cell_ram_0_write16;
1547
zbank_memory_map[i].read = cell_ram_0_read8;
1548
zbank_memory_map[i].write = cell_ram_0_write8;
1549
}
1550
1551
/* Word-RAM 1 assigned to SUB-CPU */
1552
for (i=0x08; i<0x0c; i++)
1553
{
1554
/* DOT image mapped at $080000-$0BFFFF */
1555
s68k.memory_map[i].read8 = dot_ram_1_read8;
1556
s68k.memory_map[i].read16 = dot_ram_1_read16;
1557
s68k.memory_map[i].write8 = dot_ram_1_write8;
1558
s68k.memory_map[i].write16 = dot_ram_1_write16;
1559
}
1560
1561
for (i=0x0c; i<0x0e; i++)
1562
{
1563
/* Word-RAM 1 data mapped at $0C0000-$0DFFFF */
1564
s68k.memory_map[i].base = scd.word_ram[1] + ((i & 0x01) << 16);
1565
s68k.memory_map[i].read8 = NULL;
1566
s68k.memory_map[i].read16 = NULL;
1567
s68k.memory_map[i].write8 = NULL;
1568
s68k.memory_map[i].write16 = NULL;
1569
}
1570
}
1571
}
1572
else
1573
{
1574
/* 2M mode */
1575
load_param(scd.word_ram_2M, sizeof(scd.word_ram_2M));
1576
1577
for (i=scd.cartridge.boot+0x20; i<scd.cartridge.boot+0x24; i++)
1578
{
1579
/* MAIN-CPU: $200000-$23FFFF is mapped to 256K Word-RAM */
1580
m68k.memory_map[i].base = scd.word_ram_2M + ((i & 0x03) << 16);
1581
m68k.memory_map[i].read8 = NULL;
1582
m68k.memory_map[i].read16 = NULL;
1583
m68k.memory_map[i].write8 = NULL;
1584
m68k.memory_map[i].write16 = NULL;
1585
zbank_memory_map[i].read = NULL;
1586
zbank_memory_map[i].write = NULL;
1587
}
1588
1589
for (i=0x08; i<0x0c; i++)
1590
{
1591
/* SUB-CPU: $080000-$0BFFFF is mapped to 256K Word-RAM */
1592
s68k.memory_map[i].read8 = NULL;
1593
s68k.memory_map[i].read16 = NULL;
1594
s68k.memory_map[i].write8 = NULL;
1595
s68k.memory_map[i].write16 = NULL;
1596
}
1597
1598
for (i=0x0c; i<0x0e; i++)
1599
{
1600
/* SUB-CPU: $0C0000-$0DFFFF is unmapped */
1601
s68k.memory_map[i].read8 = s68k_read_bus_8;
1602
s68k.memory_map[i].read16 = s68k_read_bus_16;
1603
s68k.memory_map[i].write8 = s68k_unused_8_w;
1604
s68k.memory_map[i].write16 = s68k_unused_16_w;
1605
}
1606
}
1607
1608
/* MAIN-CPU & SUB-CPU polling */
1609
load_param(&m68k.poll, sizeof(m68k.poll));
1610
load_param(&s68k.poll, sizeof(s68k.poll));
1611
1612
/* H-INT default vector */
1613
load_param(&tmp16, 2);
1614
*(uint16 *)(m68k.memory_map[scd.cartridge.boot].base + 0x72) = tmp16;
1615
1616
/* SUB-CPU internal state */
1617
load_param(&s68k.cycles, sizeof(s68k.cycles));
1618
load_param(&s68k.int_level, sizeof(s68k.int_level));
1619
load_param(&s68k.stopped, sizeof(s68k.stopped));
1620
1621
/* SUB-CPU registers */
1622
load_param(&tmp32, 4); s68k_set_reg(M68K_REG_D0, tmp32);
1623
load_param(&tmp32, 4); s68k_set_reg(M68K_REG_D1, tmp32);
1624
load_param(&tmp32, 4); s68k_set_reg(M68K_REG_D2, tmp32);
1625
load_param(&tmp32, 4); s68k_set_reg(M68K_REG_D3, tmp32);
1626
load_param(&tmp32, 4); s68k_set_reg(M68K_REG_D4, tmp32);
1627
load_param(&tmp32, 4); s68k_set_reg(M68K_REG_D5, tmp32);
1628
load_param(&tmp32, 4); s68k_set_reg(M68K_REG_D6, tmp32);
1629
load_param(&tmp32, 4); s68k_set_reg(M68K_REG_D7, tmp32);
1630
load_param(&tmp32, 4); s68k_set_reg(M68K_REG_A0, tmp32);
1631
load_param(&tmp32, 4); s68k_set_reg(M68K_REG_A1, tmp32);
1632
load_param(&tmp32, 4); s68k_set_reg(M68K_REG_A2, tmp32);
1633
load_param(&tmp32, 4); s68k_set_reg(M68K_REG_A3, tmp32);
1634
load_param(&tmp32, 4); s68k_set_reg(M68K_REG_A4, tmp32);
1635
load_param(&tmp32, 4); s68k_set_reg(M68K_REG_A5, tmp32);
1636
load_param(&tmp32, 4); s68k_set_reg(M68K_REG_A6, tmp32);
1637
load_param(&tmp32, 4); s68k_set_reg(M68K_REG_A7, tmp32);
1638
load_param(&tmp32, 4); s68k_set_reg(M68K_REG_PC, tmp32);
1639
load_param(&tmp16, 2); s68k_set_reg(M68K_REG_SR, tmp16);
1640
load_param(&tmp32, 4); s68k_set_reg(M68K_REG_USP,tmp32);
1641
load_param(&tmp32, 4); s68k_set_reg(M68K_REG_ISP,tmp32);
1642
1643
/* bootable MD cartridge hardware */
1644
if (scd.cartridge.boot)
1645
{
1646
bufferptr += md_cart_context_load(&state[bufferptr]);
1647
}
1648
1649
load_param(scd.bram, 0x2000);
1650
// we don't save scd.cartridge.id separately, so it must be non-changing!
1651
if (scd.cartridge.id)
1652
load_param(scd.cartridge.area, scd.cartridge.mask + 1);
1653
1654
return bufferptr;
1655
}
1656
1657
int scd_68k_irq_ack(int level)
1658
{
1659
#ifdef LOG_SCD
1660
error("INT ack level %d (%X)\n", level, s68k.pc);
1661
#endif
1662
1663
#if 0
1664
/* level 5 interrupt is normally acknowledged by CDC */
1665
if (level != 5)
1666
#endif
1667
{
1668
/* clear pending interrupt flag */
1669
scd.pending &= ~(1 << level);
1670
1671
/* level 2 interrupt acknowledge */
1672
if (level == 2)
1673
{
1674
/* clear IFL2 flag */
1675
scd.regs[0x00].byte.h &= ~0x01;
1676
}
1677
1678
/* update IRQ level */
1679
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
1680
}
1681
1682
return M68K_INT_ACK_AUTOVECTOR;
1683
}
1684
1685