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