1 /***************************************************************************
2
3 Atari CAGE Audio Board
4
5 ****************************************************************************/
6
7
8 #define LOG_COMM (0)
9 #define LOG_WAVE (0)
10
11
12 #include "driver.h"
13 #include "cpu/tms32031/tms32031.h"
14 #include "cage.h"
15
16 #if (LOG_WAVE)
17 #include "sound/wavwrite.h"
18 #endif
19
20
21
22 /*************************************
23 *
24 * Constants/macros
25 *
26 *************************************/
27
28 #define DAC_BUFFER_CHANNELS 4
29 #define DAC_BUFFER_FRAMES 4096
30 #define DAC_BUFFER_SAMPLES (DAC_BUFFER_FRAMES * DAC_BUFFER_CHANNELS)
31 #define DAC_BUFFER_FRAMES_MASK (DAC_BUFFER_FRAMES - 1)
32 #define DAC_BUFFER_SAMPLES_MASK (DAC_BUFFER_SAMPLES - 1)
33
34 #define ADDR_RANGE(s,e) ((s)*4), ((e)*4+3)
35
36
37
38 /*************************************
39 *
40 * Statics
41 *
42 *************************************/
43
44 static int sound_stream;
45 static int cage_cpu;
46 static double cage_cpu_clock_period;
47 static double cage_cpu_h1_clock;
48
49 static UINT8 cpu_to_cage_ready;
50 static UINT8 cage_to_cpu_ready;
51
52 static void (*cage_irqhandler)(int);
53
54 static INT16 *sound_buffer;
55 static UINT32 buffer_in, buffer_out, buffer_out_step;
56
57 static double serial_time_per_word;
58
59 static UINT8 dma_enabled;
60 static void *dma_timer;
61
62 static UINT8 timer_enabled[2];
63 static void *timer[2];
64
65 static data32_t *tms32031_io_regs;
66
67 static UINT16 cage_from_main;
68 static UINT16 cage_control;
69
70 static data32_t *speedup_ram;
71
72 #if (LOG_WAVE)
73 static void *wavfile;
74 #endif
75
76
77
78 /*************************************
79 *
80 * I/O port definitions
81 *
82 *************************************/
83
84 #define DMA_GLOBAL_CTL 0x00
85 #define DMA_SOURCE_ADDR 0x04
86 #define DMA_DEST_ADDR 0x06
87 #define DMA_TRANSFER_COUNT 0x08
88
89 #define TIMER0_GLOBAL_CTL 0x20
90 #define TIMER0_COUNTER 0x24
91 #define TIMER0_PERIOD 0x28
92
93 #define TIMER1_GLOBAL_CTL 0x30
94 #define TIMER1_COUNTER 0x34
95 #define TIMER1_PERIOD 0x38
96
97 #define SPORT_GLOBAL_CTL 0x40
98 #define SPORT_TX_CTL 0x42
99 #define SPORT_RX_CTL 0x43
100 #define SPORT_TIMER_CTL 0x44
101 #define SPORT_TIMER_COUNTER 0x45
102 #define SPORT_TIMER_PERIOD 0x46
103 #define SPORT_DATA_TX 0x48
104 #define SPORT_DATA_RX 0x4c
105
106 static const char *register_names[] =
107 {
108 "TMS32031-DMA global control", NULL, NULL, NULL,
109 "TMS32031-DMA source address", NULL, "TMS32031-DMA destination address", NULL,
110 "TMS32031-DMA transfer counter", NULL, NULL, NULL,
111 NULL, NULL, NULL, NULL,
112
113 NULL, NULL, NULL, NULL,
114 NULL, NULL, NULL, NULL,
115 NULL, NULL, NULL, NULL,
116 NULL, NULL, NULL, NULL,
117
118 "TMS32031-Timer 0 global control", NULL, NULL, NULL,
119 "TMS32031-Timer 0 counter", NULL, NULL, NULL,
120 "TMS32031-Timer 0 period", NULL, NULL, NULL,
121 NULL, NULL, NULL, NULL,
122
123 "TMS32031-Timer 1 global control", NULL, NULL, NULL,
124 "TMS32031-Timer 1 counter", NULL, NULL, NULL,
125 "TMS32031-Timer 1 period", NULL, NULL, NULL,
126 NULL, NULL, NULL, NULL,
127
128 "TMS32031-Serial port global control", NULL, "TMS32031-Serial port TX control", "TMS32031-Serial port RX control",
129 "TMS32031-Serial port timer control", "TMS32031-Serial port timer counter", "TMS32031-Serial port timer period", NULL,
130 "TMS32031-Serial port data TX", NULL, NULL, NULL,
131 "TMS32031-Serial port data RX", NULL, NULL, NULL,
132
133 NULL, NULL, NULL, NULL,
134 NULL, NULL, NULL, NULL,
135 NULL, NULL, NULL, NULL,
136 NULL, NULL, NULL, NULL,
137
138 NULL, NULL, NULL, NULL,
139 "TMS32031-Primary bus control", NULL, NULL, NULL,
140 NULL, NULL, NULL, NULL,
141 NULL, NULL, NULL, NULL,
142
143 NULL, NULL, NULL, NULL,
144 NULL, NULL, NULL, NULL,
145 NULL, NULL, NULL, NULL,
146 NULL, NULL, NULL, NULL
147 };
148
149
150
151 /*************************************
152 *
153 * Prototypes
154 *
155 *************************************/
156
157 static void dma_timer_callback(int param);
158 static void timer_callback(int param);
159 static void update_timer(int which);
160 static WRITE32_HANDLER( speedup_w );
161
162
163
164 /*************************************
165 *
166 * Initialization
167 *
168 *************************************/
169
cage_init(int boot_region,offs_t speedup)170 void cage_init(int boot_region, offs_t speedup)
171 {
172 cage_irqhandler = NULL;
173
174 cpu_setbank(10, memory_region(boot_region));
175 cpu_setbank(11, memory_region(boot_region + 1));
176
177 cage_cpu = mame_find_cpu_index("cage");
178 cage_cpu_clock_period = 1.0 / (double)Machine->drv->cpu[cage_cpu].cpu_clock;
179 cage_cpu_h1_clock = cage_cpu_clock_period * 2.0;
180
181 dma_timer = timer_alloc(dma_timer_callback);
182 timer[0] = timer_alloc(timer_callback);
183 timer[1] = timer_alloc(timer_callback);
184
185 buffer_in = buffer_out = 0;
186
187 if (speedup)
188 speedup_ram = install_mem_write32_handler(cage_cpu, ADDR_RANGE(speedup, speedup), speedup_w);
189 }
190
191
cage_set_irq_handler(void (* irqhandler)(int))192 void cage_set_irq_handler(void (*irqhandler)(int))
193 {
194 cage_irqhandler = irqhandler;
195 }
196
197
cage_reset_w(int state)198 void cage_reset_w(int state)
199 {
200 if (state)
201 cage_control_w(0);
202 cpunum_set_reset_line(cage_cpu, state ? ASSERT_LINE : CLEAR_LINE);
203 }
204
205
206
207 /*************************************
208 *
209 * DAC update routine
210 *
211 *************************************/
212
dac_update(int num,INT16 ** buffer,int length)213 static void dac_update(int num, INT16 **buffer, int length)
214 {
215 INT16 *dest[DAC_BUFFER_CHANNELS];
216 UINT32 current = buffer_out;
217 UINT32 step = buffer_out_step;
218 int i, j;
219
220 for (j = 0; j < DAC_BUFFER_CHANNELS; j++)
221 dest[j] = buffer[j];
222
223 /* fill in with samples until we hit the end or run out */
224 for (i = 0; i < length; i++)
225 {
226 UINT32 indx = (current >> 16) * DAC_BUFFER_CHANNELS;
227 if (indx + DAC_BUFFER_CHANNELS - 1 >= buffer_in)
228 break;
229 current += step;
230 for (j = 0; j < DAC_BUFFER_CHANNELS; j++)
231 *dest[j]++ = sound_buffer[(indx + j) & DAC_BUFFER_SAMPLES_MASK];
232 }
233
234 /* fill the rest with the last sample */
235 for ( ; i < length; i++)
236 {
237 UINT32 indx = ((buffer_in - 1) / DAC_BUFFER_CHANNELS) * DAC_BUFFER_CHANNELS;
238 for (j = 0; j < DAC_BUFFER_CHANNELS; j++)
239 *dest[j]++ = sound_buffer[(indx + j) & DAC_BUFFER_SAMPLES_MASK];
240 }
241
242 /* mask off extra bits */
243 while (current >= (DAC_BUFFER_FRAMES << 16))
244 {
245 current -= DAC_BUFFER_FRAMES << 16;
246 buffer_in -= DAC_BUFFER_SAMPLES;
247 }
248
249 /* update the final values */
250 buffer_out = current;
251
252 #if (LOG_WAVE)
253 #if (DAC_BUFFER_CHANNELS == 4)
254 wav_add_data_16lr(wavfile, buffer[0], buffer[1], length);
255 #else
256 wav_add_data_16lr(wavfile, (buffer[0] + buffer[2]) / 2, (buffer[1] + buffer[3]) / 2, length);
257 #endif
258 #endif
259 }
260
261
262
263 /*************************************
264 *
265 * Custom sound start/stop
266 *
267 *************************************/
268
custom_start(const struct MachineSound * msound)269 static int custom_start(const struct MachineSound *msound)
270 {
271 #if (DAC_BUFFER_CHANNELS == 4)
272 const char *names[] = { "Forward R", "Back L", "Forward L", "Back R" };
273 int mixing_levels[] = { MIXER(50, MIXER_PAN_RIGHT), MIXER(50, MIXER_PAN_LEFT), MIXER(50, MIXER_PAN_LEFT), MIXER(50, MIXER_PAN_RIGHT) };
274 #else
275 const char *names[] = { "DAC L", "DAC R" };
276 int mixing_levels[] = { MIXER(100, MIXER_PAN_LEFT), MIXER(100, MIXER_PAN_RIGHT)) };
277 #endif
278
279 /* allocate a DAC stream */
280 sound_stream = stream_init_multi(DAC_BUFFER_CHANNELS, names, mixing_levels, Machine->sample_rate, 0, dac_update);
281
282 /* allocate memory for our buffers */
283 sound_buffer = auto_malloc(DAC_BUFFER_SAMPLES * sizeof(INT16));
284 if (!sound_buffer)
285 return 1;
286
287 #if (LOG_WAVE)
288 wavfile = wav_open("cage.wav", Machine->sample_rate, 2);
289 #endif
290
291 return 0;
292 }
293
294
custom_stop(void)295 static void custom_stop(void)
296 {
297 #if (LOG_WAVE)
298 wav_close(wavfile);
299 #endif
300 }
301
302
303
304 /*************************************
305 *
306 * DMA timers
307 *
308 *************************************/
309
dma_timer_callback(int param)310 static void dma_timer_callback(int param)
311 {
312 /* set the final count to 0 and the source address to the final address */
313 tms32031_io_regs[DMA_TRANSFER_COUNT] = 0;
314 tms32031_io_regs[DMA_SOURCE_ADDR] = param;
315
316 /* set the interrupt */
317 cpu_set_irq_line(cage_cpu, TMS32031_DINT, ASSERT_LINE);
318 dma_enabled = 0;
319 }
320
321
update_dma_state(void)322 static void update_dma_state(void)
323 {
324 /* determine the new enabled state */
325 int enabled = ((tms32031_io_regs[DMA_GLOBAL_CTL] & 3) == 3) && (tms32031_io_regs[DMA_TRANSFER_COUNT] != 0);
326
327 /* see if we turned on */
328 if (enabled && !dma_enabled)
329 {
330 UINT32 addr, inc;
331 int i;
332
333 /* make sure our assumptions are correct */
334 if (tms32031_io_regs[DMA_DEST_ADDR] != 0x808048)
335 log_cb(RETRO_LOG_DEBUG, LOGPRE "CAGE DMA: unexpected dest address %08X!\n", tms32031_io_regs[DMA_DEST_ADDR]);
336 if ((tms32031_io_regs[DMA_GLOBAL_CTL] & 0xfef) != 0xe03)
337 log_cb(RETRO_LOG_DEBUG, LOGPRE "CAGE DMA: unexpected transfer params %08X!\n", tms32031_io_regs[DMA_GLOBAL_CTL]);
338
339 /* do the DMA up front */
340 addr = tms32031_io_regs[DMA_SOURCE_ADDR];
341 inc = (tms32031_io_regs[DMA_GLOBAL_CTL] >> 4) & 1;
342 for (i = 0; i < tms32031_io_regs[DMA_TRANSFER_COUNT]; i++)
343 {
344 sound_buffer[(buffer_in + i) & DAC_BUFFER_SAMPLES_MASK] = cpu_readmem26ledw_dword(addr * 4);
345 addr += inc;
346 }
347 buffer_in += tms32031_io_regs[DMA_TRANSFER_COUNT];
348
349 /* compute the time of the interrupt and set the timer */
350 timer_adjust(dma_timer, serial_time_per_word * tms32031_io_regs[DMA_TRANSFER_COUNT], addr, TIME_NEVER);
351 }
352
353 /* see if we turned off */
354 else if (!enabled && dma_enabled)
355 {
356 timer_adjust(dma_timer, TIME_NEVER, 0, TIME_NEVER);
357 }
358
359 /* set the new state */
360 dma_enabled = enabled;
361 }
362
363
364
365 /*************************************
366 *
367 * Internal timers
368 *
369 *************************************/
370
timer_callback(int which)371 static void timer_callback(int which)
372 {
373 /* set the interrupt */
374 cpu_set_irq_line(cage_cpu, TMS32031_TINT0 + which, ASSERT_LINE);
375 timer_enabled[which] = 0;
376 update_timer(which);
377 }
378
379
update_timer(int which)380 static void update_timer(int which)
381 {
382 /* determine the new enabled state */
383 int base = 0x10 * which;
384 int enabled = ((tms32031_io_regs[base + TIMER0_GLOBAL_CTL] & 0xc0) == 0xc0);
385
386 /* see if we turned on */
387 if (enabled && !timer_enabled[which])
388 {
389 double period = cage_cpu_h1_clock * 2. * (double)tms32031_io_regs[base + TIMER0_PERIOD];
390
391 /* make sure our assumptions are correct */
392 if (tms32031_io_regs[base + TIMER0_GLOBAL_CTL] != 0x2c1)
393 log_cb(RETRO_LOG_DEBUG, LOGPRE "CAGE TIMER%d: unexpected timer config %08X!\n", which, tms32031_io_regs[base + TIMER0_GLOBAL_CTL]);
394
395 timer_adjust(timer[which], period, which, TIME_NEVER);
396 }
397
398 /* see if we turned off */
399 else if (!enabled && timer_enabled[which])
400 {
401 timer_adjust(timer[which], TIME_NEVER, which, TIME_NEVER);
402 }
403
404 /* set the new state */
405 timer_enabled[which] = enabled;
406 }
407
408
409
410 /*************************************
411 *
412 * Serial port I/O
413 *
414 *************************************/
415
update_serial(void)416 static void update_serial(void)
417 {
418 double serial_clock, bit_clock;
419
420 /* we start out at half the H1 frequency (or 2x the H1 period) */
421 serial_clock = cage_cpu_h1_clock * 2.0;
422
423 /* if we're in clock mode, muliply by another factor of 2 */
424 if (tms32031_io_regs[SPORT_GLOBAL_CTL] & 4)
425 serial_clock *= 2.0;
426
427 /* now multiply by the timer period */
428 bit_clock = serial_clock * (double)(tms32031_io_regs[SPORT_TIMER_PERIOD] & 0xffff);
429
430 /* and times the number of bits per sample */
431 serial_time_per_word = bit_clock * 8.0 * (double)(((tms32031_io_regs[SPORT_GLOBAL_CTL] >> 18) & 3) + 1);
432
433 /* compute the step value to stretch this to the Machine->sample_rate */
434 buffer_out_step = (UINT32)(65536.0 / (serial_time_per_word * DAC_BUFFER_CHANNELS * (double)Machine->sample_rate));
435 }
436
437
438
439 /*************************************
440 *
441 * Master read/write
442 *
443 *************************************/
444
READ32_HANDLER(tms32031_io_r)445 static READ32_HANDLER( tms32031_io_r )
446 {
447 UINT16 result = tms32031_io_regs[offset];
448
449 switch (offset)
450 {
451 case DMA_GLOBAL_CTL:
452 result = (result & ~0xc) | (dma_enabled ? 0xc : 0x0);
453 break;
454 }
455
456 log_cb(RETRO_LOG_DEBUG, LOGPRE "CAGE:%06X:%s read -> %08X\n", activecpu_get_pc(), register_names[offset & 0x7f], result);
457 return result;
458 }
459
460
WRITE32_HANDLER(tms32031_io_w)461 static WRITE32_HANDLER( tms32031_io_w )
462 {
463 COMBINE_DATA(&tms32031_io_regs[offset]);
464
465 log_cb(RETRO_LOG_DEBUG, LOGPRE "CAGE:%06X:%s write = %08X\n", activecpu_get_pc(), register_names[offset & 0x7f], tms32031_io_regs[offset]);
466
467 switch (offset)
468 {
469 case DMA_GLOBAL_CTL:
470 case DMA_SOURCE_ADDR:
471 case DMA_DEST_ADDR:
472 case DMA_TRANSFER_COUNT:
473 update_dma_state();
474 break;
475
476 case TIMER0_GLOBAL_CTL:
477 case TIMER0_COUNTER:
478 case TIMER0_PERIOD:
479 update_timer(0);
480 break;
481
482 case TIMER1_GLOBAL_CTL:
483 case TIMER1_COUNTER:
484 case TIMER1_PERIOD:
485 update_timer(1);
486 break;
487
488 case SPORT_TX_CTL:
489 case SPORT_RX_CTL:
490 case SPORT_TIMER_COUNTER:
491 case SPORT_DATA_RX:
492 break;
493
494 case SPORT_DATA_TX:
495 #if (DAC_BUFFER_CHANNELS == 4)
496 if ((int)(1.0 / serial_time_per_word) == 22050*4 && (tms32031_io_regs[SPORT_RX_CTL] & 0xff) == 0x62)
497 tms32031_io_regs[SPORT_RX_CTL] ^= 0x800;
498 #endif
499 break;
500
501 case SPORT_GLOBAL_CTL:
502 case SPORT_TIMER_CTL:
503 case SPORT_TIMER_PERIOD:
504 update_serial();
505 break;
506 }
507 }
508
509
510
511 /*************************************
512 *
513 * External interfaces
514 *
515 *************************************/
516
update_control_lines(void)517 static void update_control_lines(void)
518 {
519 int val;
520
521 /* set the IRQ to the main CPU */
522 if (cage_irqhandler)
523 {
524 int reason = 0;
525
526 if ((cage_control & 3) == 3 && !cpu_to_cage_ready)
527 reason |= CAGE_IRQ_REASON_BUFFER_EMPTY;
528 if ((cage_control & 2) && cage_to_cpu_ready)
529 reason |= CAGE_IRQ_REASON_DATA_READY;
530
531 (*cage_irqhandler)(reason);
532 }
533
534 /* set the IOF input lines */
535 cpuintrf_push_context(cage_cpu);
536 val = activecpu_get_reg(TMS32031_IOF);
537 val &= ~0x88;
538 if (cpu_to_cage_ready) val |= 0x08;
539 if (cage_to_cpu_ready) val |= 0x80;
540 activecpu_set_reg(TMS32031_IOF, val);
541 cpuintrf_pop_context();
542 }
543
544
READ32_HANDLER(cage_from_main_r)545 static READ32_HANDLER( cage_from_main_r )
546 {
547 log_cb(RETRO_LOG_DEBUG, LOGPRE "%06X:CAGE read command = %04X\n", activecpu_get_pc(), cage_from_main);
548 cpu_to_cage_ready = 0;
549 update_control_lines();
550 return cage_from_main;
551 }
552
553
WRITE32_HANDLER(cage_from_main_ack_w)554 static WRITE32_HANDLER( cage_from_main_ack_w )
555 {
556 log_cb(RETRO_LOG_DEBUG, LOGPRE "%06X:CAGE ack command = %04X\n", activecpu_get_pc(), cage_from_main);
557 }
558
559
WRITE32_HANDLER(cage_to_main_w)560 static WRITE32_HANDLER( cage_to_main_w )
561 {
562 log_cb(RETRO_LOG_DEBUG, LOGPRE "%06X:Data from CAGE = %04X\n", activecpu_get_pc(), data);
563 soundlatch_word_w(0, data, mem_mask);
564 cage_to_cpu_ready = 1;
565 update_control_lines();
566 }
567
568
READ32_HANDLER(cage_io_status_r)569 static READ32_HANDLER( cage_io_status_r )
570 {
571 int result = 0;
572 if (cpu_to_cage_ready)
573 result |= 0x80;
574 if (!cage_to_cpu_ready)
575 result |= 0x40;
576 return result;
577 }
578
579
main_from_cage_r(void)580 UINT16 main_from_cage_r(void)
581 {
582 log_cb(RETRO_LOG_DEBUG, LOGPRE "%06X:main read data = %04X\n", activecpu_get_pc(), soundlatch_word_r(0, 0));
583 cage_to_cpu_ready = 0;
584 update_control_lines();
585 return soundlatch_word_r(0, 0);
586 }
587
588
deferred_cage_w(int param)589 static void deferred_cage_w(int param)
590 {
591 cage_from_main = param;
592 cpu_to_cage_ready = 1;
593 update_control_lines();
594 cpu_set_irq_line(cage_cpu, TMS32031_IRQ0, ASSERT_LINE);
595 }
596
597
main_to_cage_w(UINT16 data)598 void main_to_cage_w(UINT16 data)
599 {
600 log_cb(RETRO_LOG_DEBUG, LOGPRE "%06X:Command to CAGE = %04X\n", activecpu_get_pc(), data);
601 timer_set(TIME_NOW, data, deferred_cage_w);
602 }
603
604
cage_control_r(void)605 UINT16 cage_control_r(void)
606 {
607 UINT16 result = 0;
608
609 if (cpu_to_cage_ready)
610 result |= 2;
611 if (cage_to_cpu_ready)
612 result |= 1;
613
614 return result;
615 }
616
617
cage_control_w(UINT16 data)618 void cage_control_w(UINT16 data)
619 {
620 cage_control = data;
621
622 /* CPU is reset if both control lines are 0 */
623 if (!(cage_control & 3))
624 {
625 cpu_set_reset_line(cage_cpu, ASSERT_LINE);
626
627 dma_enabled = 0;
628 timer_adjust(dma_timer, TIME_NEVER, 0, TIME_NEVER);
629
630 timer_enabled[0] = 0;
631 timer_enabled[1] = 0;
632 timer_adjust(timer[0], TIME_NEVER, 0, TIME_NEVER);
633 timer_adjust(timer[1], TIME_NEVER, 0, TIME_NEVER);
634
635 memset(tms32031_io_regs, 0, 0x60 * 4);
636
637 cpu_to_cage_ready = 0;
638 cage_to_cpu_ready = 0;
639 }
640 else
641 cpu_set_reset_line(cage_cpu, CLEAR_LINE);
642
643 /* update the control state */
644 update_control_lines();
645 }
646
647
648
649 /*************************************
650 *
651 * Speedups
652 *
653 *************************************/
654
WRITE32_HANDLER(speedup_w)655 static WRITE32_HANDLER( speedup_w )
656 {
657 activecpu_eat_cycles(100);
658 COMBINE_DATA(&speedup_ram[offset]);
659 }
660
661
662
663 /*************************************
664 *
665 * CPU memory map & config
666 *
667 *************************************/
668
669 static struct tms32031_config cage_config =
670 {
671 0x400000
672 };
673
674
MEMORY_READ32_START(readmem_cage)675 static MEMORY_READ32_START( readmem_cage )
676 { ADDR_RANGE(0x000000, 0x00ffff), MRA32_RAM },
677 { ADDR_RANGE(0x400000, 0x47ffff), MRA32_BANK10 },
678 { ADDR_RANGE(0x808000, 0x8080ff), tms32031_io_r },
679 { ADDR_RANGE(0x809800, 0x809fff), MRA32_RAM },
680 { ADDR_RANGE(0xa00000, 0xa00000), cage_from_main_r },
681 { ADDR_RANGE(0xc00000, 0xffffff), MRA32_BANK11 },
682 MEMORY_END
683
684
685 static MEMORY_WRITE32_START( writemem_cage )
686 { ADDR_RANGE(0x000000, 0x00ffff), MWA32_RAM },
687 { ADDR_RANGE(0x200000, 0x200000), MWA32_NOP },
688 { ADDR_RANGE(0x400000, 0x47ffff), MWA32_ROM },
689 { ADDR_RANGE(0x808000, 0x8080ff), tms32031_io_w, &tms32031_io_regs },
690 { ADDR_RANGE(0x809800, 0x809fff), MWA32_RAM },
691 { ADDR_RANGE(0xa00000, 0xa00000), cage_to_main_w },
692 { ADDR_RANGE(0xc00000, 0xffffff), MWA32_ROM },
693 MEMORY_END
694
695
696 static MEMORY_READ32_START( readmem_cage_seattle )
697 { ADDR_RANGE(0x000000, 0x00ffff), MRA32_RAM },
698 { ADDR_RANGE(0x400000, 0x47ffff), MRA32_BANK10 },
699 { ADDR_RANGE(0x808000, 0x8080ff), tms32031_io_r },
700 { ADDR_RANGE(0x809800, 0x809fff), MRA32_RAM },
701 { ADDR_RANGE(0xa00000, 0xa00000), cage_from_main_r },
702 { ADDR_RANGE(0xa00003, 0xa00003), cage_io_status_r },
703 { ADDR_RANGE(0xc00000, 0xffffff), MRA32_BANK11 },
704 MEMORY_END
705
706
707 static MEMORY_WRITE32_START( writemem_cage_seattle )
708 { ADDR_RANGE(0x000000, 0x00ffff), MWA32_RAM },
709 { ADDR_RANGE(0x200000, 0x200000), MWA32_NOP },
710 { ADDR_RANGE(0x400000, 0x47ffff), MWA32_ROM },
711 { ADDR_RANGE(0x808000, 0x8080ff), tms32031_io_w, &tms32031_io_regs },
712 { ADDR_RANGE(0x809800, 0x809fff), MWA32_RAM },
713 { ADDR_RANGE(0xa00000, 0xa00000), cage_from_main_ack_w },
714 { ADDR_RANGE(0xa00001, 0xa00001), cage_to_main_w },
715 { ADDR_RANGE(0xc00000, 0xffffff), MWA32_ROM },
716 MEMORY_END
717
718
719
720 /*************************************
721 *
722 * CAGE machine driver
723 *
724 *************************************/
725
726 /* Custom structure */
727 struct CustomSound_interface cage_custom_interface =
728 {
729 custom_start,custom_stop,0
730 };
731
732
733 MACHINE_DRIVER_START( cage )
734
735 /* basic machine hardware */
736 MDRV_CPU_ADD_TAG("cage", TMS32031, 33868800)
737 MDRV_CPU_FLAGS(CPU_AUDIO_CPU)
738 MDRV_CPU_CONFIG(cage_config)
739 MDRV_CPU_MEMORY(readmem_cage,writemem_cage)
740
741 /* sound hardware */
742 MDRV_SOUND_ATTRIBUTES(SOUND_SUPPORTS_STEREO)
743 MDRV_SOUND_ADD(CUSTOM, cage_custom_interface)
744 MACHINE_DRIVER_END
745
746
747 MACHINE_DRIVER_START( cage_seattle )
748 MDRV_IMPORT_FROM(cage)
749
750 MDRV_CPU_MODIFY("cage")
751 MDRV_CPU_MEMORY(readmem_cage_seattle,writemem_cage_seattle)
752 MACHINE_DRIVER_END
753