1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles,Paul Leaman
3 /***************************************************************************
4 
5     Cinemat/Leland driver
6 
7     Leland sound hardware
8     driver by Aaron Giles and Paul Leaman
9 
10     -------------------------------------------------------------------
11 
12     1st generation sound hardware was controlled by the master Z80.
13     It drove either an AY-8910/AY-8912 for music. It also had two DACs
14     that were driven by the video refresh. At the end of each scanline
15     there are 8-bit DAC samples that can be enabled via the output
16     ports on the AY-8910. The DACs run at a fixed frequency of 15.3kHz,
17     since they are clocked once each scanline.
18 
19     -------------------------------------------------------------------
20 
21     2nd generation sound hardware was used in Redline Racer. It
22     consisted of an 80186 microcontroller driving 8 8-bit DACs. The
23     frequency of the DACs were controlled by one of 3 Intel 8254
24     programmable interval timers (PITs):
25 
26         DAC number  Clock source
27         ----------  -----------------
28             0       8254 PIT 1 output 0
29             1       8254 PIT 1 output 1
30             2       8254 PIT 1 output 2
31             3       8254 PIT 2 output 0
32             4       8254 PIT 2 output 1
33             5-7     8254 PIT 3 output 0
34 
35     The clock outputs for each DAC can be read, and are polled to
36     determine when data should be updated on the chips. The 80186's
37     two DMA channels are generally used to drive the first two DACs,
38     with the remaining 6 DACs being fed manually via polling.
39 
40     -------------------------------------------------------------------
41 
42     3rd generation sound hardware appeared in the football games
43     (Quarterback, AAFB) and the later games up through Pigout. This
44     variant is closely based on the Redline Racer sound system, but
45     they took out two of the DACs and replaced them with a higher
46     resolution (10-bit) DAC. The driving clocks have been rearranged
47     a bit, and the number of PITs reduced from 3 to 2:
48 
49         DAC number  Clock source
50         ----------  -----------------
51             0       8254 PIT 1 output 0
52             1       8254 PIT 1 output 1
53             2       8254 PIT 1 output 2
54             3       8254 PIT 2 output 0
55             4       8254 PIT 2 output 1
56             5       8254 PIT 2 output 2
57             10-bit  80186 timer 0
58 
59     Like the 2nd generation board, the first two DACs are driven via
60     the DMA channels, and the remaining 5 DACs are polled.
61 
62     -------------------------------------------------------------------
63 
64     4th generation sound hardware showed up in Ataxx, Indy Heat, and
65     World Soccer Finals. For this variant, they removed one more PIT
66     and 3 of the 8-bit DACs, and added a YM2151 music chip and an
67     externally-fed 8-bit DAC.
68 
69         DAC number  Clock source
70         ----------  -----------------
71             0       8254 PIT 1 output 0
72             1       8254 PIT 1 output 1
73             2       8254 PIT 1 output 2
74             10-bit  80186 timer 0
75             ext     80186 timer 1
76 
77     The externally driven DACs have registers for a start/stop address
78     and triggers to control the clocking.
79 
80 ***************************************************************************/
81 
82 #include "emu.h"
83 #include "audio/leland.h"
84 
85 #include "cpu/z80/z80.h"
86 #include "speaker.h"
87 
88 #define LOG_COMM 0
89 #define LOG_EXTERN 0
90 
91 /*************************************
92  *
93  *  2nd-4th generation sound
94  *
95  *************************************/
96 
WRITE_LINE_MEMBER(leland_80186_sound_device::pit0_2_w)97 WRITE_LINE_MEMBER(leland_80186_sound_device::pit0_2_w)
98 {
99 	set_clock_line(2, state);
100 }
101 
WRITE_LINE_MEMBER(leland_80186_sound_device::pit1_0_w)102 WRITE_LINE_MEMBER(leland_80186_sound_device::pit1_0_w)
103 {
104 	set_clock_line(3, state);
105 }
106 
WRITE_LINE_MEMBER(leland_80186_sound_device::pit1_1_w)107 WRITE_LINE_MEMBER(leland_80186_sound_device::pit1_1_w)
108 {
109 	set_clock_line(4, state);
110 }
111 
WRITE_LINE_MEMBER(leland_80186_sound_device::pit1_2_w)112 WRITE_LINE_MEMBER(leland_80186_sound_device::pit1_2_w)
113 {
114 	set_clock_line(5, state);
115 }
116 
WRITE_LINE_MEMBER(leland_80186_sound_device::i80186_tmr0_w)117 WRITE_LINE_MEMBER(leland_80186_sound_device::i80186_tmr0_w)
118 {
119 	set_clock_line(6, state);
120 }
121 
WRITE_LINE_MEMBER(leland_80186_sound_device::i80186_tmr1_w)122 WRITE_LINE_MEMBER(leland_80186_sound_device::i80186_tmr1_w)
123 {
124 	if (m_ext_base != nullptr)
125 	{
126 		if (state)
127 		{
128 			if (m_ext_active && (m_ext_start < m_ext_stop))
129 			{
130 				m_dac[3]->write(m_ext_base[m_ext_start]);
131 				m_ext_start++;
132 			}
133 		}
134 	}
135 	set_clock_line(7, state);
136 }
137 
device_add_mconfig(machine_config & config)138 void leland_80186_sound_device::device_add_mconfig(machine_config &config)
139 {
140 	I80186(config, m_audiocpu, 16_MHz_XTAL);
141 	m_audiocpu->set_addrmap(AS_PROGRAM, &leland_80186_sound_device::leland_80186_map_program);
142 	m_audiocpu->set_addrmap(AS_IO, &leland_80186_sound_device::leland_80186_map_io);
143 	m_audiocpu->chip_select_callback().set(FUNC(leland_80186_sound_device::peripheral_ctrl));
144 	m_audiocpu->tmrout0_handler().set(FUNC(leland_80186_sound_device::i80186_tmr0_w));
145 
146 	SPEAKER(config, "speaker").front_center();
147 	for (int i = 0; i < 6; i++)
148 	{
149 		AD7524(config, m_dac[i], 0).add_route(ALL_OUTPUTS, "speaker", 0.2); // 74hc374.u31..6 + ad7524.u46..51
150 		DAC_8BIT_BINARY_WEIGHTED(config, m_dacvol[i], 0).set_output_range(0, 1); // 74hc374.u17..22 + rX2-rX9 (24k,12k,6.2k,3k,1.5k,750,360,160) where X is 0..5
151 		m_dacvol[i]->add_route(0, m_dac[i], 1.0, DAC_INPUT_RANGE_HI);
152 		m_dacvol[i]->add_route(0, m_dac[i], -1.0, DAC_INPUT_RANGE_LO);
153 	}
154 	AD7533(config, "dac9", 0).add_route(ALL_OUTPUTS, "speaker", 1.0); // ad7533.u64
155 
156 	PIT8254(config, m_pit[0], 0);
157 	m_pit[0]->set_clk<0>(4000000);
158 	m_pit[0]->out_handler<0>().set(m_audiocpu, FUNC(i80186_cpu_device::drq0_w));
159 	m_pit[0]->set_clk<1>(4000000);
160 	m_pit[0]->out_handler<1>().set(m_audiocpu, FUNC(i80186_cpu_device::drq1_w));
161 	m_pit[0]->set_clk<2>(4000000);
162 	m_pit[0]->out_handler<2>().set(FUNC(leland_80186_sound_device::pit0_2_w));
163 
164 	PIT8254(config, m_pit[1], 0);
165 	m_pit[1]->set_clk<0>(4000000);
166 	m_pit[1]->out_handler<0>().set(FUNC(leland_80186_sound_device::pit1_0_w));
167 	m_pit[1]->set_clk<1>(4000000);
168 	m_pit[1]->out_handler<1>().set(FUNC(leland_80186_sound_device::pit1_1_w));
169 	m_pit[1]->set_clk<2>(4000000);
170 	m_pit[1]->out_handler<2>().set(FUNC(leland_80186_sound_device::pit1_2_w));
171 
172 	GENERIC_LATCH_16(config, m_soundlatch);
173 }
174 
device_add_mconfig(machine_config & config)175 void redline_80186_sound_device::device_add_mconfig(machine_config &config)
176 {
177 	I80186(config, m_audiocpu, 16_MHz_XTAL);
178 	m_audiocpu->set_addrmap(AS_PROGRAM, &redline_80186_sound_device::leland_80186_map_program);
179 	m_audiocpu->set_addrmap(AS_IO, &redline_80186_sound_device::redline_80186_map_io);
180 	m_audiocpu->chip_select_callback().set(FUNC(leland_80186_sound_device::peripheral_ctrl));
181 
182 	SPEAKER(config, "speaker").front_center();
183 	for (int i = 0; i < 8; i++)
184 	{
185 		AD7524(config, m_dac[i], 0).add_route(ALL_OUTPUTS, "speaker", 0.2); // unknown DAC
186 		DAC_8BIT_BINARY_WEIGHTED(config, m_dacvol[i], 0).set_output_range(0, 1);
187 		m_dacvol[i]->add_route(0, m_dac[i], 1.0, DAC_INPUT_RANGE_HI);
188 		m_dacvol[i]->add_route(0, m_dac[i], -1.0, DAC_INPUT_RANGE_LO); // unknown DAC
189 	}
190 
191 	PIT8254(config, m_pit[0], 0);
192 	m_pit[0]->set_clk<0>(7000000);
193 	m_pit[0]->out_handler<0>().set(m_audiocpu, FUNC(i80186_cpu_device::drq0_w));
194 	m_pit[0]->set_clk<1>(7000000);
195 	m_pit[0]->out_handler<1>().set(m_audiocpu, FUNC(i80186_cpu_device::drq1_w));
196 	m_pit[0]->set_clk<2>(7000000);
197 	m_pit[0]->out_handler<2>().set(FUNC(leland_80186_sound_device::pit0_2_w));
198 
199 	PIT8254(config, m_pit[1], 0);
200 	m_pit[1]->set_clk<0>(7000000);
201 	m_pit[1]->out_handler<0>().set(FUNC(leland_80186_sound_device::pit1_0_w));
202 	m_pit[1]->set_clk<1>(7000000);
203 	m_pit[1]->out_handler<1>().set(FUNC(leland_80186_sound_device::pit1_1_w));
204 	m_pit[1]->set_clk<2>(7000000);
205 
206 	PIT8254(config, m_pit[2], 0);
207 	m_pit[2]->set_clk<0>(7000000);
208 	m_pit[2]->out_handler<0>().set(FUNC(leland_80186_sound_device::pit1_2_w));
209 	m_pit[2]->set_clk<1>(7000000);
210 	m_pit[2]->set_clk<2>(7000000);
211 
212 	GENERIC_LATCH_16(config, m_soundlatch);
213 }
214 
device_add_mconfig(machine_config & config)215 void ataxx_80186_sound_device::device_add_mconfig(machine_config &config)
216 {
217 	I80186(config, m_audiocpu, 16_MHz_XTAL);
218 	m_audiocpu->set_addrmap(AS_PROGRAM, &ataxx_80186_sound_device::leland_80186_map_program);
219 	m_audiocpu->set_addrmap(AS_IO, &ataxx_80186_sound_device::ataxx_80186_map_io);
220 	m_audiocpu->chip_select_callback().set(FUNC(leland_80186_sound_device::peripheral_ctrl));
221 	m_audiocpu->tmrout0_handler().set(FUNC(leland_80186_sound_device::i80186_tmr0_w));
222 
223 	SPEAKER(config, "speaker").front_center();
224 	for (int i = 0; i < 4; i++)
225 	{
226 		AD7524(config, m_dac[i], 0).add_route(ALL_OUTPUTS, "speaker", 0.2); // unknown DAC
227 		DAC_8BIT_BINARY_WEIGHTED(config, m_dacvol[i], 0).set_output_range(0, 1); // unknown DAC
228 		m_dacvol[i]->add_route(0, m_dac[i], 1.0, DAC_INPUT_RANGE_HI);
229 		m_dacvol[i]->add_route(0, m_dac[i], -1.0, DAC_INPUT_RANGE_LO);
230 	}
231 	AD7533(config, "dac9", 0).add_route(ALL_OUTPUTS, "speaker", 1.0); // unknown DAC
232 
233 	PIT8254(config, m_pit[0], 0);
234 	m_pit[0]->set_clk<0>(4000000);
235 	m_pit[0]->out_handler<0>().set(m_audiocpu, FUNC(i80186_cpu_device::drq0_w));
236 	m_pit[0]->set_clk<1>(4000000);
237 	m_pit[0]->out_handler<1>().set(m_audiocpu, FUNC(i80186_cpu_device::drq1_w));
238 	m_pit[0]->set_clk<2>(4000000);
239 	m_pit[0]->out_handler<2>().set(FUNC(leland_80186_sound_device::pit0_2_w));
240 
241 	GENERIC_LATCH_16(config, m_soundlatch);
242 }
243 
device_add_mconfig(machine_config & config)244 void wsf_80186_sound_device::device_add_mconfig(machine_config &config)
245 {
246 	I80186(config, m_audiocpu, 16_MHz_XTAL);
247 	m_audiocpu->set_addrmap(AS_PROGRAM, &wsf_80186_sound_device::leland_80186_map_program);
248 	m_audiocpu->set_addrmap(AS_IO, &wsf_80186_sound_device::ataxx_80186_map_io);
249 	m_audiocpu->chip_select_callback().set(FUNC(leland_80186_sound_device::peripheral_ctrl));
250 	m_audiocpu->tmrout0_handler().set(FUNC(leland_80186_sound_device::i80186_tmr0_w));
251 	m_audiocpu->tmrout1_handler().set(FUNC(leland_80186_sound_device::i80186_tmr1_w));
252 
253 	SPEAKER(config, "speaker").front_center();
254 	for (int i = 0; i < 4; i++)
255 	{
256 		AD7524(config, m_dac[i], 0).add_route(ALL_OUTPUTS, "speaker", 0.2); // unknown DAC
257 		DAC_8BIT_BINARY_WEIGHTED(config, m_dacvol[i], 0).set_output_range(0, 1); // unknown DAC
258 		m_dacvol[i]->add_route(0, m_dac[i], 1.0, DAC_INPUT_RANGE_HI);
259 		m_dacvol[i]->add_route(0, m_dac[i], -1.0, DAC_INPUT_RANGE_LO); // unknown DAC
260 	}
261 	AD7533(config, "dac9", 0).add_route(ALL_OUTPUTS, "speaker", 1.0); // unknown DAC
262 
263 	/* sound hardware */
264 	YM2151(config, m_ymsnd, 4000000);
265 	m_ymsnd->add_route(0, "speaker", 0.40);
266 	m_ymsnd->add_route(1, "speaker", 0.40);
267 
268 	PIT8254(config, m_pit[0], 0);
269 	m_pit[0]->set_clk<0>(4000000);
270 	m_pit[0]->out_handler<0>().set(m_audiocpu, FUNC(i80186_cpu_device::drq0_w));
271 	m_pit[0]->set_clk<1>(4000000);
272 	m_pit[0]->out_handler<1>().set(m_audiocpu, FUNC(i80186_cpu_device::drq1_w));
273 	m_pit[0]->set_clk<2>(4000000);
274 	m_pit[0]->out_handler<2>().set(FUNC(leland_80186_sound_device::pit0_2_w));
275 
276 	GENERIC_LATCH_16(config, m_soundlatch);
277 }
278 
279 
leland_80186_map_program(address_map & map)280 void leland_80186_sound_device::leland_80186_map_program(address_map &map)
281 {
282 	map(0x00000, 0x03fff).mirror(0x1c000).ram();
283 	map(0x20000, 0xfffff).rom().region("audiocpu", 0x20000);
284 }
285 
ataxx_80186_map_io(address_map & map)286 void leland_80186_sound_device::ataxx_80186_map_io(address_map &map)
287 {
288 }
289 
redline_80186_map_io(address_map & map)290 void redline_80186_sound_device::redline_80186_map_io(address_map &map)
291 {
292 	map(0x0000, 0xffff).w(FUNC(redline_80186_sound_device::redline_dac_w));
293 }
294 
295 
leland_80186_map_io(address_map & map)296 void leland_80186_sound_device::leland_80186_map_io(address_map &map)
297 {
298 	map(0x0000, 0xffff).w(FUNC(leland_80186_sound_device::dac_w));
299 }
300 
301 /*************************************
302  *
303  *  Sound initialization
304  *
305  *************************************/
306 
device_start()307 void leland_80186_sound_device::device_start()
308 {
309 	// register for savestates
310 	save_item(NAME(m_peripheral));
311 	save_item(NAME(m_last_control));
312 	save_item(NAME(m_clock_active));
313 	save_item(NAME(m_clock_tick));
314 	save_item(NAME(m_sound_command));
315 	save_item(NAME(m_sound_response));
316 	save_item(NAME(m_ext_start));
317 	save_item(NAME(m_ext_stop));
318 	save_item(NAME(m_ext_active));
319 
320 	// zerofill
321 	m_peripheral = 0;
322 	m_last_control = 0;
323 	m_clock_active = 0;
324 	m_clock_tick = 0;
325 	m_sound_command = 0;
326 	m_sound_response = 0;
327 	m_ext_start = 0;
328 	m_ext_stop = 0;
329 	m_ext_active = 0;
330 }
331 
device_reset()332 void leland_80186_sound_device::device_reset()
333 {
334 	m_last_control = 0xf8;
335 	m_clock_active = 0;
336 	m_clock_tick = 0;
337 	m_ext_start = 0;
338 	m_ext_stop = 0;
339 	m_ext_active = 0;
340 	if (m_type == TYPE_WSF)
341 		m_dacvol[3]->write(0xff);  //TODO: determine how to set this if at all
342 }
343 
344 DEFINE_DEVICE_TYPE(LELAND_80186, leland_80186_sound_device, "leland_80186_sound", "80186 DAC (Leland)")
345 
leland_80186_sound_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock)346 leland_80186_sound_device::leland_80186_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
347 	: leland_80186_sound_device(mconfig, LELAND_80186, tag, owner, clock)
348 {
349 	m_type = TYPE_LELAND;
350 }
351 
leland_80186_sound_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,u32 clock)352 leland_80186_sound_device::leland_80186_sound_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
353 	: device_t(mconfig, type, tag, owner, clock)
354 	, m_soundlatch(*this, "soundlatch")
355 	, m_dac(*this, "dac%u", 1U)
356 	, m_dac9(*this, "dac9")
357 	, m_dacvol(*this, "dac%uvol", 1U)
358 	, m_pit(*this, "pit%u", 0U)
359 	, m_audiocpu(*this, "audiocpu")
360 	, m_ymsnd(*this, "ymsnd")
361 	, m_master(*this, finder_base::DUMMY_TAG)
362 	, m_ext_base(*this, "ext")
363 {
364 }
365 
366 DEFINE_DEVICE_TYPE(REDLINE_80186, redline_80186_sound_device, "redline_80186_sound", "80186 DAC (Redline Racer)")
367 
redline_80186_sound_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock)368 redline_80186_sound_device::redline_80186_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
369 	: leland_80186_sound_device(mconfig, REDLINE_80186, tag, owner, clock)
370 {
371 	m_type = TYPE_REDLINE;
372 }
373 
374 DEFINE_DEVICE_TYPE(ATAXX_80186, ataxx_80186_sound_device, "ataxx_80186_sound", "80186 DAC (Ataxx)")
375 
ataxx_80186_sound_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock)376 ataxx_80186_sound_device::ataxx_80186_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
377 	: leland_80186_sound_device(mconfig, ATAXX_80186, tag, owner, clock)
378 {
379 	m_type = TYPE_ATAXX;
380 }
381 
382 DEFINE_DEVICE_TYPE(WSF_80186, wsf_80186_sound_device, "wsf_80186_sound", "80186 DAC (WSF)")
383 
wsf_80186_sound_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock)384 wsf_80186_sound_device::wsf_80186_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
385 	: leland_80186_sound_device(mconfig, WSF_80186, tag, owner, clock)
386 {
387 	m_type = TYPE_WSF;
388 }
389 
peripheral_ctrl(offs_t offset,u16 data)390 void leland_80186_sound_device::peripheral_ctrl(offs_t offset, u16 data)
391 {
392 	switch (offset)
393 	{
394 		case 2:
395 			m_peripheral = data;
396 			break;
397 
398 		case 4:
399 		{
400 			u32 temp = (m_peripheral & 0xffc0) << 4;
401 			if (data & 0x0040)
402 			{
403 				m_audiocpu->space(AS_PROGRAM).install_readwrite_handler(temp, temp + 0x2ff, read16s_delegate(*this, FUNC(leland_80186_sound_device::peripheral_r)), write16s_delegate(*this, FUNC(leland_80186_sound_device::peripheral_w)));
404 			}
405 			else
406 			{
407 				temp &= 0xffff;
408 				m_audiocpu->space(AS_IO).install_readwrite_handler(temp, temp + 0x2ff, read16s_delegate(*this, FUNC(leland_80186_sound_device::peripheral_r)), write16s_delegate(*this, FUNC(leland_80186_sound_device::peripheral_w)));
409 			}
410 			break;
411 		}
412 
413 		default:
414 			break;
415 	}
416 }
417 
418 /*************************************
419  *
420  *  External 80186 control
421  *
422  *************************************/
423 
leland_80186_control_w(u8 data)424 void leland_80186_sound_device::leland_80186_control_w(u8 data)
425 {
426 	/* see if anything changed */
427 	int diff = (m_last_control ^ data) & 0xf8;
428 	if (diff == 0)
429 		return;
430 	m_last_control = data;
431 
432 	if (LOG_COMM)
433 	{
434 		logerror("%s:80186 control = %02X", machine().describe_context(), data);
435 		if (!(data & 0x80)) logerror("  /RESET");
436 		if (!(data & 0x40)) logerror("  ZNMI");
437 		if (!(data & 0x20)) logerror("  INT0");
438 		if (!(data & 0x10)) logerror("  /TEST");
439 		if (!(data & 0x08)) logerror("  INT1");
440 		logerror("\n");
441 	}
442 
443 	/* /RESET */
444 	m_audiocpu->set_input_line(INPUT_LINE_RESET, (data & 0x80) ? CLEAR_LINE : ASSERT_LINE);
445 	m_audiocpu->set_input_line(INPUT_LINE_TEST, (data & 0x10) ? CLEAR_LINE : ASSERT_LINE);
446 
447 	/* /NMI */
448 /*  If the master CPU doesn't get a response by the time it's ready to send
449     the next command, it uses an NMI to force the issue; unfortunately, this
450     seems to really screw up the sound system. It turns out it's better to
451     just wait for the original interrupt to occur naturally */
452 /*  m_audiocpu->set_input_line(INPUT_LINE_NMI, (data & 0x40) ? CLEAR_LINE : ASSERT_LINE);*/
453 
454 	/* INT0 */
455 	m_audiocpu->int0_w(data & 0x20);
456 	/* INT1 */
457 	m_audiocpu->int1_w(data & 0x08);
458 	/* handle reset here */
459 	if ((diff & 0x80) && (data & 0x80))
460 		reset();
461 }
462 
463 
464 
465 /*************************************
466  *
467  *  Sound command handling
468  *
469  *************************************/
470 
command_lo_w(u8 data)471 void leland_80186_sound_device::command_lo_w(u8 data)
472 {
473 	if (LOG_COMM) logerror("%s:Write sound command latch lo = %02X\n", machine().describe_context(), data);
474 	m_sound_command = (m_sound_command & 0xff00) | data;
475 	m_soundlatch->write(m_sound_command);
476 }
477 
478 
command_hi_w(u8 data)479 void leland_80186_sound_device::command_hi_w(u8 data)
480 {
481 	if (LOG_COMM) logerror("%s:Write sound command latch hi = %02X\n", machine().describe_context(), data);
482 	m_sound_command = (m_sound_command & 0x00ff) | (data << 8);
483 	m_soundlatch->write(m_sound_command);
484 }
485 
486 
487 
488 
489 /*************************************
490  *
491  *  Sound response handling
492  *
493  *************************************/
494 
delayed_response_r(void * ptr,int param)495 void leland_80186_sound_device::delayed_response_r(void *ptr, int param)
496 {
497 	int checkpc = param;
498 	int pc = m_master->pc();
499 	int oldaf = m_master->state_int(Z80_AF);
500 
501 	/* This is pretty cheesy, but necessary. Since the CPUs run in round-robin order,
502 	   synchronizing on the write to this register from the slave side does nothing.
503 	   In order to make sure the master CPU get the real response, we synchronize on
504 	   the read. However, the value we returned the first time around may not be
505 	   accurate, so after the system has synced up, we go back into the master CPUs
506 	   state and put the proper value into the A register. */
507 	if (pc == checkpc)
508 	{
509 		if (LOG_COMM) logerror("(Updated sound response latch to %02X)\n", m_sound_response);
510 
511 		oldaf = (oldaf & 0x00ff) | (m_sound_response << 8);
512 		m_master->set_state_int(Z80_AF, oldaf);
513 	}
514 	else if(LOG_COMM)
515 		logerror("ERROR: delayed_response_r - current PC = %04X, checkPC = %04X\n", pc, checkpc);
516 }
517 
518 
response_r()519 u8 leland_80186_sound_device::response_r()
520 {
521 	offs_t pc = m_master->pcbase();
522 
523 	if (LOG_COMM) logerror("%04X:Read sound response latch = %02X\n", pc, m_sound_response);
524 
525 	/* synchronize the response */
526 	machine().scheduler().synchronize(timer_expired_delegate(FUNC(leland_80186_sound_device::delayed_response_r), this), pc + 2);
527 	return m_sound_response;
528 }
529 
530 
531 
532 /*************************************
533  *
534  *  Low-level DAC I/O
535  *
536  *************************************/
537 
dac_w(offs_t offset,u16 data,u16 mem_mask)538 void leland_80186_sound_device::dac_w(offs_t offset, u16 data, u16 mem_mask)
539 {
540 	int dac = offset & 7;
541 
542 	/* handle value changes */
543 	if (ACCESSING_BITS_0_7)
544 	{
545 		if ((offset & 0x60) == 0x40)
546 			m_audiocpu->drq0_w(CLEAR_LINE);
547 		else if ((offset & 0x60) == 0x60)
548 			m_audiocpu->drq1_w(CLEAR_LINE);
549 
550 		m_dac[dac]->write(data & 0xff);
551 
552 		set_clock_line(dac, 0);
553 	}
554 
555 	/* handle volume changes */
556 	if (ACCESSING_BITS_8_15)
557 	{
558 		m_dacvol[dac]->write(data >> 8);
559 	}
560 }
561 
562 
redline_dac_w(offs_t offset,u16 data)563 void redline_80186_sound_device::redline_dac_w(offs_t offset, u16 data)
564 {
565 	data = (data & 0xff) | (offset << 8);
566 	offset = ((offset >> 8) & 7) | ((offset & 0x2000) ? 0x40 : 0) | ((offset & 0x800) ? 0x20 : 0);
567 	dac_w(offset, data, 0xffff);
568 }
569 
ataxx_dac_control(offs_t offset,u16 data,u16 mem_mask)570 void leland_80186_sound_device::ataxx_dac_control(offs_t offset, u16 data, u16 mem_mask)
571 {
572 	if (ACCESSING_BITS_0_7)
573 	{
574 		/* handle common offsets */
575 		switch (offset & 0x1f)
576 		{
577 		case 0x00:
578 			dac_w(0x40, data, 0x00ff);
579 			return;
580 		case 0x01:
581 			dac_w(0x61, data, 0x00ff);
582 			return;
583 		case 0x02:
584 			dac_w(2, data, 0x00ff);
585 			return;
586 		case 0x03:
587 			m_dacvol[0]->write((data & 7) << 5);
588 			m_dacvol[1]->write(((data >> 3) & 7) << 5);
589 			m_dacvol[2]->write(((data >> 6) & 3) << 6);
590 			return;
591 		}
592 	}
593 
594 	/* if we have a YM2151 (and an external DAC), handle those offsets */
595 	switch (m_type)
596 	{
597 	case TYPE_WSF:
598 		switch (offset)
599 		{
600 		case 0x04:
601 			m_ext_active = 1;
602 			if (LOG_EXTERN) logerror("External DAC active\n");
603 			return;
604 		case 0x05:
605 			m_ext_active = 0;
606 			if (LOG_EXTERN) logerror("External DAC inactive\n");
607 			return;
608 		case 0x06:
609 			m_ext_start >>= 4;
610 			COMBINE_DATA(&m_ext_start);
611 			m_ext_start <<= 4;
612 			if (LOG_EXTERN) logerror("External DAC start = %05X\n", m_ext_start);
613 			return;
614 		case 0x07:
615 			m_ext_stop >>= 4;
616 			COMBINE_DATA(&m_ext_stop);
617 			m_ext_stop <<= 4;
618 			if (LOG_EXTERN) logerror("External DAC stop = %05X\n", m_ext_stop);
619 			return;
620 		}
621 		break;
622 	}
623 
624 	logerror("%s:Unexpected peripheral write %d/%02X = %02X\n", machine().describe_context(), 5, offset, data);
625 }
626 
627 
628 
629 /*************************************
630  *
631  *  Peripheral chip dispatcher
632  *
633  *************************************/
634 
peripheral_r(offs_t offset,u16 mem_mask)635 u16 leland_80186_sound_device::peripheral_r(offs_t offset, u16 mem_mask)
636 {
637 	int select = offset / 0x40;
638 	offset &= 0x3f;
639 
640 	switch (select)
641 	{
642 		case 0:
643 			/* we have to return 0 periodically so that they handle interrupts */
644 			//if ((++m_clock_tick & 7) == 0)
645 			//  return 0;
646 
647 			/* if we've filled up all the active channels, we can give this CPU a rest */
648 			/* until the next interrupt */
649 			if (m_type != TYPE_REDLINE)
650 				return ((m_clock_active >> 1) & 0x3e);
651 			else
652 				return ((m_clock_active << 1) & 0x7e);
653 
654 		case 1:
655 			if (LOG_COMM) logerror("%s:Read sound command latch = %02X\n", machine().describe_context(), m_soundlatch->read());
656 			return m_soundlatch->read();
657 
658 		case 2:
659 			if (ACCESSING_BITS_0_7)
660 				return m_pit[0]->read(offset & 3);
661 			break;
662 
663 		case 3:
664 			if (m_type <= TYPE_REDLINE)
665 			{
666 				if (ACCESSING_BITS_0_7)
667 					return m_pit[1]->read(offset & 3);
668 			}
669 			else if (m_type == TYPE_WSF)
670 				return m_ymsnd->read(offset);
671 			break;
672 
673 		case 4:
674 			if (m_type == TYPE_REDLINE)
675 			{
676 				if (ACCESSING_BITS_0_7)
677 					return m_pit[2]->read(offset & 3);
678 			}
679 			else
680 				logerror("%s:Unexpected peripheral read %d/%02X\n", machine().describe_context(), select, offset*2);
681 			break;
682 
683 		default:
684 			logerror("%s:Unexpected peripheral read %d/%02X\n", machine().describe_context(), select, offset*2);
685 			break;
686 	}
687 	return 0xffff;
688 }
689 
690 
peripheral_w(offs_t offset,u16 data,u16 mem_mask)691 void leland_80186_sound_device::peripheral_w(offs_t offset, u16 data, u16 mem_mask)
692 {
693 	int select = offset / 0x40;
694 	offset &= 0x3f;
695 
696 	switch (select)
697 	{
698 		case 1:
699 			if (LOG_COMM) logerror("%s:Write sound response latch = %02X\n", machine().describe_context(), data);
700 			m_sound_response = data;
701 			break;
702 
703 		case 2:
704 			if (ACCESSING_BITS_0_7)
705 				m_pit[0]->write(offset & 3, data);
706 			break;
707 
708 		case 3:
709 			if (m_type <= TYPE_REDLINE)
710 			{
711 				if (ACCESSING_BITS_0_7)
712 					m_pit[1]->write(offset & 3, data);
713 			}
714 			else if(m_type == TYPE_WSF)
715 				m_ymsnd->write(offset, data);
716 			break;
717 
718 		case 4:
719 			if (m_type == TYPE_REDLINE)
720 			{
721 				if (ACCESSING_BITS_0_7)
722 					m_pit[2]->write(offset & 3, data);
723 			}
724 			else if (mem_mask == 0xffff)
725 			{
726 				m_dac9->write(data);
727 				set_clock_line(6, 0);
728 			}
729 			break;
730 
731 		case 5: /* Ataxx/WSF/Indy Heat only */
732 			if (m_type > TYPE_REDLINE)
733 				ataxx_dac_control(offset, data, mem_mask);
734 			break;
735 
736 		default:
737 			logerror("%s:Unexpected peripheral write %d/%02X = %02X\n", machine().describe_context(), select, offset, data);
738 			break;
739 	}
740 }
741 
742 
743 
744 /*************************************
745  *
746  *  Game-specific handlers
747  *
748  *************************************/
749 
ataxx_80186_control_w(u8 data)750 void leland_80186_sound_device::ataxx_80186_control_w(u8 data)
751 {
752 	/* compute the bit-shuffled variants of the bits and then write them */
753 	int modified =  ((data & 0x01) << 7) |
754 					((data & 0x02) << 5) |
755 					((data & 0x04) << 3) |
756 					((data & 0x08) << 1);
757 	leland_80186_control_w(modified);
758 }
759