mirror of
https://github.com/holub/mame
synced 2025-07-06 02:18:09 +03:00
nitendo/n8080.cpp: Encapsulated sound boards.
This commit is contained in:
parent
c516e72e0c
commit
04aac6dc77
@ -157,7 +157,7 @@ license:CC0-1.0
|
||||
</software>
|
||||
|
||||
<!-- Needs a working light pen interface -->
|
||||
<software name="lpengrph" supported="partial">
|
||||
<software name="lpengrph" supported="no">
|
||||
<description>Light Pen Graphic v1.0 (Japan)</description>
|
||||
<year>1984</year>
|
||||
<publisher>Sanyo</publisher>
|
||||
@ -17678,7 +17678,7 @@ Side B
|
||||
</software>
|
||||
|
||||
<!-- Only part 1 can be loaded -->
|
||||
<software name="queensfs" supported="partial">
|
||||
<software name="queensfs" supported="no">
|
||||
<description>The Queen's Footsteps (English)</description>
|
||||
<year>2020</year>
|
||||
<publisher>Davide Bucci</publisher>
|
||||
|
@ -978,7 +978,6 @@ template <bool Debugger, bool Caching> 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);
|
||||
|
@ -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<netlist_mame_analog_output_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;
|
||||
|
@ -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++)
|
||||
{
|
||||
|
@ -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<u8> 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<i8080a_cpu_device> m_maincpu;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<n8080_sound_device_base> 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<u8> 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 )
|
||||
|
@ -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<uint8_t> 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<i8080a_cpu_device> m_maincpu;
|
||||
required_device<i8035_device> m_audiocpu;
|
||||
optional_device<dac_bit_interface> m_n8080_dac;
|
||||
optional_device<sn76477_device> m_sn;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_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<dac_8bit_r2r_device> m_dac;
|
||||
required_shared_ptr<uint8_t> 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
|
@ -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"
|
||||
|
||||
|
||||
constexpr double ATTACK_RATE = 10e-6 * 500;
|
||||
constexpr double DECAY_RATE = 10e-6 * 16000;
|
||||
#include <cmath>
|
||||
|
||||
|
||||
void spacefev_state::update_SN76477_status()
|
||||
namespace {
|
||||
|
||||
template <unsigned Monostables>
|
||||
class n8080_csg_sound_device_base : public n8080_sound_device_base
|
||||
{
|
||||
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")
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
required_device<dac_bit_interface> m_dac;
|
||||
required_device<sn76477_device> m_sn;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int t1_r()
|
||||
{
|
||||
return BIT(current_pins(), 12);
|
||||
}
|
||||
|
||||
void dac_w(u8 data)
|
||||
{
|
||||
m_dac->write(BIT(data, 7));
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(stop_mono_flop_callback)
|
||||
{
|
||||
stop_mono_flop(param);
|
||||
}
|
||||
|
||||
virtual void update_sn_status() = 0;
|
||||
|
||||
emu_timer *m_mono_timer[Monostables];
|
||||
bool m_mono_flop[Monostables];
|
||||
};
|
||||
|
||||
|
||||
template <unsigned Monostables>
|
||||
void n8080_csg_sound_device_base<Monostables>::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));
|
||||
|
||||
SPEAKER(config, "speaker").front_center();
|
||||
|
||||
DAC_1BIT(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.15);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
template <unsigned Monostables>
|
||||
void n8080_csg_sound_device_base<Monostables>::device_start()
|
||||
{
|
||||
n8080_sound_device_base::device_start();
|
||||
|
||||
for (unsigned i = 0; Monostables > i; ++i)
|
||||
m_mono_timer[i] = timer_alloc(FUNC(n8080_csg_sound_device_base::stop_mono_flop_callback), this);
|
||||
|
||||
save_item(NAME(m_mono_flop));
|
||||
}
|
||||
|
||||
template <unsigned Monostables>
|
||||
void n8080_csg_sound_device_base<Monostables>::device_reset()
|
||||
{
|
||||
n8080_sound_device_base::device_reset();
|
||||
|
||||
for (unsigned i = 0; Monostables > i; ++i)
|
||||
m_mono_flop[i] = false;
|
||||
}
|
||||
|
||||
|
||||
template <unsigned Monostables>
|
||||
void n8080_csg_sound_device_base<Monostables>::start_mono_flop(unsigned n, attotime const &expiry)
|
||||
{
|
||||
m_mono_flop[n] = true;
|
||||
|
||||
update_sn_status();
|
||||
|
||||
m_mono_timer[n]->adjust(expiry, n);
|
||||
}
|
||||
|
||||
template <unsigned Monostables>
|
||||
void n8080_csg_sound_device_base<Monostables>::stop_mono_flop(unsigned n)
|
||||
{
|
||||
m_mono_flop[n] = false;
|
||||
|
||||
update_sn_status();
|
||||
|
||||
m_mono_timer[n]->adjust(attotime::never, n);
|
||||
}
|
||||
|
||||
|
||||
|
||||
class spacefev_sound_device : public n8080_csg_sound_device_base<3>
|
||||
{
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
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_DEVICE_CALLBACK_MEMBER(vco_voltage_timer);
|
||||
};
|
||||
|
||||
|
||||
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 spacefev_sound_device::update_sn_status()
|
||||
{
|
||||
double dblR0 = RES_M(1.0);
|
||||
double dblR1 = RES_M(1.5);
|
||||
if (!mono_flop(0))
|
||||
dblR0 = 1.0 / (1.0 / RES_K(150) + 1.0 / dblR0); // ?
|
||||
|
||||
if (!m_mono_flop[0])
|
||||
{
|
||||
dblR0 = 1 / (1 / RES_K(150) + 1 / dblR0); /* ? */
|
||||
}
|
||||
if (!m_mono_flop[1])
|
||||
{
|
||||
dblR1 = 1 / (1 / RES_K(620) + 1 / dblR1); /* ? */
|
||||
}
|
||||
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(
|
||||
!m_mono_flop[0] &&
|
||||
!m_mono_flop[1] &&
|
||||
!m_mono_flop[2]);
|
||||
|
||||
m_sn->vco_w(m_mono_flop[1]);
|
||||
|
||||
m_sn->mixer_b_w(m_mono_flop[0]);
|
||||
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 sheriff_state::update_SN76477_status()
|
||||
void spacefev_sound_device::pins_changed(u16 curr, u16 prev)
|
||||
{
|
||||
if (m_mono_flop[1])
|
||||
{
|
||||
m_sn->vco_voltage_w(5);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sn->vco_voltage_w(0);
|
||||
}
|
||||
u16 const changes = ~curr & prev;
|
||||
|
||||
m_sn->enable_w(
|
||||
!m_mono_flop[0] &&
|
||||
!m_mono_flop[1]);
|
||||
|
||||
m_sn->vco_w(m_mono_flop[0]);
|
||||
|
||||
m_sn->mixer_b_w(!m_mono_flop[0]);
|
||||
}
|
||||
|
||||
|
||||
void n8080_state::update_SN76477_status()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void n8080_state::start_mono_flop( int n, const attotime &expire )
|
||||
{
|
||||
m_mono_flop[n] = 1;
|
||||
|
||||
update_SN76477_status();
|
||||
|
||||
m_sound_timer[n]->adjust(expire, n);
|
||||
}
|
||||
|
||||
|
||||
void n8080_state::stop_mono_flop( int n )
|
||||
{
|
||||
m_mono_flop[n] = 0;
|
||||
|
||||
update_SN76477_status();
|
||||
|
||||
m_sound_timer[n]->adjust(attotime::never, n);
|
||||
}
|
||||
|
||||
|
||||
TIMER_CALLBACK_MEMBER( n8080_state::stop_mono_flop_callback )
|
||||
{
|
||||
stop_mono_flop(param);
|
||||
}
|
||||
|
||||
|
||||
void spacefev_state::sound_pins_changed()
|
||||
{
|
||||
uint16_t changes = ~m_curr_sound_pins & m_prev_sound_pins;
|
||||
|
||||
if (changes & (1 << 0x3))
|
||||
{
|
||||
if (BIT(changes, 3))
|
||||
stop_mono_flop(1);
|
||||
}
|
||||
if (changes & ((1 << 0x3) | (1 << 0x6)))
|
||||
{
|
||||
|
||||
if (BIT(changes, 3) || BIT(changes, 6))
|
||||
stop_mono_flop(2);
|
||||
}
|
||||
if (changes & (1 << 0x3))
|
||||
{
|
||||
|
||||
if (BIT(changes, 3))
|
||||
start_mono_flop(0, attotime::from_usec(550 * 36 * 100));
|
||||
}
|
||||
if (changes & (1 << 0x6))
|
||||
{
|
||||
|
||||
if (BIT(changes, 6))
|
||||
start_mono_flop(1, attotime::from_usec(550 * 22 * 33));
|
||||
}
|
||||
if (changes & (1 << 0x4))
|
||||
{
|
||||
|
||||
if (BIT(changes, 4))
|
||||
start_mono_flop(2, attotime::from_usec(550 * 22 * 33));
|
||||
}
|
||||
|
||||
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);
|
||||
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 sheriff_state::sound_pins_changed()
|
||||
{
|
||||
uint16_t changes = ~m_curr_sound_pins & m_prev_sound_pins;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
void helifire_state::sound_pins_changed()
|
||||
{
|
||||
//uint16_t changes = ~m_curr_sound_pins & m_prev_sound_pins;
|
||||
|
||||
/* ((m_curr_sound_pins >> 0xa) & 1) not emulated */
|
||||
/* ((m_curr_sound_pins >> 0xb) & 1) not emulated */
|
||||
/* ((m_curr_sound_pins >> 0xc) & 1) not emulated */
|
||||
|
||||
bool irq_active = (~m_curr_sound_pins & (1 << 6)) != 0;
|
||||
m_audiocpu->set_input_line(INPUT_LINE_IRQ0, irq_active ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
|
||||
void n8080_state::sound_pins_changed()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void n8080_state::delayed_sound_1(int data)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void spacefev_state::delayed_sound_1(int data)
|
||||
{
|
||||
if (data & ~m_prev_snd_data & 0x10)
|
||||
start_red_cannon();
|
||||
|
||||
m_red_screen = data & 0x08;
|
||||
|
||||
n8080_state::delayed_sound_1(data);
|
||||
}
|
||||
|
||||
|
||||
TIMER_CALLBACK_MEMBER( n8080_state::delayed_sound_1_callback )
|
||||
{
|
||||
delayed_sound_1(param);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void spacefev_state::delayed_sound_2(int data)
|
||||
{
|
||||
flip_screen_set(data & 0x20);
|
||||
|
||||
n8080_state::delayed_sound_2(data);
|
||||
}
|
||||
|
||||
void helifire_state::delayed_sound_2(int data)
|
||||
{
|
||||
m_flash = data & 0x20;
|
||||
|
||||
n8080_state::delayed_sound_2(data);
|
||||
}
|
||||
|
||||
|
||||
TIMER_CALLBACK_MEMBER( n8080_state::delayed_sound_2_callback )
|
||||
{
|
||||
delayed_sound_2(param);
|
||||
}
|
||||
|
||||
|
||||
void n8080_state::n8080_sound_1_w(uint8_t 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(uint8_t data)
|
||||
{
|
||||
machine().scheduler().synchronize(timer_expired_delegate(FUNC(n8080_state::delayed_sound_2_callback), this), data); /* force CPUs to sync */
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
int n8080_state::n8080_8035_t0_r()
|
||||
{
|
||||
return (m_curr_sound_pins >> 0x7) & 1;
|
||||
}
|
||||
|
||||
int n8080_state::n8080_8035_t1_r()
|
||||
{
|
||||
return (m_curr_sound_pins >> 0xc) & 1;
|
||||
}
|
||||
|
||||
|
||||
int helifire_state::helifire_8035_t0_r()
|
||||
{
|
||||
return (m_curr_sound_pins >> 0x3) & 1;
|
||||
}
|
||||
|
||||
int helifire_state::helifire_8035_t1_r()
|
||||
{
|
||||
return (m_curr_sound_pins >> 0x4) & 1;
|
||||
}
|
||||
|
||||
|
||||
uint8_t helifire_state::helifire_8035_external_ram_r()
|
||||
{
|
||||
uint8_t val = 0;
|
||||
|
||||
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;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
uint8_t helifire_state::helifire_8035_p2_r()
|
||||
{
|
||||
return ((m_curr_sound_pins >> 0xc) & 1) ? 0x10 : 0x00; /* not used */
|
||||
}
|
||||
|
||||
|
||||
void n8080_state::n8080_dac_w(uint8_t data)
|
||||
{
|
||||
m_n8080_dac->write(BIT(data, 7));
|
||||
}
|
||||
|
||||
|
||||
void helifire_state::sound_ctrl_w(uint8_t data)
|
||||
{
|
||||
m_dac_phase = data & 0x80;
|
||||
|
||||
/* data & 0x40 not emulated */
|
||||
/* data & 0x20 not emulated */
|
||||
|
||||
if (m_dac_phase)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(spacefev_state::vco_voltage_timer)
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(spacefev_sound_device::vco_voltage_timer)
|
||||
{
|
||||
double voltage = 0;
|
||||
|
||||
if (m_mono_flop[2])
|
||||
{
|
||||
voltage = 5 * (1 - exp(- m_sound_timer[2]->elapsed().as_double() / 0.22));
|
||||
}
|
||||
if (mono_flop(2))
|
||||
voltage = 5.0 * (1.0 - exp(-mono_elapsed(2).as_double() / 0.22));
|
||||
|
||||
m_sn->vco_voltage_w(voltage);
|
||||
}
|
||||
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(helifire_state::dac_volume_timer)
|
||||
{
|
||||
double t = m_dac_timing - machine().time().as_double();
|
||||
|
||||
if (m_dac_phase)
|
||||
class sheriff_sound_device : public n8080_csg_sound_device_base<2>
|
||||
{
|
||||
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)
|
||||
{
|
||||
m_dac_volume = 1 - exp(t / ATTACK_RATE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dac_volume = exp(t / DECAY_RATE);
|
||||
}
|
||||
|
||||
m_dac->set_output_gain(ALL_OUTPUTS, m_dac_volume);
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
void sheriff_sound_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
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 spacefev_state::sound_start()
|
||||
void sheriff_sound_device::update_sn_status()
|
||||
{
|
||||
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));
|
||||
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 spacefev_state::sound_reset()
|
||||
void sheriff_sound_device::pins_changed(u16 curr, u16 prev)
|
||||
{
|
||||
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;
|
||||
u16 const changes = ~curr & prev;
|
||||
|
||||
delayed_sound_1(0);
|
||||
delayed_sound_2(0);
|
||||
if (BIT(changes, 6))
|
||||
stop_mono_flop(1);
|
||||
|
||||
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));
|
||||
|
||||
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 sheriff_state::sound_start()
|
||||
{
|
||||
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);
|
||||
|
||||
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));
|
||||
class helifire_sound_device : public n8080_sound_device_base
|
||||
{
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
u8 ram_r()
|
||||
{
|
||||
return bitswap<4>(current_pins(), 1, 9, 8, 7);
|
||||
}
|
||||
|
||||
u8 p2_r()
|
||||
{
|
||||
return BIT(current_pins(), 12) ? 0x10 : 0x00; // not used
|
||||
}
|
||||
|
||||
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<dac_8bit_r2r_device> m_dac;
|
||||
|
||||
double m_dac_volume;
|
||||
double m_dac_timing;
|
||||
bool m_dac_phase;
|
||||
};
|
||||
|
||||
|
||||
void helifire_sound_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
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 sheriff_state::sound_reset()
|
||||
void helifire_sound_device::device_start()
|
||||
{
|
||||
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;
|
||||
n8080_sound_device_base::device_start();
|
||||
|
||||
delayed_sound_1(0);
|
||||
delayed_sound_2(0);
|
||||
}
|
||||
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void helifire_state::sound_reset()
|
||||
void helifire_sound_device::device_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;
|
||||
n8080_sound_device_base::device_reset();
|
||||
|
||||
delayed_sound_1(0);
|
||||
delayed_sound_2(0);
|
||||
m_dac_volume = 1.0;
|
||||
m_dac_timing = 0.0;
|
||||
m_dac_phase = false;
|
||||
}
|
||||
|
||||
|
||||
void n8080_state::n8080_sound_cpu_map(address_map &map)
|
||||
void helifire_sound_device::ctrl_w(u8 data)
|
||||
{
|
||||
m_dac_phase = BIT(data, 7);
|
||||
|
||||
// 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);
|
||||
else
|
||||
m_dac_timing += DECAY_RATE * log(m_dac_volume);
|
||||
}
|
||||
|
||||
|
||||
void helifire_sound_device::pins_changed(u16 curr, u16 prev)
|
||||
{
|
||||
// bit 10 not emulated
|
||||
// bit 11 not emulated
|
||||
// bit 12 not emulated
|
||||
|
||||
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_sound_device::volume_timer)
|
||||
{
|
||||
double const t = m_dac_timing - machine().time().as_double();
|
||||
|
||||
if (m_dac_phase)
|
||||
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 helifire_sound_device::io_map(address_map &map)
|
||||
{
|
||||
map(0x00, 0x00).mirror(0x7f).r(FUNC(helifire_sound_device::ram_r));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
|
||||
void n8080_sound_device_base::sound1_w(u8 data)
|
||||
{
|
||||
u16 const prev = m_curr_pins;
|
||||
|
||||
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 n8080_sound_device_base::sound2_w(u8 data)
|
||||
{
|
||||
u16 const prev = m_curr_pins;
|
||||
|
||||
m_curr_pins &= ~((1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 2) | (1 << 12));
|
||||
|
||||
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;
|
||||
|
||||
pins_changed(m_curr_pins, prev);
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void n8080_sound_device_base::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
I8035(config, m_cpu, 6_MHz_XTAL);
|
||||
m_cpu->set_addrmap(AS_PROGRAM, &n8080_sound_device_base::prg_map);
|
||||
}
|
||||
|
||||
void n8080_sound_device_base::device_start()
|
||||
{
|
||||
save_item(NAME(m_curr_pins));
|
||||
}
|
||||
|
||||
|
||||
void n8080_sound_device_base::prg_map(address_map &map)
|
||||
{
|
||||
map.global_mask(0x3ff);
|
||||
map(0x0000, 0x03ff).rom();
|
||||
}
|
||||
|
||||
void helifire_state::sound_io_map(address_map &map)
|
||||
{
|
||||
map(0x00, 0x00).mirror(0x7f).r(FUNC(helifire_state::helifire_8035_external_ram_r));
|
||||
}
|
||||
|
||||
void spacefev_state::spacefev_sound(machine_config &config)
|
||||
{
|
||||
/* 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));
|
||||
|
||||
TIMER(config, "vco_timer").configure_periodic(FUNC(spacefev_state::vco_voltage_timer), attotime::from_hz(1000));
|
||||
template class device_finder<n8080_sound_device_base, false>;
|
||||
template class device_finder<n8080_sound_device_base, true>;
|
||||
|
||||
/* sound hardware */
|
||||
SPEAKER(config, "speaker").front_center();
|
||||
|
||||
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();
|
||||
|
||||
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")
|
||||
|
47
src/mame/nintendo/n8080_a.h
Normal file
47
src/mame/nintendo/n8080_a.h
Normal file
@ -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<i8035_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
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user