diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index 836b217dbee..6204a58c2dc 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -2975,6 +2975,8 @@ files { MAME_DIR .. "src/mame/includes/skykid.h", MAME_DIR .. "src/mame/video/skykid.cpp", MAME_DIR .. "src/mame/drivers/sweetland.cpp", + MAME_DIR .. "src/mame/audio/nl_tankbatt.h", + MAME_DIR .. "src/mame/audio/nl_tankbatt.cpp", MAME_DIR .. "src/mame/drivers/tankbatt.cpp", MAME_DIR .. "src/mame/includes/tankbatt.h", MAME_DIR .. "src/mame/video/tankbatt.cpp", diff --git a/src/lib/netlist/devices/nld_devinc.h b/src/lib/netlist/devices/nld_devinc.h index 298db9083cb..48e41f6e561 100644 --- a/src/lib/netlist/devices/nld_devinc.h +++ b/src/lib/netlist/devices/nld_devinc.h @@ -595,7 +595,7 @@ // --------------------------------------------------------------------- // Source: src/lib/netlist/devices/nld_4006.cpp // --------------------------------------------------------------------- -// usage : CD4006(name, pCLOCK, pD1, pD2, pD3, pD4, pD1P4, pD1P4S, pD2P4, pD2P5, pD3P4, pD4P4, pD3P5) +// usage : CD4006(name, pCLOCK, pD1, pD2, pD3, pD4, pD1P4, pD1P4S, pD2P4, pD2P5, pD3P4, pD4P4, pD4P5) // auto connect: VCC, GND #define CD4006(...) \ NET_REGISTER_DEVEXT(CD4006, __VA_ARGS__) diff --git a/src/mame/audio/nl_tankbatt.cpp b/src/mame/audio/nl_tankbatt.cpp new file mode 100644 index 00000000000..f318daf1cd1 --- /dev/null +++ b/src/mame/audio/nl_tankbatt.cpp @@ -0,0 +1,165 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz + +// +// Netlist for Tank Battalion +// +// Derived from the schematics in the manual. +// +// Known problems/issues: +// +// * None. +// + +#include "netlist/devices/net_lib.h" +#include "nl_tankbatt.h" + +// +// Main netlist +// + +NETLIST_START(tankbatt) + + SOLVER(Solver, 48000) + ANALOG_INPUT(V5, 5) + ALIAS(VCC, V5) + + CLOCK(2V, 4000) // 18.432MHz / (3 * 384 * 2) + CLOCK(4V, 2000) // 18.432MHz / (3 * 384 * 4) + + TTL_INPUT(S1, 0) // active high + TTL_INPUT(S2, 0) // active high + TTL_INPUT(OFF, 1) // active high + TTL_INPUT(ENGINE_HI, 0) // active high + TTL_INPUT(SHOOT, 0) // active high + TTL_INPUT(HIT, 0) // active high + + RES(R31, 470) + RES(R32, 470) + RES(R35, RES_K(4.7)) + RES(R36, RES_K(4.7)) + RES(R37, RES_K(6.8)) + RES(R38, RES_K(10)) + //RES(R41, RES_K(22)) + RES(R42, RES_K(22)) + RES(R43, RES_K(22)) + RES(R44, RES_K(33)) + RES(R45, RES_K(47)) + RES(R46, RES_K(4.7)) // Possible schematic or scan-quality error: Schematic says 47K + RES(R47, RES_K(4.7)) + RES(R48, RES_K(4.7)) + RES(R49, RES_K(4.7)) // Possible schematic or scan-quality error: Schematic says 47K + RES(R50, RES_K(150)) + RES(R51, RES_K(150)) + RES(R52, RES_K(220)) + RES(R53, RES_K(470)) + RES(R54, RES_K(470)) + RES(R56_1, RES_K(1)) + RES(R56_2, RES_K(1)) + RES(R57, RES_K(10)) + RES(R58, RES_K(1)) + RES(R59, RES_K(1)) + RES(R60, RES_K(1)) + RES(R61, RES_K(1)) + + CAP(C10, CAP_U(2.2)) + CAP(C11, CAP_U(2.2)) + CAP(C12, CAP_U(2.2)) + CAP(C13, CAP_U(2.2)) + CAP(C14, CAP_U(0.1)) + CAP(C15, CAP_U(0.01)) + CAP(C16, CAP_U(0.01)) + CAP(C17, CAP_U(0.01)) + CAP(C18, CAP_U(0.01)) + CAP(C42, CAP_U(0.1)) + + DIODE(D8, "D") // Generic diodes, types not listed on schematic + DIODE(D9, "D") + DIODE(D10, "D") + DIODE(D11, "D") + + CD4006(_6F) + CD4066_DIP(_6L) + LM324_DIP(_6J) + TTL_7486_DIP(_6K) + TTL_7492_DIP(_5K) + + NET_C(VCC, _5K.5, _6F.VDD, _6J.4, _6K.7, _6L.14, S1.VCC, S2.VCC, OFF.VCC, ENGINE_HI.VCC, SHOOT.VCC, HIT.VCC, 2V.VCC, 4V.VCC) + NET_C(GND, _5K.10, _6F.VSS, _6J.11, _6K.14, _6L.7, S1.GND, S2.GND, OFF.GND, ENGINE_HI.GND, SHOOT.GND, HIT.GND, 2V.GND, 4V.GND) + + // Noise generation (presumably) + NET_C(_6F.CLOCK, 2V) + NET_C(_6F.D1P4, _6F.D3) + NET_C(_6F.D3P4, _6F.D4, _6L.12, _6L.6) + NET_C(_6F.D1, _6F.D2P5, _6K.A.A) + NET_C(_6F.D4P4, _6K.A.B) + NET_C(_6K.A.Q, R38.1) + NET_C(_6F.D2, R38.2, D9.K) + NET_C(_6F.D4P5, D8.A, R53.1) + NET_C(D8.K, R53.2, C42.1, _6J.2) + NET_C(_6J.1, C42.2, D9.A) + NET_C(_6J.3, C12.1, R43.1, R44.1, _6J.12, _6J.10) + NET_C(C12.2, GND) + NET_C(R43.2, GND) + NET_C(R44.2, V5) + + // S1 + NET_C(S1.Q, _6L.5) + NET_C(4V, _6L.4) + NET_C(_6L.3, R35.1) + + // S2 + NET_C(S2.Q, _6L.13) + NET_C(2V, _6L.1) + NET_C(_6L.2, R36.1) + + // Hit + NET_C(HIT.Q, R31.1) + NET_C(R31.2, D10.A) + NET_C(D10.K, C10.1, _6L.8) + NET_C(C10.2, GND) + NET_C(_6L.9, R50.1) + NET_C(R50.2, R42.1, C15.1, C16.1) + NET_C(R42.2, GND) + NET_C(C16.2, R54.1, _6J.9) + NET_C(C15.2, R54.2, _6J.8, R56_1.1) + + // Shoot + NET_C(SHOOT.Q, R32.1) + NET_C(R32.2, D11.A) + NET_C(D11.K, C11.1, _6L.11) + NET_C(C11.2, GND) + NET_C(_6L.10, R45.1) + NET_C(R45.2, R37.1, C17.1, C18.1) + NET_C(R37.2, GND) + NET_C(C18.2, R51.1, _6J.13) + NET_C(C17.2, R51.2, _6J.14, R56_2.1) + + // Engine Rumble + NET_C(ENGINE_HI.Q, _6K.B.A) + NET_C(_6K.B.B, _6K.C.Q) + NET_C(_6K.B.Q, R52.1, _5K.1) + NET_C(R52.2, R46.1, _6J.6, C14.1) + NET_C(C14.2, GND) + NET_C(_6J.5, R47.1, R48.1, R49.1) + NET_C(R47.2, V5) + NET_C(R48.2, GND) + NET_C(R49.2, R57.1, _6J.7, R46.2, _6K.C.A) + NET_C(R57.2, GND) + NET_C(_6K.C.B, VCC) + NET_C(_5K.7, VCC) + NET_C(_5K.6, OFF.Q) + NET_C(_5K.11, R60.1, _6K.D.A) + NET_C(_5K.8, R58.1, _6K.D.B) + NET_C(_6K.D.Q, _5K.14) + NET_C(_5K.12, R61.1) + NET_C(R58.2, R60.2, R61.2, C13.1, R59.1) + NET_C(C13.2, GND) + + // Mixing + //NET_C(R56_1.2, R56_2.2) + //NET_C(R35.2, R36.2) + //NET_C(R56_2.2, R59.2) + NET_C(R35.2, R36.2, R56_1.2, R56_2.2, R59.2) + //NET_C(R41.2, GND) +NETLIST_END() diff --git a/src/mame/audio/nl_tankbatt.h b/src/mame/audio/nl_tankbatt.h new file mode 100644 index 00000000000..6fa318cc2d6 --- /dev/null +++ b/src/mame/audio/nl_tankbatt.h @@ -0,0 +1,10 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +#ifndef MAME_AUDIO_NL_TANKBATT_H +#define MAME_AUDIO_NL_TANKBATT_H + +#pragma once + +NETLIST_EXTERNAL(tankbatt) + +#endif // MAME_AUDIO_NL_TANKBATT_H diff --git a/src/mame/drivers/tankbatt.cpp b/src/mame/drivers/tankbatt.cpp index 8b7b2f127d0..daa014fc07c 100644 --- a/src/mame/drivers/tankbatt.cpp +++ b/src/mame/drivers/tankbatt.cpp @@ -6,49 +6,71 @@ Tank Battalion memory map (verified) driver by Brad Oliver -$0000-$000f : bullet ram, first entry is player's bullet -$0010-$01ff : zero page & stack -$0200-$07ff : RAM -$0800-$0bff : videoram -$0c00-$0c1f : I/O +Memory Map: + $0000-$03ff : Work RAM 0 + $0400-$07ff : Work RAM 1 + $0800-$0bff : VRAM + $0c00-$0fff : I/O + $2000-$3fff : ROM -Read: - $0c00-$0c03 : p1 joystick - $0c04 - $0c07 : stop at grid self-test if bit 7 is low - $0c0f : stop at first self-test if bit 7 is low +A 4-bit BCD value is created from the following four bits: + Bit 0: A3 + Bit 1: A4 + Bit 2: Read + Bit 3: !(A10 & A11) - $0c18 : Cabinet, 0 = table, 1 = upright - $0c19-$0c1a : Coinage, 00 = free play, 01 = 2 coin 1 credit, 10 = 1 coin 2 credits, 11 = 1 coin 1 credit - $0c1b-$0c1c : Bonus, 00 = 10000, 01 = 15000, 10 = 20000, 11 = none - $0c1d : Tanks, 0 = 3, 1 = 2 - $0c1e-$0c1f : ?? +For writes, the following upper ranges are decoded: + xxxx 11xx xxx0 0xxx: OUT0 + xxxx 11xx xxx0 1xxx: OUT1 + xxxx 11xx xxx1 0xxx: INTACK + xxxx 11xx xxx1 1xxx: Watchdog -Write: - $0c00-$0c01 : p1/p2 start leds - $0c02 : ?? written to at end of IRQ, either 0 or 1 - coin counter? - $0c03 : ?? written to during IRQ if grid test is on - $0c08 : ?? written to during IRQ if grid test is on - $0c09 : Sound - coin ding - $0c0a : Sound enable (active low) ?? game only ?? - $0c0b : Sound - background noise, 0 - low rumble, 1 - high rumble - $0c0c : Sound - player fire - $0c0d : Sound - explosion - $0c0f : NMI enable (active high) ?? demo only ?? +For reads, the following upper ranges are decoded: + xxxx 11xx xxx0 0xxx: IN0 + xxxx 11xx xxx0 1xxx: IN1 + xxxx 11xx xxx1 0xxx: - + xxxx 11xx xxx1 1xxx: DIP switches - $0c10 : IRQ ack (written at the end of the irq routine) - $0c18 : Watchdog +OUT0: + 000: Edge Pin F P1 LED (schematic states Unused) + 001: Edge Pin 6 P2 LED (schematic states Unused) + 010: Edge Pin H Coin Counter (schematic states Unused) + 011: Edge Pin 7 Coin Lockout (schematic states Coin Counter) + 1xx: Unused -$2000-$3fff : ROM (A14, A15 not decoded) +OUT1: + 000: S1 (Square Wave 1, connected to 2V) + 001: S2 (Square Wave 2, connected to 4V) + 010: Sound off (1), on (0) + 011: Rumble hi (1), rumble low (0) + 100: Shoot sound effect + 101: Hit sound effect + 110: Unused + 111: NMI Enable + +IN0: + 000: Edge Pin Y Joystick Up + 001: Edge Pin M Joystick Left + 010: Edge Pin 14 Joystick Down + 011: Edge Pin 11 Joystick Right + 100: Edge Pin N Shoot + 101: Edge Pin J Coin 1 + 110: Edge Pin 8 Coin 2 + 111: Edge Pin 9 Service Switch + +IN1: + 000: Edge Pin 21 Joystick Up (Cocktail) + 001: Edge Pin P Joystick Left (Cocktail) + 010: Edge Pin V Joystick Down (Cocktail) + 011: Edge Pin 13 Joystick Right (Cocktail) + 100: Edge Pin 12 Shoot (Cocktail) + 101: Edge Pin L P1 Start + 110: Edge Pin 10 P2 Start + 111: Edge Pin K Test DIP Switch TODO: - . Needs proper discrete emulation . Resistor values on the color prom need to be corrected -Known issues: - . The 'moving' tank rumble noise seems to keep playing a second too long - . Sample support is all a crapshoot. I have no idea how it really works - ***************************************************************************/ #include "emu.h" @@ -58,7 +80,6 @@ Known issues: #include "machine/74259.h" #include "machine/input_merger.h" #include "machine/watchdog.h" -#include "sound/samples.h" #include "screen.h" #include "speaker.h" @@ -70,62 +91,17 @@ void tankbatt_state::machine_start() uint8_t tankbatt_state::in0_r(offs_t offset) { - int val; - - val = ioport("P1")->read(); - return ((val << (7 - offset)) & 0x80); + return BIT(m_player_input[0]->read(), offset) << 7; } uint8_t tankbatt_state::in1_r(offs_t offset) { - int val; - - val = ioport("P2")->read(); - return ((val << (7 - offset)) & 0x80); + return BIT(m_player_input[1]->read(), offset) << 7; } uint8_t tankbatt_state::dsw_r(offs_t offset) { - int val; - - val = ioport("DSW")->read(); - return ((val << (7 - offset)) & 0x80); -} - -WRITE_LINE_MEMBER(tankbatt_state::sound_off_w) -{ - m_sound_enable = !state; - - // turn off the engine noise - if (state) m_samples->stop(2); -} - -WRITE_LINE_MEMBER(tankbatt_state::sh_expl_w) -{ - if (state) // rising edge - { - m_samples->start(1, 3); - } -} - -WRITE_LINE_MEMBER(tankbatt_state::sh_engine_w) -{ - if (m_sound_enable) - { - if (state) - m_samples->start(2, 2, true); - else - m_samples->start(2, 1, true); - } - else m_samples->stop(2); -} - -WRITE_LINE_MEMBER(tankbatt_state::sh_fire_w) -{ - if (state) // rising edge - { - m_samples->start(0, 0); - } + return BIT(m_dips->read(), offset) << 7; } void tankbatt_state::intack_w(uint8_t data) @@ -172,7 +148,7 @@ static INPUT_PORTS_START( tankbatt ) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 ) - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_TILT ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_START("P2") /* IN1 */ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_4WAY PORT_COCKTAIL @@ -237,17 +213,6 @@ GFXDECODE_END -static const char *const tankbatt_sample_names[] = -{ - "*tankbatt", - "fire", - "engine1", - "engine2", - "explode1", - nullptr /* end of array */ -}; - - void tankbatt_state::tankbatt(machine_config &config) { /* basic machine hardware */ @@ -268,12 +233,12 @@ void tankbatt_state::tankbatt(machine_config &config) // Q4 through Q7 are not connected cd4099_device &outlatch1(CD4099(config, "outlatch1")); // 4099 at 4H or 259 at 4J - outlatch1.q_out_cb<0>().set_nop(); // TODO: S1 tone - outlatch1.q_out_cb<1>().set_nop(); // TODO: S2 tone - outlatch1.q_out_cb<2>().set(FUNC(tankbatt_state::sound_off_w)); - outlatch1.q_out_cb<3>().set(FUNC(tankbatt_state::sh_engine_w)); - outlatch1.q_out_cb<4>().set(FUNC(tankbatt_state::sh_fire_w)); - outlatch1.q_out_cb<5>().set(FUNC(tankbatt_state::sh_expl_w)); // bit 7 also set by ASL instruction + outlatch1.q_out_cb<0>().set(m_sound_s1, FUNC(netlist_mame_logic_input_device::write_line)); + outlatch1.q_out_cb<1>().set(m_sound_s2, FUNC(netlist_mame_logic_input_device::write_line)); + outlatch1.q_out_cb<2>().set(m_sound_off, FUNC(netlist_mame_logic_input_device::write_line)); + outlatch1.q_out_cb<3>().set(m_sound_engine_hi, FUNC(netlist_mame_logic_input_device::write_line)); + outlatch1.q_out_cb<4>().set(m_sound_shoot, FUNC(netlist_mame_logic_input_device::write_line)); + outlatch1.q_out_cb<5>().set(m_sound_hit, FUNC(netlist_mame_logic_input_device::write_line)); // Q6 is not connected outlatch1.q_out_cb<7>().set("nmigate", FUNC(input_merger_device::in_w<1>)); @@ -290,10 +255,18 @@ void tankbatt_state::tankbatt(machine_config &config) /* sound hardware */ SPEAKER(config, "mono").front_center(); - SAMPLES(config, m_samples); - m_samples->set_channels(3); - m_samples->set_samples_names(tankbatt_sample_names); - m_samples->add_route(ALL_OUTPUTS, "mono", 0.25); + NETLIST_SOUND(config, "sound_nl", 48000) + .set_source(NETLIST_NAME(tankbatt)) + .add_route(ALL_OUTPUTS, "mono", 1.0); + + NETLIST_LOGIC_INPUT(config, "sound_nl:s1", "S1.IN", 0); + NETLIST_LOGIC_INPUT(config, "sound_nl:s2", "S2.IN", 0); + NETLIST_LOGIC_INPUT(config, "sound_nl:off", "OFF.IN", 0); + NETLIST_LOGIC_INPUT(config, "sound_nl:engine_hi", "ENGINE_HI.IN", 0); + NETLIST_LOGIC_INPUT(config, "sound_nl:shoot", "SHOOT.IN", 0); + NETLIST_LOGIC_INPUT(config, "sound_nl:hit", "HIT.IN", 0); + + NETLIST_STREAM_OUTPUT(config, "sound_nl:cout0", 0, "R35.2").set_mult_offset(10000.0, 0.0); } diff --git a/src/mame/includes/tankbatt.h b/src/mame/includes/tankbatt.h index 1617ceb8a52..c27436328e4 100644 --- a/src/mame/includes/tankbatt.h +++ b/src/mame/includes/tankbatt.h @@ -6,7 +6,11 @@ #pragma once #include "machine/timer.h" -#include "sound/samples.h" +#include "machine/netlist.h" + +#include "netlist/nl_setup.h" +#include "audio/nl_tankbatt.h" + #include "emupal.h" #include "tilemap.h" @@ -16,37 +20,49 @@ public: tankbatt_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), m_maincpu(*this, "maincpu"), - m_samples(*this, "samples"), m_gfxdecode(*this, "gfxdecode"), m_palette(*this, "palette"), m_bulletsram(*this, "bulletsram"), - m_videoram(*this, "videoram") + m_videoram(*this, "videoram"), + m_player_input(*this, "P%u", 1U), + m_dips(*this, "DSW"), + m_sound_s1(*this, "sound_nl:s1"), + m_sound_s2(*this, "sound_nl:s2"), + m_sound_off(*this, "sound_nl:off"), + m_sound_engine_hi(*this, "sound_nl:engine_hi"), + m_sound_shoot(*this, "sound_nl:shoot"), + m_sound_hit(*this, "sound_nl:hit") { } void tankbatt(machine_config &config); private: required_device m_maincpu; - required_device m_samples; required_device m_gfxdecode; required_device m_palette; required_shared_ptr m_bulletsram; required_shared_ptr m_videoram; + required_ioport_array<2> m_player_input; + required_ioport m_dips; + + required_device m_sound_s1; + required_device m_sound_s2; + required_device m_sound_off; + required_device m_sound_engine_hi; + required_device m_sound_shoot; + required_device m_sound_hit; + int m_sound_enable; tilemap_t *m_bg_tilemap; uint8_t in0_r(offs_t offset); uint8_t in1_r(offs_t offset); uint8_t dsw_r(offs_t offset); - DECLARE_WRITE_LINE_MEMBER(sound_off_w); - DECLARE_WRITE_LINE_MEMBER(sh_expl_w); - DECLARE_WRITE_LINE_MEMBER(sh_engine_w); - DECLARE_WRITE_LINE_MEMBER(sh_fire_w); void intack_w(uint8_t data); - DECLARE_WRITE_LINE_MEMBER(coincounter_w); - DECLARE_WRITE_LINE_MEMBER(coinlockout_w); + void coincounter_w(int state); + void coinlockout_w(int state); void videoram_w(offs_t offset, uint8_t data); TIMER_DEVICE_CALLBACK_MEMBER(scanline_interrupt);