1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles
3 /***************************************************************************
4 
5     gottlieb.cpp
6 
7     Gottlieb 6502-based sound hardware implementations.
8 
9     Dedicated to Warren Davis, Jeff Lee, Tim Skelly & David Thiel
10 
11 ***************************************************************************/
12 
13 #include "emu.h"
14 #include "audio/gottlieb.h"
15 
16 #include "sound/dac.h"
17 #include "machine/input_merger.h"
18 
19 
20 namespace {
21 
22 constexpr XTAL SOUND1_CLOCK(3'579'545);
23 constexpr XTAL SOUND2_CLOCK(4'000'000);
24 constexpr XTAL SOUND2_SPEECH_CLOCK(3'120'000);
25 
26 } // anonymous namespace
27 
28 
29 //**************************************************************************
30 //  GLOBAL VARIABLES
31 //**************************************************************************
32 
33 DEFINE_DEVICE_TYPE(GOTTLIEB_SOUND_REV0,        gottlieb_sound_r0_device,             "gotsndr0",   "Gottlieb Sound rev. 0")
34 DEFINE_DEVICE_TYPE(GOTTLIEB_SOUND_REV1,        gottlieb_sound_r1_device,             "gotsndr1",   "Gottlieb Sound rev. 1")
35 DEFINE_DEVICE_TYPE(GOTTLIEB_SOUND_REV1_VOTRAX, gottlieb_sound_r1_with_votrax_device, "gotsndr1vt", "Gottlieb Sound rev. 1 with Votrax")
36 DEFINE_DEVICE_TYPE(GOTTLIEB_SOUND_REV2,        gottlieb_sound_r2_device,             "gotsndr2",   "Gottlieb Sound rev. 2")
37 
38 
39 //**************************************************************************
40 //  REV 0 SOUND BOARD: 6502 + 6530 + DAC
41 //**************************************************************************
42 
43 //-------------------------------------------------
44 //  gottlieb_sound_r0_device - constructors
45 //-------------------------------------------------
46 
gottlieb_sound_r0_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)47 gottlieb_sound_r0_device::gottlieb_sound_r0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
48 	: device_t(mconfig, GOTTLIEB_SOUND_REV0, tag, owner, clock)
49 	, device_mixer_interface(mconfig, *this)
50 	, m_audiocpu(*this, "audiocpu")
51 	, m_r6530(*this, "r6530")
52 	, m_sndcmd(0)
53 {
54 }
55 
56 
57 //-------------------------------------------------
58 //  read port -
59 //-------------------------------------------------
60 
r6530b_r()61 uint8_t gottlieb_sound_r0_device::r6530b_r()
62 {
63 	return m_sndcmd;
64 }
65 
66 
67 //-------------------------------------------------
68 //  write - handle an external command write
69 //-------------------------------------------------
70 
write(offs_t offset,uint8_t data)71 void gottlieb_sound_r0_device::write(offs_t offset, uint8_t data)
72 {
73 	// write the command data to the low 4 bits
74 	uint8_t pb0_3 = data ^ 15;
75 	uint8_t pb4_7 = ioport("SB0")->read() & 0x90;
76 	m_sndcmd = pb0_3 | pb4_7;
77 	m_r6530->write(offset, m_sndcmd);
78 }
79 
80 
81 //-------------------------------------------------
82 //  audio CPU map
83 //-------------------------------------------------
84 
gottlieb_sound_r0_map(address_map & map)85 void gottlieb_sound_r0_device::gottlieb_sound_r0_map(address_map &map)
86 {
87 	map.global_mask(0x0fff);
88 	map(0x0000, 0x003f).ram().mirror(0x1c0);
89 	map(0x0200, 0x020f).rw(m_r6530, FUNC(mos6530_device::read), FUNC(mos6530_device::write));
90 	map(0x0400, 0x0fff).rom();
91 }
92 
93 
94 //-------------------------------------------------
95 //  input ports
96 //-------------------------------------------------
97 
98 INPUT_PORTS_START( gottlieb_sound_r0 )
99 	PORT_START("SB0")
PORT_CODE(KEYCODE_0)100 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Audio Diag") PORT_CODE(KEYCODE_0) PORT_CHANGED_MEMBER(DEVICE_SELF, gottlieb_sound_r0_device, audio_nmi, 0)
101 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Attract") PORT_CODE(KEYCODE_F1) PORT_TOGGLE
102 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Music") PORT_CODE(KEYCODE_F2) PORT_TOGGLE
103 INPUT_PORTS_END
104 
105 INPUT_CHANGED_MEMBER( gottlieb_sound_r0_device::audio_nmi )
106 {
107 	// Diagnostic button sends a pulse to NMI pin
108 	if (newval==CLEAR_LINE)
109 		m_audiocpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
110 }
111 
112 
113 //-------------------------------------------------
114 // device_add_mconfig - add device configuration
115 //-------------------------------------------------
116 
device_add_mconfig(machine_config & config)117 void gottlieb_sound_r0_device::device_add_mconfig(machine_config &config)
118 {
119 	// audio CPU
120 	M6502(config, m_audiocpu, SOUND1_CLOCK/4); // M6503 - clock is a gate, a resistor and a capacitor. Freq unknown.
121 	m_audiocpu->set_addrmap(AS_PROGRAM, &gottlieb_sound_r0_device::gottlieb_sound_r0_map);
122 
123 	// I/O configuration
124 	MOS6530(config, m_r6530, SOUND1_CLOCK/4); // unknown - same as cpu
125 	m_r6530->out_pa_callback().set("dac", FUNC(dac_byte_interface::data_w));
126 	m_r6530->in_pb_callback().set(FUNC(gottlieb_sound_r0_device::r6530b_r));
127 
128 	// sound devices
129 	DAC_8BIT_R2R(config, "dac", 0).add_route(ALL_OUTPUTS, *this, 0.25); // unknown DAC
130 }
131 
132 
133 //-------------------------------------------------
134 //  device_input_ports - return a pointer to
135 //  the device's I/O ports
136 //-------------------------------------------------
137 
device_input_ports() const138 ioport_constructor gottlieb_sound_r0_device::device_input_ports() const
139 {
140 	return INPUT_PORTS_NAME( gottlieb_sound_r0 );
141 }
142 
143 
144 //-------------------------------------------------
145 //  device_start - device-specific startup
146 //-------------------------------------------------
147 
device_start()148 void gottlieb_sound_r0_device::device_start()
149 {
150 }
151 
152 
153 //**************************************************************************
154 //  REV 1 SOUND BOARD: 6502 + DAC
155 //**************************************************************************
156 
157 //-------------------------------------------------
158 //  gottlieb_sound_r1_device - constructors
159 //-------------------------------------------------
160 
gottlieb_sound_r1_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)161 gottlieb_sound_r1_device::gottlieb_sound_r1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
162 	: gottlieb_sound_r1_device(mconfig, GOTTLIEB_SOUND_REV1, tag, owner, clock)
163 {
164 }
165 
gottlieb_sound_r1_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)166 gottlieb_sound_r1_device::gottlieb_sound_r1_device(
167 		const machine_config &mconfig,
168 		device_type type,
169 		const char *tag,
170 		device_t *owner,
171 		uint32_t clock)
172 	: device_t(mconfig, type, tag, owner, clock)
173 	, device_mixer_interface(mconfig, *this)
174 	, m_riot(*this, "riot")
175 {
176 }
177 
178 
179 //-------------------------------------------------
180 //  write - handle an external command write
181 //-------------------------------------------------
182 
write(u8 data)183 void gottlieb_sound_r1_device::write(u8 data)
184 {
185 	// write the command data to the low 6 bits, and the trigger to the upper bit
186 	uint8_t pa7 = (data & 0x0f) != 0xf;
187 	uint8_t pa0_5 = ~data & 0x3f;
188 	m_riot->porta_in_set(pa0_5 | (pa7 << 7), 0xbf);
189 }
190 
191 
192 //-------------------------------------------------
193 //  audio CPU map
194 //-------------------------------------------------
195 
gottlieb_sound_r1_map(address_map & map)196 void gottlieb_sound_r1_device::gottlieb_sound_r1_map(address_map &map)
197 {
198 	// A15 not decoded except in expansion socket
199 	map.global_mask(0x7fff);
200 	map(0x0000, 0x007f).mirror(0x0d80).ram();
201 	map(0x0200, 0x021f).mirror(0x0de0).rw("riot", FUNC(riot6532_device::read), FUNC(riot6532_device::write));
202 	map(0x1000, 0x1000).mirror(0x0fff).w("dac", FUNC(dac_byte_interface::data_w));
203 	map(0x6000, 0x7fff).rom();
204 }
205 
gottlieb_sound_r1_map(address_map & map)206 void gottlieb_sound_r1_with_votrax_device::gottlieb_sound_r1_map(address_map &map)
207 {
208 	// A15 not decoded except in expansion socket
209 	gottlieb_sound_r1_device::gottlieb_sound_r1_map(map);
210 	map(0x2000, 0x2000).mirror(0x0fff).w(FUNC(gottlieb_sound_r1_with_votrax_device::votrax_data_w));
211 	map(0x3000, 0x3000).mirror(0x0fff).w(FUNC(gottlieb_sound_r1_with_votrax_device::speech_clock_dac_w));
212 }
213 
214 
215 //-------------------------------------------------
216 //  input ports
217 //-------------------------------------------------
218 
219 INPUT_PORTS_START( gottlieb_sound_r1 )
220 	PORT_START("SB1")
221 	PORT_DIPUNKNOWN_DIPLOC( 0x01, 0x01, "SB1:7" )
222 	PORT_DIPUNKNOWN_DIPLOC( 0x02, 0x02, "SB1:6" )
223 	PORT_DIPUNKNOWN_DIPLOC( 0x04, 0x04, "SB1:5" )
224 	PORT_DIPUNKNOWN_DIPLOC( 0x08, 0x08, "SB1:1" )
225 	PORT_DIPUNKNOWN_DIPLOC( 0x10, 0x10, "SB1:4" )
226 	PORT_DIPUNKNOWN_DIPLOC( 0x20, 0x20, "SB1:3" )
227 	PORT_DIPNAME( 0x40, 0x40, "Sound Test" )            PORT_DIPLOCATION("SB1:2")
DEF_STR(Off)228 	PORT_DIPSETTING(    0x40, DEF_STR( Off ) )
229 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
230 	PORT_BIT( 0x80, 0x80, IPT_CUSTOM )
231 INPUT_PORTS_END
232 
233 INPUT_PORTS_START( gottlieb_sound_r1_with_votrax )
234 	PORT_INCLUDE(gottlieb_sound_r1)
235 	PORT_MODIFY("SB1")
236 	PORT_BIT( 0x80, 0x80, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("votrax", votrax_sc01_device, request)
237 INPUT_PORTS_END
238 
239 
240 //-------------------------------------------------
241 // device_add_mconfig - add device configuration
242 //-------------------------------------------------
243 
244 void gottlieb_sound_r1_device::device_add_mconfig(machine_config &config)
245 {
246 	// audio CPU
247 	m6502_device &audiocpu(M6502(config, "audiocpu", SOUND1_CLOCK/4)); // the board can be set to /2 as well
248 	audiocpu.set_addrmap(AS_PROGRAM, &gottlieb_sound_r1_device::gottlieb_sound_r1_map);
249 
250 	INPUT_MERGER_ANY_HIGH(config, "nmi").output_handler().set_inputline("audiocpu", INPUT_LINE_NMI);
251 
252 	// I/O configuration
253 	RIOT6532(config, m_riot, SOUND1_CLOCK/4);
254 	m_riot->in_pb_callback().set_ioport("SB1");
255 	m_riot->out_pb_callback().set("nmi", FUNC(input_merger_device::in_w<0>)).bit(7).invert(); // unsure if this is ever used, but the NMI is connected to the RIOT's PB7
256 	m_riot->irq_callback().set_inputline("audiocpu", M6502_IRQ_LINE);
257 
258 	// sound devices
259 	DAC_8BIT_R2R(config, "dac", 0).add_route(ALL_OUTPUTS, *this, 0.25); // unknown DAC
260 }
261 
262 
263 //-------------------------------------------------
264 //  device_input_ports - return a pointer to
265 //  the device's I/O ports
266 //-------------------------------------------------
267 
device_input_ports() const268 ioport_constructor gottlieb_sound_r1_device::device_input_ports() const
269 {
270 	return INPUT_PORTS_NAME( gottlieb_sound_r1 );
271 }
272 
273 
274 //-------------------------------------------------
275 //  device_start - device-specific startup
276 //-------------------------------------------------
277 
device_start()278 void gottlieb_sound_r1_device::device_start()
279 {
280 }
281 
282 
283 
284 //**************************************************************************
285 //  REV 1 SOUND BOARD WITH VOTRAX
286 //**************************************************************************
287 
288 //-------------------------------------------------
289 //  gottlieb_sound_r1_with_votrax_device -
290 //  constructor
291 //-------------------------------------------------
292 
gottlieb_sound_r1_with_votrax_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)293 gottlieb_sound_r1_with_votrax_device::gottlieb_sound_r1_with_votrax_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
294 	: gottlieb_sound_r1_device(mconfig, GOTTLIEB_SOUND_REV1_VOTRAX, tag, owner, clock)
295 	, m_votrax(*this, "votrax")
296 	, m_last_speech_clock(0)
297 {
298 }
299 
300 
301 //-------------------------------------------------
302 // device_add_mconfig - add device configuration
303 //-------------------------------------------------
304 
device_add_mconfig(machine_config & config)305 void gottlieb_sound_r1_with_votrax_device::device_add_mconfig(machine_config &config)
306 {
307 	gottlieb_sound_r1_device::device_add_mconfig(config);
308 
309 	// add the VOTRAX
310 	VOTRAX_SC01(config, m_votrax, 720000);
311 	m_votrax->ar_callback().set("nmi", FUNC(input_merger_device::in_w<1>));
312 	m_votrax->add_route(ALL_OUTPUTS, *this, 0.5);
313 }
314 
315 
316 //-------------------------------------------------
317 //  device_input_ports - return a pointer to
318 //  the device's I/O ports
319 //-------------------------------------------------
320 
device_input_ports() const321 ioport_constructor gottlieb_sound_r1_with_votrax_device::device_input_ports() const
322 {
323 	return INPUT_PORTS_NAME( gottlieb_sound_r1_with_votrax );
324 }
325 
326 
327 //-------------------------------------------------
328 //  device_start - device-specific startup
329 //-------------------------------------------------
330 
device_start()331 void gottlieb_sound_r1_with_votrax_device::device_start()
332 {
333 	gottlieb_sound_r1_device::device_start();
334 	save_item(NAME(m_last_speech_clock));
335 }
336 
337 
device_post_load()338 void gottlieb_sound_r1_with_votrax_device::device_post_load()
339 {
340 	gottlieb_sound_r1_device::device_post_load();
341 
342 	// totally random guesswork; would like to get real measurements on a board
343 	m_votrax->set_unscaled_clock(900000 + (m_last_speech_clock - 0xa0) * 9000);
344 }
345 
346 
347 //-------------------------------------------------
348 //  votrax_data_w - write data to the Votrax SC-01
349 //  speech chip
350 //-------------------------------------------------
351 
votrax_data_w(uint8_t data)352 void gottlieb_sound_r1_with_votrax_device::votrax_data_w(uint8_t data)
353 {
354 	m_votrax->inflection_w(data >> 6);
355 	m_votrax->write(~data & 0x3f);
356 }
357 
358 
359 //-------------------------------------------------
360 //  speech_clock_dac_w - modify the clock driving
361 //  the Votrax SC-01 speech chip
362 //-------------------------------------------------
363 
speech_clock_dac_w(uint8_t data)364 void gottlieb_sound_r1_with_votrax_device::speech_clock_dac_w(uint8_t data)
365 {
366 	// prevent negative clock values (and possible crash)
367 	if (data < 0x60) data = 0x60;
368 
369 	// nominal clock is 0xa0
370 	if (data != m_last_speech_clock)
371 	{
372 		logerror("clock = %02X\n", data);
373 
374 		// totally random guesswork; would like to get real measurements on a board
375 		m_votrax->set_unscaled_clock(950000 + (data - 0xa0) * 5500);
376 		m_last_speech_clock = data;
377 	}
378 }
379 
380 
381 
382 //**************************************************************************
383 //  REV 2 SOUND BOARD: 6502 + 2 x DAC + 2 x AY-8913
384 //**************************************************************************
385 
386 //-------------------------------------------------
387 //  gottlieb_sound_r2_device - constructor
388 //-------------------------------------------------
389 
gottlieb_sound_r2_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)390 gottlieb_sound_r2_device::gottlieb_sound_r2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
391 	: device_t(mconfig, GOTTLIEB_SOUND_REV2, tag, owner, clock),
392 		device_mixer_interface(mconfig, *this),
393 		m_audiocpu(*this, "audiocpu"),
394 		m_speechcpu(*this, "speechcpu"),
395 		m_ay1(*this, "ay1"),
396 		m_ay2(*this, "ay2"),
397 		m_sp0250(*this, "spsnd"),
398 		m_cobram3_mod(false),
399 		m_nmi_timer(nullptr),
400 		m_nmi_state(0),
401 		m_audiocpu_latch(0),
402 		m_speechcpu_latch(0),
403 		m_speech_control(0),
404 		m_last_command(0),
405 		m_psg_latch(0),
406 		m_psg_data_latch(0),
407 		m_sp0250_latch(0)
408 {
409 }
410 
411 
412 //-------------------------------------------------
413 //  write - handle an external command write
414 //-------------------------------------------------
415 
write(u8 data)416 void gottlieb_sound_r2_device::write(u8 data)
417 {
418 	// when data is not 0xff, the transparent latch at A3 allows it to pass through unmolested
419 	if (data != 0xff)
420 	{
421 		// latch data on a timer
422 		synchronize(TID_SOUND_LATCH_WRITE, data);
423 
424 		// if the previous data was 0xff, clock an IRQ on each
425 		if (m_last_command == 0xff)
426 		{
427 			m_audiocpu->set_input_line(M6502_IRQ_LINE, ASSERT_LINE);
428 			m_speechcpu->set_input_line(M6502_IRQ_LINE, ASSERT_LINE);
429 		}
430 	}
431 	m_last_command = data;
432 }
433 
434 
435 //-------------------------------------------------
436 //  nmi_timer_adjust - adjust the NMI timer to
437 //  fire based on its configured rate
438 //-------------------------------------------------
439 
nmi_timer_adjust()440 inline void gottlieb_sound_r2_device::nmi_timer_adjust()
441 {
442 	// adjust timer to go off in the future based on the current rate
443 	m_nmi_timer->adjust(attotime::from_hz(SOUND2_CLOCK/16) * (256 * (256 - m_nmi_rate)));
444 }
445 
446 
447 //-------------------------------------------------
448 //  nmi_state_update - update the NMI state based
449 //  on the timer firing and the enable control
450 //-------------------------------------------------
451 
nmi_state_update()452 inline void gottlieb_sound_r2_device::nmi_state_update()
453 {
454 	// update the NMI line state based on the enable and state
455 	m_speechcpu->set_input_line(INPUT_LINE_NMI, (m_nmi_state && (m_speech_control & 1)) ? ASSERT_LINE : CLEAR_LINE);
456 }
457 
458 
459 //-------------------------------------------------
460 //  speech_data_r - read the input command latch
461 //  from the audio CPU
462 //-------------------------------------------------
463 
audio_data_r()464 uint8_t gottlieb_sound_r2_device::audio_data_r()
465 {
466 	m_audiocpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE);
467 	return m_audiocpu_latch;
468 }
469 
470 
471 //-------------------------------------------------
472 //  speech_data_r - read the input command latch
473 //  from the speech CPU
474 //-------------------------------------------------
475 
speech_data_r()476 uint8_t gottlieb_sound_r2_device::speech_data_r()
477 {
478 	m_speechcpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE);
479 	return m_speechcpu_latch;
480 }
481 
482 
483 //-------------------------------------------------
484 //  signal_audio_nmi_w - signal an NMI from the
485 //  speech CPU to the audio CPU
486 //-------------------------------------------------
487 
signal_audio_nmi_w(uint8_t data)488 void gottlieb_sound_r2_device::signal_audio_nmi_w(uint8_t data)
489 {
490 	m_audiocpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
491 	m_audiocpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
492 }
493 
494 
495 //-------------------------------------------------
496 //  nmi_rate_w - adjust the NMI rate on the speech
497 //  CPU
498 //-------------------------------------------------
499 
nmi_rate_w(uint8_t data)500 void gottlieb_sound_r2_device::nmi_rate_w(uint8_t data)
501 {
502 	// the new rate is picked up when the previous timer expires
503 	m_nmi_rate = data;
504 }
505 
506 
507 //-------------------------------------------------
508 //  speech_drq_custom_r - return the SP0250
509 //  request line as an input port bit
510 //-------------------------------------------------
511 
CUSTOM_INPUT_MEMBER(gottlieb_sound_r2_device::speech_drq_custom_r)512 CUSTOM_INPUT_MEMBER( gottlieb_sound_r2_device::speech_drq_custom_r )
513 {
514 	return m_sp0250->drq_r();
515 }
516 
517 
518 //-------------------------------------------------
519 //  speech_control_w - primary audio control
520 //  register on the speech board
521 //-------------------------------------------------
522 
speech_control_w(uint8_t data)523 void gottlieb_sound_r2_device::speech_control_w(uint8_t data)
524 {
525 	uint8_t previous = m_speech_control;
526 	m_speech_control = data;
527 
528 	// bit 0 enables/disables the NMI line
529 	nmi_state_update();
530 
531 	// bit 1 controls a LED on the sound board
532 
533 	// bits 2-4 control the AY-8913, but act differently between the
534 	// standard sound board and the modified Cobra Command board
535 	if (!m_cobram3_mod)
536 	{
537 		// bit 2 goes to 8913 BDIR pin
538 		if ((previous & 0x04) != 0 && (data & 0x04) == 0)
539 		{
540 			// bit 3 selects which of the two 8913 to enable
541 			// bit 4 goes to the 8913 BC1 pin
542 			if ((data & 0x08) != 0)
543 				m_ay1->data_address_w(data >> 4, m_psg_latch);
544 			else
545 				m_ay2->data_address_w(data >> 4, m_psg_latch);
546 		}
547 	}
548 	else
549 	{
550 		if ( data & 0x10 )
551 		{
552 			m_psg_data_latch = m_psg_latch;
553 		}
554 		else
555 		{
556 			ay8913_device *ay = (data & 0x08) ? m_ay1 : m_ay2;
557 			ay->address_w(m_psg_latch);
558 			ay->data_w(m_psg_data_latch);
559 		}
560 	}
561 
562 	// bit 5 goes to the speech chip DIRECT DATA TEST pin
563 
564 	// bit 6 = speech chip DATA PRESENT pin; high then low to make the chip read data
565 	if ((previous & 0x40) == 0 && (data & 0x40) != 0)
566 		m_sp0250->write(m_sp0250_latch);
567 
568 	// bit 7 goes to the speech chip RESET pin
569 	if ((previous ^ data) & 0x80)
570 		m_sp0250->reset();
571 }
572 
573 
574 //-------------------------------------------------
575 //  psg_latch_w - store an 8-bit value in the PSG
576 //  latch register
577 //-------------------------------------------------
578 
psg_latch_w(uint8_t data)579 void gottlieb_sound_r2_device::psg_latch_w(uint8_t data)
580 {
581 	m_psg_latch = data;
582 }
583 
584 
585 //-------------------------------------------------
586 //  psg_latch_w - store an 8-bit value in the
587 //  SP0250 latch register
588 //-------------------------------------------------
589 
sp0250_latch_w(uint8_t data)590 void gottlieb_sound_r2_device::sp0250_latch_w(uint8_t data)
591 {
592 	m_sp0250_latch = data;
593 }
594 
595 
596 //-------------------------------------------------
597 //  sound CPU address map
598 //-------------------------------------------------
599 
gottlieb_sound_r2_map(address_map & map)600 void gottlieb_sound_r2_device::gottlieb_sound_r2_map(address_map &map)
601 {
602 	map(0x0000, 0x03ff).mirror(0x3c00).ram();
603 	map(0x4000, 0x4000).mirror(0x3ffe).w("dacvol", FUNC(dac_byte_interface::data_w));
604 	map(0x4001, 0x4001).mirror(0x3ffe).w("dac", FUNC(dac_byte_interface::data_w));
605 	map(0x8000, 0x8000).mirror(0x3fff).r(FUNC(gottlieb_sound_r2_device::audio_data_r));
606 	map(0xc000, 0xdfff).mirror(0x2000).rom();
607 }
608 
609 
610 //-------------------------------------------------
611 //  sppech CPU address map
612 //-------------------------------------------------
613 
gottlieb_speech_r2_map(address_map & map)614 void gottlieb_sound_r2_device::gottlieb_speech_r2_map(address_map &map)
615 {
616 	map(0x0000, 0x03ff).mirror(0x1c00).ram();
617 	map(0x2000, 0x2000).mirror(0x1fff).w(FUNC(gottlieb_sound_r2_device::sp0250_latch_w));
618 	map(0x4000, 0x4000).mirror(0x1fff).w(FUNC(gottlieb_sound_r2_device::speech_control_w));
619 	map(0x6000, 0x6000).mirror(0x1fff).portr("SB2");
620 	map(0x8000, 0x8000).mirror(0x1fff).w(FUNC(gottlieb_sound_r2_device::psg_latch_w));
621 	map(0xa000, 0xa000).mirror(0x07ff).w(FUNC(gottlieb_sound_r2_device::nmi_rate_w));
622 	map(0xa800, 0xa800).mirror(0x07ff).r(FUNC(gottlieb_sound_r2_device::speech_data_r));
623 	map(0xb000, 0xb000).mirror(0x07ff).w(FUNC(gottlieb_sound_r2_device::signal_audio_nmi_w));
624 	map(0xc000, 0xffff).rom();
625 }
626 
627 
628 //-------------------------------------------------
629 //  input ports
630 //-------------------------------------------------
631 
632 INPUT_PORTS_START( gottlieb_sound_r2 )
633 	PORT_START("SB2")
634 	PORT_DIPUNKNOWN_DIPLOC( 0x01, 0x01, "SB2:1")
635 	PORT_DIPUNKNOWN_DIPLOC( 0x02, 0x02, "SB2:2")
636 	PORT_DIPUNKNOWN_DIPLOC( 0x04, 0x04, "SB2:3")
637 	PORT_DIPUNKNOWN_DIPLOC( 0x08, 0x08, "SB2:4")
638 	PORT_DIPUNKNOWN_DIPLOC( 0x10, 0x10, "SB2:5")
639 	PORT_DIPUNKNOWN_DIPLOC( 0x20, 0x20, "SB2:6")
640 	PORT_DIPNAME( 0x40, 0x40, "Sound Test" )            PORT_DIPLOCATION("SB2:7")
DEF_STR(Off)641 	PORT_DIPSETTING(    0x40, DEF_STR( Off ) )
642 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
643 	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(gottlieb_sound_r2_device, speech_drq_custom_r)
644 INPUT_PORTS_END
645 
646 
647 //-------------------------------------------------
648 // device_add_mconfig - add device configuration
649 //-------------------------------------------------
650 
651 void gottlieb_sound_r2_device::device_add_mconfig(machine_config &config)
652 {
653 	// audio CPUs
654 	M6502(config, m_audiocpu, SOUND2_CLOCK/4);
655 	m_audiocpu->set_addrmap(AS_PROGRAM, &gottlieb_sound_r2_device::gottlieb_sound_r2_map);
656 
657 	M6502(config, m_speechcpu, SOUND2_CLOCK/4);
658 	m_speechcpu->set_addrmap(AS_PROGRAM, &gottlieb_sound_r2_device::gottlieb_speech_r2_map);
659 
660 	// sound hardware
661 	DAC_8BIT_R2R(config, "dac", 0).add_route(ALL_OUTPUTS, *this, 0.075); // unknown DAC
662 	DAC_8BIT_R2R(config, "dacvol", 0)
663 		.set_output_range(0, 1)
664 		.add_route(0, "dac", 1.0, DAC_INPUT_RANGE_HI)
665 		.add_route(0, "dac", -1.0, DAC_INPUT_RANGE_LO); // unknown DAC
666 
667 	AY8913(config, m_ay1, SOUND2_CLOCK/2).add_route(ALL_OUTPUTS, *this, 0.15);
668 
669 	AY8913(config, m_ay2, SOUND2_CLOCK/2).add_route(ALL_OUTPUTS, *this, 0.15);
670 
671 	SP0250(config, m_sp0250, SOUND2_SPEECH_CLOCK).add_route(ALL_OUTPUTS, *this, 1.0);
672 }
673 
674 
675 //-------------------------------------------------
676 //  device_input_ports - return a pointer to
677 //  the device's I/O ports
678 //-------------------------------------------------
679 
device_input_ports() const680 ioport_constructor gottlieb_sound_r2_device::device_input_ports() const
681 {
682 	return INPUT_PORTS_NAME( gottlieb_sound_r2 );
683 }
684 
685 
686 //-------------------------------------------------
687 //  device_start - device-specific startup
688 //-------------------------------------------------
689 
device_start()690 void gottlieb_sound_r2_device::device_start()
691 {
692 	// set up the NMI timer
693 	m_nmi_timer = timer_alloc(TID_NMI_GENERATE);
694 	m_nmi_rate = 0;
695 	nmi_timer_adjust();
696 
697 	// disable the non-speech CPU for cobram3
698 	if (m_cobram3_mod)
699 		m_audiocpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
700 
701 	// register for save states
702 	save_item(NAME(m_nmi_rate));
703 	save_item(NAME(m_nmi_state));
704 	save_item(NAME(m_speech_control));
705 	save_item(NAME(m_last_command));
706 }
707 
708 
709 //-------------------------------------------------
710 //  device_timer - handle timer-based behaviors
711 //-------------------------------------------------
712 
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)713 void gottlieb_sound_r2_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
714 {
715 	switch (id)
716 	{
717 		case TID_NMI_GENERATE:
718 			// update state
719 			m_nmi_state = 1;
720 			nmi_state_update();
721 
722 			// set a timer to turn it off again on the next SOUND_CLOCK/16
723 			timer_set(attotime::from_hz(SOUND2_CLOCK/16), TID_NMI_CLEAR);
724 
725 			// adjust the NMI timer for the next time
726 			nmi_timer_adjust();
727 			break;
728 
729 		case TID_NMI_CLEAR:
730 			// update state
731 			m_nmi_state = 0;
732 			nmi_state_update();
733 			break;
734 
735 		case TID_SOUND_LATCH_WRITE:
736 			// each CPU has its own latch
737 			m_audiocpu_latch = param;
738 			m_speechcpu_latch = param;
739 			break;
740 	}
741 }
742 
743