1 /***************************************************************************
2
3 Midway DCS Audio Board
4
5 ****************************************************************************/
6
7 #include "driver.h"
8 #include "cpu/adsp2100/adsp2100.h"
9 #include "dcs.h"
10
11 #include <math.h>
12
13 #define LOG_DCS_TRANSFERS (0)
14 #define LOG_DCS_IO (0)
15 #define LOG_BUFFER_FILLING (0)
16
17
18 /***************************************************************************
19 CONSTANTS
20 ****************************************************************************/
21
22 #define DCS_BUFFER_SIZE 4096
23 #define DCS_BUFFER_MASK (DCS_BUFFER_SIZE - 1)
24
25 #define LCTRL_OUTPUT_EMPTY 0x400
26 #define LCTRL_INPUT_EMPTY 0x800
27
28 #define IS_OUTPUT_EMPTY() (dcs.latch_control & LCTRL_OUTPUT_EMPTY)
29 #define IS_OUTPUT_FULL() (!(dcs.latch_control & LCTRL_OUTPUT_EMPTY))
30 #define SET_OUTPUT_EMPTY() (dcs.latch_control |= LCTRL_OUTPUT_EMPTY)
31 #define SET_OUTPUT_FULL() (dcs.latch_control &= ~LCTRL_OUTPUT_EMPTY)
32
33 #define IS_INPUT_EMPTY() (dcs.latch_control & LCTRL_INPUT_EMPTY)
34 #define IS_INPUT_FULL() (!(dcs.latch_control & LCTRL_INPUT_EMPTY))
35 #define SET_INPUT_EMPTY() (dcs.latch_control |= LCTRL_INPUT_EMPTY)
36 #define SET_INPUT_FULL() (dcs.latch_control &= ~LCTRL_INPUT_EMPTY)
37
38 /* These are the some of the control register, we dont use them all */
39 enum
40 {
41 S1_AUTOBUF_REG = 15,
42 S1_RFSDIV_REG,
43 S1_SCLKDIV_REG,
44 S1_CONTROL_REG,
45 S0_AUTOBUF_REG,
46 S0_RFSDIV_REG,
47 S0_SCLKDIV_REG,
48 S0_CONTROL_REG,
49 S0_MCTXLO_REG,
50 S0_MCTXHI_REG,
51 S0_MCRXLO_REG,
52 S0_MCRXHI_REG,
53 TIMER_SCALE_REG,
54 TIMER_COUNT_REG,
55 TIMER_PERIOD_REG,
56 WAITSTATES_REG,
57 SYSCONTROL_REG
58 };
59
60
61
62 /***************************************************************************
63 STRUCTURES
64 ****************************************************************************/
65
66 struct dcs_state
67 {
68 int stream;
69 UINT8 auto_ack;
70
71 UINT8 * mem;
72 UINT16 size;
73 UINT16 incs;
74 void * reg_timer;
75 void * sport_timer;
76 int ireg;
77 UINT16 ireg_base;
78 UINT16 control_regs[32];
79
80 UINT16 rombank;
81 UINT16 rombank_count;
82 UINT16 srambank;
83 UINT16 drambank;
84 UINT16 drambank_count;
85 UINT8 enabled;
86
87 INT16 * buffer;
88 INT16 * buffer2;
89 UINT32 buffer_in;
90 UINT32 sample_step;
91 UINT32 sample_position;
92 INT16 current_sample;
93
94 UINT16 latch_control;
95 UINT16 input_data;
96 UINT16 output_data;
97 UINT16 output_control;
98 UINT32 output_control_cycles;
99
100 UINT8 last_output_full;
101 UINT8 last_input_empty;
102
103 void (*output_full_cb)(int);
104 void (*input_empty_cb)(int);
105 UINT16 (*fifo_data_r)(void);
106 UINT16 (*fifo_status_r)(void);
107 };
108
109
110
111 /***************************************************************************
112 STATIC GLOBALS
113 ****************************************************************************/
114
115 static INT8 dcs_cpunum;
116
117 static struct dcs_state dcs;
118
119 static data16_t *dcs_speedup1;
120 static data16_t *dcs_speedup2;
121 static data16_t *dcs_speedup3;
122 static data16_t *dcs_speedup4;
123
124 static data16_t *dcs_sram_bank0;
125 static data16_t *dcs_sram_bank1;
126 static data16_t *dcs_expanded_rom;
127
128 static data16_t *dcs_polling_base;
129
130 #if (LOG_DCS_TRANSFERS)
131 static data16_t *transfer_dest;
132 static int transfer_state;
133 static int transfer_start;
134 static int transfer_stop;
135 static int transfer_writes_left;
136 static UINT16 transfer_sum;
137 #endif
138
139
140
141 /***************************************************************************
142 PROTOTYPES
143 ****************************************************************************/
144
145 static int dcs_custom_start(const struct MachineSound *msound);
146 static int dcs2_custom_start(const struct MachineSound *msound);
147 static void dcs_dac_update(int num, INT16 *buffer, int length);
148 static void dcs2_dac_update(int num, INT16 **buffer, int length);
149
150 static READ16_HANDLER( dcs_sdrc_asic_ver_r );
151
152 static WRITE16_HANDLER( dcs_rombank_select_w );
153 static READ16_HANDLER( dcs_rombank_data_r );
154 static WRITE16_HANDLER( dcs_sram_bank_w );
155 static READ16_HANDLER( dcs_sram_bank_r );
156 static WRITE16_HANDLER( dcs_dram_bank_w );
157 static READ16_HANDLER( dcs_dram_bank_r );
158
159 static WRITE16_HANDLER( dcs_control_w );
160
161 static READ16_HANDLER( latch_status_r );
162 static READ16_HANDLER( fifo_input_r );
163 static READ16_HANDLER( input_latch_r );
164 static WRITE16_HANDLER( input_latch_ack_w );
165 static WRITE16_HANDLER( output_latch_w );
166 static READ16_HANDLER( output_control_r );
167 static WRITE16_HANDLER( output_control_w );
168
169 static void dcs_irq(int state);
170 static void sport0_irq(int state);
171 static void sound_tx_callback(int port, INT32 data);
172
173 static READ16_HANDLER( dcs_polling_r );
174
175 static WRITE16_HANDLER(dcs_speedup1_w);
176 static WRITE16_HANDLER(dcs_speedup2_w);
177 static WRITE16_HANDLER(dcs_speedup3_w);
178 static WRITE16_HANDLER(dcs_speedup4_w);
179 static void dcs_speedup_common(void);
180
181
182 /***************************************************************************
183 PROCESSOR STRUCTURES
184 ****************************************************************************/
185
186 /* DCS readmem/writemem structures */
MEMORY_READ16_START(dcs_readmem)187 MEMORY_READ16_START( dcs_readmem )
188 { ADSP_DATA_ADDR_RANGE(0x0000, 0x1fff), MRA16_RAM }, /* ??? */
189 { ADSP_DATA_ADDR_RANGE(0x2000, 0x2fff), dcs_rombank_data_r }, /* banked roms read */
190 { ADSP_DATA_ADDR_RANGE(0x3400, 0x3403), input_latch_r }, /* soundlatch read */
191 { ADSP_DATA_ADDR_RANGE(0x3800, 0x39ff), MRA16_RAM }, /* internal data ram */
192 { ADSP_PGM_ADDR_RANGE (0x0000, 0x1fff), MRA16_RAM }, /* internal/external program ram */
193 MEMORY_END
194
195
196 MEMORY_WRITE16_START( dcs_writemem )
197 { ADSP_DATA_ADDR_RANGE(0x0000, 0x1fff), MWA16_RAM }, /* ??? */
198 { ADSP_DATA_ADDR_RANGE(0x3000, 0x3000), dcs_rombank_select_w }, /* bank selector */
199 { ADSP_DATA_ADDR_RANGE(0x3400, 0x3403), output_latch_w }, /* soundlatch write */
200 { ADSP_DATA_ADDR_RANGE(0x3800, 0x39ff), MWA16_RAM }, /* internal data ram */
201 { ADSP_DATA_ADDR_RANGE(0x3fe0, 0x3fff), dcs_control_w }, /* adsp control regs */
202 { ADSP_PGM_ADDR_RANGE (0x0000, 0x1fff), MWA16_RAM }, /* internal/external program ram */
203 MEMORY_END
204
205
206
207 /* DCS with UART readmem/writemem structures */
208 MEMORY_READ16_START( dcs_uart_readmem )
209 { ADSP_DATA_ADDR_RANGE(0x0000, 0x1fff), MRA16_RAM }, /* ??? */
210 { ADSP_DATA_ADDR_RANGE(0x2000, 0x2fff), dcs_rombank_data_r }, /* banked roms read */
211 { ADSP_DATA_ADDR_RANGE(0x3400, 0x3402), MRA16_NOP }, /* UART (ignored) */
212 { ADSP_DATA_ADDR_RANGE(0x3403, 0x3403), input_latch_r }, /* soundlatch read */
213 { ADSP_DATA_ADDR_RANGE(0x3404, 0x3405), MRA16_NOP }, /* UART (ignored) */
214 { ADSP_DATA_ADDR_RANGE(0x3800, 0x39ff), MRA16_RAM }, /* internal data ram */
215 { ADSP_PGM_ADDR_RANGE (0x0000, 0x1fff), MRA16_RAM }, /* internal/external program ram */
216 MEMORY_END
217
218
219 MEMORY_WRITE16_START( dcs_uart_writemem )
220 { ADSP_DATA_ADDR_RANGE(0x0000, 0x1fff), MWA16_RAM }, /* ??? */
221 { ADSP_DATA_ADDR_RANGE(0x3000, 0x3000), dcs_rombank_select_w }, /* bank selector */
222 { ADSP_DATA_ADDR_RANGE(0x3400, 0x3402), MWA16_NOP }, /* UART (ignored) */
223 { ADSP_DATA_ADDR_RANGE(0x3403, 0x3403), output_latch_w }, /* soundlatch write */
224 { ADSP_DATA_ADDR_RANGE(0x3404, 0x3405), MWA16_NOP }, /* UART (ignored) */
225 { ADSP_DATA_ADDR_RANGE(0x3800, 0x39ff), MWA16_RAM }, /* internal data ram */
226 { ADSP_DATA_ADDR_RANGE(0x3fe0, 0x3fff), dcs_control_w }, /* adsp control regs */
227 { ADSP_PGM_ADDR_RANGE (0x0000, 0x1fff), MWA16_RAM }, /* internal/external program ram */
228 MEMORY_END
229
230
231
232 /* DCS2-based readmem/writemem structures */
233 MEMORY_READ16_START( dcs2_readmem )
234 { ADSP_DATA_ADDR_RANGE(0x0000, 0x03ff), MRA16_BANK20 }, /* D/RAM */
235 { ADSP_DATA_ADDR_RANGE(0x0400, 0x0400), input_latch_r }, /* input latch read */
236 { ADSP_DATA_ADDR_RANGE(0x0402, 0x0402), output_control_r }, /* secondary soundlatch read */
237 { ADSP_DATA_ADDR_RANGE(0x0403, 0x0403), latch_status_r }, /* latch status read */
238 { ADSP_DATA_ADDR_RANGE(0x0404, 0x0407), fifo_input_r }, /* FIFO input read */
239 { ADSP_DATA_ADDR_RANGE(0x0480, 0x0480), dcs_sram_bank_r }, /* S/RAM bank */
240 { ADSP_DATA_ADDR_RANGE(0x0481, 0x0481), MRA16_NOP }, /* LED in bit $2000 */
241 { ADSP_DATA_ADDR_RANGE(0x0482, 0x0482), dcs_dram_bank_r }, /* D/RAM bank */
242 { ADSP_DATA_ADDR_RANGE(0x0483, 0x0483), dcs_sdrc_asic_ver_r }, /* SDRC version number */
243 { ADSP_DATA_ADDR_RANGE(0x0800, 0x17ff), MRA16_RAM }, /* S/RAM */
244 { ADSP_DATA_ADDR_RANGE(0x1800, 0x27ff), MRA16_BANK21 }, /* banked S/RAM */
245 { ADSP_DATA_ADDR_RANGE(0x2800, 0x37ff), MRA16_RAM }, /* S/RAM */
246 { ADSP_DATA_ADDR_RANGE(0x3800, 0x39ff), MRA16_RAM }, /* internal data ram */
247 { ADSP_PGM_ADDR_RANGE (0x0000, 0x3fff), MRA16_RAM }, /* internal/external program ram */
248 MEMORY_END
249
250
251 MEMORY_WRITE16_START( dcs2_writemem )
252 { ADSP_DATA_ADDR_RANGE(0x0000, 0x03ff), MWA16_BANK20 }, /* D/RAM */
253 { ADSP_DATA_ADDR_RANGE(0x0400, 0x0400), input_latch_ack_w }, /* input latch ack */
254 { ADSP_DATA_ADDR_RANGE(0x0401, 0x0401), output_latch_w }, /* soundlatch write */
255 { ADSP_DATA_ADDR_RANGE(0x0402, 0x0402), output_control_w }, /* secondary soundlatch write */
256 { ADSP_DATA_ADDR_RANGE(0x0480, 0x0480), dcs_sram_bank_w }, /* S/RAM bank */
257 { ADSP_DATA_ADDR_RANGE(0x0481, 0x0481), MWA16_NOP }, /* LED in bit $2000 */
258 { ADSP_DATA_ADDR_RANGE(0x0482, 0x0482), dcs_dram_bank_w }, /* D/RAM bank */
259 { ADSP_DATA_ADDR_RANGE(0x0800, 0x17ff), MWA16_RAM }, /* S/RAM */
260 { ADSP_DATA_ADDR_RANGE(0x1800, 0x27ff), MWA16_BANK21, &dcs_sram_bank0 },/* banked S/RAM */
261 { ADSP_DATA_ADDR_RANGE(0x2800, 0x37ff), MWA16_RAM }, /* S/RAM */
262 { ADSP_DATA_ADDR_RANGE(0x3800, 0x39ff), MWA16_RAM }, /* internal data ram */
263 { ADSP_DATA_ADDR_RANGE(0x3fe0, 0x3fff), dcs_control_w }, /* adsp control regs */
264 { ADSP_PGM_ADDR_RANGE (0x0000, 0x3fff), MWA16_RAM }, /* internal/external program ram */
265 MEMORY_END
266
267
268
269 /***************************************************************************
270 AUDIO STRUCTURES
271 ****************************************************************************/
272
273 /* Custom structure (DCS variant) */
274 static struct CustomSound_interface dcs_custom_interface =
275 {
276 dcs_custom_start,0,0
277 };
278
279 static struct CustomSound_interface dcs2_custom_interface =
280 {
281 dcs2_custom_start,0,0
282 };
283
284
285
286 /***************************************************************************
287 MACHINE DRIVERS
288 ****************************************************************************/
289
290 MACHINE_DRIVER_START( dcs_audio )
291 MDRV_CPU_ADD_TAG("dcs", ADSP2105, 10000000)
MDRV_CPU_FLAGS(CPU_AUDIO_CPU)292 MDRV_CPU_FLAGS(CPU_AUDIO_CPU)
293 MDRV_CPU_MEMORY(dcs_readmem,dcs_writemem)
294
295 MDRV_SOUND_ADD(CUSTOM, dcs_custom_interface)
296 MACHINE_DRIVER_END
297
298
299 MACHINE_DRIVER_START( dcs_audio_uart )
300 MDRV_IMPORT_FROM(dcs_audio)
301
302 MDRV_CPU_MODIFY("dcs")
303 MDRV_CPU_MEMORY(dcs_uart_readmem,dcs_uart_writemem)
304 MACHINE_DRIVER_END
305
306
307 MACHINE_DRIVER_START( dcs2_audio )
308 MDRV_CPU_ADD_TAG("dcs2", ADSP2115, 16000000)
309 MDRV_CPU_FLAGS(CPU_AUDIO_CPU)
310 MDRV_CPU_MEMORY(dcs2_readmem,dcs2_writemem)
311
312 MDRV_SOUND_ATTRIBUTES(SOUND_SUPPORTS_STEREO)
313 MDRV_SOUND_ADD(CUSTOM, dcs2_custom_interface)
314 MACHINE_DRIVER_END
315
316
317 MACHINE_DRIVER_START( dcs2_audio_2104 )
318 MDRV_IMPORT_FROM(dcs2_audio)
319 MDRV_CPU_REPLACE("dcs2", ADSP2104, 16000000)
320 MACHINE_DRIVER_END
321
322
323
324 /***************************************************************************
325 INITIALIZATION
326 ****************************************************************************/
327
328 static void dcs_boot(void)
329 {
330 data8_t *src = (data8_t *)(memory_region(REGION_CPU1 + dcs_cpunum) + ADSP2100_SIZE);
331 data32_t *dst = (data32_t *)(memory_region(REGION_CPU1 + dcs_cpunum) + ADSP2100_PGM_OFFSET);
332 switch (Machine->drv->cpu[dcs_cpunum].cpu_type)
333 {
334 case CPU_ADSP2104:
335 adsp2104_load_boot_data(src + 0x2000 * ((dcs.control_regs[SYSCONTROL_REG] >> 6) & 7), dst);
336 break;
337 case CPU_ADSP2105:
338 adsp2105_load_boot_data(src + (dcs.rombank & 0x7ff) * 0x1000, dst);
339 break;
340 case CPU_ADSP2115:
341 adsp2115_load_boot_data(src + (dcs.rombank & 0x7ff) * 0x1000, dst);
342 break;
343 }
344 }
345
346
dcs_reset(void)347 static void dcs_reset(void)
348 {
349 int i;
350
351 /* initialize our state structure and install the transmit callback */
352 dcs.mem = 0;
353 dcs.size = 0;
354 dcs.incs = 0;
355 dcs.ireg = 0;
356
357 /* initialize the ADSP control regs */
358 for (i = 0; i < sizeof(dcs.control_regs) / sizeof(dcs.control_regs[0]); i++)
359 dcs.control_regs[i] = 0;
360
361 /* initialize banking */
362 dcs.rombank = 0;
363 dcs.srambank = 0;
364 dcs.drambank = 0;
365 if (dcs_sram_bank0)
366 {
367 cpu_setbank(20, memory_region(REGION_CPU1 + dcs_cpunum) + ADSP2100_SIZE + 0x8000);
368 cpu_setbank(21, dcs_sram_bank0);
369 }
370
371 /* start with no sound output */
372 dcs.enabled = 0;
373
374 /* reset DAC generation */
375 dcs.buffer_in = 0;
376 dcs.sample_step = 0x10000;
377 dcs.sample_position = 0;
378 dcs.current_sample = 0;
379
380 /* initialize the ADSP Tx callback */
381 adsp2105_set_tx_callback(sound_tx_callback);
382
383 /* clear all interrupts */
384 cpu_set_irq_line(dcs_cpunum, ADSP2105_IRQ0, CLEAR_LINE);
385 cpu_set_irq_line(dcs_cpunum, ADSP2105_IRQ1, CLEAR_LINE);
386 cpu_set_irq_line(dcs_cpunum, ADSP2105_IRQ2, CLEAR_LINE);
387
388 /* initialize the comm bits */
389 SET_INPUT_EMPTY();
390 SET_OUTPUT_EMPTY();
391 if (!dcs.last_input_empty && dcs.input_empty_cb)
392 (*dcs.input_empty_cb)(dcs.last_input_empty = 1);
393 if (dcs.last_output_full && dcs.output_full_cb)
394 (*dcs.output_full_cb)(dcs.last_output_full = 0);
395
396 /* boot */
397 dcs.control_regs[SYSCONTROL_REG] = 0;
398 dcs_boot();
399
400 /* start the SPORT0 timer */
401 if (dcs.sport_timer)
402 timer_adjust(dcs.sport_timer, TIME_IN_HZ(1000), 0, TIME_IN_HZ(1000));
403 }
404
405
dcs_init(void)406 void dcs_init(void)
407 {
408 /* find the DCS CPU */
409 dcs_cpunum = mame_find_cpu_index("dcs");
410
411 /* reset RAM-based variables */
412 dcs_sram_bank0 = dcs_sram_bank1 = NULL;
413
414
415 /* install the speedup handler */
416 if (options.activate_dcs_speedhack)
417 {
418 dcs_speedup1 = install_mem_write16_handler(dcs_cpunum, ADSP_DATA_ADDR_RANGE(0x04f8, 0x04f8), dcs_speedup1_w);
419 dcs_speedup2 = install_mem_write16_handler(dcs_cpunum, ADSP_DATA_ADDR_RANGE(0x063d, 0x063d), dcs_speedup2_w);
420 dcs_speedup3 = install_mem_write16_handler(dcs_cpunum, ADSP_DATA_ADDR_RANGE(0x063a, 0x063a), dcs_speedup3_w);
421 dcs_speedup4 = install_mem_write16_handler(dcs_cpunum, ADSP_DATA_ADDR_RANGE(0x0641, 0x0641), dcs_speedup4_w);
422 }
423
424 /* create the timer */
425 dcs.reg_timer = timer_alloc(dcs_irq);
426 dcs.sport_timer = NULL;
427
428 /* disable notification by default */
429 dcs.output_full_cb = NULL;
430 dcs.input_empty_cb = NULL;
431
432 /* non-RAM based automatically acks */
433 dcs.auto_ack = 1;
434
435 /* reset the system */
436 dcs_reset();
437 }
438
439
dcs2_init(offs_t polling_offset)440 void dcs2_init(offs_t polling_offset)
441 {
442 UINT8 *romsrc;
443 int page, i;
444
445 /* find the DCS CPU */
446 dcs_cpunum = mame_find_cpu_index("dcs2");
447
448 /* borrow memory for the extra 8k */
449 dcs_sram_bank1 = (UINT16 *)(memory_region(REGION_CPU1 + dcs_cpunum) + 0x8000);
450
451 /* borrow memory also for the expanded ROM data and expand it */
452 romsrc = memory_region(REGION_CPU1 + dcs_cpunum) + ADSP2100_SIZE;
453 dcs_expanded_rom = (UINT16 *)(memory_region(REGION_CPU1 + dcs_cpunum) + 0xc000);
454 for (page = 0; page < 8; page++)
455 for (i = 0; i < 0x400; i++)
456 dcs_expanded_rom[0x400 * page + i] = romsrc[BYTE_XOR_LE(0x1000 * page + i)];
457
458 /* install the speedup handler */
459 if (options.activate_dcs_speedhack)
460 {
461 dcs_speedup1 = install_mem_write16_handler(dcs_cpunum, ADSP_DATA_ADDR_RANGE(0x04f8, 0x04f8), dcs_speedup1_w);
462 dcs_speedup2 = install_mem_write16_handler(dcs_cpunum, ADSP_DATA_ADDR_RANGE(0x063d, 0x063d), dcs_speedup2_w);
463 dcs_speedup3 = install_mem_write16_handler(dcs_cpunum, ADSP_DATA_ADDR_RANGE(0x063a, 0x063a), dcs_speedup3_w);
464 dcs_speedup4 = install_mem_write16_handler(dcs_cpunum, ADSP_DATA_ADDR_RANGE(0x0641, 0x0641), dcs_speedup4_w);
465 }
466
467 /* create the timer */
468 dcs.reg_timer = timer_alloc(dcs_irq);
469 dcs.sport_timer = timer_alloc(sport0_irq);
470
471 /* RAM based doesn't do auto-ack, but it has a FIFO */
472 dcs.auto_ack = 0;
473 dcs.output_full_cb = NULL;
474 dcs.input_empty_cb = NULL;
475 dcs.fifo_data_r = NULL;
476 dcs.fifo_status_r = NULL;
477
478 /* install the speedup handler */
479 if (polling_offset)
480 dcs_polling_base = install_mem_read16_handler(dcs_cpunum, ADSP_DATA_ADDR_RANGE(polling_offset, polling_offset), dcs_polling_r);
481
482 /* reset the system */
483 dcs_reset();
484 }
485
486
dcs_set_auto_ack(int state)487 void dcs_set_auto_ack(int state)
488 {
489 dcs.auto_ack = state;
490 }
491
492
493
494 /***************************************************************************
495 CUSTOM SOUND INTERFACES
496 ****************************************************************************/
497
dcs_custom_start(const struct MachineSound * msound)498 static int dcs_custom_start(const struct MachineSound *msound)
499 {
500 /* allocate a DAC stream */
501 dcs.stream = stream_init("DCS DAC", 100, Machine->sample_rate, 0, dcs_dac_update);
502
503 /* allocate memory for our buffer */
504 dcs.buffer = auto_malloc(DCS_BUFFER_SIZE * sizeof(INT16));
505 dcs.buffer2 = NULL;
506 if (!dcs.buffer)
507 return 1;
508
509 return 0;
510 }
511
512
dcs2_custom_start(const struct MachineSound * msound)513 static int dcs2_custom_start(const struct MachineSound *msound)
514 {
515 const char *names[] = { "DCS DAC R", "DCS DAC L" };
516 int vols[] = { MIXER(100, MIXER_PAN_RIGHT), MIXER(100, MIXER_PAN_LEFT) };
517
518 /* allocate a DAC stream */
519 dcs.stream = stream_init_multi(2, names, vols, Machine->sample_rate, 0, dcs2_dac_update);
520
521 /* allocate memory for our buffer */
522 dcs.buffer = auto_malloc(DCS_BUFFER_SIZE * sizeof(INT16));
523 dcs.buffer2 = auto_malloc(DCS_BUFFER_SIZE * sizeof(INT16));
524 if (!dcs.buffer || !dcs.buffer2)
525 return 1;
526
527 return 0;
528 }
529
530
531
532 /***************************************************************************
533 DCS ASIC VERSION
534 ****************************************************************************/
535
READ16_HANDLER(dcs_sdrc_asic_ver_r)536 static READ16_HANDLER( dcs_sdrc_asic_ver_r )
537 {
538 return 0x5a03;
539 }
540
541
542
543 /***************************************************************************
544 DCS ROM BANK SELECT
545 ****************************************************************************/
546
WRITE16_HANDLER(dcs_rombank_select_w)547 static WRITE16_HANDLER( dcs_rombank_select_w )
548 {
549 dcs.rombank = data & 0x7ff;
550
551 /* bit 11 = sound board led */
552 #if 0
553 set_led_status(2, data & 0x800);
554 #endif
555
556 if (options.activate_dcs_speedhack)
557 {
558 /* they write 0x800 here just before entering the stall loop */
559 if (data == 0x800)
560 {
561 /* calculate the next buffer address */
562 int source = activecpu_get_reg(ADSP2100_I0 + dcs.ireg);
563 int ar = source + dcs.size / 2;
564
565 /* check for wrapping */
566 if (ar >= (dcs.ireg_base + dcs.size))
567 ar = dcs.ireg_base;
568
569 /* set it */
570 activecpu_set_reg(ADSP2100_AR, ar);
571
572 /* go around the buffer syncing code, we sync manually */
573 activecpu_set_reg(ADSP2100_PC, activecpu_get_pc() + 8);
574 cpu_spinuntil_int();
575 }
576 }
577 }
578
579
READ16_HANDLER(dcs_rombank_data_r)580 static READ16_HANDLER( dcs_rombank_data_r )
581 {
582 UINT8 *banks = memory_region(REGION_CPU1 + dcs_cpunum) + ADSP2100_SIZE;
583
584 offset += (dcs.rombank & 0x7ff) << 12;
585 return banks[BYTE_XOR_LE(offset)];
586 }
587
588
589
590 /***************************************************************************
591 DCS STATIC RAM BANK SELECT
592 ****************************************************************************/
593
WRITE16_HANDLER(dcs_sram_bank_w)594 static WRITE16_HANDLER( dcs_sram_bank_w )
595 {
596 COMBINE_DATA(&dcs.srambank);
597 cpu_setbank(21, (dcs.srambank & 0x1000) ? dcs_sram_bank1 : dcs_sram_bank0);
598
599 /* it appears that the Vegas games also access the boot ROM via this location */
600 if (((dcs.srambank >> 7) & 7) == dcs.drambank)
601 cpu_setbank(20, dcs_expanded_rom + ((dcs.srambank >> 7) & 7) * 0x400);
602 }
603
604
READ16_HANDLER(dcs_sram_bank_r)605 static READ16_HANDLER( dcs_sram_bank_r )
606 {
607 return dcs.srambank;
608 }
609
610
611
612 /***************************************************************************
613 DCS DRAM BANK SELECT
614 ****************************************************************************/
615
WRITE16_HANDLER(dcs_dram_bank_w)616 static WRITE16_HANDLER( dcs_dram_bank_w )
617 {
618 dcs.drambank = data;
619 cpu_setbank(20, memory_region(REGION_CPU1 + dcs_cpunum) + ADSP2100_SIZE + 0x8000 + (dcs.drambank & 0x7ff) * 0x400*2);
620 }
621
622
READ16_HANDLER(dcs_dram_bank_r)623 static READ16_HANDLER( dcs_dram_bank_r )
624 {
625 return dcs.drambank;
626 }
627
628
629
630 /***************************************************************************
631 DCS COMMUNICATIONS
632 ****************************************************************************/
633
dcs_set_io_callbacks(void (* output_full_cb)(int),void (* input_empty_cb)(int))634 void dcs_set_io_callbacks(void (*output_full_cb)(int), void (*input_empty_cb)(int))
635 {
636 dcs.input_empty_cb = input_empty_cb;
637 dcs.output_full_cb = output_full_cb;
638 }
639
640
dcs_set_fifo_callbacks(UINT16 (* fifo_data_r)(void),UINT16 (* fifo_status_r)(void))641 void dcs_set_fifo_callbacks(UINT16 (*fifo_data_r)(void), UINT16 (*fifo_status_r)(void))
642 {
643 dcs.fifo_data_r = fifo_data_r;
644 dcs.fifo_status_r = fifo_status_r;
645 }
646
647
dcs_control_r(void)648 int dcs_control_r(void)
649 {
650 /* only boost for DCS2 boards */
651 if (!dcs.auto_ack)
652 cpu_boost_interleave(TIME_IN_USEC(0.5), TIME_IN_USEC(5));
653 return dcs.latch_control;
654 }
655
656
dcs_reset_w(int state)657 void dcs_reset_w(int state)
658 {
659 /* going low halts the CPU */
660 if (!state)
661 {
662 log_cb(RETRO_LOG_DEBUG, LOGPRE "%08x: DCS reset = %d\n", activecpu_get_pc(), state);
663
664 /* just run through the init code again */
665 dcs_reset();
666 cpu_set_reset_line(dcs_cpunum, ASSERT_LINE);
667 }
668
669 /* going high resets and reactivates the CPU */
670 else
671 cpu_set_reset_line(dcs_cpunum, CLEAR_LINE);
672 }
673
674
READ16_HANDLER(latch_status_r)675 static READ16_HANDLER( latch_status_r )
676 {
677 int result = 0;
678 if (IS_INPUT_FULL())
679 result |= 0x80;
680 if (IS_OUTPUT_EMPTY())
681 result |= 0x40;
682 if (dcs.fifo_status_r)
683 result |= (*dcs.fifo_status_r)() & 0x38;
684 return result;
685 }
686
687
READ16_HANDLER(fifo_input_r)688 static READ16_HANDLER( fifo_input_r )
689 {
690 if (dcs.fifo_data_r)
691 return (*dcs.fifo_data_r)();
692 else
693 return 0xffff;
694 }
695
696
697
698 /***************************************************************************
699 INPUT LATCH (data from host to DCS)
700 ****************************************************************************/
701
dcs_data_w(int data)702 void dcs_data_w(int data)
703 {
704 #if (LOG_DCS_TRANSFERS)
705 if (dcs.sport_timer)
706 switch (transfer_state)
707 {
708 case 0:
709 if (data == 0x55d0 || data == 0x55d1)
710 {
711 log_cb(RETRO_LOG_DEBUG, LOGPRE "DCS Transfer command %04X\n", data);
712 transfer_state++;
713 }
714 else
715 log_cb(RETRO_LOG_DEBUG, LOGPRE "Command: %04X\n", data);
716 break;
717
718 case 1:
719 transfer_start = data << 16;
720 transfer_state++;
721 break;
722
723 case 2:
724 transfer_start |= data;
725 transfer_state++;
726 transfer_dest = (data16_t *)(memory_region(REGION_CPU1 + dcs_cpunum) + ADSP2100_SIZE + 0x8000 + transfer_start*2);
727 log_cb(RETRO_LOG_DEBUG, LOGPRE "Start address = %08X\n", transfer_start);
728 break;
729
730 case 3:
731 transfer_stop = data << 16;
732 transfer_state++;
733 break;
734
735 case 4:
736 transfer_stop |= data;
737 transfer_state++;
738 log_cb(RETRO_LOG_DEBUG, LOGPRE "Stop address = %08X\n", transfer_stop);
739 transfer_writes_left = transfer_stop - transfer_start + 1;
740 transfer_sum = 0;
741 break;
742
743 case 5:
744 transfer_sum += data;
745 if (--transfer_writes_left == 0)
746 {
747 log_cb(RETRO_LOG_DEBUG, LOGPRE "Transfer done, sum = %04X\n", transfer_sum);
748 transfer_state = 0;
749 }
750 break;
751 }
752 #endif
753
754 log_cb(RETRO_LOG_DEBUG, LOGPRE "%08X:dcs_data_w(%04X)\n", activecpu_get_pc(), data);
755
756 cpu_boost_interleave(TIME_IN_USEC(0.5), TIME_IN_USEC(5));
757 cpu_set_irq_line(dcs_cpunum, ADSP2105_IRQ2, ASSERT_LINE);
758
759 if (dcs.last_input_empty && dcs.input_empty_cb)
760 (*dcs.input_empty_cb)(dcs.last_input_empty = 0);
761 SET_INPUT_FULL();
762 dcs.input_data = data;
763 }
764
765
WRITE16_HANDLER(input_latch_ack_w)766 static WRITE16_HANDLER( input_latch_ack_w )
767 {
768 if (!dcs.last_input_empty && dcs.input_empty_cb)
769 (*dcs.input_empty_cb)(dcs.last_input_empty = 1);
770 SET_INPUT_EMPTY();
771 cpu_set_irq_line(dcs_cpunum, ADSP2105_IRQ2, CLEAR_LINE);
772 }
773
774
READ16_HANDLER(input_latch_r)775 static READ16_HANDLER( input_latch_r )
776 {
777 if (dcs.auto_ack)
778 input_latch_ack_w(0,0,0);
779 log_cb(RETRO_LOG_DEBUG, LOGPRE "%08X:input_latch_r(%04X)\n", activecpu_get_pc(), dcs.input_data);
780 return dcs.input_data;
781 }
782
783
784
785 /***************************************************************************
786 OUTPUT LATCH (data from DCS to host)
787 ****************************************************************************/
788
latch_delayed_w(int data)789 static void latch_delayed_w(int data)
790 {
791 if (!dcs.last_output_full && dcs.output_full_cb)
792 (*dcs.output_full_cb)(dcs.last_output_full = 1);
793 SET_OUTPUT_FULL();
794 dcs.output_data = data;
795 }
796
797
WRITE16_HANDLER(output_latch_w)798 static WRITE16_HANDLER( output_latch_w )
799 {
800 log_cb(RETRO_LOG_DEBUG, LOGPRE "%08X:output_latch_w(%04X) (empty=%d)\n", activecpu_get_pc(), data, IS_OUTPUT_EMPTY());
801 timer_set(TIME_NOW, data, latch_delayed_w);
802 }
803
804
delayed_ack_w(int param)805 static void delayed_ack_w(int param)
806 {
807 SET_OUTPUT_EMPTY();
808 }
809
810
dcs_ack_w(void)811 void dcs_ack_w(void)
812 {
813 timer_set(TIME_NOW, 0, delayed_ack_w);
814 }
815
816
dcs_data_r(void)817 int dcs_data_r(void)
818 {
819 /* data is actually only 8 bit (read from d8-d15) */
820 if (dcs.last_output_full && dcs.output_full_cb)
821 (*dcs.output_full_cb)(dcs.last_output_full = 0);
822 if (dcs.auto_ack)
823 delayed_ack_w(0);
824
825 log_cb(RETRO_LOG_DEBUG, LOGPRE "%08X:dcs_data_r(%04X)\n", activecpu_get_pc(), dcs.output_data);
826 return dcs.output_data;
827 }
828
829
830
831 /***************************************************************************
832 OUTPUT CONTROL BITS (has 3 additional lines to the host)
833 ****************************************************************************/
834
output_control_delayed_w(int data)835 static void output_control_delayed_w(int data)
836 {
837 log_cb(RETRO_LOG_DEBUG, LOGPRE "output_control = %04X\n", data);
838 dcs.output_control = data;
839 dcs.output_control_cycles = 0;
840 }
841
842
WRITE16_HANDLER(output_control_w)843 static WRITE16_HANDLER( output_control_w )
844 {
845 log_cb(RETRO_LOG_DEBUG, LOGPRE "%04X:output_control = %04X\n", activecpu_get_pc(), data);
846 timer_set(TIME_NOW, data, output_control_delayed_w);
847 }
848
849
READ16_HANDLER(output_control_r)850 static READ16_HANDLER( output_control_r )
851 {
852 dcs.output_control_cycles = activecpu_gettotalcycles();
853 return dcs.output_control;
854 }
855
856
dcs_data2_r(void)857 int dcs_data2_r(void)
858 {
859 return dcs.output_control;
860 }
861
862
863
864 /***************************************************************************
865 SOUND GENERATION
866 ****************************************************************************/
867
dcs_dac_update(int num,INT16 * buffer,int length)868 static void dcs_dac_update(int num, INT16 *buffer, int length)
869 {
870 UINT32 current, step, indx;
871 INT16 *source;
872 int i;
873
874 /* DAC generation */
875 if (dcs.enabled)
876 {
877 source = dcs.buffer;
878 current = dcs.sample_position;
879 step = dcs.sample_step;
880
881 /* fill in with samples until we hit the end or run out */
882 for (i = 0; i < length; i++)
883 {
884 indx = current >> 16;
885 if (indx >= dcs.buffer_in)
886 break;
887 current += step;
888 *buffer++ = source[indx & DCS_BUFFER_MASK];
889 }
890
891 if (i < length)
892 log_cb(RETRO_LOG_DEBUG, LOGPRE "DCS ran out of input data\n");
893
894 /* fill the rest with the last sample */
895 for ( ; i < length; i++)
896 *buffer++ = source[(dcs.buffer_in - 1) & DCS_BUFFER_MASK];
897
898 /* mask off extra bits */
899 while (current >= (DCS_BUFFER_SIZE << 16))
900 {
901 current -= DCS_BUFFER_SIZE << 16;
902 dcs.buffer_in -= DCS_BUFFER_SIZE;
903 }
904
905 log_cb(RETRO_LOG_DEBUG, LOGPRE "DCS dac update: bytes in buffer = %d\n", dcs.buffer_in - (current >> 16));
906
907 /* update the final values */
908 dcs.sample_position = current;
909 }
910 else
911 memset(buffer, 0, length * sizeof(INT16));
912 }
913
914
dcs2_dac_update(int num,INT16 ** buffer,int length)915 static void dcs2_dac_update(int num, INT16 **buffer, int length)
916 {
917 INT16 *destl = buffer[0], *destr = buffer[1];
918 UINT32 current, step, indx;
919 INT16 *sourcel, *sourcer;
920 int i;
921
922 /* DAC generation */
923 if (dcs.enabled)
924 {
925 sourcel = dcs.buffer;
926 sourcer = dcs.buffer2;
927 current = dcs.sample_position;
928 step = dcs.sample_step;
929
930 /* fill in with samples until we hit the end or run out */
931 for (i = 0; i < length; i++)
932 {
933 indx = current >> 16;
934 if (indx >= dcs.buffer_in)
935 break;
936 current += step;
937 *destl++ = sourcel[indx & DCS_BUFFER_MASK];
938 *destr++ = sourcer[indx & DCS_BUFFER_MASK];
939 }
940
941 if (i < length)
942 log_cb(RETRO_LOG_DEBUG, LOGPRE "DCS ran out of input data\n");
943
944 /* fill the rest with the last sample */
945 for ( ; i < length; i++)
946 {
947 *destl++ = sourcel[(dcs.buffer_in - 1) & DCS_BUFFER_MASK];
948 *destr++ = sourcer[(dcs.buffer_in - 1) & DCS_BUFFER_MASK];
949 }
950
951 /* mask off extra bits */
952 while (current >= (DCS_BUFFER_SIZE << 16))
953 {
954 current -= DCS_BUFFER_SIZE << 16;
955 dcs.buffer_in -= DCS_BUFFER_SIZE;
956 }
957
958 log_cb(RETRO_LOG_DEBUG, LOGPRE "DCS dac update: bytes in buffer = %d\n", dcs.buffer_in - (current >> 16));
959
960 /* update the final values */
961 dcs.sample_position = current;
962 }
963 else
964 {
965 memset(destl, 0, length * sizeof(INT16));
966 memset(destr, 0, length * sizeof(INT16));
967 }
968 }
969
970
971
972 /***************************************************************************
973 ADSP CONTROL & TRANSMIT CALLBACK
974 ****************************************************************************/
975
976 /*
977 The ADSP2105 memory map when in boot rom mode is as follows:
978
979 Program Memory:
980 0x0000-0x03ff = Internal Program Ram (contents of boot rom gets copied here)
981 0x0400-0x07ff = Reserved
982 0x0800-0x3fff = External Program Ram
983
984 Data Memory:
985 0x0000-0x03ff = External Data - 0 Waitstates
986 0x0400-0x07ff = External Data - 1 Waitstates
987 0x0800-0x2fff = External Data - 2 Waitstates
988 0x3000-0x33ff = External Data - 3 Waitstates
989 0x3400-0x37ff = External Data - 4 Waitstates
990 0x3800-0x39ff = Internal Data Ram
991 0x3a00-0x3bff = Reserved (extra internal ram space on ADSP2101, etc)
992 0x3c00-0x3fff = Memory Mapped control registers & reserved.
993 */
994
WRITE16_HANDLER(dcs_control_w)995 static WRITE16_HANDLER( dcs_control_w )
996 {
997 dcs.control_regs[offset] = data;
998 switch (offset)
999 {
1000 case SYSCONTROL_REG:
1001 if (data & 0x0200)
1002 {
1003 /* boot force */
1004 cpu_set_reset_line(dcs_cpunum, PULSE_LINE);
1005 dcs_boot();
1006 dcs.control_regs[SYSCONTROL_REG] &= ~0x0200;
1007 }
1008
1009 /* see if SPORT1 got disabled */
1010 stream_update(dcs.stream, 0);
1011 if ((data & 0x0800) == 0)
1012 {
1013 dcs.enabled = 0;
1014 timer_adjust(dcs.reg_timer, TIME_NEVER, 0, 0);
1015 }
1016 break;
1017
1018 case S1_AUTOBUF_REG:
1019 /* autobuffer off: nuke the timer, and disable the DAC */
1020 stream_update(dcs.stream, 0);
1021 if ((data & 0x0002) == 0)
1022 {
1023 dcs.enabled = 0;
1024 timer_adjust(dcs.reg_timer, TIME_NEVER, 0, 0);
1025 }
1026 break;
1027
1028 case S1_CONTROL_REG:
1029 if (((data >> 4) & 3) == 2)
1030 log_cb(RETRO_LOG_DEBUG, LOGPRE "Oh no!, the data is compresed with u-law encoding\n");
1031 if (((data >> 4) & 3) == 3)
1032 log_cb(RETRO_LOG_DEBUG, LOGPRE "Oh no!, the data is compresed with A-law encoding\n");
1033 break;
1034 }
1035 }
1036
1037
1038
1039 /***************************************************************************
1040 DCS IRQ GENERATION CALLBACKS
1041 ****************************************************************************/
1042
dcs_irq(int state)1043 static void dcs_irq(int state)
1044 {
1045 /* get the index register */
1046 int reg = cpunum_get_reg(dcs_cpunum, ADSP2100_I0 + dcs.ireg);
1047
1048 /* translate into data memory bus address */
1049 int source = ADSP2100_DATA_OFFSET + (reg << 1);
1050 int i;
1051
1052 /* copy the current data into the buffer */
1053 if (!dcs.buffer2)
1054 {
1055 for (i = 0; i < dcs.size / 2; i += dcs.incs)
1056 dcs.buffer[dcs.buffer_in++ & DCS_BUFFER_MASK] = ((UINT16 *)&dcs.mem[source])[i];
1057 }
1058 else
1059 {
1060 for (i = 0; i < dcs.size / 2; i += dcs.incs * 2)
1061 {
1062 dcs.buffer[dcs.buffer_in & DCS_BUFFER_MASK] = ((UINT16 *)&dcs.mem[source])[i];
1063 dcs.buffer2[dcs.buffer_in & DCS_BUFFER_MASK] = ((UINT16 *)&dcs.mem[source])[i + dcs.incs];
1064 dcs.buffer_in++;
1065 }
1066 }
1067
1068 /* increment it */
1069 reg += dcs.size / 2;
1070
1071 /* check for wrapping */
1072 if (reg >= dcs.ireg_base + dcs.size)
1073 {
1074 /* reset the base pointer */
1075 reg = dcs.ireg_base;
1076
1077 /* generate the (internal, thats why the pulse) irq */
1078 cpu_set_irq_line(dcs_cpunum, ADSP2105_IRQ1, PULSE_LINE);
1079 }
1080
1081 /* store it */
1082 cpunum_set_reg(dcs_cpunum, ADSP2100_I0 + dcs.ireg, reg);
1083
1084 if (options.activate_dcs_speedhack)
1085 /* this is the same trigger as an interrupt */
1086 cpu_triggerint(dcs_cpunum);
1087 }
1088
1089
sport0_irq(int state)1090 static void sport0_irq(int state)
1091 {
1092 /* this latches internally, so we just pulse */
1093 /* note that there is non-interrupt code that reads/modifies/writes the output_control */
1094 /* register; if we don't interlock it, we will eventually lose sound (see CarnEvil) */
1095 /* so we skip the SPORT interrupt if we read with output_control within the last 5 cycles */
1096 if ((cpunum_gettotalcycles(dcs_cpunum) - dcs.output_control_cycles) > 5)
1097 cpu_set_irq_line(dcs_cpunum, ADSP2115_SPORT0_RX, PULSE_LINE);
1098 }
1099
1100
sound_tx_callback(int port,INT32 data)1101 static void sound_tx_callback(int port, INT32 data)
1102 {
1103 /* check if it's for SPORT1 */
1104 if (port != 1)
1105 return;
1106
1107 /* check if SPORT1 is enabled */
1108 if (dcs.control_regs[SYSCONTROL_REG] & 0x0800) /* bit 11 */
1109 {
1110 /* we only support autobuffer here (wich is what this thing uses), bail if not enabled */
1111 if (dcs.control_regs[S1_AUTOBUF_REG] & 0x0002) /* bit 1 */
1112 {
1113 /* get the autobuffer registers */
1114 int mreg, lreg;
1115 UINT16 source;
1116 int sample_rate;
1117
1118 stream_update(dcs.stream, 0);
1119
1120 dcs.ireg = (dcs.control_regs[S1_AUTOBUF_REG] >> 9) & 7;
1121 mreg = (dcs.control_regs[S1_AUTOBUF_REG] >> 7) & 3;
1122 mreg |= dcs.ireg & 0x04; /* msb comes from ireg */
1123 lreg = dcs.ireg;
1124
1125 /* now get the register contents in a more legible format */
1126 /* we depend on register indexes to be continuous (wich is the case in our core) */
1127 source = cpunum_get_reg(dcs_cpunum, ADSP2100_I0 + dcs.ireg);
1128 dcs.incs = cpunum_get_reg(dcs_cpunum, ADSP2100_M0 + mreg);
1129 dcs.size = cpunum_get_reg(dcs_cpunum, ADSP2100_L0 + lreg);
1130
1131 /* get the base value, since we need to keep it around for wrapping */
1132 source -= dcs.incs;
1133
1134 /* make it go back one so we dont lose the first sample */
1135 cpunum_set_reg(dcs_cpunum, ADSP2100_I0 + dcs.ireg, source);
1136
1137 /* save it as it is now */
1138 dcs.ireg_base = source;
1139
1140 /* get the memory chunk to read the data from */
1141 dcs.mem = memory_region(REGION_CPU1 + dcs_cpunum);
1142
1143 /* enable the dac playing */
1144 dcs.enabled = 1;
1145
1146 /* calculate how long until we generate an interrupt */
1147
1148 /* frequency in Hz per each bit sent */
1149 sample_rate = Machine->drv->cpu[dcs_cpunum].cpu_clock / (2 * (dcs.control_regs[S1_SCLKDIV_REG] + 1));
1150
1151 /* now put it down to samples, so we know what the channel frequency has to be */
1152 sample_rate /= 16;
1153 if (dcs.buffer2)
1154 sample_rate /= 2;
1155
1156 /* fire off a timer wich will hit every half-buffer */
1157 if (!dcs.buffer2)
1158 timer_adjust(dcs.reg_timer, TIME_IN_HZ(sample_rate) * (dcs.size / (2 * dcs.incs)), 0, TIME_IN_HZ(sample_rate) * (dcs.size / (2 * dcs.incs)));
1159 else
1160 timer_adjust(dcs.reg_timer, TIME_IN_HZ(sample_rate) * (dcs.size / (4 * dcs.incs)), 0, TIME_IN_HZ(sample_rate) * (dcs.size / (4 * dcs.incs)));
1161
1162 /* configure the DAC generator */
1163 dcs.sample_step = (int)(sample_rate * 65536.0 / (double)Machine->sample_rate);
1164 dcs.sample_position = 0;
1165 dcs.buffer_in = 0;
1166
1167 return;
1168 }
1169 else
1170 log_cb(RETRO_LOG_DEBUG, LOGPRE "ADSP SPORT1: trying to transmit and autobuffer not enabled!\n" );
1171 }
1172
1173 /* if we get there, something went wrong. Disable playing */
1174 stream_update(dcs.stream, 0);
1175 dcs.enabled = 0;
1176
1177 /* remove timer */
1178 timer_adjust(dcs.reg_timer, TIME_NEVER, 0, 0);
1179 }
1180
1181 /***************************************************************************
1182 DCS SPEEDUPS
1183 ****************************************************************************/
1184
WRITE16_HANDLER(dcs_speedup1_w)1185 static WRITE16_HANDLER( dcs_speedup1_w )
1186 {
1187 /*
1188 MK3: trigger = $04F8 = 2, PC = $00FD, SKIPTO = $0128
1189 UMK3: trigger = $04F8 = 2, PC = $00FD, SKIPTO = $0128
1190 OPENICE: trigger = $04F8 = 2, PC = $00FD, SKIPTO = $0128
1191 WWFMANIA:trigger = $04F8 = 2, PC = $00FD, SKIPTO = $0128
1192 NBAHANGT:trigger = $04F8 = 2, PC = $00FD, SKIPTO = $0128
1193 NBAMAXHT:trigger = $04F8 = 2, PC = $00FD, SKIPTO = $0128
1194 RMPGWT: trigger = $04F8 = 2, PC = $00FD, SKIPTO = $0128
1195 */
1196 COMBINE_DATA(&dcs_speedup1[offset]);
1197 if (data == 2 && activecpu_get_pc() == 0xfd)
1198 dcs_speedup_common();
1199 }
1200
1201
WRITE16_HANDLER(dcs_speedup2_w)1202 static WRITE16_HANDLER( dcs_speedup2_w )
1203 {
1204 /*
1205 MK2: trigger = $063D = 2, PC = $00F6, SKIPTO = $0121
1206 REVX: trigger = $063D = 2, PC = $00F6, SKIPTO = $0121
1207 KINST: trigger = $063D = 2, PC = $00F6, SKIPTO = $0121
1208 */
1209 COMBINE_DATA(&dcs_speedup2[offset]);
1210 if (data == 2 && activecpu_get_pc() == 0xf6)
1211 dcs_speedup_common();
1212 }
1213
1214
WRITE16_HANDLER(dcs_speedup3_w)1215 static WRITE16_HANDLER( dcs_speedup3_w )
1216 {
1217 /*
1218 CRUSNUSA: trigger = $063A = 2, PC = $00E1, SKIPTO = $010C
1219 */
1220 COMBINE_DATA(&dcs_speedup3[offset]);
1221 if (data == 2 && activecpu_get_pc() == 0xe1)
1222 dcs_speedup_common();
1223 }
1224
1225
WRITE16_HANDLER(dcs_speedup4_w)1226 static WRITE16_HANDLER( dcs_speedup4_w )
1227 {
1228 /*
1229 CRUSNWLD: trigger = $0641 = 2, PC = $00DA, SKIPTO = $0105
1230 OFFROADC: trigger = $0641 = 2, PC = $00DA, SKIPTO = $0105
1231 */
1232 COMBINE_DATA(&dcs_speedup4[offset]);
1233 if (data == 2 && activecpu_get_pc() == 0xda)
1234 dcs_speedup_common();
1235 }
1236
1237
dcs_speedup_common(void)1238 static void dcs_speedup_common(void)
1239 {
1240 /*
1241 00F4: AR = $0002
1242 00F5: DM($063D) = AR
1243 00F6: SI = $0040
1244 00F7: DM($063E) = SI
1245 00F8: SR = LSHIFT SI BY -1 (LO)
1246 00F9: DM($063F) = SR0
1247 00FA: M0 = $3FFF
1248 00FB: CNTR = $0006
1249 00FC: DO $0120 UNTIL CE
1250 00FD: I4 = $0780
1251 00FE: I5 = $0700
1252 00FF: I0 = $3800
1253 0100: I1 = $3800
1254 0101: AY0 = DM($063E)
1255 0102: M2 = AY0
1256 0103: MODIFY (I1,M2)
1257 0104: I2 = I1
1258 0105: AR = AY0 - 1
1259 0106: M3 = AR
1260 0107: CNTR = DM($063D)
1261 0108: DO $0119 UNTIL CE
1262 0109: CNTR = DM($063F)
1263 010A: MY0 = DM(I4,M5)
1264 010B: MY1 = DM(I5,M5)
1265 010C: MX0 = DM(I1,M1)
1266 010D: DO $0116 UNTIL CE
1267 010E: MR = MX0 * MY0 (SS), MX1 = DM(I1,M1)
1268 010F: MR = MR - MX1 * MY1 (RND), AY0 = DM(I0,M1)
1269 0110: MR = MX1 * MY0 (SS), AX0 = MR1
1270 0111: MR = MR + MX0 * MY1 (RND), AY1 = DM(I0,M0)
1271 0112: AR = AY0 - AX0, MX0 = DM(I1,M1)
1272 0113: AR = AX0 + AY0, DM(I0,M1) = AR
1273 0114: AR = AY1 - MR1, DM(I2,M1) = AR
1274 0115: AR = MR1 + AY1, DM(I0,M1) = AR
1275 0116: DM(I2,M1) = AR
1276 0117: MODIFY (I2,M2)
1277 0118: MODIFY (I1,M3)
1278 0119: MODIFY (I0,M2)
1279 011A: SI = DM($063D)
1280 011B: SR = LSHIFT SI BY 1 (LO)
1281 011C: DM($063D) = SR0
1282 011D: SI = DM($063F)
1283 011E: DM($063E) = SI
1284 011F: SR = LSHIFT SI BY -1 (LO)
1285 0120: DM($063F) = SR0
1286 */
1287
1288 INT16 *source = (INT16 *)memory_region(REGION_CPU1 + dcs_cpunum);
1289 int mem63d = 2;
1290 int mem63e = 0x40;
1291 int mem63f = mem63e >> 1;
1292 int i, j, k;
1293
1294 for (i = 0; i < 6; i++)
1295 {
1296 INT16 *i4 = &source[0x780];
1297 INT16 *i5 = &source[0x700];
1298 INT16 *i0 = &source[0x3800];
1299 INT16 *i1 = &source[0x3800 + mem63e];
1300 INT16 *i2 = i1;
1301
1302 for (j = 0; j < mem63d; j++)
1303 {
1304 INT32 mx0, mx1, my0, my1, ax0, ay0, ay1, mr1, temp;
1305
1306 my0 = *i4++;
1307 my1 = *i5++;
1308
1309 for (k = 0; k < mem63f; k++)
1310 {
1311 mx0 = *i1++;
1312 mx1 = *i1++;
1313 ax0 = (mx0 * my0 - mx1 * my1) >> 15;
1314 mr1 = (mx1 * my0 + mx0 * my1) >> 15;
1315 ay0 = i0[0];
1316 ay1 = i0[1];
1317
1318 temp = ay0 - ax0;
1319 /*if (temp < -32768) temp = -32768;*/
1320 /*else if (temp > 32767) temp = 32767;*/
1321 *i0++ = temp;
1322
1323 temp = ax0 + ay0;
1324 /*if (temp < -32768) temp = -32768;*/
1325 /*else if (temp > 32767) temp = 32767;*/
1326 *i2++ = temp;
1327
1328 temp = ay1 - mr1;
1329 /*if (temp < -32768) temp = -32768;*/
1330 /*else if (temp > 32767) temp = 32767;*/
1331 *i0++ = temp;
1332
1333 temp = ay1 + mr1;
1334 /*if (temp < -32768) temp = -32768;*/
1335 /*else if (temp > 32767) temp = 32767;*/
1336 *i2++ = temp;
1337 }
1338 i2 += mem63e;
1339 i1 += mem63e;
1340 i0 += mem63e;
1341 }
1342 mem63d <<= 1;
1343 mem63e = mem63f;
1344 mem63f >>= 1;
1345 }
1346 activecpu_set_reg(ADSP2100_PC, activecpu_get_pc() + 0x121 - 0xf6);
1347 }
1348
1349
1350 /* War Gods:
1351 2BA4: 0000 AR = $0002
1352 2BA5: 0000 DM($0A09) = AR
1353 2BA6: 0000 SI = $0040
1354 2BA7: 0000 DM($0A0B) = SI
1355 2BA8: 0000 SR = LSHIFT SI BY -1 (LO)
1356 2BA9: 0000 DM($0A0D) = SR0
1357 2BAA: 0000 M0 = $3FFF
1358 2BAB: 0000 CNTR = $0006
1359 2BAC: 0000 DO $2BD0 UNTIL CE
1360 2BAD: 0000 I4 = $1080
1361 2BAE: 0000 I5 = $1000
1362 2BAF: 0000 I0 = $2000
1363 2BB0: 0000 I1 = $2000
1364 2BB1: 0000 AY0 = DM($0A0B)
1365 2BB2: 0000 M2 = AY0
1366 2BB3: 0000 MODIFY (I1,M2)
1367 2BB4: 0000 I2 = I1
1368 2BB5: 0000 AR = AY0 - 1
1369 2BB6: 0000 M3 = AR
1370 2BB7: 0000 CNTR = DM($0A09)
1371 2BB8: 0000 DO $2BC9 UNTIL CE
1372 2BB9: 0000 CNTR = DM($0A0D)
1373 2BBA: 0000 MY0 = DM(I4,M5)
1374 2BBB: 0000 MY1 = DM(I5,M5)
1375 2BBC: 0000 MX0 = DM(I1,M1)
1376 2BBD: 0000 DO $2BC6 UNTIL CE
1377 2BBE: 0000 MR = MX0 * MY0 (SS), MX1 = DM(I1,M1)
1378 2BBF: 0000 MR = MR - MX1 * MY1 (RND), AY0 = DM(I0,M1)
1379 2BC0: 0000 MR = MX1 * MY0 (SS), AX0 = MR1
1380 2BC1: 0000 MR = MR + MX0 * MY1 (RND), AY1 = DM(I0,M0)
1381 2BC2: 0000 AR = AY0 - AX0, MX0 = DM(I1,M1)
1382 2BC3: 0000 AR = AX0 + AY0, DM(I0,M1) = AR
1383 2BC4: 0000 AR = AY1 - MR1, DM(I2,M1) = AR
1384 2BC5: 0000 AR = MR1 + AY1, DM(I0,M1) = AR
1385 2BC6: 0000 DM(I2,M1) = AR
1386 2BC7: 0000 MODIFY (I2,M2)
1387 2BC8: 0000 MODIFY (I1,M3)
1388 2BC9: 0000 MODIFY (I0,M2)
1389 2BCA: 0000 SI = DM($0A09)
1390 2BCB: 0000 SR = LSHIFT SI BY 1 (LO)
1391 2BCC: 0000 DM($0A09) = SR0
1392 2BCD: 0000 SI = DM($0A0D)
1393 2BCE: 0000 DM($0A0B) = SI
1394 2BCF: 0000 SR = LSHIFT SI BY -1 (LO)
1395 2BD0: 0000 DM($0A0D) = SR0
1396 */
1397
1398
1399 /***************************************************************************
1400 VERY BASIC & SAFE OPTIMIZATIONS
1401 ****************************************************************************/
1402
READ16_HANDLER(dcs_polling_r)1403 static READ16_HANDLER( dcs_polling_r )
1404 {
1405 activecpu_eat_cycles(100);
1406 return *dcs_polling_base;
1407 }
1408