1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles
3 /***************************************************************************
4
5 Midway DCS Audio Board
6
7 ****************************************************************************
8
9 There are several variations of this board, which was in use by
10 Midway and eventually Atari for almost 10 years.
11
12 DCS ROM-based mono:
13 * ADSP-2105 @ 10MHz
14 * single channel output
15 * 2k external shared program/data RAM
16 * ROM-based, up to 8MB total
17 * used in:
18 Mortal Kombat 2 (1993)
19 Cruisin' USA (1994)
20 Revolution X (1994)
21 Killer Instinct (1994)
22 Killer Instinct 2 (1995)
23 Cruisin' World (1996)
24 Offroad Challenge (1997)
25
26 * 8k external shared program/data RAM
27 * used in:
28 Mortal Kombat 3 (1994)
29 Ultimate Mortal Kombat 3 (1994)
30 2 On 2 Open Ice Challenge (1995)
31 WWF Wrestlemania (1995)
32 NBA Hangtime (1996)
33 NBA Maximum Hangtime (1996)
34 Rampage World Tour (1997)
35
36 DCS2 RAM-based stereo (Seattle):
37 * ADSP-2115 @ 16MHz
38 * dual channel output (stereo)
39 * SDRC ASIC for RAM/ROM access
40 * RAM-based, 2MB total
41 * used in:
42 War Gods (1995)
43 Wayne Gretzky's 3D Hockey (1996)
44 Mace: The Dark Age (1996)
45 Biofreaks (1997)
46 NFL Blitz (1997)
47 California Speed (1998)
48 Vapor TRX (1998)
49 NFL Blitz '99 (1998)
50 CarnEvil (1998)
51 Hyperdrive (1998)
52 NFL Blitz 2000 Gold (1999)
53
54 DCS2 ROM-based stereo (Zeus):
55 * ADSP-2104 @ 16MHz
56 * dual channel output (stereo)
57 * SDRC ASIC for RAM/ROM access
58 * ROM-based, up to 16MB total
59 * used in:
60 Mortal Kombat 4 (1997)
61 Invasion (1999)
62 Cruisin' Exotica (1999)
63 The Grid (2001)
64
65 DCS2 RAM-based stereo (Vegas):
66 * ADSP-2104 @ 16MHz
67 * dual channel output (stereo)
68 * SDRC ASIC for RAM/ROM access
69 * RAM-based, 4MB total
70 * used in:
71 Gauntlet Legends (1998)
72 Tenth Degree (1998)
73 Gauntlet Dark Legacy (1999)
74 War: The Final Assault (1999)
75
76 DCS2 RAM-based stereo (DSIO):
77 * ADSP-2181 @ 16.667MHz
78 * dual channel output (stereo)
79 * custom ASIC for RAM/ROM access
80 * RAM-based, 4MB total
81 * used in:
82 Road Burners (1999)
83
84 DCS2 RAM-based multi-channel (Denver):
85 * ADSP-2181 @ 16.667MHz
86 * 2-6 channel output
87 * custom ASIC for RAM/ROM access
88 * RAM-based, 4MB total
89 * used in:
90 San Francisco Rush: 2049 (1998)
91
92 Unknown other DCS boards:
93 * NBA Jam Extreme
94 * NBA Showtime
95 * NBA Showtime / NFL Blitz 2000 Gold
96 * Cart Fury
97
98 *****************************************************************************
99
100 SDRC (Sound DRAM Control) ASIC
101 * Boot ROM = 32k x 8
102 * Data ROM = Up to 16MB ROM (4 chip selects)
103 * SRAM = 32k x 24 or 8k x 24
104 * common map:
105 PGM 0800-0fff -> RAM 4800-4fff
106 PGM 1000-1fff -> RAM 5000-5fff
107 PGM 2000-2fff -> RAM 6000-6fff
108 PGM 3000-3fff -> RAM 7000-7fff
109 * bank = 0:
110 DATA 0800-0fff -> RAM 0800-0fff
111 DATA 1000-17ff -> RAM 0000-07ff
112 DATA 1800-1fff -> RAM 1800-1fff
113 DATA 2000-27ff -> RAM 1000-17ff
114 DATA 2800-2fff -> RAM 2800-2fff
115 DATA 3000-37ff -> RAM 2000-27ff
116 * bank = 1:
117 DATA 0800-0fff -> unmapped
118 DATA 1000-17ff -> unmapped
119 DATA 1800-1fff -> RAM 3800-3fff
120 DATA 2000-27ff -> RAM 3000-37ff
121 DATA 2800-2fff -> RAM 2800-2fff
122 DATA 3000-37ff -> RAM 2000-27ff
123
124 0480 (reset = XXX0 0X00 0X00 XX00)
125 15:13 = SMODE (write only)
126 12 = SM_BK (SRAM bank: 0 or 1)
127 11 = SM_EN (SRAM enable: 0=disabled, 1=enabled)
128 9:7 = ROM_PG (ROM page select: 0-7)
129 5 = ROM_MS (ROM memory select: 0=boot memory, 1=data memory)
130 4 = ROM_SZ (ROM area size: 0=4k words, 1=1k words)
131 1:0 = ROM_ST (ROM memory start: 0=0000, 1=3000, 2=3400, 3=none)
132
133 0481 (reset = 000X 00X0 0X00 XX00)
134 15 = AREF_ACT (read only, 1=DRAM auto refresh in progress)
135 14 = /MUTE (mute output)
136 13 = /LED (LED output)
137 11:10 = /RES_TFS (Reset TFS outputs: low bit = channel 1&2, high = channel 3&4)
138 8 = TFS_INV (TFS output polarity: 0=same, 1=inverted)
139 7 = DM_3WS (DRAM wait states: 0=2, 1=3)
140 5:4 = DM_REF (DRAM refresh: 0=disabled, 1=manual, 2=auto, 3=auto 2x)
141 1:0 = DM_ST (DRAM memory start: 0=none, 1=0000, 2=3000, 3=3400)
142
143 0482 (reset = XXX0 0000 0000 0000)
144 10:0 = DM_PG[10..0] (DRAM page)
145 12:0 = EPM_PG[12..0] (EPROM page [low 10 bits used for 4k pages])
146
147 0483 (reset = 1010 0000 1000 0001)
148 15:8 = SDRC_ID[7..0] (revision: 5A = ASIC version, A0 = FPGA version)
149 7 = SEC_D7
150 6 = SEC_D[6..1]
151 0 = SEC_D0
152
153 ****************************************************************************/
154
155 #include "emu.h"
156 #include "dcs.h"
157 #include "speaker.h"
158
159
160 #define LOG_DCS_TRANSFERS (0)
161 #define LOG_DCS_IO (0)
162 #define LOG_BUFFER_FILLING (0)
163
164 #define ENABLE_HLE_TRANSFERS (1)
165
166
167
168 /*************************************
169 *
170 * Constants
171 *
172 *************************************/
173
174 #define LCTRL_OUTPUT_EMPTY 0x400
175 #define LCTRL_INPUT_EMPTY 0x800
176
177 #define IS_OUTPUT_EMPTY() (m_latch_control & LCTRL_OUTPUT_EMPTY)
178 #define IS_OUTPUT_FULL() (!(m_latch_control & LCTRL_OUTPUT_EMPTY))
179 #define SET_OUTPUT_EMPTY() (m_latch_control |= LCTRL_OUTPUT_EMPTY)
180 #define SET_OUTPUT_FULL() (m_latch_control &= ~LCTRL_OUTPUT_EMPTY)
181
182 #define IS_INPUT_EMPTY() (m_latch_control & LCTRL_INPUT_EMPTY)
183 #define IS_INPUT_FULL() (!(m_latch_control & LCTRL_INPUT_EMPTY))
184 #define SET_INPUT_EMPTY() (m_latch_control |= LCTRL_INPUT_EMPTY)
185 #define SET_INPUT_FULL() (m_latch_control &= ~LCTRL_INPUT_EMPTY)
186
187
188 /* These are some of the control registers. We don't use them all */
189 enum
190 {
191 IDMA_CONTROL_REG = 0, /* 3fe0 */
192 BDMA_INT_ADDR_REG, /* 3fe1 */
193 BDMA_EXT_ADDR_REG, /* 3fe2 */
194 BDMA_CONTROL_REG, /* 3fe3 */
195 BDMA_WORD_COUNT_REG, /* 3fe4 */
196 PROG_FLAG_DATA_REG, /* 3fe5 */
197 PROG_FLAG_CONTROL_REG, /* 3fe6 */
198
199 S1_AUTOBUF_REG = 15, /* 3fef */
200 S1_RFSDIV_REG, /* 3ff0 */
201 S1_SCLKDIV_REG, /* 3ff1 */
202 S1_CONTROL_REG, /* 3ff2 */
203 S0_AUTOBUF_REG, /* 3ff3 */
204 S0_RFSDIV_REG, /* 3ff4 */
205 S0_SCLKDIV_REG, /* 3ff5 */
206 S0_CONTROL_REG, /* 3ff6 */
207 S0_MCTXLO_REG, /* 3ff7 */
208 S0_MCTXHI_REG, /* 3ff8 */
209 S0_MCRXLO_REG, /* 3ff9 */
210 S0_MCRXHI_REG, /* 3ffa */
211 TIMER_SCALE_REG, /* 3ffb */
212 TIMER_COUNT_REG, /* 3ffc */
213 TIMER_PERIOD_REG, /* 3ffd */
214 WAITSTATES_REG, /* 3ffe */
215 SYSCONTROL_REG /* 3fff */
216 };
217
218
219 /* these macros are used to reference the SDRC ASIC */
220 #define SDRC_ROM_ST ((m_sdrc.reg[0] >> 0) & 3) /* 0=0000, 1=3000, 2=3400, 3=none */
221 #define SDRC_ROM_SZ ((m_sdrc.reg[0] >> 4) & 1) /* 0=4k, 1=1k */
222 #define SDRC_ROM_MS ((m_sdrc.reg[0] >> 5) & 1) /* 0=/BMS, 1=/DMS */
223 #define SDRC_ROM_PG ((m_sdrc.reg[0] >> 7) & 7)
224 #define SDRC_SM_EN ((m_sdrc.reg[0] >> 11) & 1)
225 #define SDRC_SM_BK ((m_sdrc.reg[0] >> 12) & 1)
226 #define SDRC_SMODE ((m_sdrc.reg[0] >> 13) & 7)
227
228 #define SDRC_DM_ST ((m_sdrc.reg[1] >> 0) & 3) /* 0=none, 1=0000, 2=3000, 3=3400 */
229 #define SDRC_DM_REF ((m_sdrc.reg[1] >> 4) & 3)
230 #define SDRC_DM_3WS ((m_sdrc.reg[1] >> 7) & 1)
231 #define SDRC_TFS_INV ((m_sdrc.reg[1] >> 8) & 1)
232 #define SDRC_RES_TFS ((m_sdrc.reg[1] >> 10) & 3)
233 #define SDRC_LED ((m_sdrc.reg[1] >> 13) & 1)
234 #define SDRC_MUTE ((m_sdrc.reg[1] >> 14) & 1)
235 #define SDRC_AREF_ACT ((m_sdrc.reg[1] >> 15) & 1)
236
237 #define SDRC_DM_PG ((m_sdrc.reg[2] >> 0) & 0x7ff)
238 #define SDRC_EPM_PG ((m_sdrc.reg[2] >> 0) & 0x1fff)
239
240
241 /* these macros are used to reference the DSIO ASIC */
242 #define DSIO_EMPTY_FIFO ((m_dsio.reg[1] >> 0) & 1)
243 #define DSIO_CUR_OUTPUT ((m_dsio.reg[1] >> 4) & 1)
244 #define DSIO_RES_TFS ((m_dsio.reg[1] >> 10) & 1)
245 #define DSIO_LED ((m_dsio.reg[1] >> 13) & 1)
246 #define DSIO_MUTE ((m_dsio.reg[1] >> 14) & 1)
247
248 #define DSIO_DM_PG ((m_dsio.reg[2] >> 0) & 0x1fff)
249
250 #define DSIO_BANK_END 0x3ff
251
252 /* these macros are used to reference the DENVER ASIC */
253 #define DENV_DSP_SPEED ((m_dsio.reg[1] >> 2) & 3) /* read only: 1=33.33MHz */
254 #define DENV_RES_TFS ((m_dsio.reg[1] >> 10) & 1)
255 #define DENV_CHANNELS ((m_dsio.reg[1] >> 11) & 3) /* 0=2ch, 1=4ch, 2=6ch */
256 #define DENV_LED ((m_dsio.reg[1] >> 13) & 1)
257 #define DENV_MUTE ((m_dsio.reg[1] >> 14) & 1)
258
259 #define DENV_DM_PG ((m_dsio.reg[2] >> 0) & 0x1fff)
260
261 #define DENV_NUM_BANK 0x800
262
263
264 /*************************************
265 *
266 * Original DCS Memory Maps
267 *
268 *************************************/
269
270 /* DCS 2k memory map */
dcs_2k_program_map(address_map & map)271 void dcs_audio_device::dcs_2k_program_map(address_map &map)
272 {
273 map(0x0000, 0x03ff).ram().share("dcsint");
274 map(0x0800, 0x0fff).ram().share("dcsext");
275 map(0x1000, 0x17ff).ram().share("dcsext");
276 map(0x1800, 0x1fff).ram().share("dcsext");
277 }
278
dcs_2k_data_map(address_map & map)279 void dcs_audio_device::dcs_2k_data_map(address_map &map)
280 {
281 map(0x0000, 0x07ff).mirror(0x1800).rw(FUNC(dcs_audio_device::dcs_dataram_r), FUNC(dcs_audio_device::dcs_dataram_w));
282 map(0x2000, 0x2fff).bankr("databank");
283 map(0x3000, 0x33ff).w(FUNC(dcs_audio_device::dcs_data_bank_select_w));
284 map(0x3400, 0x37ff).rw(FUNC(dcs_audio_device::input_latch_r), FUNC(dcs_audio_device::output_latch_w));
285 map(0x3800, 0x39ff).ram();
286 map(0x3fe0, 0x3fff).rw(FUNC(dcs_audio_device::adsp_control_r), FUNC(dcs_audio_device::adsp_control_w));
287 }
288
289
290 /* DCS 2k with UART memory map */
dcs_2k_uart_data_map(address_map & map)291 void dcs_audio_device::dcs_2k_uart_data_map(address_map &map)
292 {
293 map(0x0000, 0x07ff).mirror(0x1800).rw(FUNC(dcs_audio_device::dcs_dataram_r), FUNC(dcs_audio_device::dcs_dataram_w));
294 map(0x2000, 0x2fff).bankr("databank");
295 map(0x3000, 0x33ff).w(FUNC(dcs_audio_device::dcs_data_bank_select_w));
296 map(0x3400, 0x3402).noprw(); /* UART (ignored) */
297 map(0x3403, 0x3403).rw(FUNC(dcs_audio_device::input_latch_r), FUNC(dcs_audio_device::output_latch_w));
298 map(0x3404, 0x3405).noprw(); /* UART (ignored) */
299 map(0x3800, 0x39ff).ram().share("iram");
300 map(0x3fe0, 0x3fff).rw(FUNC(dcs_audio_device::adsp_control_r), FUNC(dcs_audio_device::adsp_control_w));
301 }
302
303
304 /* DCS 8k memory map */
dcs_8k_program_map(address_map & map)305 void dcs_audio_device::dcs_8k_program_map(address_map &map)
306 {
307 map(0x0000, 0x03ff).ram().share("dcsint");
308 map(0x0800, 0x1fff).ram().share("dcsext");
309 map(0x3000, 0x3003).rw(FUNC(dcs_audio_device::input_latch32_r), FUNC(dcs_audio_device::output_latch32_w)); // why?
310 }
311
dcs_8k_data_map(address_map & map)312 void dcs_audio_device::dcs_8k_data_map(address_map &map)
313 {
314 map(0x0000, 0x07ff).ram();
315 map(0x0800, 0x1fff).rw(FUNC(dcs_audio_device::dcs_dataram_r), FUNC(dcs_audio_device::dcs_dataram_w));
316 map(0x2000, 0x2fff).bankr("databank");
317 map(0x3000, 0x3000).w(FUNC(dcs_audio_device::dcs_data_bank_select_w));
318 map(0x3400, 0x3403).rw(FUNC(dcs_audio_device::input_latch_r), FUNC(dcs_audio_device::output_latch_w)); // mk3 etc. need this
319 map(0x3800, 0x39ff).ram().share("iram");
320 map(0x3fe0, 0x3fff).rw(FUNC(dcs_audio_device::adsp_control_r), FUNC(dcs_audio_device::adsp_control_w));
321 }
322
323 /* Williams WPC DCS/Security Pinball */
dcs_wpc_program_map(address_map & map)324 void dcs_audio_device::dcs_wpc_program_map(address_map &map)
325 {
326 map(0x0000, 0x03ff).ram().share("dcsint");
327 map(0x1000, 0x3fff).ram().share("dcsext");
328 }
329
dcs_wpc_data_map(address_map & map)330 void dcs_audio_wpc_device::dcs_wpc_data_map(address_map &map)
331 {
332 map(0x0000, 0x07ff).bankr("databank");
333 map(0x1000, 0x2fff).rw(FUNC(dcs_audio_wpc_device::dcs_dataram_r), FUNC(dcs_audio_wpc_device::dcs_dataram_w));
334 map(0x3000, 0x3000).w(FUNC(dcs_audio_wpc_device::dcs_data_bank_select_w));
335 map(0x3100, 0x3100).w(FUNC(dcs_audio_wpc_device::dcs_data_bank_select2_w));
336 map(0x3300, 0x3303).rw(FUNC(dcs_audio_wpc_device::input_latch_r), FUNC(dcs_audio_wpc_device::output_latch_w));
337 map(0x3800, 0x39ff).ram().share("iram");
338 map(0x3fe0, 0x3fff).rw(FUNC(dcs_audio_wpc_device::adsp_control_r), FUNC(dcs_audio_wpc_device::adsp_control_w));
339 }
340
341 /*************************************
342 *
343 * DCS2 Memory Maps
344 *
345 *************************************/
346
dcs2_2115_program_map(address_map & map)347 void dcs_audio_device::dcs2_2115_program_map(address_map &map)
348 {
349 map.unmap_value_high();
350 map(0x0000, 0x03ff).ram().share("dcsint");
351 }
352
dcs2_2104_program_map(address_map & map)353 void dcs_audio_device::dcs2_2104_program_map(address_map &map)
354 {
355 map.unmap_value_high();
356 map(0x0000, 0x01ff).ram().share("dcsint");
357 }
358
359
dcs2_2115_data_map(address_map & map)360 void dcs_audio_device::dcs2_2115_data_map(address_map &map)
361 {
362 map.unmap_value_high();
363 map(0x0400, 0x0400).rw(FUNC(dcs_audio_device::input_latch_r), FUNC(dcs_audio_device::input_latch_ack_w));
364 map(0x0401, 0x0401).w(FUNC(dcs_audio_device::output_latch_w));
365 map(0x0402, 0x0402).rw(FUNC(dcs_audio_device::output_control_r), FUNC(dcs_audio_device::output_control_w));
366 map(0x0403, 0x0403).r(FUNC(dcs_audio_device::latch_status_r));
367 map(0x0404, 0x0407).r(FUNC(dcs_audio_device::fifo_input_r));
368 map(0x0480, 0x0483).rw(FUNC(dcs_audio_device::sdrc_r), FUNC(dcs_audio_device::sdrc_w));
369 map(0x3800, 0x39ff).ram().share("iram");
370 map(0x3fe0, 0x3fff).rw(FUNC(dcs_audio_device::adsp_control_r), FUNC(dcs_audio_device::adsp_control_w));
371 }
372
dcs2_2104_data_map(address_map & map)373 void dcs_audio_device::dcs2_2104_data_map(address_map &map)
374 {
375 map.unmap_value_high();
376 map(0x0400, 0x0400).rw(FUNC(dcs_audio_device::input_latch_r), FUNC(dcs_audio_device::input_latch_ack_w));
377 map(0x0401, 0x0401).w(FUNC(dcs_audio_device::output_latch_w));
378 map(0x0402, 0x0402).rw(FUNC(dcs_audio_device::output_control_r), FUNC(dcs_audio_device::output_control_w));
379 map(0x0403, 0x0403).r(FUNC(dcs_audio_device::latch_status_r));
380 map(0x0404, 0x0407).r(FUNC(dcs_audio_device::fifo_input_r));
381 map(0x0480, 0x0483).rw(FUNC(dcs_audio_device::sdrc_r), FUNC(dcs_audio_device::sdrc_w));
382 map(0x3800, 0x39ff).ram().share("iram");
383 map(0x3fe0, 0x3fff).rw(FUNC(dcs_audio_device::adsp_control_r), FUNC(dcs_audio_device::adsp_control_w));
384 }
385
386
387
388 /*************************************
389 *
390 * DSIO Memory Maps
391 *
392 *************************************/
393
dsio_program_map(address_map & map)394 void dcs_audio_device::dsio_program_map(address_map &map)
395 {
396 map.unmap_value_high();
397 map(0x0000, 0x3fff).ram().share("dcsint");
398 }
399
400
dsio_data_map(address_map & map)401 void dcs_audio_device::dsio_data_map(address_map &map)
402 {
403 map.unmap_value_high();
404 map(0x0000, 0x1fff).m("data_map_bank", FUNC(address_map_bank_device::amap16));
405 map(0x2000, 0x3fdf).ram().share("dcsint_data");
406 map(0x3fe0, 0x3fff).rw(FUNC(dcs_audio_device::adsp_control_r), FUNC(dcs_audio_device::adsp_control_w));
407 }
408
dsio_rambank_map(address_map & map)409 void dcs_audio_device::dsio_rambank_map(address_map &map)
410 {
411 map(0x0000, 0x1fff).ram();
412 map(0x2000, 0x3fff).bankrw("databank");
413 }
414
dsio_io_map(address_map & map)415 void dcs_audio_device::dsio_io_map(address_map &map)
416 {
417 map.unmap_value_high();
418 map(0x0400, 0x0400).rw(FUNC(dcs_audio_device::input_latch_r), FUNC(dcs_audio_device::input_latch_ack_w));
419 map(0x0401, 0x0401).w(FUNC(dcs_audio_device::output_latch_w));
420 map(0x0402, 0x0402).rw(FUNC(dcs_audio_device::output_control_r), FUNC(dcs_audio_device::output_control_w));
421 map(0x0403, 0x0403).r(FUNC(dcs_audio_device::latch_status_r));
422 map(0x0404, 0x0407).r(FUNC(dcs_audio_device::fifo_input_r));
423 map(0x0480, 0x0483).rw(FUNC(dcs_audio_device::dsio_r), FUNC(dcs_audio_device::dsio_w));
424 }
425
426
427
428 /*************************************
429 *
430 * Denver Memory Maps
431 *
432 *************************************/
433
denver_program_map(address_map & map)434 void dcs_audio_device::denver_program_map(address_map &map)
435 {
436 map.unmap_value_high();
437 map(0x0000, 0x3fff).ram().share("dcsint");
438 }
439
440
denver_data_map(address_map & map)441 void dcs_audio_device::denver_data_map(address_map &map)
442 {
443 map.unmap_value_high();
444 map(0x0000, 0x1fff).m("data_map_bank", FUNC(address_map_bank_device::amap16));
445 map(0x2000, 0x3fdf).ram().share("dcsint_data");
446 map(0x3fe0, 0x3fff).rw(FUNC(dcs_audio_device::adsp_control_r), FUNC(dcs_audio_device::adsp_control_w));
447 }
448
denver_rambank_map(address_map & map)449 void dcs_audio_device::denver_rambank_map(address_map &map)
450 {
451 map(0x0000, 0x3fff).ram();
452 map(0x4000, 0x7fff).bankrw("databank");
453 }
454
455
denver_io_map(address_map & map)456 void dcs_audio_device::denver_io_map(address_map &map)
457 {
458 map.unmap_value_high();
459 map(0x0400, 0x0400).rw(FUNC(dcs_audio_device::input_latch_r), FUNC(dcs_audio_device::input_latch_ack_w));
460 map(0x0401, 0x0401).w(FUNC(dcs_audio_device::output_latch_w));
461 map(0x0402, 0x0402).rw(FUNC(dcs_audio_device::output_control_r), FUNC(dcs_audio_device::output_control_w));
462 map(0x0403, 0x0403).r(FUNC(dcs_audio_device::latch_status_r));
463 map(0x0404, 0x0407).r(FUNC(dcs_audio_device::fifo_input_r));
464 map(0x0480, 0x0483).rw(FUNC(dcs_audio_device::denver_r), FUNC(dcs_audio_device::denver_w));
465 }
466
467
468 /*************************************
469 *
470 * ADSP booting
471 *
472 *************************************/
473
dcs_boot()474 void dcs_audio_device::dcs_boot()
475 {
476 switch (m_rev)
477 {
478 /* rev 1/1.5: use the last set data bank to boot from */
479 case REV_DCS1:
480 case REV_DCS1P5:
481 {
482 /* determine the base */
483 // max_banks = m_bootrom_words / 0x1000;
484 uint16_t* base = m_bootrom + ((m_sounddata_bank * 0x1000) % m_bootrom_words);
485
486 /* convert from 16-bit data to 8-bit data and boot */
487 uint8_t buffer[0x1000];
488 for (int i = 0; i < 0x1000; i++)
489 {
490 buffer[i] = base[i];
491 }
492 assert(m_internal_program_ram != nullptr);
493 m_cpu->load_boot_data(buffer, m_internal_program_ram);
494 break;
495 }
496
497 /* rev 2: use the ROM page in the SDRC to boot from */
498 case REV_DCS2:
499 {
500 /* determine the base */
501 uint16_t* base;
502 if (m_bootrom == m_sounddata)
503 {
504 /* EPROM case: page is selected from the page register */
505 base = m_bootrom + ((SDRC_EPM_PG * 0x1000) % m_bootrom_words);
506 }
507 else
508 {
509 /* DRAM case: page is selected from the ROM page register */
510 base = m_bootrom + ((SDRC_ROM_PG * 0x1000) % m_bootrom_words);
511 }
512
513 /* convert from 16-bit data to 8-bit data and boot */
514 uint8_t buffer[0x1000];
515 for (int i = 0; i < 0x1000; i++)
516 {
517 buffer[i] = base[i];
518 }
519 assert(m_internal_program_ram != nullptr);
520 m_cpu->load_boot_data(buffer, m_internal_program_ram);
521 break;
522 }
523
524 /* rev 3/4: HALT the ADSP-2181 until program is downloaded via IDMA */
525 case REV_DSIO:
526 case REV_DENV:
527 m_cpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
528 m_dsio.start_on_next_write = 0;
529 break;
530 }
531 }
532
533
534
535 /*************************************
536 *
537 * System reset
538 *
539 *************************************/
540
TIMER_CALLBACK_MEMBER(dcs_audio_device::dcs_reset)541 TIMER_CALLBACK_MEMBER( dcs_audio_device::dcs_reset )
542 {
543 if (LOG_DCS_IO)
544 logerror("dcs_reset\n");
545
546 /* reset the memory banking */
547 switch (m_rev)
548 {
549 /* rev 1/1.5: just reset the bank to 0 */
550 case REV_DCS1:
551 case REV_DCS1P5:
552 m_sounddata_bank = 0;
553 m_data_bank->set_entry(0);
554 break;
555
556 /* rev 2: reset the SDRC ASIC */
557 case REV_DCS2:
558 sdrc_reset();
559 break;
560
561 /* rev 3: reset the DSIO ASIC */
562 case REV_DSIO:
563 dsio_reset();
564 break;
565
566 /* rev 4: reset the Denver ASIC */
567 case REV_DENV:
568 denver_reset();
569 break;
570 }
571 /* initialize our state structure and install the transmit callback */
572 m_size = 0;
573 m_incs = 0;
574 m_ireg = 0;
575
576 /* initialize the ADSP control regs */
577 memset(m_control_regs, 0, sizeof(m_control_regs));
578 /* clear all interrupts */
579 m_cpu->set_input_line(ADSP2105_IRQ0, CLEAR_LINE);
580 m_cpu->set_input_line(ADSP2105_IRQ1, CLEAR_LINE);
581 m_cpu->set_input_line(ADSP2105_IRQ2, CLEAR_LINE);
582
583 /* initialize the comm bits */
584 SET_INPUT_EMPTY();
585 SET_OUTPUT_EMPTY();
586 if (!m_last_input_empty && !m_input_empty_cb.isnull())
587 m_input_empty_cb(m_last_input_empty = 1);
588 if (m_last_output_full && !m_output_full_cb.isnull())
589 m_output_full_cb(m_last_output_full = 0);
590
591 /* boot */
592 dcs_boot();
593
594 /* reset timers */
595 m_timer_ignore = false;
596 m_timer_enable = 0;
597 m_timer_scale = 1;
598 m_internal_timer->reset();
599
600 /* reset the HLE transfer states */
601 m_transfer.dcs_state = m_transfer.state = 0;
602
603 }
604
605
606
607 /*************************************
608 *
609 * System setup
610 *
611 *************************************/
612
dcs_register_state()613 void dcs_audio_device::dcs_register_state()
614 {
615 save_item(NAME(m_sdrc.reg));
616 save_item(NAME(m_sdrc.seed));
617
618 save_item(NAME(m_dsio.reg));
619 save_item(NAME(m_dsio.start_on_next_write));
620 save_item(NAME(m_dsio.channelbits));
621
622 save_item(NAME(m_channels));
623 save_item(NAME(m_size));
624 save_item(NAME(m_incs));
625 save_item(NAME(m_ireg));
626 save_item(NAME(m_ireg_base));
627 save_item(NAME(m_control_regs));
628
629 save_item(NAME(m_sounddata_bank));
630 save_item(NAME(m_dmovlay_val));
631
632 save_item(NAME(m_auto_ack));
633 save_item(NAME(m_latch_control));
634 save_item(NAME(m_input_data));
635 save_item(NAME(m_output_data));
636 save_item(NAME(m_output_control));
637 save_item(NAME(m_output_control_cycles));
638 save_item(NAME(m_last_output_full));
639 save_item(NAME(m_last_input_empty));
640 save_item(NAME(m_progflags));
641
642 save_item(NAME(m_timer_enable));
643 save_item(NAME(m_timer_ignore));
644 save_item(NAME(m_timer_start_cycles));
645 save_item(NAME(m_timer_start_count));
646 save_item(NAME(m_timer_scale));
647 save_item(NAME(m_timer_period));
648 save_item(NAME(m_timers_fired));
649
650 save_item(NAME(m_transfer.dcs_state));
651 save_item(NAME(m_transfer.state));
652 save_item(NAME(m_transfer.start));
653 save_item(NAME(m_transfer.stop));
654 save_item(NAME(m_transfer.type));
655 save_item(NAME(m_transfer.temp));
656 save_item(NAME(m_transfer.writes_left));
657 save_item(NAME(m_transfer.sum));
658 save_item(NAME(m_transfer.fifo_entries));
659
660 save_item(NAME(m_polling_value));
661 save_item(NAME(m_polling32_value));
662
663 if (m_sram != nullptr)
664 save_pointer(NAME(m_sram), 0x8000*4 / sizeof(m_sram[0]));
665
666 if (m_rev == REV_DCS2)
667 machine().save().register_postload(save_prepost_delegate(FUNC(dcs_audio_device::sdrc_remap_memory), this));
668
669 if (m_rev == REV_DENV)
670 machine().save().register_postload(save_prepost_delegate(FUNC(dcs_audio_device::denver_postload), this));
671 }
672
denver_postload()673 void dcs_audio_device::denver_postload()
674 {
675 m_data_bank->set_entry(DENV_DM_PG % m_sounddata_banks);
676 dmovlay_remap_memory();
677 denver_alloc_dmadac();
678 install_speedup();
679 }
680
681 //-------------------------------------------------
682 // dcs_audio_device - constructor
683 //-------------------------------------------------
684
dcs_audio_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock,int rev)685 dcs_audio_device::dcs_audio_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int rev) :
686 device_t(mconfig, type, tag, owner, clock),
687 m_cpu(nullptr),
688 m_program(nullptr),
689 m_data(nullptr),
690 m_rev(rev),
691 m_polling_offset(0),
692 m_polling_count(0),
693 m_channels(0),
694 m_size(0),
695 m_incs(0),
696 m_reg_timer(nullptr),
697 m_sport0_timer(nullptr),
698 m_internal_timer(nullptr),
699 m_ireg(0),
700 m_ireg_base(0),
701 m_bootrom(nullptr),
702 m_bootrom_words(0),
703 m_sounddata(nullptr),
704 m_sounddata_words(0),
705 m_sounddata_banks(0),
706 m_sounddata_bank(0),
707 m_ram_map(*this, "data_map_bank"),
708 m_data_bank(*this, "databank"),
709 m_rom_page(nullptr),
710 m_dram_page(nullptr),
711 m_auto_ack(0),
712 m_latch_control(0),
713 m_input_data(0),
714 m_output_data(0),
715 m_output_control(0),
716 m_output_control_cycles(0),
717 m_last_output_full(0),
718 m_last_input_empty(0),
719 m_progflags(0),
720 m_output_full_cb(*this),
721 m_input_empty_cb(*this),
722 m_fifo_data_r(*this),
723 m_fifo_status_r(*this),
724 m_fifo_reset_w(*this),
725 m_timer_enable(0),
726 m_timer_ignore(false),
727 m_timer_start_cycles(0),
728 m_timer_start_count(0),
729 m_timer_scale(0),
730 m_timer_period(0),
731 m_timers_fired(0),
732 m_sram(nullptr),
733 m_internal_program_ram(nullptr),
734 m_external_program_ram(nullptr),
735 m_internal_data_ram(nullptr),
736 m_dram_in_mb(0),
737 m_iram(*this, "iram"),
738 m_maincpu(*this, ":maincpu")
739 {
740 m_dmadac[0] = m_dmadac[1] = m_dmadac[2] = m_dmadac[3] = m_dmadac[4] = m_dmadac[5] = nullptr;
741 memset(m_control_regs, 0, sizeof(m_control_regs));
742 memset(&m_sdrc, 0, sizeof(m_sdrc));
743 memset(&m_dsio, 0, sizeof(m_dsio));
744 memset(&m_transfer, 0, sizeof(m_transfer));
745 }
746
device_reset()747 void dcs_audio_device::device_reset()
748 {
749 dcs_reset(nullptr, 0);
750 }
751
device_start()752 void dcs_audio_device::device_start()
753 {
754 m_sram = nullptr;
755
756 memory_share *internal_ram = memshare("dcsint");
757 if (internal_ram != nullptr)
758 {
759 m_internal_program_ram = (uint32_t *)internal_ram->ptr();
760 }
761 memory_share *external_ram = memshare("dcsext");
762 if (external_ram != nullptr)
763 {
764 m_external_program_ram = (uint32_t *)external_ram->ptr();
765 }
766
767 /* find the DCS CPU and the sound ROMs */
768 m_cpu = subdevice<adsp21xx_device>("dcs");
769 if (m_cpu != nullptr && !m_cpu->started())
770 throw device_missing_dependencies();
771
772 m_program = &m_cpu->space(AS_PROGRAM);
773 m_data = &m_cpu->space(AS_DATA);
774 m_channels = 1;
775 m_dmadac[0] = subdevice<dmadac_sound_device>("dac");
776
777 /* configure boot and sound ROMs */
778 m_bootrom = (uint16_t *)machine().root_device().memregion("dcs")->base();
779 m_bootrom_words = machine().root_device().memregion("dcs")->bytes() / 2;
780 m_sounddata = m_bootrom;
781 m_sounddata_words = m_bootrom_words;
782 if (m_rev == REV_DCS1)
783 {
784 m_sounddata_banks = m_sounddata_words / 0x1000;
785 m_data_bank->configure_entries(0, m_sounddata_banks, m_sounddata, 0x1000*2);
786 }
787 else
788 {
789 m_sounddata_banks = m_sounddata_words / 0x800;
790 m_data_bank->configure_entries(0, m_sounddata_banks, m_sounddata, 0x800*2);
791 }
792
793 /* create the timers */
794 m_internal_timer = subdevice<timer_device>("dcs_int_timer");
795 m_reg_timer = subdevice<timer_device>("dcs_reg_timer");
796
797 /* non-RAM based automatically acks */
798 m_auto_ack = true;
799 /* register for save states */
800 dcs_register_state();
801 /* reset the system */
802 dcs_reset(nullptr, 0);
803 }
804
805
device_start()806 void dcs2_audio_device::device_start()
807 {
808 int soundbank_words;
809
810 memory_share *internal_ram = memshare("dcsint");
811 if (internal_ram != nullptr)
812 {
813 m_internal_program_ram = (uint32_t *)internal_ram->ptr();
814 }
815 memory_share *external_ram = memshare("dcsext");
816 if (external_ram != nullptr)
817 {
818 m_external_program_ram = (uint32_t *)external_ram->ptr();
819 }
820 memory_share *internal_data_ram = memshare("dcsint_data");
821 if (internal_data_ram != nullptr)
822 {
823 m_internal_data_ram = (uint32_t *)internal_ram->ptr();
824 }
825
826 /* find the DCS CPU and the sound ROMs */
827 m_cpu = subdevice<adsp21xx_device>("dcs2");
828 m_rev = REV_DCS2;
829 soundbank_words = 0x1000;
830 if (m_cpu == nullptr)
831 {
832 m_cpu = subdevice<adsp21xx_device>("dsio");
833 m_rev = REV_DSIO;
834 soundbank_words = DSIO_BANK_END + 1;
835 }
836 if (m_cpu == nullptr)
837 {
838 m_cpu = subdevice<adsp21xx_device>("denver");
839 m_rev = REV_DENV;
840 soundbank_words = ((m_dram_in_mb << 20) / 2) / DENV_NUM_BANK;
841 }
842 if (m_cpu != nullptr && !m_cpu->started())
843 throw device_missing_dependencies();
844
845 m_program = &m_cpu->space(AS_PROGRAM);
846 m_data = &m_cpu->space(AS_DATA);
847 m_channels = 2;
848 m_dmadac[0] = subdevice<dmadac_sound_device>("dac1");
849 m_dmadac[1] = subdevice<dmadac_sound_device>("dac2");
850
851 /* always boot from the base of "dcs" */
852 memory_region *bootrom_region = machine().root_device().memregion("dcs");
853 if (bootrom_region != nullptr)
854 {
855 m_bootrom = (uint16_t *)bootrom_region->base();
856 m_bootrom_words = bootrom_region->bytes() / 2;
857 }
858
859 /* supports both RAM and ROM variants */
860 if (m_dram_in_mb != 0)
861 {
862 m_sounddata_words = (m_dram_in_mb << 20) / 2;
863 m_sounddata_ptr = std::make_unique<uint16_t[]>(m_sounddata_words);
864 m_sounddata = m_sounddata_ptr.get();
865 save_pointer(NAME(m_sounddata), m_sounddata_words);
866 }
867 else
868 {
869 m_sounddata = m_bootrom;
870 m_sounddata_words = m_bootrom_words;
871 }
872 m_sounddata_banks = m_sounddata_words / soundbank_words;
873 if (m_rev != REV_DCS2)
874 {
875 if (m_ram_map)
876 m_ram_map->set_bank(0);
877 m_data_bank->configure_entries(0, m_sounddata_banks, m_sounddata, soundbank_words * 2);
878 logerror("device_start: audio ram banks: %x size: %x\n", m_sounddata_banks, soundbank_words);
879 }
880
881
882 /* allocate memory for the SRAM */
883 m_sram = std::make_unique<uint16_t[]>(0x8000*4/2);
884
885 /* create the timers */
886 m_internal_timer = subdevice<timer_device>("dcs_int_timer");
887 m_reg_timer = subdevice<timer_device>("dcs_reg_timer");
888 m_sport0_timer = subdevice<timer_device>("dcs_sport0_timer");
889
890 /* we don't do auto-ack by default */
891 m_auto_ack = false;
892
893 /* install the speedup handler */
894 install_speedup();
895
896 /* allocate a watchdog timer for HLE transfers */
897 m_transfer.hle_enabled = (ENABLE_HLE_TRANSFERS && m_dram_in_mb != 0 && m_rev < REV_DSIO);
898 if (m_transfer.hle_enabled)
899 m_transfer.watchdog = subdevice<timer_device>("dcs_hle_timer");
900
901 /* register for save states */
902 dcs_register_state();
903
904 /* reset the system */
905 dcs_reset(nullptr, 0);
906 }
907
908
install_speedup(void)909 void dcs_audio_device::install_speedup(void)
910 {
911 if (m_polling_offset) {
912 if (m_rev < REV_DSIO) {
913 m_cpu->space(AS_DATA).install_read_handler(m_polling_offset, m_polling_offset, read16mo_delegate(*this, FUNC(dcs_audio_device::dcs_polling_r)));
914 m_cpu->space(AS_DATA).install_write_handler(m_polling_offset, m_polling_offset, write16s_delegate(*this, FUNC(dcs_audio_device::dcs_polling_w)));
915 }
916 else {
917 // ADSP 2181 (DSIO and DENVER) use program memory
918 m_cpu->space(AS_PROGRAM).install_read_handler(m_polling_offset, m_polling_offset, read32mo_delegate(*this, FUNC(dcs_audio_device::dcs_polling32_r)));
919 m_cpu->space(AS_PROGRAM).install_write_handler(m_polling_offset, m_polling_offset, write32s_delegate(*this, FUNC(dcs_audio_device::dcs_polling32_w)));
920 // DSIO and DENVER poll in two spots. This offset covers all three machines (mwskins, sf2049, roadburn).
921 m_cpu->space(AS_PROGRAM).install_read_handler(m_polling_offset + 9, m_polling_offset + 9, read32mo_delegate(*this, FUNC(dcs_audio_device::dcs_polling32_r)));
922 m_cpu->space(AS_PROGRAM).install_write_handler(m_polling_offset + 9, m_polling_offset + 9, write32s_delegate(*this, FUNC(dcs_audio_device::dcs_polling32_w)));
923 }
924 }
925 }
926
set_auto_ack(int state)927 void dcs_audio_device::set_auto_ack(int state)
928 {
929 m_auto_ack = state;
930 }
931
932
933
934 /*************************************
935 *
936 * Original DCS read/write handlers
937 *
938 *************************************/
939
dcs_dataram_r(offs_t offset)940 uint16_t dcs_audio_device::dcs_dataram_r(offs_t offset)
941 {
942 assert(m_external_program_ram != nullptr);
943 return m_external_program_ram[offset] >> 8;
944 }
945
946
dcs_dataram_w(offs_t offset,uint16_t data,uint16_t mem_mask)947 void dcs_audio_device::dcs_dataram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
948 {
949 assert(m_external_program_ram != nullptr);
950 uint16_t val = m_external_program_ram[offset] >> 8;
951 COMBINE_DATA(&val);
952 m_external_program_ram[offset] = (val << 8) | (m_external_program_ram[offset] & 0x0000ff);
953 }
954
955
dcs_data_bank_select_w(uint16_t data)956 void dcs_audio_device::dcs_data_bank_select_w(uint16_t data)
957 {
958 if (m_rev != REV_DCS1P5)
959 m_sounddata_bank = data & 0x7ff;
960 else
961 m_sounddata_bank = (m_sounddata_bank & 0xff00) | (data & 0xff);
962
963 m_data_bank->set_entry(m_sounddata_bank % m_sounddata_banks);
964
965 /* bit 11 = sound board led */
966 #if 0
967 if (m_rev != REV_DCS1P5)
968 output().set_led_value(2, data & 0x800);
969 #endif
970 }
971
dcs_data_bank_select2_w(uint16_t data)972 void dcs_audio_device::dcs_data_bank_select2_w(uint16_t data)
973 {
974 m_sounddata_bank = (m_sounddata_bank & 0x00ff) | ((data & 0x01) << 8) | ((data & 0xfc) << 7);
975
976 m_data_bank->set_entry(m_sounddata_bank % m_sounddata_banks);
977 }
978
979 /*************************************
980 *
981 * SDRC ASIC Memory handling
982 *
983 *************************************/
984
sdrc_update_bank_pointers()985 void dcs_audio_device::sdrc_update_bank_pointers()
986 {
987 if (SDRC_SM_EN != 0)
988 {
989 int pagesize = (SDRC_ROM_SZ == 0 && SDRC_ROM_ST != 0) ? 4096 : 1024;
990
991 /* update the bank pointer based on whether we are ROM-based or RAM-based */
992 if (m_bootrom == m_sounddata)
993 {
994 /* ROM-based; use the memory page to select from ROM */
995 if (SDRC_ROM_MS == 1 && SDRC_ROM_ST != 3)
996 {
997 m_rom_page->set_base(&m_sounddata[(SDRC_EPM_PG * pagesize) % m_sounddata_words]);
998 }
999 }
1000 else
1001 {
1002 /* RAM-based; use the ROM page to select from ROM, and the memory page to select from RAM */
1003 if (SDRC_ROM_MS == 1 && SDRC_ROM_ST != 3)
1004 {
1005 m_rom_page->set_base(&m_bootrom[(SDRC_ROM_PG * 4096 /*pagesize*/) % m_bootrom_words]);
1006 }
1007 if (SDRC_DM_ST != 0)
1008 {
1009 m_dram_page->set_base(&m_sounddata[(SDRC_DM_PG * 1024) % m_sounddata_words]);
1010 }
1011 }
1012 }
1013 }
1014
1015
sdrc_remap_memory()1016 void dcs_audio_device::sdrc_remap_memory()
1017 {
1018 /* if SRAM disabled, clean it out */
1019 if (SDRC_SM_EN == 0)
1020 {
1021 m_program->unmap_readwrite(0x0800, 0x3fff);
1022 m_data->unmap_readwrite(0x0800, 0x37ff);
1023 }
1024
1025 /* otherwise, map the SRAM */
1026 else
1027 {
1028 /* first start with a clean program map */
1029 m_program->install_ram(0x0800, 0x3fff, &m_sram[0x4800]);
1030
1031 /* set up the data map based on the SRAM banking */
1032 /* map 0: ram from 0800-37ff */
1033 if (SDRC_SM_BK == 0)
1034 {
1035 m_data->install_ram(0x0800, 0x17ff, &m_sram[0x0000]);
1036 m_data->install_ram(0x1800, 0x27ff, &m_sram[0x1000]);
1037 m_data->install_ram(0x2800, 0x37ff, &m_sram[0x2000]);
1038 }
1039
1040 /* map 1: nothing from 0800-17ff, alternate RAM at 1800-27ff, same RAM at 2800-37ff */
1041 else
1042 {
1043 m_data->unmap_readwrite(0x0800, 0x17ff);
1044 m_data->install_ram(0x1800, 0x27ff, &m_sram[0x3000]);
1045 m_data->install_ram(0x2800, 0x37ff, &m_sram[0x2000]);
1046 }
1047 }
1048
1049 /* map the ROM page as bank 25 */
1050 if (SDRC_ROM_MS == 1 && SDRC_ROM_ST != 3)
1051 {
1052 int baseaddr = (SDRC_ROM_ST == 0) ? 0x0000 : (SDRC_ROM_ST == 1) ? 0x3000 : 0x3400;
1053 int pagesize = (SDRC_ROM_SZ == 0 && SDRC_ROM_ST != 0) ? 4096 : 1024;
1054 m_data->install_read_bank(baseaddr, baseaddr + pagesize - 1, "rompage");
1055 m_rom_page = membank("rompage");
1056 }
1057
1058 /* map the DRAM page as bank 26 */
1059 if (SDRC_DM_ST != 0)
1060 {
1061 int baseaddr = (SDRC_DM_ST == 1) ? 0x0000 : (SDRC_DM_ST == 2) ? 0x3000 : 0x3400;
1062 m_data->install_readwrite_bank(baseaddr, baseaddr + 0x3ff, "drampage");
1063 m_dram_page = membank("drampage");
1064 }
1065
1066 /* update the bank pointers */
1067 sdrc_update_bank_pointers();
1068
1069 /* reinstall the polling hotspot */
1070 install_speedup();
1071 }
1072
1073
sdrc_reset()1074 void dcs_audio_device::sdrc_reset()
1075 {
1076 memset(m_sdrc.reg, 0, sizeof(m_sdrc.reg));
1077 sdrc_remap_memory();
1078 }
1079
1080
1081
1082 /*************************************
1083 *
1084 * SDRC ASIC read/write
1085 *
1086 *************************************/
1087
sdrc_r(offs_t offset)1088 uint16_t dcs_audio_device::sdrc_r(offs_t offset)
1089 {
1090 sdrc_state &sdrc = m_sdrc;
1091 uint16_t result = sdrc.reg[offset];
1092
1093 /* offset 3 is for security */
1094 if (offset == 3)
1095 {
1096 switch (SDRC_SMODE)
1097 {
1098 default:
1099 case 0: /* no-op */
1100 result = 0x5a81;
1101 break;
1102
1103 case 1: /* write seed */
1104 result = 0x5aa4;
1105 break;
1106
1107 case 2: /* read data */
1108 result = 0x5a00 | ((sdrc.seed & 0x3f) << 1);
1109 break;
1110
1111 case 3: /* shift left */
1112 result = 0x5ab9;
1113 break;
1114
1115 case 4: /* add */
1116 result = 0x5a03;
1117 break;
1118
1119 case 5: /* xor */
1120 result = 0x5a69;
1121 break;
1122
1123 case 6: /* prg */
1124 result = 0x5a20;
1125 break;
1126
1127 case 7: /* invert */
1128 result = 0x5aff;
1129 break;
1130 }
1131 }
1132
1133 return result;
1134 }
1135
1136
sdrc_w(offs_t offset,uint16_t data)1137 void dcs_audio_device::sdrc_w(offs_t offset, uint16_t data)
1138 {
1139 sdrc_state &sdrc = m_sdrc;
1140 uint16_t diff = sdrc.reg[offset] ^ data;
1141
1142 switch (offset)
1143 {
1144 /* offset 0 controls ROM mapping */
1145 case 0:
1146 sdrc.reg[0] = data;
1147 if (diff & 0x1833)
1148 sdrc_remap_memory();
1149 if (diff & 0x0380)
1150 sdrc_update_bank_pointers();
1151 break;
1152
1153 /* offset 1 controls RAM mapping */
1154 case 1:
1155 sdrc.reg[1] = data;
1156 //dmadac_enable(&m_dmadac[0], m_channels, SDRC_MUTE);
1157 if (diff & 0x0003)
1158 sdrc_remap_memory();
1159 break;
1160
1161 /* offset 2 controls paging */
1162 case 2:
1163 sdrc.reg[2] = data;
1164 if (diff & 0x1fff)
1165 sdrc_update_bank_pointers();
1166 break;
1167
1168 /* offset 3 controls security */
1169 case 3:
1170 switch (SDRC_SMODE)
1171 {
1172 case 0: /* no-op */
1173 case 2: /* read data */
1174 break;
1175
1176 case 1: /* write seed */
1177 sdrc.seed = data & 0xff;
1178 break;
1179
1180 case 3: /* shift left */
1181 sdrc.seed = (sdrc.seed << 1) | 1;
1182 break;
1183
1184 case 4: /* add */
1185 sdrc.seed += sdrc.seed >> 1;
1186 break;
1187
1188 case 5: /* xor */
1189 sdrc.seed ^= (sdrc.seed << 1) | 1;
1190 break;
1191
1192 case 6: /* prg */
1193 sdrc.seed = (((sdrc.seed << 7) ^ (sdrc.seed << 5) ^ (sdrc.seed << 4) ^ (sdrc.seed << 3)) & 0x80) | (sdrc.seed >> 1);
1194 break;
1195
1196 case 7: /* invert */
1197 sdrc.seed = ~sdrc.seed;
1198 break;
1199 }
1200 break;
1201 }
1202 }
1203
1204
1205
1206 /*************************************
1207 *
1208 * DSIO ASIC read/write
1209 *
1210 *************************************/
1211
dsio_reset()1212 void dcs_audio_device::dsio_reset()
1213 {
1214 memset(&m_dsio, 0, sizeof(m_dsio));
1215 m_dmovlay_val = 0;
1216 dmovlay_remap_memory();
1217 }
1218
1219
dsio_r(offs_t offset)1220 uint16_t dcs_audio_device::dsio_r(offs_t offset)
1221 {
1222 dsio_state &dsio = m_dsio;
1223 uint16_t result = dsio.reg[offset];
1224
1225 if (offset == 1)
1226 {
1227 /* bit 4 specifies which channel is being output */
1228 dsio.channelbits ^= 0x0010;
1229 result = (result & ~0x0010) | dsio.channelbits;
1230 }
1231 if (LOG_DCS_IO && offset != 2) logerror("%s dsio_r 0x%x = %04x\n", machine().describe_context(), offset, result);
1232 return result;
1233 }
1234
1235
dsio_w(offs_t offset,uint16_t data)1236 void dcs_audio_device::dsio_w(offs_t offset, uint16_t data)
1237 {
1238 dsio_state &dsio = m_dsio;
1239
1240 switch (offset)
1241 {
1242 /* offset 1 controls I/O */
1243 case 1:
1244 dsio.reg[1] = data;
1245
1246 /* determine /MUTE and number of channels */
1247 dmadac_enable(&m_dmadac[0], m_channels, DSIO_MUTE);
1248
1249 /* bit 0 resets the FIFO */
1250 if (!m_fifo_reset_w.isnull())
1251 m_fifo_reset_w(DSIO_EMPTY_FIFO ^ 1);
1252 break;
1253
1254 /* offset 2 controls RAM pages */
1255 case 2:
1256 dsio.reg[2] = data;
1257 m_data_bank->set_entry(DSIO_DM_PG % m_sounddata_banks);
1258 break;
1259 }
1260 if (LOG_DCS_IO) logerror("%s dsio_w 0x%x = %04x\n", machine().describe_context(), offset, data);
1261 }
1262
1263
1264
1265 /*************************************
1266 *
1267 * Denver ASIC read/write
1268 *
1269 *************************************/
1270
denver_reset()1271 void dcs_audio_device::denver_reset()
1272 {
1273 memset(&m_dsio, 0, sizeof(m_dsio));
1274 m_dmovlay_val = 0;
1275 dmovlay_remap_memory();
1276 dmadac_enable(&m_dmadac[0], m_channels, 0);
1277 m_reg_timer->reset();
1278 m_sport0_timer->reset();
1279 }
1280
denver_alloc_dmadac()1281 void dcs_audio_device::denver_alloc_dmadac()
1282 {
1283 int enable = DENV_MUTE;
1284 for (int chan = 0; chan < m_channels; chan++)
1285 {
1286 char buffer[10];
1287 sprintf(buffer, "dac%d", chan + 1);
1288 m_dmadac[chan] = subdevice<dmadac_sound_device>(buffer);
1289 }
1290 dmadac_enable(&m_dmadac[0], m_channels, enable);
1291 if (m_channels < 6)
1292 dmadac_enable(&m_dmadac[m_channels], 6 - m_channels, false);
1293 //if (enable)
1294 // recompute_sample_rate();
1295 }
1296
denver_r(offs_t offset)1297 uint16_t dcs_audio_device::denver_r(offs_t offset)
1298 {
1299 uint16_t result = m_dsio.reg[offset];
1300
1301 if (offset == 3)
1302 {
1303 /* returns 1 for DRAM, 2 for EPROM-based */
1304 // SDRC Revision
1305 result = 0x0003;
1306 }
1307 if (LOG_DCS_IO && offset != 0x2) logerror("%s denver_r %s 0x%x = %04x\n", machine().describe_context(), denver_regname[offset], offset, result);
1308
1309 return result;
1310 }
1311
1312
denver_w(offs_t offset,uint16_t data)1313 void dcs_audio_device::denver_w(offs_t offset, uint16_t data)
1314 {
1315 dsio_state &dsio = m_dsio;
1316 int channels;
1317
1318 uint16_t data_change = dsio.reg[offset] ^ data;
1319
1320 switch (offset)
1321 {
1322 /* offset 1 controls I/O */
1323 case 1:
1324 dsio.reg[1] = data;
1325 // Ignore LED
1326 data_change &= ~(1 << 13);
1327 /* determine /MUTE and number of channels */
1328 channels = 2 + 2 * DENV_CHANNELS;
1329
1330 /* if the number of channels has changed adjust */
1331 if (channels != m_channels)
1332 {
1333 m_channels = channels;
1334 denver_alloc_dmadac();
1335 }
1336 // Set MUTE
1337 if (data_change & (1 << 14)) {
1338 dmadac_enable(&m_dmadac[0], m_channels, DENV_MUTE);
1339 if (m_channels < 6)
1340 dmadac_enable(&m_dmadac[m_channels], 6 - m_channels, false);
1341 }
1342 // Disable timer after DENV_RES_TFS
1343 if (!m_timer_ignore && DENV_RES_TFS && DENV_MUTE) {
1344 logerror("%s denver_w: Disabling timer\n", machine().describe_context());
1345 m_timer_ignore = true;
1346 }
1347 break;
1348
1349 /* offset 2 controls RAM pages */
1350 case 2:
1351 dsio.reg[2] = data;
1352 m_data_bank->set_entry(DENV_DM_PG % m_sounddata_banks);
1353 break;
1354 /* offset 3 controls FIFO reset */
1355 case 3:
1356 if (!m_fifo_reset_w.isnull())
1357 m_fifo_reset_w(1);
1358 break;
1359 }
1360 if (LOG_DCS_IO && offset != 0x2) logerror("%s denver_w %s 0x%x = %04x\n", machine().describe_context(), denver_regname[offset], offset, data);
1361 }
1362
1363
1364
1365 /*************************************
1366 *
1367 * DSIO/Denver IDMA access
1368 *
1369 *************************************/
1370
dsio_idma_addr_w(uint32_t data)1371 void dcs_audio_device::dsio_idma_addr_w(uint32_t data)
1372 {
1373 if (LOG_DCS_TRANSFERS)
1374 logerror("%s IDMA_addr = %04X\n", machine().describe_context(), data);
1375 downcast<adsp2181_device *>(m_cpu)->idma_addr_w(data);
1376 if (data == 0)
1377 m_dsio.start_on_next_write = 2;
1378 }
1379
1380
dsio_idma_data_w(offs_t offset,uint32_t data,uint32_t mem_mask)1381 void dcs_audio_device::dsio_idma_data_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1382 {
1383 dsio_state &dsio = m_dsio;
1384 // IDMA is to internal memory only
1385 if (m_dmovlay_val)
1386 m_ram_map->set_bank(0);
1387 if (ACCESSING_BITS_0_15)
1388 {
1389 if (LOG_DCS_TRANSFERS && !(downcast<adsp2181_device *>(m_cpu)->idma_addr_r() & 0x00ff))
1390 logerror("%s IDMA_data_w(%04X) = %04X\n", machine().describe_context(), downcast<adsp2181_device *>(m_cpu)->idma_addr_r(), data & 0xffff);
1391 downcast<adsp2181_device *>(m_cpu)->idma_data_w(data & 0xffff);
1392 }
1393 if (ACCESSING_BITS_16_31)
1394 {
1395 if (LOG_DCS_TRANSFERS && !(downcast<adsp2181_device *>(m_cpu)->idma_addr_r() & 0x00ff))
1396 logerror("%s IDMA_data_w(%04X) = %04X\n", machine().describe_context(), downcast<adsp2181_device *>(m_cpu)->idma_addr_r(), data >> 16);
1397 downcast<adsp2181_device *>(m_cpu)->idma_data_w(data >> 16);
1398 }
1399 if (dsio.start_on_next_write && --dsio.start_on_next_write == 0)
1400 {
1401 logerror("%s: Starting DSIO CPU\n", machine().describe_context());
1402 m_cpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
1403 }
1404 // Restore internal/external mapping
1405 if (m_dmovlay_val)
1406 m_ram_map->set_bank(m_dmovlay_val);
1407
1408 }
1409
1410
dsio_idma_data_r()1411 uint32_t dcs_audio_device::dsio_idma_data_r()
1412 {
1413 uint32_t result;
1414 // IDMA is to internal memory only
1415 m_ram_map->set_bank(0);
1416 result = downcast<adsp2181_device *>(m_cpu)->idma_data_r();
1417 // Restore internal/external mapping
1418 m_ram_map->set_bank(m_dmovlay_val);
1419 if (LOG_DCS_TRANSFERS)
1420 logerror("%s IDMA_data_r(%04X) = %04X\n", machine().describe_context(), downcast<adsp2181_device *>(m_cpu)->idma_addr_r(), result);
1421 return result;
1422 }
1423
dmovlay_remap_memory()1424 void dcs_audio_device::dmovlay_remap_memory()
1425 {
1426 // Switch banks
1427 // Internal ram is bank 0
1428 if (m_dmovlay_val == 0) {
1429 m_ram_map->set_bank(0);
1430 } else {
1431 m_ram_map->set_bank(1);
1432 }
1433 if (LOG_DCS_IO) {
1434 if (m_dmovlay_val==0)
1435 logerror("%s dmovlay_remap_memory: Switching to internal data ram location dmovlay=%i\n", machine().describe_context(), m_dmovlay_val);
1436 else
1437 logerror("%s dmovlay_remap_memory: Switching to external data ram location dmovlay=%i\n", machine().describe_context(), m_dmovlay_val);
1438 }
1439 }
1440
dmovlay_callback(uint32_t data)1441 void dcs_audio_device::dmovlay_callback(uint32_t data)
1442 {
1443 // Do some checking first
1444 if (data < 0 || data > 1) {
1445 logerror("dmovlay_callback: Error! dmovlay called with value = %X\n", data);
1446 } else {
1447 m_dmovlay_val = data;
1448 dmovlay_remap_memory();
1449 }
1450 }
1451
1452
1453 /***************************************************************************
1454 DCS COMMUNICATIONS
1455 ****************************************************************************/
1456
set_io_callbacks(write_line_delegate output_full_cb,write_line_delegate input_empty_cb)1457 void dcs_audio_device::set_io_callbacks(write_line_delegate output_full_cb, write_line_delegate input_empty_cb)
1458 {
1459 m_input_empty_cb = input_empty_cb;
1460 m_output_full_cb = output_full_cb;
1461 }
1462
1463
set_fifo_callbacks(read16smo_delegate fifo_data_r,read16mo_delegate fifo_status_r,write_line_delegate fifo_reset_w)1464 void dcs_audio_device::set_fifo_callbacks(read16smo_delegate fifo_data_r, read16mo_delegate fifo_status_r, write_line_delegate fifo_reset_w)
1465 {
1466 m_fifo_data_r = fifo_data_r;
1467 m_fifo_status_r = fifo_status_r;
1468 m_fifo_reset_w = fifo_reset_w;
1469 }
1470
1471
control_r()1472 int dcs_audio_device::control_r()
1473 {
1474 /* only boost for DCS2 boards */
1475 if (!m_auto_ack && !m_transfer.hle_enabled)
1476 machine().scheduler().boost_interleave(attotime::from_nsec(500), attotime::from_usec(5));
1477 if ( /* m_rev == REV_DSC1 || */ m_rev == REV_DCS1P5) // == 1 check breaks mk3
1478 return IS_OUTPUT_FULL() ? 0x80 : 0x00;
1479 return m_latch_control;
1480 }
1481
1482
reset_w(int state)1483 void dcs_audio_device::reset_w(int state)
1484 {
1485 /* going low halts the CPU */
1486 if (!state)
1487 {
1488 // logerror("%s: DCS reset = %d\n", machine().describe_context(), state);
1489
1490 /* just run through the init code again */
1491 machine().scheduler().synchronize(timer_expired_delegate(FUNC(dcs_audio_device::dcs_reset),this));
1492 m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
1493 }
1494
1495 /* going high resets and reactivates the CPU */
1496 else
1497 m_cpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
1498 }
1499
1500
latch_status_r(address_space & space)1501 uint16_t dcs_audio_device::latch_status_r(address_space &space)
1502 {
1503 int result = 0;
1504 if (IS_INPUT_FULL())
1505 result |= 0x80;
1506 if (IS_OUTPUT_EMPTY())
1507 result |= 0x40;
1508 if (!m_fifo_status_r.isnull() && (!m_transfer.hle_enabled || m_transfer.state == 0))
1509 result |= m_fifo_status_r(space) & 0x38;
1510 if (m_transfer.hle_enabled && m_transfer.state != 0)
1511 result |= 0x08;
1512 return result;
1513 }
1514
1515
fifo_input_r()1516 uint16_t dcs_audio_device::fifo_input_r()
1517 {
1518 if (!m_fifo_data_r.isnull())
1519 return m_fifo_data_r();
1520 else
1521 return 0xffff;
1522 }
1523
1524
1525
1526 /***************************************************************************
1527 INPUT LATCH (data from host to DCS)
1528 ****************************************************************************/
1529
dcs_delayed_data_w(uint16_t data)1530 void dcs_audio_device::dcs_delayed_data_w(uint16_t data)
1531 {
1532 if (LOG_DCS_IO)
1533 logerror("%s:dcs_data_w(%04X)\n", machine().describe_context(), data);
1534
1535 /* boost the interleave temporarily */
1536 machine().scheduler().boost_interleave(attotime::from_nsec(500), attotime::from_usec(5));
1537
1538 /* set the IRQ line on the ADSP */
1539 m_cpu->set_input_line(ADSP2105_IRQ2, ASSERT_LINE);
1540
1541 /* indicate we are no longer empty */
1542 if (m_last_input_empty && !m_input_empty_cb.isnull())
1543 m_input_empty_cb(m_last_input_empty = 0);
1544 SET_INPUT_FULL();
1545
1546 /* set the data */
1547 m_input_data = data;
1548 }
1549
1550
TIMER_CALLBACK_MEMBER(dcs_audio_device::dcs_delayed_data_w_callback)1551 TIMER_CALLBACK_MEMBER( dcs_audio_device::dcs_delayed_data_w_callback )
1552 {
1553 dcs_delayed_data_w(param);
1554 }
1555
1556
data_w(uint16_t data)1557 void dcs_audio_device::data_w(uint16_t data)
1558 {
1559 /* preprocess the write */
1560 // ADSP2181 variants use IDMA to transfer data
1561 if (m_rev <= REV_DCS2 && preprocess_write(data))
1562 return;
1563
1564 /* if we are DCS1, set a timer to latch the data */
1565 if (m_sport0_timer == nullptr)
1566 machine().scheduler().synchronize(timer_expired_delegate(FUNC(dcs_audio_device::dcs_delayed_data_w_callback),this), data);
1567 else
1568 dcs_delayed_data_w(data);
1569 }
1570
1571
input_latch_ack_w(uint16_t data)1572 void dcs_audio_device::input_latch_ack_w(uint16_t data)
1573 {
1574 if (!m_last_input_empty && !m_input_empty_cb.isnull())
1575 m_input_empty_cb(m_last_input_empty = 1);
1576 SET_INPUT_EMPTY();
1577 m_cpu->set_input_line(ADSP2105_IRQ2, CLEAR_LINE);
1578
1579 if (LOG_DCS_IO)
1580 logerror("%s input_latch_ack_w\n", machine().describe_context());
1581 }
1582
1583
input_latch_r()1584 uint16_t dcs_audio_device::input_latch_r()
1585 {
1586 if (m_auto_ack)
1587 input_latch_ack_w(0);
1588
1589 if (LOG_DCS_IO)
1590 logerror("%s input_latch_r(%04X)\n", machine().describe_context(), m_input_data);
1591 return m_input_data;
1592 }
1593
input_latch32_r()1594 uint32_t dcs_audio_device::input_latch32_r()
1595 {
1596 if (m_auto_ack)
1597 input_latch_ack_w(0);
1598 if (LOG_DCS_IO)
1599 logerror("%s input_latch32_r(%04X)\n", machine().describe_context(), m_input_data);
1600 return m_input_data << 8;
1601 }
1602
1603 /***************************************************************************
1604 OUTPUT LATCH (data from DCS to host)
1605 ****************************************************************************/
1606
TIMER_CALLBACK_MEMBER(dcs_audio_device::latch_delayed_w)1607 TIMER_CALLBACK_MEMBER( dcs_audio_device::latch_delayed_w )
1608 {
1609 if (!m_last_output_full && !m_output_full_cb.isnull())
1610 m_output_full_cb(m_last_output_full = 1);
1611 SET_OUTPUT_FULL();
1612 m_output_data = m_pre_output_data;
1613 }
1614
1615
output_latch_w(uint16_t data)1616 void dcs_audio_device::output_latch_w(uint16_t data)
1617 {
1618 m_pre_output_data = data;
1619 if (LOG_DCS_IO)
1620 logerror("%s output_latch_w(%04X) (empty=%d)\n", machine().describe_context(), data, IS_OUTPUT_EMPTY());
1621
1622 machine().scheduler().synchronize(timer_expired_delegate(FUNC(dcs_audio_device::latch_delayed_w),this), data>>8);
1623 }
1624
output_latch32_w(uint32_t data)1625 void dcs_audio_device::output_latch32_w(uint32_t data)
1626 {
1627 m_pre_output_data = data >> 8;
1628 if (LOG_DCS_IO)
1629 logerror("%s output_latch32_w(%04X) (empty=%d)\n", machine().describe_context(), data>>8, IS_OUTPUT_EMPTY());
1630
1631 machine().scheduler().synchronize(timer_expired_delegate(FUNC(dcs_audio_device::latch_delayed_w),this), data>>8);
1632 }
1633
1634
delayed_ack_w()1635 void dcs_audio_device::delayed_ack_w()
1636 {
1637 SET_OUTPUT_EMPTY();
1638 }
1639
1640
TIMER_CALLBACK_MEMBER(dcs_audio_device::delayed_ack_w_callback)1641 TIMER_CALLBACK_MEMBER( dcs_audio_device::delayed_ack_w_callback )
1642 {
1643 delayed_ack_w();
1644 }
1645
1646
ack_w()1647 void dcs_audio_device::ack_w()
1648 {
1649 if (LOG_DCS_IO)
1650 logerror("%s:ack_w\n", machine().describe_context());
1651 machine().scheduler().synchronize(timer_expired_delegate(FUNC(dcs_audio_device::delayed_ack_w_callback),this));
1652 }
1653
1654
data_r()1655 uint16_t dcs_audio_device::data_r()
1656 {
1657 // If the cpu is reading empty data it is probably polling so eat some cyles
1658 if IS_OUTPUT_EMPTY()
1659 m_maincpu->eat_cycles(4444);
1660
1661 /* data is actually only 8 bit (read from d8-d15, which is d0-d7 from the data access instructions POV) on early dcs, but goes 16 on later (seattle) */
1662 if (m_last_output_full && !m_output_full_cb.isnull())
1663 m_output_full_cb(m_last_output_full = 0);
1664 if (m_auto_ack)
1665 delayed_ack_w();
1666
1667 if (LOG_DCS_IO)
1668 logerror("%s:dcs_data_r(%04X)\n", machine().describe_context(), m_output_data);
1669 return m_output_data;
1670 }
1671
1672
1673
1674 /***************************************************************************
1675 OUTPUT CONTROL BITS (has 3 additional lines to the host)
1676 ****************************************************************************/
1677
TIMER_CALLBACK_MEMBER(dcs_audio_device::output_control_delayed_w)1678 TIMER_CALLBACK_MEMBER( dcs_audio_device::output_control_delayed_w )
1679 {
1680 //if (LOG_DCS_IO)
1681 // logerror("output_control = %04X\n", param);
1682 m_output_control = param;
1683 m_output_control_cycles = 0;
1684 }
1685
1686
output_control_w(uint16_t data)1687 void dcs_audio_device::output_control_w(uint16_t data)
1688 {
1689 if (LOG_DCS_IO)
1690 logerror("%s output_control_w = %04X\n", machine().describe_context(), data);
1691 machine().scheduler().synchronize(timer_expired_delegate(FUNC(dcs_audio_device::output_control_delayed_w),this), data);
1692 }
1693
1694
output_control_r()1695 uint16_t dcs_audio_device::output_control_r()
1696 {
1697 if (LOG_DCS_IO)
1698 logerror("%s output_control_r = %04X\n", machine().describe_context(), m_output_control);
1699 m_output_control_cycles = m_cpu->total_cycles();
1700 return m_output_control;
1701 }
1702
1703
data2_r()1704 int dcs_audio_device::data2_r()
1705 {
1706 if (LOG_DCS_IO)
1707 logerror("%s: dcs:data2_r = %04X\n", machine().describe_context(), m_output_control);
1708
1709 return m_output_control;
1710 }
1711
1712
1713
1714 /*************************************
1715 *
1716 * Timer management
1717 *
1718 *************************************/
1719
update_timer_count()1720 void dcs_audio_device::update_timer_count()
1721 {
1722 uint64_t periods_since_start;
1723 uint64_t elapsed_cycles;
1724 uint64_t elapsed_clocks;
1725
1726 /* if not enabled, skip */
1727 if (!m_timer_enable)
1728 return;
1729
1730 /* count cycles */
1731 elapsed_cycles = m_cpu->total_cycles() - m_timer_start_cycles;
1732 elapsed_clocks = elapsed_cycles / m_timer_scale;
1733
1734 /* if we haven't counted past the initial count yet, just do that */
1735 if (elapsed_clocks < m_timer_start_count + 1) {
1736 m_timer_start_count -= elapsed_clocks;
1737 m_control_regs[TIMER_COUNT_REG] = m_timer_start_count;
1738
1739 /* otherwise, count how many periods */
1740 }
1741 else
1742 {
1743 elapsed_clocks -= m_timer_start_count + 1;
1744 periods_since_start = elapsed_clocks / (m_timer_period + 1);
1745 elapsed_clocks -= periods_since_start * (m_timer_period + 1);
1746 m_timer_start_count = m_timer_period - elapsed_clocks;
1747 m_control_regs[TIMER_COUNT_REG] = m_timer_start_count;
1748 }
1749 }
1750
1751
TIMER_DEVICE_CALLBACK_MEMBER(dcs_audio_device::internal_timer_callback)1752 TIMER_DEVICE_CALLBACK_MEMBER( dcs_audio_device::internal_timer_callback )
1753 {
1754 int64_t target_cycles;
1755
1756 /* compute the absolute cycle when the next one should fire */
1757 /* we do this to avoid drifting */
1758 m_timers_fired++;
1759 target_cycles = m_timer_start_cycles + m_timer_scale * (m_timer_start_count + 1 + m_timers_fired * (uint64_t)(m_timer_period + 1));
1760 target_cycles -= m_cpu->total_cycles();
1761
1762 /* set the next timer, but only if it's for a reasonable number */
1763 if (!m_timer_ignore && (m_timer_period > 10 || m_timer_scale > 1))
1764 timer.adjust(m_cpu->cycles_to_attotime(target_cycles));
1765
1766 /* the IRQ line is edge triggered */
1767 m_cpu->set_input_line(ADSP2105_TIMER, ASSERT_LINE);
1768 m_cpu->set_input_line(ADSP2105_TIMER, CLEAR_LINE);
1769 }
1770
1771
reset_timer()1772 void dcs_audio_device::reset_timer()
1773 {
1774 /* if not enabled, skip */
1775 if (!m_timer_enable)
1776 return;
1777
1778 /* compute the time until the first firing */
1779 m_timer_start_cycles = m_cpu->total_cycles();
1780 m_timers_fired = 0;
1781
1782 /* if this is the first timer, check the IRQ routine for the DRAM refresh stub */
1783 /* if that's all the timer does, we don't really need to fire */
1784 if (!m_timer_ignore)
1785 {
1786 // Denver variants (mwskins and sf2049) use the timer as a scaler for another count so we can't disable here
1787 // Denver gets disabled when reset TFS in the adsp control written
1788 // Road Burners: Code gets moved after initial diagnostic checks
1789 /* Road Burners: @ 28: JMP $0032 18032F, same code at $32 */
1790 /* Road Burners: @ 28: JMP $0030 18030F, same code at $30 */
1791 if (m_rev < REV_DSIO &&
1792 m_program->read_dword(0x18) == 0x0c0030 && /* ENA SEC_REG */
1793 m_program->read_dword(0x19) == 0x804828 && /* SI = DM($0482) */
1794 m_program->read_dword(0x1a) == 0x904828 && /* DM($0482) = SI */
1795 m_program->read_dword(0x1b) == 0x0C0020 && /* DIS SEC_REG */
1796 m_program->read_dword(0x1c) == 0x0A001F) /* RTI */
1797 {
1798 if (LOG_DCS_IO)
1799 logerror("reset_timer: Disabled timer %llu\n", m_timer_start_cycles);
1800 m_timer_ignore = true;
1801 } else if (m_rev == REV_DSIO &&
1802 m_program->read_dword(0x30) == 0x0c0030 && /* ENA SEC_REG */
1803 m_program->read_dword(0x31) == 0x014828 && /* SI = IO($0482) */
1804 m_program->read_dword(0x32) == 0x01c828 && /* IO($0482) = SI */
1805 m_program->read_dword(0x33) == 0x0C0020 && /* DIS SEC_REG */
1806 m_program->read_dword(0x34) == 0x0A001F) /* RTI */
1807 {
1808 if (LOG_DCS_IO)
1809 logerror("reset_timer: Disabled timer %llu\n", m_timer_start_cycles);
1810 m_timer_ignore = true;
1811 }
1812 }
1813
1814 /* adjust the timer if not optimized */
1815 if (!m_timer_ignore)
1816 m_internal_timer->adjust(m_cpu->cycles_to_attotime(m_timer_scale * (m_timer_start_count + 1)));
1817 }
1818
1819
WRITE_LINE_MEMBER(dcs_audio_device::timer_enable_callback)1820 WRITE_LINE_MEMBER(dcs_audio_device::timer_enable_callback)
1821 {
1822 if (state)
1823 {
1824 //logerror("Timer enabled @ %d cycles/int, or %f Hz\n", m_timer_scale * (m_timer_period + 1), 1.0 / m_cpu->cycles_to_attotime(m_timer_scale * (m_timer_period + 1)).as_double());
1825 m_timer_enable = state;
1826 reset_timer();
1827 }
1828 else
1829 {
1830 //logerror("Timer disabled\n");
1831 // Update the timer so the start count is correct the next time the timer is enabled
1832 update_timer_count();
1833 m_timer_enable = state;
1834 m_internal_timer->reset();
1835 }
1836 }
1837
1838
1839
1840 /***************************************************************************
1841 ADSP CONTROL & TRANSMIT CALLBACK
1842 ****************************************************************************/
1843
1844 /*
1845 The ADSP2105 memory map when in boot rom mode is as follows:
1846
1847 Program Memory:
1848 0x0000-0x03ff = Internal Program Ram (contents of boot rom gets copied here)
1849 0x0400-0x07ff = Reserved
1850 0x0800-0x3fff = External Program Ram
1851
1852 Data Memory:
1853 0x0000-0x03ff = External Data - 0 Waitstates
1854 0x0400-0x07ff = External Data - 1 Waitstates
1855 0x0800-0x2fff = External Data - 2 Waitstates
1856 0x3000-0x33ff = External Data - 3 Waitstates
1857 0x3400-0x37ff = External Data - 4 Waitstates
1858 0x3800-0x39ff = Internal Data Ram
1859 0x3a00-0x3bff = Reserved (extra internal ram space on ADSP2101, etc)
1860 0x3c00-0x3fff = Memory Mapped control registers & reserved.
1861 */
1862
adsp_control_r(offs_t offset)1863 uint16_t dcs_audio_device::adsp_control_r(offs_t offset)
1864 {
1865 uint16_t result = 0xffff;
1866
1867 switch (offset)
1868 {
1869 case PROG_FLAG_DATA_REG:
1870 // Probably some sort of frame start for DAC with external clock
1871 // Denver Atlantis mwskins wants 0x2 to toggle
1872 // Denver Durnago sf2049te wants 0x6 to toogle
1873 result = (m_control_regs[PROG_FLAG_CONTROL_REG] & m_control_regs[PROG_FLAG_DATA_REG]) | (m_progflags & ~m_control_regs[PROG_FLAG_CONTROL_REG]);
1874 m_progflags ^= 0x6;
1875 break;
1876
1877 case IDMA_CONTROL_REG:
1878 if (m_rev == REV_DSIO || m_rev == REV_DENV)
1879 result = downcast<adsp2181_device *>(m_cpu)->idma_addr_r();
1880 break;
1881
1882 case TIMER_COUNT_REG:
1883 update_timer_count();
1884 result = m_control_regs[offset];
1885 break;
1886
1887 default:
1888 result = m_control_regs[offset];
1889 break;
1890 }
1891 if (LOG_DCS_IO)
1892 logerror("%s adsp_control_r(%06x) = %04X\n", machine().describe_context(), offset + 0x3fe0, result);
1893 return result;
1894 }
1895
1896
adsp_control_w(offs_t offset,uint16_t data)1897 void dcs_audio_device:: adsp_control_w(offs_t offset, uint16_t data)
1898 {
1899 m_control_regs[offset] = data;
1900
1901 switch (offset)
1902 {
1903 case SYSCONTROL_REG:
1904 /* bit 9 forces a reset (not on 2181) */
1905 if ((data & 0x0200) && !(m_rev == REV_DSIO || m_rev == REV_DENV))
1906 {
1907 logerror("%s Rebooting DCS due to SYSCONTROL write = %04X\n", machine().describe_context(), data);
1908 m_cpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero);
1909 dcs_boot();
1910 m_control_regs[SYSCONTROL_REG] = 0;
1911 }
1912
1913 /* see if SPORT1 got disabled */
1914 if ((data & 0x0800) == 0)
1915 {
1916 dmadac_enable(&m_dmadac[0], m_channels, 0);
1917 m_reg_timer->reset();
1918 }
1919
1920 // Check SPORT0 enabled
1921 if (m_sport0_timer != nullptr) {
1922 if (data & 0x1000) {
1923 // Start the SPORT0 timer
1924 // SPORT0 is used as a 1kHz timer
1925 m_sport0_timer->adjust(attotime::from_usec(10), 0, attotime::from_hz(1000));
1926 if (LOG_DCS_IO)
1927 logerror("adsp_control_w: Setting SPORT0 freqency to 1kHz\n");
1928 }
1929 else {
1930 // Stop the SPORT0 timer
1931 m_sport0_timer->reset();
1932 }
1933 }
1934 break;
1935
1936 case S1_AUTOBUF_REG:
1937 /* autobuffer off: nuke the timer, and disable the DAC */
1938 if ((data & 0x0002) == 0)
1939 {
1940 dmadac_enable(&m_dmadac[0], m_channels, 0);
1941 m_reg_timer->reset();
1942 }
1943 break;
1944
1945 case S1_CONTROL_REG:
1946 if (((data >> 4) & 3) == 2)
1947 logerror("DCS: Oh no!, the data is compressed with u-law encoding\n");
1948 if (((data >> 4) & 3) == 3)
1949 logerror("DCS: Oh no!, the data is compressed with A-law encoding\n");
1950 break;
1951
1952 case TIMER_SCALE_REG:
1953 data = (data & 0xff) + 1;
1954 if (data != m_timer_scale)
1955 {
1956 update_timer_count();
1957 m_timer_scale = data;
1958 reset_timer();
1959 }
1960 break;
1961
1962 case TIMER_COUNT_REG:
1963 m_timer_start_count = data;
1964 reset_timer();
1965 break;
1966
1967 case TIMER_PERIOD_REG:
1968 if (data != m_timer_period)
1969 {
1970 update_timer_count();
1971 m_timer_period = data;
1972 reset_timer();
1973 }
1974 break;
1975
1976 case IDMA_CONTROL_REG:
1977 if (m_rev == REV_DSIO || m_rev == REV_DENV)
1978 dsio_idma_addr_w(data);
1979 break;
1980 }
1981 if (LOG_DCS_IO)
1982 logerror("%s adsp_control_w(%06x) = %04X\n", machine().describe_context(), offset + 0x3fe0, data);
1983 }
1984
1985
1986 /***************************************************************************
1987 DCS IRQ GENERATION CALLBACKS
1988 ****************************************************************************/
1989
TIMER_DEVICE_CALLBACK_MEMBER(dcs_audio_device::dcs_irq)1990 TIMER_DEVICE_CALLBACK_MEMBER( dcs_audio_device::dcs_irq )
1991 {
1992 /* get the index register */
1993 int reg = m_cpu->state_int(ADSP2100_I0 + m_ireg);
1994 if (LOG_DCS_IO)
1995 logerror("dcs_irq: m_ireg: %x m_size: %x m_incs: %x m_channels: %d m_ireg_base: %x reg: %06x\n", m_ireg, m_size, m_incs, m_channels, m_ireg_base, reg);
1996
1997 /* copy the current data into the buffer */
1998 {
1999 int count = m_size / (2*(m_incs ? m_incs : 1));
2000 // sf2049se was having overflow issues with fixed size of 0x400 buffer (m_size==0xb40, count=0x5a0).
2001 int16_t buffer[0x800];
2002 int i;
2003
2004 for (i = 0; i < count; i++)
2005 {
2006 buffer[i] = m_data->read_word(reg);
2007 reg += m_incs;
2008 }
2009
2010 if (m_channels)
2011 dmadac_transfer(&m_dmadac[0], m_channels, 1, m_channels, count / m_channels, buffer);
2012 }
2013
2014 /* check for wrapping */
2015 m_ireg_base = m_cpu->get_ibase(m_ireg);
2016 if (reg >= m_ireg_base + m_size)
2017 {
2018 /* reset the base pointer */
2019 reg = m_ireg_base;
2020
2021 /* generate the (internal, thats why the pulse) irq */
2022 if (LOG_DCS_IO)
2023 logerror("dcs_irq: Genrating interrupt\n");
2024 m_cpu->pulse_input_line(ADSP2105_IRQ1, m_cpu->minimum_quantum_time());
2025 }
2026
2027 /* store it */
2028 m_cpu->set_state_int(ADSP2100_I0 + m_ireg, reg);
2029 if (LOG_DCS_IO)
2030 logerror("dcs_irq end: m_size: %x m_incs: %x m_channels: %d m_ireg_base: %x reg: %06x\n", m_size, m_incs, m_channels, m_ireg_base, reg);
2031 }
2032
TIMER_DEVICE_CALLBACK_MEMBER(dcs_audio_device::sport0_irq)2033 TIMER_DEVICE_CALLBACK_MEMBER( dcs_audio_device::sport0_irq )
2034 {
2035
2036 /* this latches internally, so we just pulse */
2037 /* note that there is non-interrupt code that reads/modifies/writes the output_control */
2038 /* register; if we don't interlock it, we will eventually lose sound (see CarnEvil) */
2039 /* so we skip the SPORT interrupt if we read with output_control within the last 5 cycles */
2040 uint64_t diff = m_cpu->total_cycles() - m_output_control_cycles;
2041 if (diff > 5)
2042 {
2043 m_cpu->set_input_line(ADSP2115_SPORT0_RX, ASSERT_LINE);
2044 m_cpu->set_input_line(ADSP2115_SPORT0_RX, CLEAR_LINE);
2045 }
2046 }
2047
2048
recompute_sample_rate()2049 void dcs_audio_device::recompute_sample_rate()
2050 {
2051 /* calculate how long until we generate an interrupt */
2052
2053 /* frequency the time per each bit sent */
2054 attotime sample_period;
2055 if (m_control_regs[S1_CONTROL_REG] & 0x4000) {
2056 // Use internal clock for SPORT1 Tx timing
2057 sample_period = attotime::from_hz(m_cpu->unscaled_clock()) * (2 * (m_control_regs[S1_SCLKDIV_REG] + 1));
2058 /* now put it down to samples, so we know what the channel frequency has to be */
2059 sample_period *= (16 * m_channels);
2060 }
2061 else {
2062 // Use external clock for SPORT1 Tx timing 31.25 KHz sample clock
2063 sample_period = attotime::from_hz(31250);
2064 }
2065
2066 dmadac_set_frequency(&m_dmadac[0], m_channels, sample_period.as_hz());
2067 dmadac_enable(&m_dmadac[0], m_channels, 1);
2068 if (LOG_DCS_IO)
2069 logerror("recompute_sample_rate: Channels: %d Freq: %e Size: 0x%x m_incs: 0x%x\n", m_channels, sample_period.as_hz(), m_size, m_incs);
2070
2071 /* fire off a timer which will hit every half-buffer */
2072 if (m_incs)
2073 {
2074 attotime period = (sample_period * m_size) / (2 * m_channels * m_incs);
2075 m_reg_timer->adjust(period, 0, period);
2076 }
2077 }
2078
sound_tx_callback(offs_t offset,uint32_t data)2079 void dcs_audio_device::sound_tx_callback(offs_t offset, uint32_t data)
2080 {
2081 /* check if it's for SPORT1 */
2082 if (offset != 1) {
2083 logerror("sound_tx_callback: No code for offset %x\n", offset);
2084 return;
2085 }
2086
2087 /* check if SPORT1 is enabled */
2088 if (m_control_regs[SYSCONTROL_REG] & 0x0800) /* bit 11 */
2089 {
2090 /* we only support autobuffer here (wich is what this thing uses), bail if not enabled */
2091 if (m_control_regs[S1_AUTOBUF_REG] & 0x0002) /* bit 1 */
2092 {
2093 /* get the autobuffer registers */
2094 int mreg, lreg;
2095 uint16_t source;
2096
2097 m_ireg = (m_control_regs[S1_AUTOBUF_REG] >> 9) & 7;
2098 mreg = (m_control_regs[S1_AUTOBUF_REG] >> 7) & 3;
2099 mreg |= m_ireg & 0x04; /* msb comes from ireg */
2100 lreg = m_ireg;
2101
2102 /* now get the register contents in a more legible format */
2103 /* we depend on register indexes to be continuous (which is the case in our core) */
2104 source = m_cpu->state_int(ADSP2100_I0 + m_ireg);
2105 m_incs = m_cpu->state_int(ADSP2100_M0 + mreg);
2106 m_size = m_cpu->state_int(ADSP2100_L0 + lreg);
2107
2108 /* get the base value, since we need to keep it around for wrapping */
2109 //source -= m_incs;
2110 // Just clear lower 4 bits of source since some DCS versions haven't incremented yet
2111 source &= ~0xf;
2112
2113 /* make it go back one so we dont lose the first sample */
2114 m_cpu->set_state_int(ADSP2100_I0 + m_ireg, source);
2115
2116 /* save it as it is now */
2117 m_ireg_base = source;
2118
2119 if (LOG_DCS_IO)
2120 logerror("sound_tx_callback: m_ireg_base: %x m_size: %x m_incs: %x \n", m_ireg_base, m_size, m_incs);
2121 /* recompute the sample rate and timer */
2122 recompute_sample_rate();
2123 return;
2124 }
2125 else
2126 logerror( "ADSP SPORT1: trying to transmit and autobuffer not enabled!\n" );
2127 }
2128
2129 /* if we get there, something went wrong. Disable playing */
2130 dmadac_enable(&m_dmadac[0], m_channels, 0);
2131
2132 /* remove timer */
2133 m_reg_timer->reset();
2134 }
2135
2136
2137
2138 /***************************************************************************
2139 VERY BASIC & SAFE OPTIMIZATIONS
2140 ****************************************************************************/
2141
dcs_polling_r(address_space & space)2142 uint16_t dcs_audio_device::dcs_polling_r(address_space &space)
2143 {
2144 if (m_polling_count++ > 5)
2145 space.device().execute().eat_cycles(2000);
2146 return m_polling_value;
2147 }
2148
2149
dcs_polling_w(offs_t offset,uint16_t data,uint16_t mem_mask)2150 void dcs_audio_device::dcs_polling_w(offs_t offset, uint16_t data, uint16_t mem_mask)
2151 {
2152 m_polling_count = 0;
2153 COMBINE_DATA(&m_polling_value);
2154 }
2155
dcs_polling32_r(address_space & space)2156 uint32_t dcs_audio_device::dcs_polling32_r(address_space &space)
2157 {
2158 space.device().execute().eat_cycles(1000);
2159 return m_polling32_value;
2160 }
2161
dcs_polling32_w(offs_t offset,uint32_t data,uint32_t mem_mask)2162 void dcs_audio_device::dcs_polling32_w(offs_t offset, uint32_t data, uint32_t mem_mask)
2163 {
2164 m_polling_count = 0;
2165 COMBINE_DATA(&m_polling32_value);
2166 }
2167
2168
2169
2170 /***************************************************************************
2171 DATA TRANSFER HLE MECHANISM
2172 ****************************************************************************/
2173
fifo_notify(int count,int max)2174 void dcs_audio_device::fifo_notify(int count, int max)
2175 {
2176 hle_transfer_state &transfer = m_transfer;
2177
2178 /* skip if not in mid-transfer */
2179 if (!transfer.hle_enabled || transfer.state == 0 || m_fifo_data_r.isnull())
2180 {
2181 transfer.fifo_entries = 0;
2182 return;
2183 }
2184
2185 /* preprocess a word */
2186 transfer.fifo_entries = count;
2187 if (transfer.state != 5 || transfer.fifo_entries == transfer.writes_left || transfer.fifo_entries >= 256)
2188 {
2189 for ( ; transfer.fifo_entries; transfer.fifo_entries--)
2190 preprocess_write(m_fifo_data_r());
2191 }
2192 }
2193
2194
TIMER_DEVICE_CALLBACK_MEMBER(dcs_audio_device::transfer_watchdog_callback)2195 TIMER_DEVICE_CALLBACK_MEMBER( dcs_audio_device::transfer_watchdog_callback )
2196 {
2197 hle_transfer_state &transfer = m_transfer;
2198 int starting_writes_left = param;
2199
2200 if (transfer.fifo_entries && starting_writes_left == transfer.writes_left)
2201 {
2202 for ( ; transfer.fifo_entries; transfer.fifo_entries--)
2203 preprocess_write(m_fifo_data_r());
2204 }
2205 if (transfer.watchdog != nullptr)
2206 transfer.watchdog->adjust(attotime::from_msec(1), transfer.writes_left);
2207 }
2208
2209
TIMER_CALLBACK_MEMBER(dcs_audio_device::s1_ack_callback2)2210 TIMER_CALLBACK_MEMBER( dcs_audio_device::s1_ack_callback2 )
2211 {
2212 /* if the output is full, stall for a usec */
2213 if (IS_OUTPUT_FULL())
2214 {
2215 machine().scheduler().timer_set(attotime::from_usec(1), timer_expired_delegate(FUNC(dcs_audio_device::s1_ack_callback2),this), param);
2216 return;
2217 }
2218 output_latch_w(0x000a);
2219 }
2220
2221
TIMER_CALLBACK_MEMBER(dcs_audio_device::s1_ack_callback1)2222 TIMER_CALLBACK_MEMBER( dcs_audio_device::s1_ack_callback1 )
2223 {
2224 /* if the output is full, stall for a usec */
2225 if (IS_OUTPUT_FULL())
2226 {
2227 machine().scheduler().timer_set(attotime::from_usec(1), timer_expired_delegate(FUNC(dcs_audio_device::s1_ack_callback1),this), param);
2228 return;
2229 }
2230 output_latch_w(param);
2231
2232 /* chain to the next word we need to write back */
2233 machine().scheduler().timer_set(attotime::from_usec(1), timer_expired_delegate(FUNC(dcs_audio_device::s1_ack_callback2),this));
2234 }
2235
2236
preprocess_stage_1(uint16_t data)2237 int dcs_audio_device::preprocess_stage_1(uint16_t data)
2238 {
2239 hle_transfer_state &transfer = m_transfer;
2240
2241 switch (transfer.state)
2242 {
2243 case 0:
2244 /* look for command 0x001a to transfer chunks of data */
2245 if (data == 0x001a)
2246 {
2247 if (LOG_DCS_TRANSFERS)
2248 logerror("%s:DCS Transfer command %04X\n", machine().describe_context(), data);
2249 transfer.state++;
2250 if (transfer.hle_enabled)
2251 return 1;
2252 }
2253
2254 /* look for command 0x002a to start booting the uploaded program */
2255 else if (data == 0x002a)
2256 {
2257 if (LOG_DCS_TRANSFERS)
2258 logerror("%s:DCS State change %04X\n", machine().describe_context(), data);
2259 transfer.dcs_state = 1;
2260 }
2261
2262 /* anything else is ignored */
2263 else
2264 {
2265 if (LOG_DCS_TRANSFERS)
2266 logerror("Command: %04X\n", data);
2267 }
2268 break;
2269
2270 case 1:
2271 /* first word is the start address */
2272 transfer.start = data;
2273 transfer.state++;
2274 if (LOG_DCS_TRANSFERS)
2275 logerror("Start address = %04X\n", transfer.start);
2276 if (transfer.hle_enabled)
2277 return 1;
2278 break;
2279
2280 case 2:
2281 /* second word is the stop address */
2282 transfer.stop = data;
2283 transfer.state++;
2284 if (LOG_DCS_TRANSFERS)
2285 logerror("Stop address = %04X\n", transfer.stop);
2286 if (transfer.hle_enabled)
2287 return 1;
2288 break;
2289
2290 case 3:
2291 /* third word is the transfer type */
2292 /* transfer type 0 = program memory */
2293 /* transfer type 1 = SRAM bank 0 */
2294 /* transfer type 2 = SRAM bank 1 */
2295 transfer.type = data;
2296 transfer.state++;
2297 if (LOG_DCS_TRANSFERS) logerror("Transfer type = %04X\n", transfer.type);
2298
2299 /* at this point, we can compute how many words to expect for the transfer */
2300 transfer.writes_left = transfer.stop - transfer.start + 1;
2301 if (transfer.type == 0)
2302 transfer.writes_left *= 2;
2303
2304 /* reset the checksum */
2305 transfer.sum = 0;
2306
2307 /* handle the HLE case */
2308 if (transfer.hle_enabled)
2309 {
2310 if (transfer.type == 1 && SDRC_SM_BK == 1)
2311 {
2312 m_sdrc.reg[0] &= ~0x1000;
2313 sdrc_remap_memory();
2314 }
2315 if (transfer.type == 2 && SDRC_SM_BK == 0)
2316 {
2317 m_sdrc.reg[0] |= 0x1000;
2318 sdrc_remap_memory();
2319 }
2320 return 1;
2321 }
2322 break;
2323
2324 case 4:
2325 /* accumulate the sum over all data */
2326 transfer.sum += data;
2327
2328 /* if we're out, stop the transfer */
2329 if (--transfer.writes_left == 0)
2330 {
2331 if (LOG_DCS_TRANSFERS) logerror("Transfer done, sum = %04X\n", transfer.sum);
2332 transfer.state = 0;
2333 }
2334
2335 /* handle the HLE case */
2336 if (transfer.hle_enabled)
2337 {
2338 /* write the new data to memory */
2339 if (transfer.type == 0)
2340 {
2341 if (transfer.writes_left & 1)
2342 transfer.temp = data;
2343 else
2344 m_program->write_dword(transfer.start++, (transfer.temp << 8) | (data & 0xff));
2345 }
2346 else
2347 m_data->write_word(transfer.start++, data);
2348
2349 /* if we're done, start a timer to send the response words */
2350 if (transfer.state == 0)
2351 machine().scheduler().timer_set(attotime::from_usec(1), timer_expired_delegate(FUNC(dcs_audio_device::s1_ack_callback1),this), transfer.sum);
2352 return 1;
2353 }
2354 break;
2355 }
2356 return 0;
2357 }
2358
2359
TIMER_CALLBACK_MEMBER(dcs_audio_device::s2_ack_callback)2360 TIMER_CALLBACK_MEMBER( dcs_audio_device::s2_ack_callback )
2361 {
2362 /* if the output is full, stall for a usec */
2363 if (IS_OUTPUT_FULL())
2364 {
2365 machine().scheduler().timer_set(attotime::from_usec(1), timer_expired_delegate(FUNC(dcs_audio_device::s2_ack_callback),this), param);
2366 return;
2367 }
2368 output_latch_w(param);
2369 output_control_w((m_output_control & ~0xff00) | 0x0300);
2370 }
2371
2372
preprocess_stage_2(uint16_t data)2373 int dcs_audio_device::preprocess_stage_2(uint16_t data)
2374 {
2375 hle_transfer_state &transfer = m_transfer;
2376
2377 switch (transfer.state)
2378 {
2379 case 0:
2380 /* look for command 0x55d0 or 0x55d1 to transfer chunks of data */
2381 if (data == 0x55d0 || data == 0x55d1)
2382 {
2383 if (LOG_DCS_TRANSFERS)
2384 logerror("%s:DCS Transfer command %04X\n", machine().describe_context(), data);
2385 transfer.state++;
2386 if (transfer.hle_enabled)
2387 return 1;
2388 }
2389
2390 /* anything else is ignored */
2391 else
2392 {
2393 if (LOG_DCS_TRANSFERS)
2394 logerror("%s:Command: %04X\n", machine().describe_context(), data);
2395 }
2396 break;
2397
2398 case 1:
2399 /* first word is the upper bits of the start address */
2400 transfer.start = data << 16;
2401 transfer.state++;
2402 if (transfer.hle_enabled)
2403 return 1;
2404 break;
2405
2406 case 2:
2407 /* second word is the lower bits of the start address */
2408 transfer.start |= data;
2409 transfer.state++;
2410 if (LOG_DCS_TRANSFERS)
2411 logerror("Start address = %08X\n", transfer.start);
2412 if (transfer.hle_enabled)
2413 return 1;
2414 break;
2415
2416 case 3:
2417 /* third word is the upper bits of the stop address */
2418 transfer.stop = data << 16;
2419 transfer.state++;
2420 if (transfer.hle_enabled)
2421 return 1;
2422 break;
2423
2424 case 4:
2425 /* fourth word is the lower bits of the stop address */
2426 transfer.stop |= data;
2427 transfer.state++;
2428 if (LOG_DCS_TRANSFERS)
2429 logerror("Stop address = %08X\n", transfer.stop);
2430
2431 /* at this point, we can compute how many words to expect for the transfer */
2432 transfer.writes_left = transfer.stop - transfer.start + 1;
2433
2434 /* reset the checksum */
2435 transfer.sum = 0;
2436 if (transfer.hle_enabled)
2437 {
2438 transfer.watchdog->adjust(attotime::from_msec(1), transfer.writes_left);
2439 return 1;
2440 }
2441 break;
2442
2443 case 5:
2444 /* accumulate the sum over all data */
2445 transfer.sum += data;
2446
2447 /* if we're out, stop the transfer */
2448 if (--transfer.writes_left == 0)
2449 {
2450 if (LOG_DCS_TRANSFERS)
2451 logerror("Transfer done, sum = %04X\n", transfer.sum);
2452 transfer.state = 0;
2453 }
2454
2455 /* handle the HLE case */
2456 if (transfer.hle_enabled)
2457 {
2458 /* write the new data to memory */
2459 m_sounddata[transfer.start++] = data;
2460
2461 /* if we're done, start a timer to send the response words */
2462 if (transfer.state == 0)
2463 {
2464 machine().scheduler().timer_set(attotime::from_usec(1), timer_expired_delegate(FUNC(dcs_audio_device::s2_ack_callback),this), transfer.sum);
2465 transfer.watchdog->reset();
2466 }
2467 return 1;
2468 }
2469 break;
2470 }
2471 return 0;
2472 }
2473
2474
preprocess_write(uint16_t data)2475 int dcs_audio_device::preprocess_write(uint16_t data)
2476 {
2477 hle_transfer_state &transfer = m_transfer;
2478 int result;
2479
2480 /* if we're not DCS2, skip */
2481 if (m_sport0_timer == nullptr)
2482 return 0;
2483
2484 /* state 0 - initialization phase */
2485 if (transfer.dcs_state == 0)
2486 result = preprocess_stage_1(data);
2487 else
2488 result = preprocess_stage_2(data);
2489
2490 /* if we did the write, toggle the full/not full state so interrupts are generated */
2491 if (result && !m_input_empty_cb.isnull())
2492 {
2493 if (m_last_input_empty)
2494 m_input_empty_cb(m_last_input_empty = 0);
2495 if (!m_last_input_empty)
2496 m_input_empty_cb(m_last_input_empty = 1);
2497 }
2498 return result;
2499 }
2500
2501 /* Basic DCS system with ADSP-2105 and 2k of SRAM (T-unit, V-unit, Killer Instinct) */
2502
add_mconfig_dcs(machine_config & config)2503 void dcs_audio_device::add_mconfig_dcs(machine_config &config)
2504 {
2505 adsp2105_device &dcs(ADSP2105(config, "dcs", XTAL(10'000'000)));
2506 dcs.sport_tx().set(FUNC(dcs_audio_device::sound_tx_callback)); /* callback for serial transmit */
2507 dcs.timer_fired().set(FUNC(dcs_audio_device::timer_enable_callback)); /* callback for timer fired */
2508 dcs.set_addrmap(AS_PROGRAM, &dcs_audio_device::dcs_2k_program_map);
2509 dcs.set_addrmap(AS_DATA, &dcs_audio_device::dcs_2k_data_map);
2510
2511 TIMER(config, "dcs_reg_timer").configure_generic(FUNC(dcs_audio_device::dcs_irq));
2512 TIMER(config, "dcs_int_timer").configure_generic(FUNC(dcs_audio_device::internal_timer_callback));
2513
2514 SPEAKER(config, "mono").front_center();
2515
2516 DMADAC(config, "dac").add_route(ALL_OUTPUTS, "mono", 1.0); // AD-1851 16bit mono
2517 }
2518
2519 DEFINE_DEVICE_TYPE(DCS_AUDIO_2K, dcs_audio_2k_device, "dcs_audio_2k", "DCS Audio 2K")
2520
2521 //-------------------------------------------------
2522 // dcs_audio_2k_device - constructor
2523 //-------------------------------------------------
2524
dcs_audio_2k_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2525 dcs_audio_2k_device::dcs_audio_2k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2526 dcs_audio_device(mconfig, DCS_AUDIO_2K, tag, owner, clock, REV_DCS1)
2527 {
2528 }
2529
device_add_mconfig(machine_config & config)2530 void dcs_audio_2k_device::device_add_mconfig(machine_config &config)
2531 {
2532 dcs_audio_device::add_mconfig_dcs(config);
2533 }
2534
2535 DEFINE_DEVICE_TYPE(DCS_AUDIO_2K_UART, dcs_audio_2k_uart_device, "dcs_audio_2k_uart", "DCS Audio 2K UART")
2536
2537 //-------------------------------------------------
2538 // dcs_audio_2k_uart_device - constructor
2539 //-------------------------------------------------
2540
dcs_audio_2k_uart_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2541 dcs_audio_2k_uart_device::dcs_audio_2k_uart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2542 dcs_audio_device(mconfig, DCS_AUDIO_2K_UART, tag, owner, clock, REV_DCS1)
2543 {
2544 }
2545
2546 /* Basic DCS system with ADSP-2105 and 2k of SRAM, using a UART for communications (X-unit) */
device_add_mconfig(machine_config & config)2547 void dcs_audio_2k_uart_device::device_add_mconfig(machine_config &config)
2548 {
2549 dcs_audio_device::add_mconfig_dcs(config);
2550 subdevice<adsp21xx_device>("dcs")->set_addrmap(AS_DATA, &dcs_audio_2k_uart_device::dcs_2k_uart_data_map);
2551 }
2552
2553 DEFINE_DEVICE_TYPE(DCS_AUDIO_8K, dcs_audio_8k_device, "dcs_audio_8k", "DCS Audio 8K")
2554
2555 //-------------------------------------------------
2556 // dcs_audio_8k_device - constructor
2557 //-------------------------------------------------
2558
dcs_audio_8k_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2559 dcs_audio_8k_device::dcs_audio_8k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2560 dcs_audio_device(mconfig, DCS_AUDIO_8K, tag, owner, clock, REV_DCS1)
2561 {
2562 }
2563
2564 /* Basic DCS system with ADSP-2105 and 8k of SRAM (Wolf-unit) */
device_add_mconfig(machine_config & config)2565 void dcs_audio_8k_device::device_add_mconfig(machine_config &config)
2566 {
2567 dcs_audio_device::add_mconfig_dcs(config);
2568 subdevice<adsp21xx_device>("dcs")->set_addrmap(AS_PROGRAM, &dcs_audio_8k_device::dcs_8k_program_map);
2569 subdevice<adsp21xx_device>("dcs")->set_addrmap(AS_DATA, &dcs_audio_8k_device::dcs_8k_data_map);
2570 }
2571
2572 DEFINE_DEVICE_TYPE(DCS_AUDIO_WPC, dcs_audio_wpc_device, "dcs_audio_wpc", "DCS Audio WPC")
2573
2574 //-------------------------------------------------
2575 // dcs_audio_wpc_device - constructor
2576 //-------------------------------------------------
2577
dcs_audio_wpc_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2578 dcs_audio_wpc_device::dcs_audio_wpc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2579 dcs_audio_device(mconfig, DCS_AUDIO_WPC, tag, owner, clock, REV_DCS1P5)
2580 {
2581 }
2582
device_add_mconfig(machine_config & config)2583 void dcs_audio_wpc_device::device_add_mconfig(machine_config &config)
2584 {
2585 dcs_audio_device::add_mconfig_dcs(config);
2586 subdevice<adsp21xx_device>("dcs")->set_addrmap(AS_PROGRAM, &dcs_audio_wpc_device::dcs_wpc_program_map);
2587 subdevice<adsp21xx_device>("dcs")->set_addrmap(AS_DATA, &dcs_audio_wpc_device::dcs_wpc_data_map);
2588 }
2589
2590
2591 //-------------------------------------------------
2592 // dcs2_audio_device - constructor
2593 //-------------------------------------------------
2594
dcs2_audio_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)2595 dcs2_audio_device::dcs2_audio_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
2596 dcs_audio_device(mconfig, type, tag, owner, clock, REV_DCS1)
2597 {
2598 }
2599
add_mconfig_dcs2(machine_config & config)2600 void dcs2_audio_device::add_mconfig_dcs2(machine_config &config)
2601 {
2602 adsp2115_device &dcs2(ADSP2115(config, "dcs2", XTAL(16'000'000)));
2603 dcs2.sport_tx().set(FUNC(dcs_audio_device::sound_tx_callback)); /* callback for serial transmit */
2604 dcs2.timer_fired().set(FUNC(dcs_audio_device::timer_enable_callback)); /* callback for timer fired */
2605 dcs2.set_addrmap(AS_PROGRAM, &dcs2_audio_device::dcs2_2115_program_map);
2606 dcs2.set_addrmap(AS_DATA, &dcs2_audio_device::dcs2_2115_data_map);
2607
2608 TIMER(config, "dcs_reg_timer").configure_generic(FUNC(dcs_audio_device::dcs_irq));
2609 TIMER(config, "dcs_sport0_timer").configure_generic(FUNC(dcs_audio_device::sport0_irq));
2610 TIMER(config, "dcs_int_timer").configure_generic(FUNC(dcs_audio_device::internal_timer_callback));
2611 TIMER(config, "dcs_hle_timer").configure_generic(FUNC(dcs_audio_device::transfer_watchdog_callback));
2612
2613 SPEAKER(config, "lspeaker").front_left();
2614 SPEAKER(config, "rspeaker").front_right();
2615
2616 DMADAC(config, "dac1").add_route(ALL_OUTPUTS, "rspeaker", 1.0);
2617 DMADAC(config, "dac2").add_route(ALL_OUTPUTS, "lspeaker", 1.0);
2618 }
2619
2620 DEFINE_DEVICE_TYPE(DCS2_AUDIO_2115, dcs2_audio_2115_device, "dcs2_audio_2115", "DCS2 Audio 2115")
2621
2622 //-------------------------------------------------
2623 // dcs2_audio_2115_device - constructor
2624 //-------------------------------------------------
2625
dcs2_audio_2115_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2626 dcs2_audio_2115_device::dcs2_audio_2115_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2627 dcs2_audio_device(mconfig, DCS2_AUDIO_2115, tag, owner, clock)
2628 {
2629 }
2630
device_add_mconfig(machine_config & config)2631 void dcs2_audio_2115_device::device_add_mconfig(machine_config &config)
2632 {
2633 dcs2_audio_device::add_mconfig_dcs2(config);
2634 }
2635
2636 DEFINE_DEVICE_TYPE(DCS2_AUDIO_2104, dcs2_audio_2104_device, "dcs2_audio_2104", "DCS2 Audio 2104")
2637
2638 //-------------------------------------------------
2639 // dcs2_audio_2104_device - constructor
2640 //-------------------------------------------------
2641
2642
dcs2_audio_2104_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2643 dcs2_audio_2104_device::dcs2_audio_2104_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2644 dcs2_audio_device(mconfig, DCS2_AUDIO_2104, tag, owner, clock)
2645 {
2646 }
2647
device_add_mconfig(machine_config & config)2648 void dcs2_audio_2104_device::device_add_mconfig(machine_config &config)
2649 {
2650 dcs2_audio_device::add_mconfig_dcs2(config);
2651
2652 adsp2104_device &dcs2(ADSP2104(config.replace(), "dcs2", XTAL(16'000'000)));
2653 dcs2.sport_tx().set(FUNC(dcs_audio_device::sound_tx_callback)); /* callback for serial transmit */
2654 dcs2.timer_fired().set(FUNC(dcs_audio_device::timer_enable_callback)); /* callback for timer fired */
2655 dcs2.set_addrmap(AS_PROGRAM, &dcs2_audio_2104_device::dcs2_2104_program_map);
2656 dcs2.set_addrmap(AS_DATA, &dcs2_audio_2104_device::dcs2_2104_data_map);
2657 }
2658
2659 DEFINE_DEVICE_TYPE(DCS2_AUDIO_DSIO, dcs2_audio_dsio_device, "dcs2_audio_dsio", "DCS2 Audio DSIO")
2660
2661 //-------------------------------------------------
2662 // dcs2_audio_dsio_device - constructor
2663 //-------------------------------------------------
2664
dcs2_audio_dsio_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2665 dcs2_audio_dsio_device::dcs2_audio_dsio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2666 dcs2_audio_device(mconfig, DCS2_AUDIO_DSIO, tag, owner, clock)
2667 {
2668 }
2669
device_add_mconfig(machine_config & config)2670 void dcs2_audio_dsio_device::device_add_mconfig(machine_config &config)
2671 {
2672 adsp2181_device &dsio(ADSP2181(config, "dsio", XTAL(32'000'000)));
2673 dsio.sport_tx().set(FUNC(dcs_audio_device::sound_tx_callback)); /* callback for serial transmit */
2674 dsio.timer_fired().set(FUNC(dcs_audio_device::timer_enable_callback)); /* callback for timer fired */
2675 dsio.dmovlay().set(FUNC(dcs_audio_device::dmovlay_callback)); /* callback for adsp 2181 dmovlay instruction */
2676 dsio.set_addrmap(AS_PROGRAM, &dcs2_audio_dsio_device::dsio_program_map);
2677 dsio.set_addrmap(AS_DATA, &dcs2_audio_dsio_device::dsio_data_map);
2678 dsio.set_addrmap(AS_IO, &dcs2_audio_dsio_device::dsio_io_map);
2679
2680 ADDRESS_MAP_BANK(config, "data_map_bank").set_map(&dcs2_audio_dsio_device::dsio_rambank_map).set_options(ENDIANNESS_LITTLE, 16, 14, 0x2000);
2681
2682 TIMER(config, "dcs_reg_timer").configure_generic(FUNC(dcs_audio_device::dcs_irq));
2683 TIMER(config, "dcs_int_timer").configure_generic(FUNC(dcs_audio_device::internal_timer_callback));
2684 TIMER(config, "dcs_sport0_timer").configure_generic(FUNC(dcs_audio_device::sport0_irq)); // roadburn needs this to pass hardware test
2685
2686 SPEAKER(config, "lspeaker").front_left();
2687 SPEAKER(config, "rspeaker").front_right();
2688
2689 DMADAC(config, "dac1").add_route(ALL_OUTPUTS, "rspeaker", 1.0);
2690 DMADAC(config, "dac2").add_route(ALL_OUTPUTS, "lspeaker", 1.0);
2691 }
2692
2693
2694 //-------------------------------------------------
2695 // dcs2_audio_denver_device - constructor
2696 //-------------------------------------------------
dcs2_audio_denver_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)2697 dcs2_audio_denver_device::dcs2_audio_denver_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
2698 dcs2_audio_device(mconfig, type, tag, owner, clock)
2699 {
2700 }
2701
device_add_mconfig(machine_config & config)2702 void dcs2_audio_denver_device::device_add_mconfig(machine_config &config)
2703 {
2704 adsp2181_device &denver(ADSP2181(config, "denver", XTAL(33'333'000)));
2705 denver.sport_tx().set(FUNC(dcs_audio_device::sound_tx_callback)); /* callback for serial transmit */
2706 denver.timer_fired().set(FUNC(dcs_audio_device::timer_enable_callback)); /* callback for timer fired */
2707 denver.dmovlay().set(FUNC(dcs_audio_device::dmovlay_callback)); /* callback for adsp 2181 dmovlay instruction */
2708 denver.set_addrmap(AS_PROGRAM, &dcs2_audio_denver_device::denver_program_map);
2709 denver.set_addrmap(AS_DATA, &dcs2_audio_denver_device::denver_data_map);
2710 denver.set_addrmap(AS_IO, &dcs2_audio_denver_device::denver_io_map);
2711
2712 ADDRESS_MAP_BANK(config, "data_map_bank").set_map(&dcs2_audio_denver_device::denver_rambank_map).set_options(ENDIANNESS_LITTLE, 16, 15, 0x2000*2);
2713
2714 TIMER(config, "dcs_reg_timer").configure_generic(FUNC(dcs_audio_device::dcs_irq));
2715 TIMER(config, "dcs_int_timer").configure_generic(FUNC(dcs_audio_device::internal_timer_callback));
2716 TIMER(config, "dcs_sport0_timer").configure_generic(FUNC(dcs_audio_device::sport0_irq)); // Atlantis driver waits for sport0 rx interrupts
2717 }
2718
dcs2_audio_denver_5ch_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2719 dcs2_audio_denver_5ch_device::dcs2_audio_denver_5ch_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2720 dcs2_audio_denver_device(mconfig, DCS2_AUDIO_DENVER_5CH, tag, owner, clock)
2721 {
2722 }
2723
device_add_mconfig(machine_config & config)2724 void dcs2_audio_denver_5ch_device::device_add_mconfig(machine_config &config)
2725 {
2726 dcs2_audio_denver_device::device_add_mconfig(config);
2727
2728 SPEAKER(config, "flspeaker").front_left();
2729 SPEAKER(config, "frspeaker").front_right();
2730 SPEAKER(config, "rlspeaker").headrest_left();
2731 SPEAKER(config, "rrspeaker").headrest_right();
2732 SPEAKER(config, "subwoofer").backrest();
2733
2734 DMADAC(config, "dac1").add_route(ALL_OUTPUTS, "flspeaker", 1.0);
2735 DMADAC(config, "dac2").add_route(ALL_OUTPUTS, "frspeaker", 1.0);
2736 DMADAC(config, "dac3").add_route(ALL_OUTPUTS, "rlspeaker", 1.0);
2737 DMADAC(config, "dac4").add_route(ALL_OUTPUTS, "rrspeaker", 1.0);
2738 DMADAC(config, "dac5").add_route(ALL_OUTPUTS, "subwoofer", 1.0);
2739 DMADAC(config, "dac6");
2740 // Does not produce sound
2741 }
2742
2743 DEFINE_DEVICE_TYPE(DCS2_AUDIO_DENVER_5CH, dcs2_audio_denver_5ch_device, "dcs2_audio_denver_5ch", "DCS2 Audio Denver 5 Channel")
2744
dcs2_audio_denver_2ch_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2745 dcs2_audio_denver_2ch_device::dcs2_audio_denver_2ch_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2746 dcs2_audio_denver_device(mconfig, DCS2_AUDIO_DENVER_2CH, tag, owner, clock)
2747 {
2748 }
2749
device_add_mconfig(machine_config & config)2750 void dcs2_audio_denver_2ch_device::device_add_mconfig(machine_config &config)
2751 {
2752 dcs2_audio_denver_device::device_add_mconfig(config);
2753
2754 SPEAKER(config, "lspeaker").front_left();
2755 SPEAKER(config, "rspeaker").front_right();
2756
2757 DMADAC(config, "dac1").add_route(ALL_OUTPUTS, "rspeaker", 1.0);
2758 DMADAC(config, "dac2").add_route(ALL_OUTPUTS, "lspeaker", 1.0);
2759 }
2760
2761 DEFINE_DEVICE_TYPE(DCS2_AUDIO_DENVER_2CH, dcs2_audio_denver_2ch_device, "dcs2_audio_denver_2ch", "DCS2 Audio Denver 2 Channel")
2762