1 // license:BSD-3-Clause
2 // copyright-holders:Stefan Jokisch
3 /***************************************************************************
4
5 Atari Destroyer Driver
6
7 TODO:
8 - missing language roms means DIP switches related to these do not function
9
10 ***************************************************************************/
11
12 #include "emu.h"
13 #include "cpu/m6800/m6800.h"
14 #include "machine/74259.h"
15 #include "machine/timer.h"
16 #include "machine/watchdog.h"
17 #include "emupal.h"
18 #include "screen.h"
19 #include "speaker.h"
20 #include "machine/netlist.h"
21
22 #include "netlist/nl_setup.h"
23 #include "audio/nl_destroyr.h"
24
25 #include "destroyr.lh"
26
27
28 class destroyr_state : public driver_device
29 {
30 public:
destroyr_state(const machine_config & mconfig,device_type type,const char * tag)31 destroyr_state(const machine_config &mconfig, device_type type, const char *tag)
32 : driver_device(mconfig, type, tag)
33 , m_maincpu(*this, "maincpu")
34 , m_watchdog(*this, "watchdog")
35 , m_gfxdecode(*this, "gfxdecode")
36 , m_screen(*this, "screen")
37 , m_palette(*this, "palette")
38 , m_inputs(*this, "IN%u", 0U)
39 , m_paddle(*this, "PADDLE")
40 , m_alpha_num_ram(*this, "alpha_nuram")
41 , m_major_obj_ram(*this, "major_obj_ram")
42 , m_minor_obj_ram(*this, "minor_obj_ram")
43 , m_sound_motor_speed(*this, "sound_nl:motor_speed")
44 , m_sound_noise(*this, "sound_nl:noise")
45 , m_sound_attract(*this, "sound_nl:attract")
46 , m_sound_songate(*this, "sound_nl:songate")
47 , m_sound_launch(*this, "sound_nl:launch")
48 , m_sound_explo(*this, "sound_nl:explo")
49 , m_sound_sonlat(*this, "sound_nl:sonlat")
50 , m_sound_hexplo(*this, "sound_nl:hexplo")
51 , m_sound_lexplo(*this, "sound_nl:lexplo")
52 { }
53
54 void destroyr(machine_config &config);
55
56 private:
57 virtual void machine_start() override;
58 virtual void machine_reset() override;
59 virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
60
61 static const device_timer_id TIMER_DIAL = 0;
62 static const device_timer_id TIMER_FRAME = 1;
63
64 void main_map(address_map &map);
65
66 void misc_w(uint8_t data);
67 void cursor_load_w(uint8_t data);
68 void interrupt_ack_w(uint8_t data);
69 uint8_t input_r(offs_t offset);
70 uint8_t scanline_r();
71
72 void palette_init(palette_device &palette) const;
73
74 uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
75
76 TIMER_CALLBACK_MEMBER(dial_callback);
77 TIMER_CALLBACK_MEMBER(frame_callback);
78 TIMER_DEVICE_CALLBACK_MEMBER(scanline_irq);
79
80 /* devices */
81 required_device<cpu_device> m_maincpu;
82 required_device<watchdog_timer_device> m_watchdog;
83 required_device<gfxdecode_device> m_gfxdecode;
84 required_device<screen_device> m_screen;
85 required_device<palette_device> m_palette;
86 required_ioport_array<3> m_inputs;
87 required_ioport m_paddle;
88
89 /* memory pointers */
90 required_shared_ptr<uint8_t> m_alpha_num_ram;
91 required_shared_ptr<uint8_t> m_major_obj_ram;
92 required_shared_ptr<uint8_t> m_minor_obj_ram;
93
94 /* audio triggers */
95 required_device<netlist_mame_logic_input_device> m_sound_motor_speed;
96 required_device<netlist_mame_logic_input_device> m_sound_noise;
97 required_device<netlist_mame_logic_input_device> m_sound_attract;
98 required_device<netlist_mame_logic_input_device> m_sound_songate;
99 required_device<netlist_mame_logic_input_device> m_sound_launch;
100 required_device<netlist_mame_logic_input_device> m_sound_explo;
101 required_device<netlist_mame_logic_input_device> m_sound_sonlat;
102 required_device<netlist_mame_logic_input_device> m_sound_hexplo;
103 required_device<netlist_mame_logic_input_device> m_sound_lexplo;
104
105 /* video-related */
106 int m_cursor;
107 int m_wavemod;
108
109 /* misc */
110 int m_potmask[2];
111 int m_potsense[2];
112 int m_attract;
113 emu_timer *m_dial_timer;
114 emu_timer *m_frame_timer;
115 };
116
117
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)118 uint32_t destroyr_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
119 {
120 bitmap.fill(0, cliprect);
121
122 /* draw major objects */
123 for (int i = 0; i < 16; i++)
124 {
125 int attr = m_major_obj_ram[2 * i + 0] ^ 0xff;
126 int horz = m_major_obj_ram[2 * i + 1];
127
128 int num = attr & 3;
129 int scan = attr & 4;
130 int flipx = attr & 8;
131
132 if (scan == 0)
133 {
134 if (horz >= 192)
135 horz -= 256;
136 }
137 else
138 {
139 if (horz < 192)
140 continue;
141 }
142
143 m_gfxdecode->gfx(2)->transpen(bitmap,cliprect, num, 0, flipx, 0, horz, 16 * i, 0);
144 }
145
146 /* draw alpha numerics */
147 for (int i = 0; i < 8; i++)
148 {
149 for (int j = 0; j < 32; j++)
150 {
151 int num = m_alpha_num_ram[32 * i + j];
152
153 m_gfxdecode->gfx(0)->transpen(bitmap,cliprect, num, 0, 0, 0, 8 * j, 8 * i, 0);
154 }
155 }
156
157 /* draw minor objects */
158 for (int i = 0; i < 2; i++)
159 {
160 int num = i << 4 | (m_minor_obj_ram[i + 0] & 0xf);
161 int horz = 256 - m_minor_obj_ram[i + 2];
162 int vert = 256 - m_minor_obj_ram[i + 4];
163
164 m_gfxdecode->gfx(1)->transpen(bitmap,cliprect, num, 0, 0, 0, horz, vert, 0);
165 }
166
167 /* draw waves */
168 for (int i = 0; i < 4; i++)
169 {
170 m_gfxdecode->gfx(3)->transpen(bitmap,cliprect, m_wavemod ? 1 : 0, 0, 0, 0, 64 * i, 0x4e, 0);
171 }
172
173 /* draw cursor */
174 for (int i = 0; i < 256; i++)
175 {
176 if (i & 4)
177 bitmap.pix(m_cursor ^ 0xff, i) = 7;
178 }
179 return 0;
180 }
181
182
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)183 void destroyr_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
184 {
185 switch (id)
186 {
187 case TIMER_DIAL:
188 dial_callback(ptr, param);
189 break;
190 case TIMER_FRAME:
191 frame_callback(ptr, param);
192 break;
193 default:
194 throw emu_fatalerror("Unknown id in destroyr_state::device_timer");
195 }
196 }
197
198
TIMER_CALLBACK_MEMBER(destroyr_state::dial_callback)199 TIMER_CALLBACK_MEMBER(destroyr_state::dial_callback)
200 {
201 int dial = param;
202
203 /* Analog inputs come from the player's depth control potentiometer.
204 The voltage is compared to a voltage ramp provided by a discrete
205 analog circuit that conditions the VBLANK signal. When the ramp
206 voltage exceeds the input voltage an NMI signal is generated. The
207 computer then reads the VSYNC data functions to tell where the
208 cursor should be located. */
209
210 m_potsense[dial] = 1;
211
212 if (m_potmask[dial])
213 {
214 m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
215 }
216 }
217
218
TIMER_CALLBACK_MEMBER(destroyr_state::frame_callback)219 TIMER_CALLBACK_MEMBER(destroyr_state::frame_callback)
220 {
221 m_potsense[0] = 0;
222 m_potsense[1] = 0;
223
224 /* PCB supports two dials, but cab has only got one */
225 m_dial_timer->adjust(m_screen->time_until_pos(m_paddle->read()));
226 m_frame_timer->adjust(m_screen->time_until_pos(0));
227 }
228
229
TIMER_DEVICE_CALLBACK_MEMBER(destroyr_state::scanline_irq)230 TIMER_DEVICE_CALLBACK_MEMBER(destroyr_state::scanline_irq)
231 {
232 // 16V clocks LS74 flip-flop with D = 32V and /Q output connected to /IRQ on 6800
233 m_maincpu->set_input_line(M6800_IRQ_LINE, BIT(param, 5) ? ASSERT_LINE : CLEAR_LINE);
234 }
235
236
machine_reset()237 void destroyr_state::machine_reset()
238 {
239 m_frame_timer->adjust(m_screen->time_until_pos(0));
240
241 m_cursor = 0;
242 m_wavemod = 0;
243 m_potmask[0] = 0;
244 m_potmask[1] = 0;
245 m_potsense[0] = 0;
246 m_potsense[1] = 0;
247 m_attract = 0;
248 }
249
250
misc_w(uint8_t data)251 void destroyr_state::misc_w(uint8_t data)
252 {
253 /* bits 0 to 2 connect to the sound circuits */
254 m_attract = BIT(data, 0);
255 m_sound_attract->write(m_attract);
256 m_sound_noise->write(BIT(data, 1));
257 m_sound_motor_speed->write(BIT(data, 2));
258 m_potmask[0] = BIT(data, 3);
259 m_wavemod = BIT(data, 4);
260 m_potmask[1] = BIT(data, 5);
261
262 machine().bookkeeping().coin_lockout_w(0, !m_attract);
263 machine().bookkeeping().coin_lockout_w(1, !m_attract);
264 }
265
266
cursor_load_w(uint8_t data)267 void destroyr_state::cursor_load_w(uint8_t data)
268 {
269 m_cursor = data;
270 m_watchdog->watchdog_reset();
271 }
272
273
interrupt_ack_w(uint8_t data)274 void destroyr_state::interrupt_ack_w(uint8_t data)
275 {
276 m_maincpu->set_input_line(M6800_IRQ_LINE, CLEAR_LINE);
277 }
278
279
input_r(offs_t offset)280 uint8_t destroyr_state::input_r(offs_t offset)
281 {
282 if (offset & 1)
283 {
284 return m_inputs[1]->read();
285 }
286
287 else
288 {
289 uint8_t ret = m_inputs[0]->read();
290 ret |= (m_potsense[0] && m_potmask[0]) ? (1 << 2) : 0;
291 ret |= (m_potsense[1] && m_potmask[1]) ? (1 << 3) : 0;
292 return ret;
293 }
294 }
295
296
scanline_r()297 uint8_t destroyr_state::scanline_r()
298 {
299 return m_screen->vpos();
300 }
301
302
main_map(address_map & map)303 void destroyr_state::main_map(address_map &map)
304 {
305 map.global_mask(0x7fff);
306 map(0x0000, 0x00ff).mirror(0xf00).ram();
307 map(0x1000, 0x1001).mirror(0xffe).r(FUNC(destroyr_state::input_r));
308 map(0x1000, 0x1007).mirror(0xff0).w("outlatch", FUNC(f9334_device::write_d0));
309 map(0x1008, 0x1008).mirror(0xff7).w(FUNC(destroyr_state::misc_w));
310 map(0x2000, 0x2000).mirror(0xfff).portr("IN2");
311 map(0x3000, 0x30ff).mirror(0xf00).writeonly().share("alpha_nuram");
312 map(0x4000, 0x401f).mirror(0xfe0).writeonly().share("major_obj_ram");
313 map(0x5000, 0x5000).mirror(0xff8).w(FUNC(destroyr_state::cursor_load_w));
314 map(0x5001, 0x5001).mirror(0xff8).w(FUNC(destroyr_state::interrupt_ack_w));
315 map(0x5002, 0x5007).mirror(0xff8).writeonly().share("minor_obj_ram");
316 map(0x6000, 0x6000).mirror(0xfff).r(FUNC(destroyr_state::scanline_r));
317 map(0x7000, 0x7fff).rom();
318 }
319
320
321 static INPUT_PORTS_START( destroyr )
322 PORT_START("IN0")
323 PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) /* call 7400 */
324 PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
325 PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) /* potsense1 */
326 PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) /* potsense2 */
327 PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START1 )
328 PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START2 )
329 PORT_DIPNAME( 0xc0, 0x80, "Extended Play" ) PORT_DIPLOCATION("SW2:8,7")
330 PORT_DIPSETTING( 0x40, "1500 points" )
331 PORT_DIPSETTING( 0x80, "2500 points" )
332 PORT_DIPSETTING( 0xc0, "3500 points" )
333 PORT_DIPSETTING( 0x00, "never" )
334
335 PORT_START("IN1")
336 PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_TILT )
337 PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Speed Control") PORT_TOGGLE
338 PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 )
339 PORT_SERVICE( 0x08, IP_ACTIVE_LOW )
340 PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_COIN1 )
341 PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_COIN2 )
342 PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
343 PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_VBLANK("screen")
344
345 PORT_START("IN2")
346 PORT_DIPNAME( 0x03, 0x02, DEF_STR( Coinage ) ) PORT_DIPLOCATION("SW:4,3")
347 PORT_DIPSETTING( 0x03, DEF_STR( 2C_1C ) )
348 PORT_DIPSETTING( 0x02, DEF_STR( 1C_1C ) )
349 PORT_DIPSETTING( 0x01, DEF_STR( 1C_2C ) )
350 PORT_DIPSETTING( 0x00, DEF_STR( Free_Play ) )
351 PORT_DIPNAME( 0x0c, 0x08, "Play Time" ) PORT_DIPLOCATION("SW:2,1")
352 PORT_DIPSETTING( 0x00, "50 seconds" )
353 PORT_DIPSETTING( 0x04, "75 seconds" )
354 PORT_DIPSETTING( 0x08, "100 seconds" )
355 PORT_DIPSETTING( 0x0c, "125 seconds" )
356 PORT_DIPNAME( 0x30, 0x00, DEF_STR( Language ) ) PORT_DIPLOCATION("SW2:5,6")
357 PORT_DIPSETTING( 0x30, DEF_STR( German ) )
358 PORT_DIPSETTING( 0x20, DEF_STR( French ) )
359 PORT_DIPSETTING( 0x10, DEF_STR( Spanish ) )
360 PORT_DIPSETTING( 0x00, DEF_STR( English ) )
361 PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
362 PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
363
364 PORT_START("PADDLE")
365 PORT_BIT( 0xff, 0x00, IPT_PADDLE_V ) PORT_MINMAX(0,160) PORT_SENSITIVITY(30) PORT_KEYDELTA(10) PORT_CENTERDELTA(0) PORT_REVERSE
366 INPUT_PORTS_END
367
368
369 static const gfx_layout destroyr_alpha_num_layout =
370 {
371 8, 8, /* width, height */
372 64, /* total */
373 1, /* planes */
374 { 0 }, /* plane offsets */
375 {
376 0x4, 0x5, 0x6, 0x7, 0xC, 0xD, 0xE, 0xF
377 },
378 {
379 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70
380 },
381 0x80 /* increment */
382 };
383
384
385 static const gfx_layout destroyr_minor_object_layout =
386 {
387 16, 16, /* width, height */
388 32, /* total */
389 1, /* planes */
390 { 0 }, /* plane offsets */
391 {
392 0x04, 0x05, 0x06, 0x07, 0x0C, 0x0D, 0x0E, 0x0F,
393 0x14, 0x15, 0x16, 0x17, 0x1C, 0x1D, 0x1E, 0x1F
394 },
395 {
396 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0,
397 0x100, 0x120, 0x140, 0x160, 0x180, 0x1a0, 0x1c0, 0x1e0
398 },
399 0x200 /* increment */
400 };
401
402 static const uint32_t destroyr_major_object_layout_xoffset[64] =
403 {
404 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
405 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E,
406 0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, 0x2E,
407 0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, 0x3E,
408 0x40, 0x42, 0x44, 0x46, 0x48, 0x4A, 0x4C, 0x4E,
409 0x50, 0x52, 0x54, 0x56, 0x58, 0x5A, 0x5C, 0x5E,
410 0x60, 0x62, 0x64, 0x66, 0x68, 0x6A, 0x6C, 0x6E,
411 0x70, 0x72, 0x74, 0x76, 0x78, 0x7A, 0x7C, 0x7E
412 };
413
414 static const gfx_layout destroyr_major_object_layout =
415 {
416 64, 16, /* width, height */
417 4, /* total */
418 2, /* planes */
419 { 1, 0 }, /* plane offsets */
420 EXTENDED_XOFFS,
421 {
422 0x000, 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380,
423 0x400, 0x480, 0x500, 0x580, 0x600, 0x680, 0x700, 0x780
424 },
425 0x0800, /* increment */
426 destroyr_major_object_layout_xoffset,
427 nullptr
428 };
429
430 static const uint32_t destroyr_waves_layout_xoffset[64] =
431 {
432 0x00, 0x01, 0x02, 0x03, 0x08, 0x09, 0x0A, 0x0B,
433 0x10, 0x11, 0x12, 0x13, 0x18, 0x19, 0x1A, 0x1B,
434 0x20, 0x21, 0x22, 0x23, 0x28, 0x29, 0x2A, 0x2B,
435 0x30, 0x31, 0x32, 0x33, 0x38, 0x39, 0x3A, 0x3B,
436 0x40, 0x41, 0x42, 0x43, 0x48, 0x49, 0x4A, 0x4B,
437 0x50, 0x51, 0x52, 0x53, 0x58, 0x59, 0x5A, 0x5B,
438 0x60, 0x61, 0x62, 0x63, 0x68, 0x69, 0x6A, 0x6B,
439 0x70, 0x71, 0x72, 0x73, 0x78, 0x79, 0x7A, 0x7B
440 };
441
442 static const gfx_layout destroyr_waves_layout =
443 {
444 64, 2, /* width, height */
445 2, /* total */
446 1, /* planes */
447 { 0 },
448 EXTENDED_XOFFS,
449 { 0x00, 0x80 },
450 0x04, /* increment */
451 destroyr_waves_layout_xoffset,
452 nullptr
453 };
454
455
456 static GFXDECODE_START( gfx_destroyr )
457 GFXDECODE_ENTRY( "gfx1", 0, destroyr_alpha_num_layout, 4, 1 )
458 GFXDECODE_ENTRY( "gfx2", 0, destroyr_minor_object_layout, 4, 1 )
459 GFXDECODE_ENTRY( "gfx3", 0, destroyr_major_object_layout, 0, 1 )
460 GFXDECODE_ENTRY( "gfx4", 0, destroyr_waves_layout, 4, 1 )
461 GFXDECODE_END
462
463
palette_init(palette_device & palette) const464 void destroyr_state::palette_init(palette_device &palette) const
465 {
466 palette.set_pen_color(0, rgb_t(0x00, 0x00, 0x00)); // major objects
467 palette.set_pen_color(1, rgb_t(0x50, 0x50, 0x50));
468 palette.set_pen_color(2, rgb_t(0xAF, 0xAF, 0xAF));
469 palette.set_pen_color(3, rgb_t(0xFF ,0xFF, 0xFF));
470 palette.set_pen_color(4, rgb_t(0x00, 0x00, 0x00)); // alpha numerics, waves, minor objects
471 palette.set_pen_color(5, rgb_t(0xFF, 0xFF, 0xFF));
472 palette.set_pen_color(6, rgb_t(0x00, 0x00, 0x00)); // cursor
473 palette.set_pen_color(7, rgb_t(0x78, 0x78, 0x78));
474 }
475
476
machine_start()477 void destroyr_state::machine_start()
478 {
479 m_dial_timer = timer_alloc(TIMER_DIAL);
480 m_frame_timer = timer_alloc(TIMER_FRAME);
481
482 save_item(NAME(m_cursor));
483 save_item(NAME(m_wavemod));
484 save_item(NAME(m_attract));
485 save_item(NAME(m_potmask));
486 save_item(NAME(m_potsense));
487 }
488
destroyr(machine_config & config)489 void destroyr_state::destroyr(machine_config &config)
490 {
491 /* basic machine hardware */
492 M6800(config, m_maincpu, 12.096_MHz_XTAL / 16);
493 m_maincpu->set_addrmap(AS_PROGRAM, &destroyr_state::main_map);
494
495 TIMER(config, "scantimer").configure_scanline(FUNC(destroyr_state::scanline_irq), m_screen, 16, 32);
496
497 f9334_device &outlatch(F9334(config, "outlatch")); // F8
498 outlatch.q_out_cb<0>().set_output("led0").invert(); // LED 1
499 outlatch.q_out_cb<1>().set_output("led1").invert(); // LED 2 (no second LED present on cab)
500 outlatch.q_out_cb<2>().set(m_sound_songate, FUNC(netlist_mame_logic_input_device::write));
501 outlatch.q_out_cb<3>().set(m_sound_launch, FUNC(netlist_mame_logic_input_device::write));
502 outlatch.q_out_cb<4>().set(m_sound_explo, FUNC(netlist_mame_logic_input_device::write));
503 outlatch.q_out_cb<5>().set(m_sound_sonlat, FUNC(netlist_mame_logic_input_device::write));
504 outlatch.q_out_cb<6>().set(m_sound_hexplo, FUNC(netlist_mame_logic_input_device::write));
505 outlatch.q_out_cb<7>().set(m_sound_lexplo, FUNC(netlist_mame_logic_input_device::write));
506
507 WATCHDOG_TIMER(config, m_watchdog);
508
509 /* video hardware */
510 SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
511 m_screen->set_raw(12.096_MHz_XTAL / 2, 384, 0, 256, 263, 0, 240);
512 m_screen->set_screen_update(FUNC(destroyr_state::screen_update));
513 m_screen->set_palette(m_palette);
514
515 GFXDECODE(config, m_gfxdecode, m_palette, gfx_destroyr);
516 PALETTE(config, m_palette, FUNC(destroyr_state::palette_init), 8);
517
518 /* sound hardware */
519 SPEAKER(config, "mono").front_center();
520
521 NETLIST_SOUND(config, "sound_nl", 48000)
522 .set_source(NETLIST_NAME(destroyr))
523 .add_route(ALL_OUTPUTS, "mono", 1.0);
524
525 NETLIST_LOGIC_INPUT(config, "sound_nl:motor_speed", "MOTOR_SPEED.IN", 0);
526 NETLIST_LOGIC_INPUT(config, "sound_nl:noise", "NOISE.IN", 0);
527 NETLIST_LOGIC_INPUT(config, "sound_nl:attract", "ATTRACT.IN", 0);
528 NETLIST_LOGIC_INPUT(config, "sound_nl:songate", "SONGATE.IN", 0);
529 NETLIST_LOGIC_INPUT(config, "sound_nl:launch", "LAUNCH.IN", 0);
530 NETLIST_LOGIC_INPUT(config, "sound_nl:explo", "EXPLO.IN", 0);
531 NETLIST_LOGIC_INPUT(config, "sound_nl:sonlat", "SONLAT.IN", 0);
532 NETLIST_LOGIC_INPUT(config, "sound_nl:hexplo", "HE.IN", 0);
533 NETLIST_LOGIC_INPUT(config, "sound_nl:lexplo", "LE.IN", 0);
534
535 NETLIST_STREAM_OUTPUT(config, "sound_nl:cout0", 0, "OUTPUT").set_mult_offset(1.0, 0.0);
536 }
537
538
539 ROM_START( destroyr )
540 ROM_REGION( 0x8000, "maincpu", 0 ) /* program code */
541 ROM_LOAD( "030138.rom",0x7000, 0x0800, NO_DUMP ) // optional add-on translation rom
542 ROM_LOAD( "030146-01.c3", 0x7800, 0x0800, CRC(e560c712) SHA1(0505ab57eee5421b4ff4e87d14505e02b18fd54c) )
543
544 ROM_REGION( 0x0400, "gfx1", 0 ) /* alpha numerics */
545 ROM_LOAD( "030135-01.p4", 0x0000, 0x0400, CRC(184824cf) SHA1(713cfd1d41ef7b1c345ea0038b652c4ba3f08301) )
546
547 ROM_REGION( 0x0800, "gfx2", 0 ) /* minor objects */
548 ROM_LOAD( "030132-01.f4", 0x0000, 0x0400, CRC(e09d3d55) SHA1(b26013397ef2cb32d0416ecb118387b9c2dffa9a) )
549 ROM_LOAD( "030132-01.k4", 0x0400, 0x0400, CRC(e09d3d55) SHA1(b26013397ef2cb32d0416ecb118387b9c2dffa9a) ) // identical to f4
550
551 ROM_REGION( 0x0400, "gfx3", 0 ) /* major objects */
552 ROM_LOAD_NIB_HIGH( "030134-01.p8", 0x0000, 0x0400, CRC(6259e007) SHA1(049f5f7160305cb4f4b499dd113cb11eea73fc95) )
553 ROM_LOAD_NIB_LOW ( "030133-01.n8", 0x0000, 0x0400, CRC(108d3e2c) SHA1(8c993369d37c6713670483af78e6d04d38f4b4fc) )
554
555 ROM_REGION( 0x0020, "gfx4", 0 ) /* waves */
556 ROM_LOAD( "030136-01.k2", 0x0000, 0x0020, CRC(532c11b1) SHA1(18ab5369a3f2cfcc9a44f38fa8649524bea5b203) )
557
558 ROM_REGION( 0x0100, "syncprom", 0 ) /* used for vsync/vblank signals */
559 ROM_LOAD( "030131-01.m1", 0x0000, 0x0100, CRC(b8094b4c) SHA1(82dc6799a19984f3b204ee3aeeb007e55afc8be3) )
560 ROM_END
561
562 ROM_START( destroyr1 )
563 ROM_REGION( 0x8000, "maincpu", 0 ) /* program code */
564 ROM_LOAD( "030138.rom",0x7000, 0x0800, NO_DUMP ) // optional add-on translation rom
565 ROM_LOAD_NIB_HIGH( "030142-01.f3", 0x7800, 0x0400, CRC(9e9a08d3) SHA1(eb31bab1537caf43ab8c3d23a6c9cc2009fcb98e) )
566 ROM_LOAD_NIB_LOW ( "030141-01.e2", 0x7800, 0x0400, CRC(c924fbce) SHA1(53aa9a3c4c6e90fb94500ddfa6c2ae3076eee2ef) )
567 ROM_LOAD_NIB_HIGH( "030144-01.j3", 0x7c00, 0x0400, CRC(0c7135c6) SHA1(6a0180353a0a6f34639dadc23179f6323aae8d62) )
568 ROM_LOAD_NIB_LOW ( "030143-01.h2", 0x7c00, 0x0400, CRC(b946e6f0) SHA1(b906024bb0e03a644fff1d5516637c24916b096e) )
569
570 ROM_REGION( 0x0400, "gfx1", 0 ) /* alpha numerics */
571 ROM_LOAD( "030135-01.p4", 0x0000, 0x0400, CRC(184824cf) SHA1(713cfd1d41ef7b1c345ea0038b652c4ba3f08301) )
572
573 ROM_REGION( 0x0800, "gfx2", 0 ) /* minor objects */
574 ROM_LOAD( "030132-01.f4", 0x0000, 0x0400, CRC(e09d3d55) SHA1(b26013397ef2cb32d0416ecb118387b9c2dffa9a) )
575 ROM_LOAD( "030132-01.k4", 0x0400, 0x0400, CRC(e09d3d55) SHA1(b26013397ef2cb32d0416ecb118387b9c2dffa9a) ) // identical to f4
576
577 ROM_REGION( 0x0400, "gfx3", 0 ) /* major objects */
578 ROM_LOAD_NIB_HIGH( "030134-01.p8", 0x0000, 0x0400, CRC(6259e007) SHA1(049f5f7160305cb4f4b499dd113cb11eea73fc95) )
579 ROM_LOAD_NIB_LOW ( "030133-01.n8", 0x0000, 0x0400, CRC(108d3e2c) SHA1(8c993369d37c6713670483af78e6d04d38f4b4fc) )
580
581 ROM_REGION( 0x0020, "gfx4", 0 ) /* waves */
582 ROM_LOAD( "030136-01.k2", 0x0000, 0x0020, CRC(532c11b1) SHA1(18ab5369a3f2cfcc9a44f38fa8649524bea5b203) )
583
584 ROM_REGION( 0x0100, "syncprom", 0 ) /* used for vsync/vblank signals */
585 ROM_LOAD( "030131-01.m1", 0x0000, 0x0100, CRC(b8094b4c) SHA1(82dc6799a19984f3b204ee3aeeb007e55afc8be3) )
586 ROM_END
587
588
589 GAMEL( 1977, destroyr, 0, destroyr, destroyr, destroyr_state, empty_init, ORIENTATION_FLIP_X, "Atari", "Destroyer (version O2)", MACHINE_SUPPORTS_SAVE, layout_destroyr )
590 GAMEL( 1977, destroyr1, destroyr, destroyr, destroyr, destroyr_state, empty_init, ORIENTATION_FLIP_X, "Atari", "Destroyer (version O1)", MACHINE_SUPPORTS_SAVE, layout_destroyr )
591