From 04aac6dc77282224e5ee09d8a8248f33ef898e46 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Sun, 10 Sep 2023 06:25:34 +1000 Subject: nitendo/n8080.cpp: Encapsulated sound boards. --- hash/msx1_cass.xml | 4 +- src/devices/cpu/dsp16/dsp16.cpp | 1 - src/mame/atari/pong.cpp | 59 ++-- src/mame/heathkit/tlb.cpp | 4 +- src/mame/nintendo/n8080.cpp | 628 +++++++++++++++++++++++++++++++++-- src/mame/nintendo/n8080.h | 209 ------------ src/mame/nintendo/n8080_a.cpp | 716 +++++++++++++++++++--------------------- src/mame/nintendo/n8080_a.h | 47 +++ src/mame/nintendo/n8080_v.cpp | 359 -------------------- 9 files changed, 1012 insertions(+), 1015 deletions(-) delete mode 100644 src/mame/nintendo/n8080.h create mode 100644 src/mame/nintendo/n8080_a.h delete mode 100644 src/mame/nintendo/n8080_v.cpp diff --git a/hash/msx1_cass.xml b/hash/msx1_cass.xml index 31c6fa7d153..f514eb76c80 100644 --- a/hash/msx1_cass.xml +++ b/hash/msx1_cass.xml @@ -157,7 +157,7 @@ license:CC0-1.0 - + Light Pen Graphic v1.0 (Japan) 1984 Sanyo @@ -17678,7 +17678,7 @@ Side B - + The Queen's Footsteps (English) 2020 Davide Bucci diff --git a/src/devices/cpu/dsp16/dsp16.cpp b/src/devices/cpu/dsp16/dsp16.cpp index 4a8b42a0753..dadd93d07cb 100644 --- a/src/devices/cpu/dsp16/dsp16.cpp +++ b/src/devices/cpu/dsp16/dsp16.cpp @@ -978,7 +978,6 @@ template inline void dsp16_device_base::execute_so case 0x1e: // Reserved throw emu_fatalerror("DSP16: reserved op %u (PC = %04X)\n", op >> 11, m_st_pcbase); - break; case 0x1f: // F1 ; y = Y ; x = *pt++[i] m_core->op_dau_ad(op) = m_core->dau_f1(op); diff --git a/src/mame/atari/pong.cpp b/src/mame/atari/pong.cpp index 9bd500717da..5ce44bbadc3 100644 --- a/src/mame/atari/pong.cpp +++ b/src/mame/atari/pong.cpp @@ -150,10 +150,10 @@ class ttl_mono_state : public driver_device { public: ttl_mono_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag), - m_maincpu(*this, "maincpu"), - m_video(*this, "fixfreq"), - m_dac(*this, "dac") /* just to have a sound device */ + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_video(*this, "fixfreq") + , m_dac(*this, "dac") /* just to have a sound device */ { } @@ -172,14 +172,6 @@ public: m_dac->write(16384 * data); } -protected: - - // driver_device overrides - virtual void machine_start() override { }; - virtual void machine_reset() override { }; - - virtual void video_start() override { }; - private: }; @@ -188,9 +180,9 @@ class pong_state : public ttl_mono_state { public: pong_state(const machine_config &mconfig, device_type type, const char *tag) - : ttl_mono_state(mconfig, type, tag), - m_sw1a(*this, "maincpu:sw1a"), - m_sw1b(*this, "maincpu:sw1b") + : ttl_mono_state(mconfig, type, tag) + , m_sw1a(*this, "maincpu:sw1a") + , m_sw1b(*this, "maincpu:sw1b") { } @@ -203,13 +195,6 @@ public: void pongd(machine_config &config); void pong(machine_config &config); -protected: - - // driver_device overrides - virtual void machine_start() override { }; - virtual void machine_reset() override { }; - virtual void video_start() override { }; - private: }; @@ -218,17 +203,17 @@ class breakout_state : public ttl_mono_state { public: breakout_state(const machine_config &mconfig, device_type type, const char *tag) - : ttl_mono_state(mconfig, type, tag), - m_led_serve(*this, "maincpu:led_serve"), - m_lamp_credit1(*this, "maincpu:lamp_credit1"), - m_lamp_credit2(*this, "maincpu:lamp_credit2"), - m_coin_counter(*this, "maincpu:coin_counter"), - m_sw1_1(*this, "maincpu:sw1_1"), - m_sw1_2(*this, "maincpu:sw1_2"), - m_sw1_3(*this, "maincpu:sw1_3"), - m_sw1_4(*this, "maincpu:sw1_4"), - m_serve_led_output(*this, "serve_led"), - m_lamp_credit_output(*this, "lamp_credit%u", 1U) + : ttl_mono_state(mconfig, type, tag) + , m_led_serve(*this, "maincpu:led_serve") + , m_lamp_credit1(*this, "maincpu:lamp_credit1") + , m_lamp_credit2(*this, "maincpu:lamp_credit2") + , m_coin_counter(*this, "maincpu:coin_counter") + , m_sw1_1(*this, "maincpu:sw1_1") + , m_sw1_2(*this, "maincpu:sw1_2") + , m_sw1_3(*this, "maincpu:sw1_3") + , m_sw1_4(*this, "maincpu:sw1_4") + , m_serve_led_output(*this, "serve_led") + , m_lamp_credit_output(*this, "lamp_credit%u", 1U) { } required_device m_led_serve; @@ -268,9 +253,7 @@ public: protected: // driver_device overrides - virtual void machine_start() override { m_serve_led_output.resolve(); m_lamp_credit_output.resolve(); }; - virtual void machine_reset() override { }; - virtual void video_start() override { }; + virtual void machine_start() override { m_serve_led_output.resolve(); m_lamp_credit_output.resolve(); } private: output_finder<> m_serve_led_output; @@ -309,9 +292,7 @@ public: protected: // driver_device overrides - virtual void machine_start() override { m_credit_led.resolve(); }; - virtual void machine_reset() override { }; - virtual void video_start() override { }; + virtual void machine_start() override { m_credit_led.resolve(); } private: output_finder<> m_credit_led; diff --git a/src/mame/heathkit/tlb.cpp b/src/mame/heathkit/tlb.cpp index 4ff616a7759..63d0f21b874 100644 --- a/src/mame/heathkit/tlb.cpp +++ b/src/mame/heathkit/tlb.cpp @@ -1335,7 +1335,7 @@ MC6845_UPDATE_ROW(heath_gp19_tlb_device::crtc_update_row) { for (int x = 0; x < x_count; x++) { - uint8_t const gfx = m_p_videoram[((ma << 1) + ( ra * x_count ) + x) & 0x3fff] ^ screen_inv; + uint8_t const gfx = m_p_videoram[((ma << 1) + (ra * x_count) + x) & 0x3fff] ^ screen_inv; for (int b = 0; 8 > b; ++b) { @@ -1345,7 +1345,7 @@ MC6845_UPDATE_ROW(heath_gp19_tlb_device::crtc_update_row) } else { - uint16_t base = m_char_gen_a11 ? 0x800 : 0x0; + uint16_t const base = m_char_gen_a11 ? 0x800 : 0x0; for (int x = 0; x < x_count; x++) { diff --git a/src/mame/nintendo/n8080.cpp b/src/mame/nintendo/n8080.cpp index 148fecbfac1..098fb54abd0 100644 --- a/src/mame/nintendo/n8080.cpp +++ b/src/mame/nintendo/n8080.cpp @@ -137,27 +137,541 @@ Notes: ***************************************************************************/ #include "emu.h" -#include "n8080.h" + +#include "n8080_a.h" + +#include "cpu/i8085/i8085.h" +#include "machine/timer.h" + +#include "emupal.h" +#include "screen.h" + + +namespace { + +class n8080_state : public driver_device +{ +public: + n8080_state(const machine_config &mconfig, device_type type, const char *tag) ATTR_COLD : + driver_device(mconfig, type, tag), + m_videoram(*this, "videoram"), + m_prom(*this, "proms"), + m_maincpu(*this, "maincpu"), + m_screen(*this, "screen"), + m_palette(*this, "palette"), + m_sound(*this, "soundboard") + { } + +protected: + virtual void machine_start() override ATTR_COLD; + virtual void machine_reset() override ATTR_COLD; + + virtual void delayed_sound_1(u8 data); + virtual void delayed_sound_2(u8 data); + + void n8080_shift_bits_w(u8 data); + void n8080_shift_data_w(u8 data); + u8 n8080_shift_r(); + void n8080_video_control_w(u8 data); + void n8080_sound_1_w(u8 data); + void n8080_sound_2_w(u8 data); + void n8080_inte_callback(int state); + void n8080_status_callback(u8 data); + void n8080_palette(palette_device &palette) const ATTR_COLD; + TIMER_DEVICE_CALLBACK_MEMBER(rst1_tick); + TIMER_DEVICE_CALLBACK_MEMBER(rst2_tick); + TIMER_CALLBACK_MEMBER(stop_mono_flop_callback); + TIMER_CALLBACK_MEMBER(delayed_sound_1_callback); + TIMER_CALLBACK_MEMBER(delayed_sound_2_callback); + + void main_cpu_map(address_map &map) ATTR_COLD; + void main_io_map(address_map &map) ATTR_COLD; + + /* memory pointers */ + required_shared_ptr m_videoram; + optional_memory_region m_prom; + + /* video-related */ + u8 m_sheriff_color_mode; + u8 m_sheriff_color_data; + + /* other */ + unsigned m_shift_data; + u8 m_shift_bits; + bool m_inte; + + /* devices */ + required_device m_maincpu; + required_device m_screen; + required_device m_palette; + required_device m_sound; +}; + +class spacefev_state : public n8080_state +{ +public: + spacefev_state(const machine_config &mconfig, device_type type, const char *tag) ATTR_COLD : + n8080_state(mconfig, type, tag), + m_video_conf(*this, "VIDEO") + { } + + void spacefev(machine_config &config) ATTR_COLD; + +protected: + virtual void machine_start() override ATTR_COLD; + virtual void machine_reset() override ATTR_COLD; + + virtual void delayed_sound_1(u8 data) override; + virtual void delayed_sound_2(u8 data) override; + +private: + TIMER_CALLBACK_MEMBER(stop_red_cannon); + void start_red_cannon(); + u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + + required_ioport m_video_conf; + + emu_timer *m_cannon_timer; + + u8 m_prev_snd_data = 0; + bool m_red_screen = false; + bool m_red_cannon = false; +}; + +class sheriff_state : public n8080_state +{ +public: + sheriff_state(const machine_config &mconfig, device_type type, const char *tag) ATTR_COLD : + n8080_state(mconfig, type, tag) + { } + + void sheriff(machine_config &config) ATTR_COLD; + void westgun2(machine_config &config) ATTR_COLD; + +protected: + virtual void machine_start() override ATTR_COLD; + virtual void machine_reset() override ATTR_COLD; + +private: + u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); +}; + +class helifire_state : public n8080_state +{ +public: + helifire_state(const machine_config &mconfig, device_type type, const char *tag) ATTR_COLD : + n8080_state(mconfig, type, tag), + m_colorram(*this, "colorram"), + m_pot(*this, "POT%u", 0) + { } + + void helifire(machine_config &config) ATTR_COLD; + +protected: + virtual void machine_start() override ATTR_COLD; + virtual void machine_reset() override ATTR_COLD; + + virtual void delayed_sound_2(u8 data) override; + +private: + void helifire_palette(palette_device &palette) const ATTR_COLD; + void next_line(); + void screen_vblank(int state); + u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + + void main_cpu_map(address_map &map) ATTR_COLD; + + required_shared_ptr m_colorram; + required_ioport_array<2> m_pot; + + bool m_flash = false; + u8 m_LSFR[63]; + unsigned m_mv = 0; + unsigned m_sc = 0; // IC56 +}; // Shifter circuit done with TTL -void n8080_state::n8080_shift_bits_w(uint8_t data) +void n8080_state::n8080_shift_bits_w(u8 data) { m_shift_bits = data & 7; } -void n8080_state::n8080_shift_data_w(uint8_t data) +void n8080_state::n8080_shift_data_w(u8 data) { m_shift_data = (m_shift_data >> 8) | (data << 8); } -uint8_t n8080_state::n8080_shift_r() +u8 n8080_state::n8080_shift_r() { return m_shift_data >> (8 - m_shift_bits); } +void n8080_state::delayed_sound_1(u8 data) +{ + m_sound->sound1_w(data); +} + +void spacefev_state::delayed_sound_1(u8 data) +{ + if (BIT(data & ~m_prev_snd_data, 4)) + start_red_cannon(); + + m_red_screen = BIT(data, 3); + + m_prev_snd_data = data; + + n8080_state::delayed_sound_1(data); +} + + +void n8080_state::delayed_sound_2(u8 data) +{ + m_sound->sound2_w(data); +} + +void spacefev_state::delayed_sound_2(u8 data) +{ + flip_screen_set(BIT(data, 5)); + + n8080_state::delayed_sound_2(data); +} + +void helifire_state::delayed_sound_2(u8 data) +{ + m_flash = BIT(data, 5); + + n8080_state::delayed_sound_2(data); +} + + +void n8080_state::n8080_video_control_w(u8 data) +{ + m_sheriff_color_mode = (data >> 3) & 3; + m_sheriff_color_data = (data >> 0) & 7; + flip_screen_set(data & 0x20); +} + + +void n8080_state::n8080_palette(palette_device &palette) const +{ + for (int i = 0; i < 8; i++) + palette.set_pen_color(i, pal1bit(i >> 0), pal1bit(i >> 1), pal1bit(i >> 2)); +} + + +void helifire_state::helifire_palette(palette_device &palette) const +{ + n8080_palette(palette); + + for (int i = 0; i < 0x100; i++) + { + int const level = 0xff * exp(-3 * i / 255.); // capacitor discharge + + palette.set_pen_color(0x000 + 8 + i, rgb_t(0x00, 0x00, level)); // shades of blue + palette.set_pen_color(0x100 + 8 + i, rgb_t(0x00, 0xc0, level)); // shades of blue w/ green star + + palette.set_pen_color(0x200 + 8 + i, rgb_t(level, 0x00, 0x00)); // shades of red + palette.set_pen_color(0x300 + 8 + i, rgb_t(level, 0xc0, 0x00)); // shades of red w/ green star + } +} + + +void spacefev_state::start_red_cannon() +{ + m_red_cannon = true; + m_cannon_timer->adjust(attotime::from_usec(550 * 68 * 10)); +} + + +TIMER_CALLBACK_MEMBER(spacefev_state::stop_red_cannon) +{ + m_red_cannon = false; + m_cannon_timer->adjust(attotime::never); +} + + +void helifire_state::next_line() +{ + m_mv++; + + if (m_sc % 4 == 2) + { + m_mv %= 256; + } + else + { + if (flip_screen()) + m_mv %= 255; + else + m_mv %= 257; + } + + if (m_mv == 128) + { + m_sc++; + } +} + + +u32 spacefev_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + const bool mono = bool(m_video_conf->read()); + u8 mask = flip_screen() ? 0xff : 0x00; + + u8 const *pRAM = m_videoram; + u8 const *const pPROM = m_prom->base(); + + for (int y = 0; y < 256; y++) + { + u16 *const pLine = &bitmap.pix(y ^ mask); + + for (int x = 0; x < 256; x += 8) + { + u8 color = 0; + + if (m_red_screen) + color = 1; + else + { + u8 val = pPROM[x >> 3]; + + if ((x >> 3) == 0x06) + { + color = m_red_cannon ? 1 : 7; + } + + if ((x >> 3) == 0x1b) + { + static const u8 ufo_color[] = + { + 1, // red + 2, // green + 7, // white + 3, // yellow + 5, // magenta + 6, // cyan + }; + + int cycle = screen.frame_number() / 32; + + color = ufo_color[cycle % 6]; + } + + for (int n = color + 1; n < 8; n++) + { + if (~val & (1 << n)) + { + color = n; + } + } + } + + if (mono) + color = 7; // force B&W here + + for (int n = 0; n < 8; n++) + { + pLine[(x + n) ^ mask] = (pRAM[x >> 3] & (1 << n)) ? color : 0; + } + } + + pRAM += 32; + } + return 0; +} + + +u32 sheriff_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + u8 mask = flip_screen() ? 0xff : 0x00; + + u8 const *pRAM = m_videoram; + u8 const *const pPROM = m_prom->base(); + + for (int y = 0; y < 256; y++) + { + u16 *const pLine = &bitmap.pix(y ^ mask); + + for (int x = 0; x < 256; x += 8) + { + u8 color = pPROM[32 * (y >> 3) + (x >> 3)]; + + if (m_sheriff_color_mode == 1 && !(color & 8)) + color = m_sheriff_color_data ^ 7; + + if (m_sheriff_color_mode == 2) + color = m_sheriff_color_data ^ 7; + + if (m_sheriff_color_mode == 3) + color = 7; + + for (int n = 0; n < 8; n++) + { + pLine[(x + n) ^ mask] = ((pRAM[x >> 3] >> n) & 1) ? (color & 7) : 0; + } + } + + pRAM += 32; + } + return 0; +} + + +u32 helifire_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + const int SUN_BRIGHTNESS = m_pot[0]->read(); + const int SEA_BRIGHTNESS = m_pot[1]->read(); + + static const int wave[8] = { 0, 1, 2, 2, 2, 1, 0, 0 }; + + unsigned saved_mv = m_mv; + unsigned saved_sc = m_sc; + + for (int y = 0; y < 256; y++) + { + u16 *const pLine = &bitmap.pix(y); + + int level = 120 + wave[m_mv & 7]; + + // draw sky + for (int x = level; x < 256; x++) + { + pLine[x] = 0x200 + 8 + SUN_BRIGHTNESS + x - level; + } + + // draw stars + if (m_mv % 8 == 4) // upper half + { + int step = (320 * (m_mv - 0)) % sizeof m_LSFR; + + int data = + ((m_LSFR[step] & 1) << 6) | + ((m_LSFR[step] & 2) << 4) | + ((m_LSFR[step] & 4) << 2) | + ((m_LSFR[step] & 8) << 0); + + pLine[0x80 + data] |= 0x100; + } + + if (m_mv % 8 == 5) // lower half + { + int step = (320 * (m_mv - 1)) % sizeof m_LSFR; + + int data = + ((m_LSFR[step] & 1) << 6) | + ((m_LSFR[step] & 2) << 4) | + ((m_LSFR[step] & 4) << 2) | + ((m_LSFR[step] & 8) << 0); + + pLine[0x00 + data] |= 0x100; + } + + // draw sea + for (int x = 0; x < level; x++) + { + pLine[x] = 8 + SEA_BRIGHTNESS + x; + } + + // draw foreground + for (int x = 0; x < 256; x += 8) + { + int offset = 32 * y + (x >> 3); + + for (int n = 0; n < 8; n++) + { + if (flip_screen()) + { + if ((m_videoram[offset ^ 0x1fff] << n) & 0x80) + { + pLine[x + n] = m_colorram[offset ^ 0x1fff] & 7; + } + } + else + { + if ((m_videoram[offset] >> n) & 1) + { + pLine[x + n] = m_colorram[offset] & 7; + } + } + } + } + + // next line + next_line(); + } + + m_mv = saved_mv; + m_sc = saved_sc; + return 0; +} + + +void helifire_state::screen_vblank(int state) +{ + // falling edge + if (!state) + { + int n = (m_screen->frame_number() >> 1) % sizeof m_LSFR; + + int i; + + for (i = 0; i < 8; i++) + { + int R = (i & 1); + int G = (i & 2); + int B = (i & 4); + + if (m_flash) + { + if (m_LSFR[n] & 0x20) + { + G |= B; + } + + if (m_screen->frame_number() & 0x04) + { + R |= G; + } + } + + m_palette->set_pen_color(i, + R ? 255 : 0, + G ? 255 : 0, + B ? 255 : 0); + } + + for (i = 0; i < 256; i++) + { + next_line(); + } + } +} + + +void n8080_state::n8080_sound_1_w(u8 data) +{ + machine().scheduler().synchronize(timer_expired_delegate(FUNC(n8080_state::delayed_sound_1_callback), this), data); // force CPUs to sync +} + +void n8080_state::n8080_sound_2_w(u8 data) +{ + machine().scheduler().synchronize(timer_expired_delegate(FUNC(n8080_state::delayed_sound_2_callback), this), data); // force CPUs to sync +} + +TIMER_CALLBACK_MEMBER(n8080_state::delayed_sound_1_callback) +{ + delayed_sound_1(param); +} + +TIMER_CALLBACK_MEMBER(n8080_state::delayed_sound_2_callback) +{ + delayed_sound_2(param); +} + + // Memory maps void n8080_state::main_cpu_map(address_map &map) @@ -193,7 +707,7 @@ void n8080_state::main_io_map(address_map &map) // Input ports -static INPUT_PORTS_START( spacefev ) +INPUT_PORTS_START( spacefev ) PORT_START("IN0") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_2WAY @@ -249,7 +763,7 @@ static INPUT_PORTS_START( spacefev ) INPUT_PORTS_END -static INPUT_PORTS_START( highsplt ) +INPUT_PORTS_START( highsplt ) PORT_INCLUDE( spacefev ) PORT_MODIFY("IN2") @@ -278,7 +792,7 @@ static INPUT_PORTS_START( highsplt ) INPUT_PORTS_END -static INPUT_PORTS_START( spacelnc ) +INPUT_PORTS_START( spacelnc ) PORT_INCLUDE( highsplt ) PORT_MODIFY("IN2") @@ -307,7 +821,7 @@ static INPUT_PORTS_START( spacelnc ) INPUT_PORTS_END -static INPUT_PORTS_START( sheriff ) +INPUT_PORTS_START( sheriff ) PORT_START("IN0") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_RIGHT ) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_LEFT ) @@ -355,7 +869,7 @@ static INPUT_PORTS_START( sheriff ) INPUT_PORTS_END -static INPUT_PORTS_START( bandido ) +INPUT_PORTS_START( bandido ) PORT_START("IN0") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_RIGHT ) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_LEFT ) @@ -406,7 +920,7 @@ static INPUT_PORTS_START( bandido ) INPUT_PORTS_END -static INPUT_PORTS_START( westgun2 ) +INPUT_PORTS_START( westgun2 ) PORT_START("IN0") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_RIGHT ) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_LEFT ) @@ -446,7 +960,7 @@ static INPUT_PORTS_START( westgun2 ) INPUT_PORTS_END -static INPUT_PORTS_START( helifire ) +INPUT_PORTS_START( helifire ) PORT_START("IN0") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) @@ -540,10 +1054,10 @@ TIMER_DEVICE_CALLBACK_MEMBER(n8080_state::rst2_tick) void n8080_state::n8080_inte_callback(int state) { - m_inte = state; + m_inte = state != 0; } -void n8080_state::n8080_status_callback(uint8_t data) +void n8080_state::n8080_status_callback(u8 data) { if (data & i8080a_cpu_device::STATUS_INTA) { @@ -566,15 +1080,43 @@ void n8080_state::machine_reset() { m_shift_data = 0; m_shift_bits = 0; - m_inte = 0; + m_inte = false; + + delayed_sound_1(0); + delayed_sound_2(0); +} + +void spacefev_state::machine_start() +{ + n8080_state::machine_start(); + + m_cannon_timer = timer_alloc(FUNC(spacefev_state::stop_red_cannon), this); + + flip_screen_set(0); + + save_item(NAME(m_prev_snd_data)); + save_item(NAME(m_red_screen)); + save_item(NAME(m_red_cannon)); } void spacefev_state::machine_reset() { + m_prev_snd_data = 0; + n8080_state::machine_reset(); - m_red_screen = 0; - m_red_cannon = 0; + m_red_screen = false; + m_red_cannon = false; +} + +void sheriff_state::machine_start() +{ + n8080_state::machine_start(); + + flip_screen_set(0); + + save_item(NAME(m_sheriff_color_mode)); + save_item(NAME(m_sheriff_color_data)); } void sheriff_state::machine_reset() @@ -585,13 +1127,33 @@ void sheriff_state::machine_reset() m_sheriff_color_data = 0; } +void helifire_state::machine_start() +{ + n8080_state::machine_start(); + + u8 data = 0; + for (int i = 0; i < 63; i++) + { + u8 const bit = (data >> 6) ^ (data >> 7) ^ 1; + data = (data << 1) | (bit & 1); + m_LSFR[i] = data; + } + + flip_screen_set(0); + + save_item(NAME(m_mv)); + save_item(NAME(m_sc)); + save_item(NAME(m_flash)); + save_item(NAME(m_LSFR)); +} + void helifire_state::machine_reset() { n8080_state::machine_reset(); m_mv = 0; m_sc = 0; - m_flash = 0; + m_flash = false; } @@ -618,7 +1180,7 @@ void spacefev_state::spacefev(machine_config &config) TIMER(config, "rst2").configure_scanline(FUNC(spacefev_state::rst2_tick), "screen", 240, 256); /* sound hardware */ - spacefev_sound(config); + SPACEFEV_SOUND(config, m_sound, u32(0)); } void sheriff_state::sheriff(machine_config &config) @@ -642,7 +1204,7 @@ void sheriff_state::sheriff(machine_config &config) TIMER(config, "rst2").configure_scanline(FUNC(sheriff_state::rst2_tick), "screen", 240, 256); /* sound hardware */ - sheriff_sound(config); + SHERIFF_SOUND(config, m_sound, u32(0)); } void sheriff_state::westgun2(machine_config &config) @@ -676,7 +1238,7 @@ void helifire_state::helifire(machine_config &config) TIMER(config, "rst2").configure_scanline(FUNC(helifire_state::rst2_tick), "screen", 240, 256); /* sound hardware */ - helifire_sound(config); + HELIFIRE_SOUND(config, m_sound, u32(0)); } @@ -692,7 +1254,7 @@ ROM_START( spacefev ) ROM_LOAD( "h2-ro-.bin", 0x1400, 0x0400, CRC(a163e800) SHA1(e8817f3e17f099a0dc66213d2d3d3fdeb117b10e) ) // "H2??" ROM_LOAD( "i1-ro-p.bin", 0x1800, 0x0400, CRC(756b5582) SHA1(b7f3d218b7f4267ce6128624306396bcacb9b44e) ) // "I1??P" - ROM_REGION( 0x0400, "audiocpu", 0 ) + ROM_REGION( 0x0400, "soundboard:cpu", 0 ) ROM_LOAD( "ss3.ic2", 0x0000, 0x0400, CRC(95c2c1ee) SHA1(42a3a382fc7d2782052372d71f6d0e8a153e74d0) ) ROM_REGION( 0x0020, "proms", 0 ) // for color video hw @@ -709,7 +1271,7 @@ ROM_START( spacefevo ) ROM_LOAD( "h2-ro-.bin", 0x1400, 0x0400, CRC(a163e800) SHA1(e8817f3e17f099a0dc66213d2d3d3fdeb117b10e) ) // "H2??" ROM_LOAD( "i1-ro-.bin", 0x1800, 0x0400, CRC(00027be2) SHA1(551a779a2e5a6455b7a348d246731c094e0ec709) ) // "I1??" - ROM_REGION( 0x0400, "audiocpu", 0 ) + ROM_REGION( 0x0400, "soundboard:cpu", 0 ) ROM_LOAD( "ss3.ic2", 0x0000, 0x0400, CRC(95c2c1ee) SHA1(42a3a382fc7d2782052372d71f6d0e8a153e74d0) ) ROM_REGION( 0x0020, "proms", 0 ) // for color video hw @@ -726,7 +1288,7 @@ ROM_START( spacefevo2 ) ROM_LOAD( "h2-i-.bin", 0x1400, 0x0400, CRC(bddbc94f) SHA1(f90cbc3cd0f695cbb9ae03b608f4bf5a4a000c64) ) // "H2?C" ROM_LOAD( "i1-i-.bin", 0x1800, 0x0400, CRC(437786c5) SHA1(2ccdb0d48dbbfe47ae82e970ca37970602405cf6) ) // "I1?C" - ROM_REGION( 0x0400, "audiocpu", 0 ) + ROM_REGION( 0x0400, "soundboard:cpu", 0 ) ROM_LOAD( "ss3.ic2", 0x0000, 0x0400, CRC(95c2c1ee) SHA1(42a3a382fc7d2782052372d71f6d0e8a153e74d0) ) ROM_REGION( 0x0020, "proms", 0 ) // for color video hw @@ -744,7 +1306,7 @@ ROM_START( highsplt ) ROM_LOAD( "hs.i1", 0x1800, 0x0400, CRC(41e18df9) SHA1(2212c836313775e7c507a875672c0b3635825e02) ) ROM_LOAD( "i2-ha-.bin", 0x1c00, 0x0400, CRC(eff9f82d) SHA1(5004e52dfa652ceefca9ed4210c0fa8f0591dc08) ) // "I2?n" - ROM_REGION( 0x0400, "audiocpu", 0 ) + ROM_REGION( 0x0400, "soundboard:cpu", 0 ) ROM_LOAD( "ss4.bin", 0x0000, 0x0400, CRC(939e01d4) SHA1(7c9ccd24e5da03831cd0aa821da17e3b81cd8381) ) ROM_REGION( 0x0020, "proms", 0 ) @@ -762,7 +1324,7 @@ ROM_START( highsplta ) ROM_LOAD( "i1-ha-.bin", 0x1800, 0x0400, CRC(aa36b25d) SHA1(28f555aab27b206a8c6f550b6caa938cece6e204) ) // "I1?n" ROM_LOAD( "i2-ha-.bin", 0x1c00, 0x0400, CRC(eff9f82d) SHA1(5004e52dfa652ceefca9ed4210c0fa8f0591dc08) ) // "I2?n" - ROM_REGION( 0x0400, "audiocpu", 0 ) + ROM_REGION( 0x0400, "soundboard:cpu", 0 ) ROM_LOAD( "ss4.bin", 0x0000, 0x0400, CRC(939e01d4) SHA1(7c9ccd24e5da03831cd0aa821da17e3b81cd8381) ) ROM_REGION( 0x0020, "proms", 0 ) @@ -780,7 +1342,7 @@ ROM_START( highspltb ) ROM_LOAD( "i1-ha-.bin", 0x1800, 0x0400, CRC(aa36b25d) SHA1(28f555aab27b206a8c6f550b6caa938cece6e204) ) // "I1?n" ROM_LOAD( "i2-ha-.bin", 0x1c00, 0x0400, CRC(eff9f82d) SHA1(5004e52dfa652ceefca9ed4210c0fa8f0591dc08) ) // "I2?n" - ROM_REGION( 0x0400, "audiocpu", 0 ) + ROM_REGION( 0x0400, "soundboard:cpu", 0 ) ROM_LOAD( "ss4.ic2", 0x0000, 0x0400, CRC(ce95dc5f) SHA1(20f7b8c565c408439dcfae240b7d1aa42c29651b) ) ROM_REGION( 0x0020, "proms", 0 ) @@ -798,7 +1360,7 @@ ROM_START( spacelnc ) ROM_LOAD( "sl.i1", 0x1800, 0x0400, CRC(d30007a3) SHA1(9e5905df8f7822385daef159a07f0e8257cb862a) ) ROM_LOAD( "sl.i2", 0x1c00, 0x0400, CRC(640ffd2f) SHA1(65c21396c39dc99ec263f66f400a8e4c7712b20a) ) - ROM_REGION( 0x0400, "audiocpu", 0 ) + ROM_REGION( 0x0400, "soundboard:cpu", 0 ) ROM_LOAD( "sl.snd", 0x0000, 0x0400, CRC(8e1ff929) SHA1(5c7da97b05fb8fff242158978199f5d35b234426) ) ROM_REGION( 0x0020, "proms", 0 ) @@ -817,7 +1379,7 @@ ROM_START( sheriff ) ROM_LOAD( "sh.i2", 0x1c00, 0x0400, CRC(5c5f3f86) SHA1(25c64ccb7d0e136f67d6e1da7927ae6d89e0ceb9) ) ROM_LOAD( "sh.j1", 0x2000, 0x0400, CRC(0aa8b79a) SHA1(aed139e8c8ba912823c57fe4cc7231b2d638f479) ) - ROM_REGION( 0x0400, "audiocpu", 0 ) + ROM_REGION( 0x0400, "soundboard:cpu", 0 ) ROM_LOAD( "sh.snd", 0x0000, 0x0400, CRC(75731745) SHA1(538a63c9c60f1886fca4caf3eb1e0bada2d3f162) ) ROM_REGION( 0x0400, "proms", 0 ) @@ -837,7 +1399,7 @@ ROM_START( bandido ) ROM_LOAD( "sh.j1", 0x2000, 0x0400, CRC(0aa8b79a) SHA1(aed139e8c8ba912823c57fe4cc7231b2d638f479) ) ROM_LOAD( "sh-a.j2", 0x2400, 0x0400, CRC(a10b848a) SHA1(c045f1f6a11cbf49a1bae06c701b659d587292a3) ) - ROM_REGION( 0x0400, "audiocpu", 0 ) + ROM_REGION( 0x0400, "soundboard:cpu", 0 ) ROM_LOAD( "sh.snd", 0x0000, 0x0400, CRC(75731745) SHA1(538a63c9c60f1886fca4caf3eb1e0bada2d3f162) ) ROM_REGION( 0x0400, "proms", 0 ) @@ -852,7 +1414,7 @@ ROM_START( westgun2 ) ROM_LOAD( "rf04.ic33", 0x1800, 0x0800, CRC(60b71f0d) SHA1(10650426972afb0ccb964548a52879ed3f0b316a) ) ROM_LOAD( "rf05.ic32", 0x2000, 0x0800, CRC(81e650fb) SHA1(e600567125294d1411fcad3a015edb98cee36ff8) ) - ROM_REGION( 0x0800, "audiocpu", 0 ) + ROM_REGION( 0x0800, "soundboard:cpu", 0 ) ROM_LOAD( "rf06.ic35", 0x0000, 0x0800, CRC(4eafe957) SHA1(78e03402219c0ad814f63ae507eadc636d95f755) ) ROM_REGION( 0x0400, "proms", 0 ) @@ -872,7 +1434,7 @@ ROM_START( helifire ) ROM_LOAD( "tub_j1_b", 0x2000, 0x0400, CRC(98ef24db) SHA1(70ad8dd6e1e8f4bf4ce431737ca1856eecc03d53) ) ROM_LOAD( "tub_j2_b", 0x2400, 0x0400, CRC(5e2b5877) SHA1(f7c747e8a1d9fe2dda71ee6304636cf3cdf727a7) ) - ROM_REGION( 0x0400, "audiocpu", 0 ) + ROM_REGION( 0x0400, "soundboard:cpu", 0 ) ROM_LOAD( "tub-e_ic5-a", 0x0000, 0x0400, CRC(9d77a31f) SHA1(36db9b5087b6661de88042854874bc247c92d985) ) ROM_END @@ -889,10 +1451,12 @@ ROM_START( helifirea ) ROM_LOAD( "hf.j1", 0x2000, 0x0400, CRC(98ef24db) SHA1(70ad8dd6e1e8f4bf4ce431737ca1856eecc03d53) ) ROM_LOAD( "hf.j2", 0x2400, 0x0400, CRC(5e2b5877) SHA1(f7c747e8a1d9fe2dda71ee6304636cf3cdf727a7) ) - ROM_REGION( 0x0400, "audiocpu", 0 ) + ROM_REGION( 0x0400, "soundboard:cpu", 0 ) ROM_LOAD( "hf.snd", 0x0000, 0x0400, CRC(9d77a31f) SHA1(36db9b5087b6661de88042854874bc247c92d985) ) ROM_END +} // anonymous namespace + // YEAR, NAME, PARENT, MACHINE, INPUT, CLASS, INIT, MONITOR, COMPANY, FULLNAME, FLAGS GAME( 1979, spacefev, 0, spacefev, spacefev, spacefev_state, empty_init, ROT270, "Nintendo", "Space Fever (new version)", MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/nintendo/n8080.h b/src/mame/nintendo/n8080.h deleted file mode 100644 index 650a71df3a6..00000000000 --- a/src/mame/nintendo/n8080.h +++ /dev/null @@ -1,209 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Pierpaolo Prazzoli -#ifndef MAME_NINTENDO_N8080_H -#define MAME_NINTENDO_N8080_H - -#pragma once - -#include "cpu/i8085/i8085.h" -#include "cpu/mcs48/mcs48.h" -#include "machine/timer.h" -#include "sound/dac.h" -#include "sound/sn76477.h" -#include "emupal.h" -#include "screen.h" - -class n8080_state : public driver_device -{ -public: - n8080_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_videoram(*this, "videoram"), - m_prom(*this, "proms"), - m_maincpu(*this, "maincpu"), - m_audiocpu(*this, "audiocpu"), - m_n8080_dac(*this, "n8080_dac"), - m_sn(*this, "snsnd"), - m_screen(*this, "screen"), - m_palette(*this, "palette") - { } - -protected: - virtual void machine_start() override; - virtual void machine_reset() override; - - virtual void sound_pins_changed(); - virtual void update_SN76477_status(); - virtual void delayed_sound_1(int data); - virtual void delayed_sound_2(int data); - - /* memory pointers */ - required_shared_ptr m_videoram; - optional_memory_region m_prom; - - /* video-related */ - int m_sheriff_color_mode; - int m_sheriff_color_data; - - /* sound-related */ - emu_timer* m_sound_timer[3]; - uint16_t m_prev_sound_pins; - uint16_t m_curr_sound_pins; - int m_mono_flop[3]; - uint8_t m_prev_snd_data; - - /* other */ - unsigned m_shift_data; - unsigned m_shift_bits; - int m_inte; - - /* devices */ - required_device m_maincpu; - required_device m_audiocpu; - optional_device m_n8080_dac; - optional_device m_sn; - required_device m_screen; - required_device m_palette; - - void n8080_shift_bits_w(uint8_t data); - void n8080_shift_data_w(uint8_t data); - uint8_t n8080_shift_r(); - void n8080_video_control_w(uint8_t data); - void n8080_sound_1_w(uint8_t data); - void n8080_sound_2_w(uint8_t data); - uint8_t n8080_8035_p1_r(); - int n8080_8035_t0_r(); - int n8080_8035_t1_r(); - void n8080_dac_w(uint8_t data); - void n8080_inte_callback(int state); - void n8080_status_callback(uint8_t data); - void n8080_palette(palette_device &palette) const; - TIMER_DEVICE_CALLBACK_MEMBER(rst1_tick); - TIMER_DEVICE_CALLBACK_MEMBER(rst2_tick); - void start_mono_flop( int n, const attotime &expire ); - void stop_mono_flop( int n ); - TIMER_CALLBACK_MEMBER( stop_mono_flop_callback ); - TIMER_CALLBACK_MEMBER( delayed_sound_1_callback ); - TIMER_CALLBACK_MEMBER( delayed_sound_2_callback ); - - void main_cpu_map(address_map &map); - void main_io_map(address_map &map); - void n8080_sound_cpu_map(address_map &map); -}; - -class spacefev_state : public n8080_state -{ -public: - spacefev_state(const machine_config &mconfig, device_type type, const char *tag) : - n8080_state(mconfig, type, tag), - m_video_conf(*this, "VIDEO") - { } - - void spacefev(machine_config &config); - -protected: - virtual void machine_reset() override; - virtual void sound_start() override; - virtual void sound_reset() override; - virtual void video_start() override; - - virtual void sound_pins_changed() override; - virtual void update_SN76477_status() override; - virtual void delayed_sound_1(int data) override; - virtual void delayed_sound_2(int data) override; - -private: - required_ioport m_video_conf; - - void spacefev_sound(machine_config &config); - - TIMER_DEVICE_CALLBACK_MEMBER(vco_voltage_timer); - - TIMER_CALLBACK_MEMBER(stop_red_cannon); - void start_red_cannon(); - uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - - emu_timer* m_cannon_timer; - int m_red_screen; - int m_red_cannon; -}; - -class sheriff_state : public n8080_state -{ -public: - sheriff_state(const machine_config &mconfig, device_type type, const char *tag) : - n8080_state(mconfig, type, tag) - { } - - void sheriff(machine_config &config); - void westgun2(machine_config &config); - -protected: - virtual void machine_reset() override; - virtual void sound_start() override; - virtual void sound_reset() override; - virtual void video_start() override; - - virtual void sound_pins_changed() override; - virtual void update_SN76477_status() override; - -private: - void sheriff_sound(machine_config &config); - - uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); -}; - -class helifire_state : public n8080_state -{ -public: - helifire_state(const machine_config &mconfig, device_type type, const char *tag) : - n8080_state(mconfig, type, tag), - m_dac(*this, "helifire_dac"), - m_colorram(*this, "colorram"), - m_pot(*this, "POT%u", 0) - { } - - void helifire(machine_config &config); - -protected: - virtual void machine_reset() override; - virtual void sound_start() override; - virtual void sound_reset() override; - virtual void video_start() override; - - virtual void sound_pins_changed() override; - virtual void delayed_sound_2(int data) override; - -private: - void helifire_sound(machine_config &config); - - TIMER_DEVICE_CALLBACK_MEMBER(dac_volume_timer); - int helifire_8035_t0_r(); - int helifire_8035_t1_r(); - uint8_t helifire_8035_external_ram_r(); - uint8_t helifire_8035_p2_r(); - void sound_ctrl_w(uint8_t data); - void sound_io_map(address_map &map); - - void helifire_palette(palette_device &palette) const; - void next_line(); - void screen_vblank(int state); - uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - void main_cpu_map(address_map &map); - - required_device m_dac; - required_shared_ptr m_colorram; - required_ioport_array<2> m_pot; - - int m_dac_phase = 0; - double m_dac_volume = 0; - double m_dac_timing = 0; - - int m_flash = 0; - uint8_t m_LSFR[63]; - unsigned m_mv = 0; - unsigned m_sc = 0; // IC56 -}; - - -#endif // MAME_NINTENDO_N8080_H diff --git a/src/mame/nintendo/n8080_a.cpp b/src/mame/nintendo/n8080_a.cpp index a15b776eb2b..abb0b55d1b8 100644 --- a/src/mame/nintendo/n8080_a.cpp +++ b/src/mame/nintendo/n8080_a.cpp @@ -7,539 +7,513 @@ ***************************************************************************/ #include "emu.h" -#include "n8080.h" +#include "n8080_a.h" + +#include "machine/timer.h" +#include "sound/dac.h" +#include "sound/sn76477.h" + #include "speaker.h" +#include -constexpr double ATTACK_RATE = 10e-6 * 500; -constexpr double DECAY_RATE = 10e-6 * 16000; +namespace { -void spacefev_state::update_SN76477_status() +template +class n8080_csg_sound_device_base : public n8080_sound_device_base { - double dblR0 = RES_M(1.0); - double dblR1 = RES_M(1.5); - - if (!m_mono_flop[0]) - { - dblR0 = 1 / (1 / RES_K(150) + 1 / dblR0); /* ? */ - } - if (!m_mono_flop[1]) +protected: + n8080_csg_sound_device_base( + machine_config const &mconfig, + device_type type, + char const *tag, + device_t *parent, + u32 clock) : + n8080_sound_device_base(mconfig, type, tag, parent, clock), + m_dac(*this, "dac"), + m_sn(*this, "snsnd") { - dblR1 = 1 / (1 / RES_K(620) + 1 / dblR1); /* ? */ } - m_sn->decay_res_w(dblR0); - - m_sn->vco_res_w(dblR1); + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; - m_sn->enable_w( - !m_mono_flop[0] && - !m_mono_flop[1] && - !m_mono_flop[2]); + bool mono_flop(unsigned n) const { return m_mono_flop[n]; } + attotime mono_elapsed(unsigned n) { return m_mono_timer[n]->elapsed(); } + void start_mono_flop(unsigned n, attotime const &expiry); + void stop_mono_flop(unsigned n); - m_sn->vco_w(m_mono_flop[1]); + required_device m_dac; + required_device m_sn; - m_sn->mixer_b_w(m_mono_flop[0]); -} +private: + u8 p1_r() + { + return bitswap<8>(current_pins(), 1, 2, 3, 5, 8, 9, 10, 11); + } + int t0_r() + { + return BIT(current_pins(), 7); + } -void sheriff_state::update_SN76477_status() -{ - if (m_mono_flop[1]) + int t1_r() { - m_sn->vco_voltage_w(5); + return BIT(current_pins(), 12); } - else + + void dac_w(u8 data) { - m_sn->vco_voltage_w(0); + m_dac->write(BIT(data, 7)); } - m_sn->enable_w( - !m_mono_flop[0] && - !m_mono_flop[1]); + TIMER_CALLBACK_MEMBER(stop_mono_flop_callback) + { + stop_mono_flop(param); + } - m_sn->vco_w(m_mono_flop[0]); + virtual void update_sn_status() = 0; - m_sn->mixer_b_w(!m_mono_flop[0]); -} + emu_timer *m_mono_timer[Monostables]; + bool m_mono_flop[Monostables]; +}; -void n8080_state::update_SN76477_status() +template +void n8080_csg_sound_device_base::device_add_mconfig(machine_config &config) { -} + n8080_sound_device_base::device_add_mconfig(config); + m_cpu->t0_in_cb().set(FUNC(n8080_csg_sound_device_base::t0_r)); + m_cpu->t1_in_cb().set(FUNC(n8080_csg_sound_device_base::t1_r)); + m_cpu->p1_in_cb().set(FUNC(n8080_csg_sound_device_base::p1_r)); + m_cpu->p2_out_cb().set(FUNC(n8080_csg_sound_device_base::dac_w)); -void n8080_state::start_mono_flop( int n, const attotime &expire ) -{ - m_mono_flop[n] = 1; + SPEAKER(config, "speaker").front_center(); - update_SN76477_status(); + DAC_1BIT(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.15); - m_sound_timer[n]->adjust(expire, n); + SN76477(config, m_sn); + m_sn->set_attack_params(CAP_U(1.0), RES_K(20)); + m_sn->set_amp_res(RES_K(150)); + m_sn->set_feedback_res(RES_K(47)); + m_sn->set_vco_params(0, CAP_N(1), RES_M(1.5)); + m_sn->set_pitch_voltage(0); + m_sn->set_vco_mode(0); + m_sn->set_mixer_params(0, 0, 0); + m_sn->set_envelope_params(1, 0); + m_sn->set_enable(1); + m_sn->add_route(ALL_OUTPUTS, "speaker", 0.35); } - -void n8080_state::stop_mono_flop( int n ) +template +void n8080_csg_sound_device_base::device_start() { - m_mono_flop[n] = 0; + n8080_sound_device_base::device_start(); - update_SN76477_status(); + for (unsigned i = 0; Monostables > i; ++i) + m_mono_timer[i] = timer_alloc(FUNC(n8080_csg_sound_device_base::stop_mono_flop_callback), this); - m_sound_timer[n]->adjust(attotime::never, n); + save_item(NAME(m_mono_flop)); } - -TIMER_CALLBACK_MEMBER( n8080_state::stop_mono_flop_callback ) +template +void n8080_csg_sound_device_base::device_reset() { - stop_mono_flop(param); + n8080_sound_device_base::device_reset(); + + for (unsigned i = 0; Monostables > i; ++i) + m_mono_flop[i] = false; } -void spacefev_state::sound_pins_changed() +template +void n8080_csg_sound_device_base::start_mono_flop(unsigned n, attotime const &expiry) { - uint16_t changes = ~m_curr_sound_pins & m_prev_sound_pins; + m_mono_flop[n] = true; - if (changes & (1 << 0x3)) - { - stop_mono_flop(1); - } - if (changes & ((1 << 0x3) | (1 << 0x6))) - { - stop_mono_flop(2); - } - if (changes & (1 << 0x3)) - { - start_mono_flop(0, attotime::from_usec(550 * 36 * 100)); - } - if (changes & (1 << 0x6)) - { - start_mono_flop(1, attotime::from_usec(550 * 22 * 33)); - } - if (changes & (1 << 0x4)) - { - start_mono_flop(2, attotime::from_usec(550 * 22 * 33)); - } + update_sn_status(); - bool irq_active = (~m_curr_sound_pins & ((1 << 0x2) | (1 << 0x3) | (1 << 0x5))) != 0; - m_audiocpu->set_input_line(INPUT_LINE_IRQ0, irq_active ? ASSERT_LINE : CLEAR_LINE); + m_mono_timer[n]->adjust(expiry, n); } - -void sheriff_state::sound_pins_changed() +template +void n8080_csg_sound_device_base::stop_mono_flop(unsigned n) { - uint16_t changes = ~m_curr_sound_pins & m_prev_sound_pins; + m_mono_flop[n] = false; - if (changes & (1 << 0x6)) - { - stop_mono_flop(1); - } - if (changes & (1 << 0x6)) - { - start_mono_flop(0, attotime::from_usec(550 * 33 * 33)); - } - if (changes & (1 << 0x4)) - { - start_mono_flop(1, attotime::from_usec(550 * 33 * 33)); - } + update_sn_status(); - bool irq_active = (~m_curr_sound_pins & ((1 << 0x2) | (1 << 0x3) | (1 << 0x5))) != 0; - m_audiocpu->set_input_line(INPUT_LINE_IRQ0, irq_active ? ASSERT_LINE : CLEAR_LINE); + m_mono_timer[n]->adjust(attotime::never, n); } -void helifire_state::sound_pins_changed() + +class spacefev_sound_device : public n8080_csg_sound_device_base<3> { - //uint16_t changes = ~m_curr_sound_pins & m_prev_sound_pins; +public: + spacefev_sound_device( + machine_config const &mconfig, + char const *tag, + device_t *parent, + u32 clock) : + n8080_csg_sound_device_base<3>(mconfig, SPACEFEV_SOUND, tag, parent, clock) + { + } - /* ((m_curr_sound_pins >> 0xa) & 1) not emulated */ - /* ((m_curr_sound_pins >> 0xb) & 1) not emulated */ - /* ((m_curr_sound_pins >> 0xc) & 1) not emulated */ +protected: + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; - bool irq_active = (~m_curr_sound_pins & (1 << 6)) != 0; - m_audiocpu->set_input_line(INPUT_LINE_IRQ0, irq_active ? ASSERT_LINE : CLEAR_LINE); -} +private: + virtual void update_sn_status() override; + virtual void pins_changed(u16 curr, u16 prev) override; + + TIMER_DEVICE_CALLBACK_MEMBER(vco_voltage_timer); +}; -void n8080_state::sound_pins_changed() +void spacefev_sound_device::device_add_mconfig(machine_config &config) { + n8080_csg_sound_device_base<3>::device_add_mconfig(config); + + m_sn->set_noise_params(RES_K(36), RES_K(150), CAP_N(1)); + m_sn->set_decay_res(RES_M(1)); + m_sn->set_slf_params(CAP_N(47), RES_M(1)); + m_sn->set_oneshot_params(CAP_N(47), RES_K(820)); + + TIMER(config, "vco_timer").configure_periodic(FUNC(spacefev_sound_device::vco_voltage_timer), attotime::from_hz(1000)); } -void n8080_state::delayed_sound_1(int data) +void spacefev_sound_device::update_sn_status() { - m_curr_sound_pins &= ~( - (1 << 0x7) | - (1 << 0x5) | - (1 << 0x6) | - (1 << 0x3) | - (1 << 0x4) | - (1 << 0x1)); - - if (~data & 0x01) m_curr_sound_pins |= 1 << 0x7; - if (~data & 0x02) m_curr_sound_pins |= 1 << 0x5; /* pulse */ - if (~data & 0x04) m_curr_sound_pins |= 1 << 0x6; /* pulse */ - if (~data & 0x08) m_curr_sound_pins |= 1 << 0x3; /* pulse (except in Helifire) */ - if (~data & 0x10) m_curr_sound_pins |= 1 << 0x4; /* pulse (except in Helifire) */ - if (~data & 0x20) m_curr_sound_pins |= 1 << 0x1; - - sound_pins_changed(); - - m_prev_sound_pins = m_curr_sound_pins; - m_prev_snd_data = data; + double dblR0 = RES_M(1.0); + if (!mono_flop(0)) + dblR0 = 1.0 / (1.0 / RES_K(150) + 1.0 / dblR0); // ? + + double dblR1 = RES_M(1.5); + if (!mono_flop(1)) + dblR1 = 1.0 / (1.0 / RES_K(620) + 1.0 / dblR1); // ? + + m_sn->decay_res_w(dblR0); + m_sn->vco_res_w(dblR1); + m_sn->enable_w((!mono_flop(0) && !mono_flop(1) && !mono_flop(2)) ? 1 : 0); + m_sn->vco_w(mono_flop(1) ? 1 : 0); + m_sn->mixer_b_w(mono_flop(0) ? 1 : 0); } -void spacefev_state::delayed_sound_1(int data) +void spacefev_sound_device::pins_changed(u16 curr, u16 prev) { - if (data & ~m_prev_snd_data & 0x10) - start_red_cannon(); + u16 const changes = ~curr & prev; - m_red_screen = data & 0x08; + if (BIT(changes, 3)) + stop_mono_flop(1); - n8080_state::delayed_sound_1(data); -} + if (BIT(changes, 3) || BIT(changes, 6)) + stop_mono_flop(2); + if (BIT(changes, 3)) + start_mono_flop(0, attotime::from_usec(550 * 36 * 100)); -TIMER_CALLBACK_MEMBER( n8080_state::delayed_sound_1_callback ) -{ - delayed_sound_1(param); -} + if (BIT(changes, 6)) + start_mono_flop(1, attotime::from_usec(550 * 22 * 33)); + if (BIT(changes, 4)) + start_mono_flop(2, attotime::from_usec(550 * 22 * 33)); -void n8080_state::delayed_sound_2(int data) -{ - m_curr_sound_pins &= ~( - (1 << 0x8) | - (1 << 0x9) | - (1 << 0xa) | - (1 << 0xb) | - (1 << 0x2) | - (1 << 0xc)); - - if (~data & 0x01) m_curr_sound_pins |= 1 << 0x8; - if (~data & 0x02) m_curr_sound_pins |= 1 << 0x9; - if (~data & 0x04) m_curr_sound_pins |= 1 << 0xa; - if (~data & 0x08) m_curr_sound_pins |= 1 << 0xb; - if (~data & 0x10) m_curr_sound_pins |= 1 << 0x2; /* pulse */ - if (~data & 0x20) m_curr_sound_pins |= 1 << 0xc; - - sound_pins_changed(); - - m_prev_sound_pins = m_curr_sound_pins; + bool const irq_active = BIT(~curr, 2) || BIT(~curr, 3) || BIT(~curr, 5); + m_cpu->set_input_line(INPUT_LINE_IRQ0, irq_active ? ASSERT_LINE : CLEAR_LINE); } -void spacefev_state::delayed_sound_2(int data) + +TIMER_DEVICE_CALLBACK_MEMBER(spacefev_sound_device::vco_voltage_timer) { - flip_screen_set(data & 0x20); + double voltage = 0; + if (mono_flop(2)) + voltage = 5.0 * (1.0 - exp(-mono_elapsed(2).as_double() / 0.22)); - n8080_state::delayed_sound_2(data); + m_sn->vco_voltage_w(voltage); } -void helifire_state::delayed_sound_2(int data) + + +class sheriff_sound_device : public n8080_csg_sound_device_base<2> { - m_flash = data & 0x20; +public: + sheriff_sound_device( + machine_config const &mconfig, + char const *tag, + device_t *parent, + u32 clock) : + n8080_csg_sound_device_base<2>(mconfig, SHERIFF_SOUND, tag, parent, clock) + { + } - n8080_state::delayed_sound_2(data); -} +protected: + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; +private: + virtual void update_sn_status() override; + virtual void pins_changed(u16 curr, u16 prev) override; +}; -TIMER_CALLBACK_MEMBER( n8080_state::delayed_sound_2_callback ) + +void sheriff_sound_device::device_add_mconfig(machine_config &config) { - delayed_sound_2(param); + n8080_csg_sound_device_base<2>::device_add_mconfig(config); + + m_sn->set_noise_params(RES_K(36), RES_K(100), CAP_N(1)); + m_sn->set_decay_res(RES_K(620)); + m_sn->set_slf_params(CAP_N(47), RES_M(1.5)); + m_sn->set_oneshot_params(CAP_N(47), RES_K(560)); } -void n8080_state::n8080_sound_1_w(uint8_t data) +void sheriff_sound_device::update_sn_status() { - machine().scheduler().synchronize(timer_expired_delegate(FUNC(n8080_state::delayed_sound_1_callback), this), data); /* force CPUs to sync */ + m_sn->vco_voltage_w(mono_flop(1) ? 5 : 0); + m_sn->enable_w((!mono_flop(0) && !mono_flop(1)) ? 1 : 0); + m_sn->vco_w(mono_flop(0) ? 1 : 0); + m_sn->mixer_b_w(mono_flop(0) ? 0 : 1); } -void n8080_state::n8080_sound_2_w(uint8_t data) +void sheriff_sound_device::pins_changed(u16 curr, u16 prev) { - machine().scheduler().synchronize(timer_expired_delegate(FUNC(n8080_state::delayed_sound_2_callback), this), data); /* force CPUs to sync */ -} + u16 const changes = ~curr & prev; + if (BIT(changes, 6)) + stop_mono_flop(1); -uint8_t n8080_state::n8080_8035_p1_r() -{ - uint8_t val = 0; - - if ((m_curr_sound_pins >> 0xb) & 1) val |= 0x01; - if ((m_curr_sound_pins >> 0xa) & 1) val |= 0x02; - if ((m_curr_sound_pins >> 0x9) & 1) val |= 0x04; - if ((m_curr_sound_pins >> 0x8) & 1) val |= 0x08; - if ((m_curr_sound_pins >> 0x5) & 1) val |= 0x10; - if ((m_curr_sound_pins >> 0x3) & 1) val |= 0x20; - if ((m_curr_sound_pins >> 0x2) & 1) val |= 0x40; - if ((m_curr_sound_pins >> 0x1) & 1) val |= 0x80; - - return val; -} + if (BIT(changes, 6)) + start_mono_flop(0, attotime::from_usec(550 * 33 * 33)); + if (BIT(changes, 4)) + start_mono_flop(1, attotime::from_usec(550 * 33 * 33)); -int n8080_state::n8080_8035_t0_r() -{ - return (m_curr_sound_pins >> 0x7) & 1; + bool const irq_active = BIT(~curr, 2) || BIT(~curr, 3) || BIT(~curr, 5); + m_cpu->set_input_line(INPUT_LINE_IRQ0, irq_active ? ASSERT_LINE : CLEAR_LINE); } -int n8080_state::n8080_8035_t1_r() -{ - return (m_curr_sound_pins >> 0xc) & 1; -} -int helifire_state::helifire_8035_t0_r() +class helifire_sound_device : public n8080_sound_device_base { - return (m_curr_sound_pins >> 0x3) & 1; -} +public: + helifire_sound_device(machine_config const &mconfig, + char const *tag, + device_t *parent, + u32 clock) : + n8080_sound_device_base(mconfig, HELIFIRE_SOUND, tag, parent, clock), + m_dac(*this, "dac"), + m_dac_volume(1.0), + m_dac_timing(0.0), + m_dac_phase(false) + { + } -int helifire_state::helifire_8035_t1_r() -{ - return (m_curr_sound_pins >> 0x4) & 1; -} +protected: + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; +private: + static inline constexpr double ATTACK_RATE = 10e-6 * 500; + static inline constexpr double DECAY_RATE = 10e-6 * 16'000; -uint8_t helifire_state::helifire_8035_external_ram_r() -{ - uint8_t val = 0; + u8 ram_r() + { + return bitswap<4>(current_pins(), 1, 9, 8, 7); + } - if ((m_curr_sound_pins >> 0x7) & 1) val |= 0x01; - if ((m_curr_sound_pins >> 0x8) & 1) val |= 0x02; - if ((m_curr_sound_pins >> 0x9) & 1) val |= 0x04; - if ((m_curr_sound_pins >> 0x1) & 1) val |= 0x08; + u8 p2_r() + { + return BIT(current_pins(), 12) ? 0x10 : 0x00; // not used + } - return val; -} + int t0_r() + { + return BIT(current_pins(), 3); + } + int t1_r() + { + return BIT(current_pins(), 4); + } + + void ctrl_w(u8 data); + + virtual void pins_changed(u16 curr, u16 prev) override; + + TIMER_DEVICE_CALLBACK_MEMBER(volume_timer); + + void io_map(address_map &map) ATTR_COLD; + + required_device m_dac; -uint8_t helifire_state::helifire_8035_p2_r() + double m_dac_volume; + double m_dac_timing; + bool m_dac_phase; +}; + + +void helifire_sound_device::device_add_mconfig(machine_config &config) { - return ((m_curr_sound_pins >> 0xc) & 1) ? 0x10 : 0x00; /* not used */ + n8080_sound_device_base::device_add_mconfig(config); + + m_cpu->set_addrmap(AS_IO, &helifire_sound_device::io_map); + m_cpu->t0_in_cb().set(FUNC(helifire_sound_device::t0_r)); + m_cpu->t1_in_cb().set(FUNC(helifire_sound_device::t1_r)); + m_cpu->p2_in_cb().set(FUNC(helifire_sound_device::p2_r)); + m_cpu->p1_out_cb().set(m_dac, FUNC(dac_byte_interface::data_w)); + m_cpu->p2_out_cb().set(FUNC(helifire_sound_device::ctrl_w)); + + TIMER(config, "volume_timer").configure_periodic(FUNC(helifire_sound_device::volume_timer), attotime::from_hz(1000)); + + SPEAKER(config, "speaker").front_center(); + + DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.15); // unknown DAC } +void helifire_sound_device::device_start() +{ + n8080_sound_device_base::device_start(); + + save_item(NAME(m_dac_volume)); + save_item(NAME(m_dac_timing)); + save_item(NAME(m_dac_phase)); +} -void n8080_state::n8080_dac_w(uint8_t data) +void helifire_sound_device::device_reset() { - m_n8080_dac->write(BIT(data, 7)); + n8080_sound_device_base::device_reset(); + + m_dac_volume = 1.0; + m_dac_timing = 0.0; + m_dac_phase = false; } -void helifire_state::sound_ctrl_w(uint8_t data) +void helifire_sound_device::ctrl_w(u8 data) { - m_dac_phase = data & 0x80; + m_dac_phase = BIT(data, 7); - /* data & 0x40 not emulated */ - /* data & 0x20 not emulated */ + // data bit 6 not emulated + // data bit 5 not emulated + m_dac_timing = machine().time().as_double(); if (m_dac_phase) - { - m_dac_timing = ATTACK_RATE * log(1 - m_dac_volume); - } + m_dac_timing += ATTACK_RATE * log(1 - m_dac_volume); else - { - m_dac_timing = DECAY_RATE * log(m_dac_volume); - } - - m_dac_timing += machine().time().as_double(); + m_dac_timing += DECAY_RATE * log(m_dac_volume); } -TIMER_DEVICE_CALLBACK_MEMBER(spacefev_state::vco_voltage_timer) +void helifire_sound_device::pins_changed(u16 curr, u16 prev) { - double voltage = 0; + // bit 10 not emulated + // bit 11 not emulated + // bit 12 not emulated - if (m_mono_flop[2]) - { - voltage = 5 * (1 - exp(- m_sound_timer[2]->elapsed().as_double() / 0.22)); - } - - m_sn->vco_voltage_w(voltage); + bool const irq_active = BIT(~curr, 6); + m_cpu->set_input_line(INPUT_LINE_IRQ0, irq_active ? ASSERT_LINE : CLEAR_LINE); } -TIMER_DEVICE_CALLBACK_MEMBER(helifire_state::dac_volume_timer) +TIMER_DEVICE_CALLBACK_MEMBER(helifire_sound_device::volume_timer) { - double t = m_dac_timing - machine().time().as_double(); + double const t = m_dac_timing - machine().time().as_double(); if (m_dac_phase) - { - m_dac_volume = 1 - exp(t / ATTACK_RATE); - } + m_dac_volume = 1.0 - exp(t / ATTACK_RATE); else - { m_dac_volume = exp(t / DECAY_RATE); - } m_dac->set_output_gain(ALL_OUTPUTS, m_dac_volume); } -void spacefev_state::sound_start() +void helifire_sound_device::io_map(address_map &map) { - m_sound_timer[0] = timer_alloc(FUNC(spacefev_state::stop_mono_flop_callback), this); - m_sound_timer[1] = timer_alloc(FUNC(spacefev_state::stop_mono_flop_callback), this); - m_sound_timer[2] = timer_alloc(FUNC(spacefev_state::stop_mono_flop_callback), this); - - save_item(NAME(m_prev_snd_data)); - save_item(NAME(m_prev_sound_pins)); - save_item(NAME(m_curr_sound_pins)); - save_item(NAME(m_mono_flop)); + map(0x00, 0x00).mirror(0x7f).r(FUNC(helifire_sound_device::ram_r)); } -void spacefev_state::sound_reset() -{ - m_mono_flop[0] = 0; - m_mono_flop[1] = 0; - m_mono_flop[2] = 0; - m_prev_snd_data = 0; - m_prev_sound_pins = 0; - m_curr_sound_pins = 0; - - delayed_sound_1(0); - delayed_sound_2(0); -} +} // anonymous namespace + -void sheriff_state::sound_start() +void n8080_sound_device_base::sound1_w(u8 data) { - m_sound_timer[0] = timer_alloc(FUNC(sheriff_state::stop_mono_flop_callback), this); - m_sound_timer[1] = timer_alloc(FUNC(sheriff_state::stop_mono_flop_callback), this); + u16 const prev = m_curr_pins; - save_item(NAME(m_prev_snd_data)); - save_item(NAME(m_prev_sound_pins)); - save_item(NAME(m_curr_sound_pins)); - save_item(NAME(m_mono_flop)); + m_curr_pins &= ~((1 << 7) | (1 << 5) | (1 << 6) | (1 << 3) | (1 << 4) | (1 << 1)); + + if (BIT(~data, 0)) m_curr_pins |= 1 << 7; + if (BIT(~data, 1)) m_curr_pins |= 1 << 5; // pulse + if (BIT(~data, 2)) m_curr_pins |= 1 << 6; // pulse + if (BIT(~data, 3)) m_curr_pins |= 1 << 3; // pulse (except in HeliFire) + if (BIT(~data, 4)) m_curr_pins |= 1 << 4; // pulse (except in HeliFire) + if (BIT(~data, 5)) m_curr_pins |= 1 << 1; + + pins_changed(m_curr_pins, prev); } -void sheriff_state::sound_reset() +void n8080_sound_device_base::sound2_w(u8 data) { - m_mono_flop[0] = 0; - m_mono_flop[1] = 0; - m_prev_snd_data = 0; - m_prev_sound_pins = 0; - m_curr_sound_pins = 0; - - delayed_sound_1(0); - delayed_sound_2(0); -} + u16 const prev = m_curr_pins; + m_curr_pins &= ~((1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 2) | (1 << 12)); -void helifire_state::sound_start() -{ - save_item(NAME(m_prev_snd_data)); - save_item(NAME(m_prev_sound_pins)); - save_item(NAME(m_curr_sound_pins)); - save_item(NAME(m_dac_volume)); - save_item(NAME(m_dac_timing)); - save_item(NAME(m_dac_phase)); -} + if (BIT(~data, 0)) m_curr_pins |= 1 << 8; + if (BIT(~data, 1)) m_curr_pins |= 1 << 9; + if (BIT(~data, 2)) m_curr_pins |= 1 << 10; + if (BIT(~data, 3)) m_curr_pins |= 1 << 11; + if (BIT(~data, 4)) m_curr_pins |= 1 << 2; // pulse + if (BIT(~data, 5)) m_curr_pins |= 1 << 12; -void helifire_state::sound_reset() -{ - m_dac_volume = 1; - m_dac_timing = 0; - m_dac_phase = 0; - m_prev_snd_data = 0; - m_prev_sound_pins = 0; - m_curr_sound_pins = 0; - - delayed_sound_1(0); - delayed_sound_2(0); + pins_changed(m_curr_pins, prev); } -void n8080_state::n8080_sound_cpu_map(address_map &map) +n8080_sound_device_base::n8080_sound_device_base( + machine_config const &mconfig, + device_type type, + char const *tag, + device_t *parent, + u32 clock) : + device_t(mconfig, type, tag, parent, clock), + m_cpu(*this, "cpu"), + m_curr_pins(0) { - map.global_mask(0x3ff); - map(0x0000, 0x03ff).rom(); } -void helifire_state::sound_io_map(address_map &map) + +void n8080_sound_device_base::device_add_mconfig(machine_config &config) { - map(0x00, 0x00).mirror(0x7f).r(FUNC(helifire_state::helifire_8035_external_ram_r)); + I8035(config, m_cpu, 6_MHz_XTAL); + m_cpu->set_addrmap(AS_PROGRAM, &n8080_sound_device_base::prg_map); } -void spacefev_state::spacefev_sound(machine_config &config) +void n8080_sound_device_base::device_start() { - /* basic machine hardware */ - I8035(config, m_audiocpu, 6_MHz_XTAL); - m_audiocpu->set_addrmap(AS_PROGRAM, &spacefev_state::n8080_sound_cpu_map); - m_audiocpu->t0_in_cb().set(FUNC(spacefev_state::n8080_8035_t0_r)); - m_audiocpu->t1_in_cb().set(FUNC(spacefev_state::n8080_8035_t1_r)); - m_audiocpu->p1_in_cb().set(FUNC(spacefev_state::n8080_8035_p1_r)); - m_audiocpu->p2_out_cb().set(FUNC(spacefev_state::n8080_dac_w)); + save_item(NAME(m_curr_pins)); +} - TIMER(config, "vco_timer").configure_periodic(FUNC(spacefev_state::vco_voltage_timer), attotime::from_hz(1000)); - /* sound hardware */ - SPEAKER(config, "speaker").front_center(); +void n8080_sound_device_base::prg_map(address_map &map) +{ + map.global_mask(0x3ff); + map(0x0000, 0x03ff).rom(); +} - DAC_1BIT(config, m_n8080_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.15); - SN76477(config, m_sn); - m_sn->set_noise_params(RES_K(36), RES_K(150), CAP_N(1)); - m_sn->set_decay_res(RES_M(1)); - m_sn->set_attack_params(CAP_U(1.0), RES_K(20)); - m_sn->set_amp_res(RES_K(150)); - m_sn->set_feedback_res(RES_K(47)); - m_sn->set_vco_params(0, CAP_N(1), RES_M(1.5)); - m_sn->set_pitch_voltage(0); - m_sn->set_slf_params(CAP_N(47), RES_M(1)); - m_sn->set_oneshot_params(CAP_N(47), RES_K(820)); - m_sn->set_vco_mode(0); - m_sn->set_mixer_params(0, 0, 0); - m_sn->set_envelope_params(1, 0); - m_sn->set_enable(1); - m_sn->add_route(ALL_OUTPUTS, "speaker", 0.35); -} -void sheriff_state::sheriff_sound(machine_config &config) -{ - /* basic machine hardware */ - I8035(config, m_audiocpu, 6_MHz_XTAL); - m_audiocpu->set_addrmap(AS_PROGRAM, &sheriff_state::n8080_sound_cpu_map); - m_audiocpu->t0_in_cb().set(FUNC(sheriff_state::n8080_8035_t0_r)); - m_audiocpu->t1_in_cb().set(FUNC(sheriff_state::n8080_8035_t1_r)); - m_audiocpu->p1_in_cb().set(FUNC(sheriff_state::n8080_8035_p1_r)); - m_audiocpu->p2_out_cb().set(FUNC(sheriff_state::n8080_dac_w)); - - /* sound hardware */ - SPEAKER(config, "speaker").front_center(); +template class device_finder; +template class device_finder; - DAC_1BIT(config, m_n8080_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.15); - SN76477(config, m_sn); - m_sn->set_noise_params(RES_K(36), RES_K(100), CAP_N(1)); - m_sn->set_decay_res(RES_K(620)); - m_sn->set_attack_params(CAP_U(1.0), RES_K(20)); - m_sn->set_amp_res(RES_K(150)); - m_sn->set_feedback_res(RES_K(47)); - m_sn->set_vco_params(0, CAP_N(1), RES_M(1.5)); - m_sn->set_pitch_voltage(0); - m_sn->set_slf_params(CAP_N(47), RES_M(1.5)); - m_sn->set_oneshot_params(CAP_N(47), RES_K(560)); - m_sn->set_vco_mode(0); - m_sn->set_mixer_params(0, 0, 0); - m_sn->set_envelope_params(1, 0); - m_sn->set_enable(1); - m_sn->add_route(ALL_OUTPUTS, "speaker", 0.35); -} -void helifire_state::helifire_sound(machine_config &config) -{ - /* basic machine hardware */ - I8035(config, m_audiocpu, 6_MHz_XTAL); - m_audiocpu->set_addrmap(AS_PROGRAM, &helifire_state::n8080_sound_cpu_map); - m_audiocpu->set_addrmap(AS_IO, &helifire_state::sound_io_map); - m_audiocpu->t0_in_cb().set(FUNC(helifire_state::helifire_8035_t0_r)); - m_audiocpu->t1_in_cb().set(FUNC(helifire_state::helifire_8035_t1_r)); - m_audiocpu->p2_in_cb().set(FUNC(helifire_state::helifire_8035_p2_r)); - m_audiocpu->p1_out_cb().set("helifire_dac", FUNC(dac_byte_interface::data_w)); - m_audiocpu->p2_out_cb().set(FUNC(helifire_state::sound_ctrl_w)); - - TIMER(config, "helifire_dac_volume_timer").configure_periodic(FUNC(helifire_state::dac_volume_timer), attotime::from_hz(1000)); - - /* sound hardware */ - SPEAKER(config, "speaker").front_center(); - DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.15); // unknown DAC -} +DEFINE_DEVICE_TYPE_PRIVATE(SPACEFEV_SOUND, n8080_sound_device_base, spacefev_sound_device, "spacefev_sound", "Nintendo Space Fever Sound Board") +DEFINE_DEVICE_TYPE_PRIVATE(SHERIFF_SOUND, n8080_sound_device_base, sheriff_sound_device, "sheriff_sound", "Nintendo Sheriff Sound Board") +DEFINE_DEVICE_TYPE_PRIVATE(HELIFIRE_SOUND, n8080_sound_device_base, helifire_sound_device, "helifire_sound", "Nintendo HeliFire Sound Board") diff --git a/src/mame/nintendo/n8080_a.h b/src/mame/nintendo/n8080_a.h new file mode 100644 index 00000000000..cd212695b1a --- /dev/null +++ b/src/mame/nintendo/n8080_a.h @@ -0,0 +1,47 @@ +// license:BSD-3-Clause +// copyright-holders:Pierpaolo Prazzoli +/*************************************************************************** + + Nintendo 8080 sound emulation + +***************************************************************************/ +#ifndef MAME_NINTENDO_N8080_A_H +#define MAME_NINTENDO_N8080_A_H + +#pragma once + +#include "cpu/mcs48/mcs48.h" + + +class n8080_sound_device_base : public device_t +{ +public: + void sound1_w(u8 data); + void sound2_w(u8 data); + +protected: + n8080_sound_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *parent, u32 clock); + + required_device m_cpu; + +protected: + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + virtual void device_start() override ATTR_COLD; + + u16 current_pins() const { return m_curr_pins; } + +private: + virtual void pins_changed(u16 curr, u16 prev) = 0; + + void prg_map(address_map &map) ATTR_COLD; + + u16 m_curr_pins; +}; + + + +DECLARE_DEVICE_TYPE(SPACEFEV_SOUND, n8080_sound_device_base) +DECLARE_DEVICE_TYPE(SHERIFF_SOUND, n8080_sound_device_base) +DECLARE_DEVICE_TYPE(HELIFIRE_SOUND, n8080_sound_device_base) + +#endif // MAME_NINTENDO_N8080_A_H diff --git a/src/mame/nintendo/n8080_v.cpp b/src/mame/nintendo/n8080_v.cpp deleted file mode 100644 index b6ce7d075b8..00000000000 --- a/src/mame/nintendo/n8080_v.cpp +++ /dev/null @@ -1,359 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Pierpaolo Prazzoli -/*************************************************************************** - - Nintendo 8080 video emulation - -***************************************************************************/ - -#include "emu.h" -#include "n8080.h" - - -void n8080_state::n8080_video_control_w(uint8_t data) -{ - m_sheriff_color_mode = (data >> 3) & 3; - m_sheriff_color_data = (data >> 0) & 7; - flip_screen_set(data & 0x20); -} - - -void n8080_state::n8080_palette(palette_device &palette) const -{ - for (int i = 0; i < 8; i++) - palette.set_pen_color(i, pal1bit(i >> 0), pal1bit(i >> 1), pal1bit(i >> 2)); -} - - -void helifire_state::helifire_palette(palette_device &palette) const -{ - n8080_palette(palette); - - for (int i = 0; i < 0x100; i++) - { - int const level = 0xff * exp(-3 * i / 255.); // capacitor discharge - - palette.set_pen_color(0x000 + 8 + i, rgb_t(0x00, 0x00, level)); // shades of blue - palette.set_pen_color(0x100 + 8 + i, rgb_t(0x00, 0xc0, level)); // shades of blue w/ green star - - palette.set_pen_color(0x200 + 8 + i, rgb_t(level, 0x00, 0x00)); // shades of red - palette.set_pen_color(0x300 + 8 + i, rgb_t(level, 0xc0, 0x00)); // shades of red w/ green star - } -} - - -void spacefev_state::start_red_cannon() -{ - m_red_cannon = 1; - m_cannon_timer->adjust(attotime::from_usec(550 * 68 * 10)); -} - - -TIMER_CALLBACK_MEMBER(spacefev_state::stop_red_cannon) -{ - m_red_cannon = 0; - m_cannon_timer->adjust(attotime::never); -} - - -void helifire_state::next_line() -{ - m_mv++; - - if (m_sc % 4 == 2) - { - m_mv %= 256; - } - else - { - if (flip_screen()) - m_mv %= 255; - else - m_mv %= 257; - } - - if (m_mv == 128) - { - m_sc++; - } -} - - -void spacefev_state::video_start() -{ - m_cannon_timer = timer_alloc(FUNC(spacefev_state::stop_red_cannon), this); - - flip_screen_set(0); - - save_item(NAME(m_red_screen)); - save_item(NAME(m_red_cannon)); -} - - -void sheriff_state::video_start() -{ - flip_screen_set(0); - - save_item(NAME(m_sheriff_color_mode)); - save_item(NAME(m_sheriff_color_data)); -} - - -void helifire_state::video_start() -{ - uint8_t data = 0; - int i; - - save_item(NAME(m_mv)); - save_item(NAME(m_sc)); - save_item(NAME(m_flash)); - save_item(NAME(m_LSFR)); - - for (i = 0; i < 63; i++) - { - int bit = - (data >> 6) ^ - (data >> 7) ^ 1; - - data = (data << 1) | (bit & 1); - - m_LSFR[i] = data; - } - - flip_screen_set(0); -} - - -uint32_t spacefev_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - const bool mono = bool(m_video_conf->read()); - uint8_t mask = flip_screen() ? 0xff : 0x00; - - uint8_t const *pRAM = m_videoram; - uint8_t const *const pPROM = m_prom->base(); - - for (int y = 0; y < 256; y++) - { - uint16_t *const pLine = &bitmap.pix(y ^ mask); - - for (int x = 0; x < 256; x += 8) - { - uint8_t color = 0; - - if (m_red_screen) - color = 1; - else - { - uint8_t val = pPROM[x >> 3]; - - if ((x >> 3) == 0x06) - { - color = m_red_cannon ? 1 : 7; - } - - if ((x >> 3) == 0x1b) - { - static const uint8_t ufo_color[] = - { - 1, // red - 2, // green - 7, // white - 3, // yellow - 5, // magenta - 6, // cyan - }; - - int cycle = screen.frame_number() / 32; - - color = ufo_color[cycle % 6]; - } - - for (int n = color + 1; n < 8; n++) - { - if (~val & (1 << n)) - { - color = n; - } - } - } - - if (mono) - color = 7; // force B&W here - - for (int n = 0; n < 8; n++) - { - pLine[(x + n) ^ mask] = (pRAM[x >> 3] & (1 << n)) ? color : 0; - } - } - - pRAM += 32; - } - return 0; -} - - -uint32_t sheriff_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - uint8_t mask = flip_screen() ? 0xff : 0x00; - - uint8_t const *pRAM = m_videoram; - uint8_t const *const pPROM = m_prom->base(); - - for (int y = 0; y < 256; y++) - { - uint16_t *const pLine = &bitmap.pix(y ^ mask); - - for (int x = 0; x < 256; x += 8) - { - uint8_t color = pPROM[32 * (y >> 3) + (x >> 3)]; - - if (m_sheriff_color_mode == 1 && !(color & 8)) - color = m_sheriff_color_data ^ 7; - - if (m_sheriff_color_mode == 2) - color = m_sheriff_color_data ^ 7; - - if (m_sheriff_color_mode == 3) - color = 7; - - for (int n = 0; n < 8; n++) - { - pLine[(x + n) ^ mask] = ((pRAM[x >> 3] >> n) & 1) ? (color & 7) : 0; - } - } - - pRAM += 32; - } - return 0; -} - - -uint32_t helifire_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - const int SUN_BRIGHTNESS = m_pot[0]->read(); - const int SEA_BRIGHTNESS = m_pot[1]->read(); - - static const int wave[8] = { 0, 1, 2, 2, 2, 1, 0, 0 }; - - unsigned saved_mv = m_mv; - unsigned saved_sc = m_sc; - - for (int y = 0; y < 256; y++) - { - uint16_t *const pLine = &bitmap.pix(y); - - int level = 120 + wave[m_mv & 7]; - - // draw sky - for (int x = level; x < 256; x++) - { - pLine[x] = 0x200 + 8 + SUN_BRIGHTNESS + x - level; - } - - // draw stars - if (m_mv % 8 == 4) // upper half - { - int step = (320 * (m_mv - 0)) % sizeof m_LSFR; - - int data = - ((m_LSFR[step] & 1) << 6) | - ((m_LSFR[step] & 2) << 4) | - ((m_LSFR[step] & 4) << 2) | - ((m_LSFR[step] & 8) << 0); - - pLine[0x80 + data] |= 0x100; - } - - if (m_mv % 8 == 5) // lower half - { - int step = (320 * (m_mv - 1)) % sizeof m_LSFR; - - int data = - ((m_LSFR[step] & 1) << 6) | - ((m_LSFR[step] & 2) << 4) | - ((m_LSFR[step] & 4) << 2) | - ((m_LSFR[step] & 8) << 0); - - pLine[0x00 + data] |= 0x100; - } - - // draw sea - for (int x = 0; x < level; x++) - { - pLine[x] = 8 + SEA_BRIGHTNESS + x; - } - - // draw foreground - for (int x = 0; x < 256; x += 8) - { - int offset = 32 * y + (x >> 3); - - for (int n = 0; n < 8; n++) - { - if (flip_screen()) - { - if ((m_videoram[offset ^ 0x1fff] << n) & 0x80) - { - pLine[x + n] = m_colorram[offset ^ 0x1fff] & 7; - } - } - else - { - if ((m_videoram[offset] >> n) & 1) - { - pLine[x + n] = m_colorram[offset] & 7; - } - } - } - } - - // next line - next_line(); - } - - m_mv = saved_mv; - m_sc = saved_sc; - return 0; -} - - -void helifire_state::screen_vblank(int state) -{ - // falling edge - if (!state) - { - int n = (m_screen->frame_number() >> 1) % sizeof m_LSFR; - - int i; - - for (i = 0; i < 8; i++) - { - int R = (i & 1); - int G = (i & 2); - int B = (i & 4); - - if (m_flash) - { - if (m_LSFR[n] & 0x20) - { - G |= B; - } - - if (m_screen->frame_number() & 0x04) - { - R |= G; - } - } - - m_palette->set_pen_color(i, - R ? 255 : 0, - G ? 255 : 0, - B ? 255 : 0); - } - - for (i = 0; i < 256; i++) - { - next_line(); - } - } -} -- cgit v1.2.3