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