summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2018-06-02 15:01:03 +1000
committer Vas Crabb <vas@vastheman.com>2018-06-02 15:01:03 +1000
commite64244db48c2778c7fb6a2f69bab5fc13f63b524 (patch)
tree86c84680878e28a49c4d3f0567bd19c45ac58e5d
parent91e39b1e68aea885e28b0c01ce82bdd04a6c9ee6 (diff)
snk6502: improve sound encapsulation and fix BGM (nw)
Still could be a lot better: * Frequency/rate should be set in config, not reset handlers * Speech should be moved into a separate device for the games that have it * Probably should be specialisations for sasuke and satansat * Not all games have three channels
-rw-r--r--src/mame/audio/snk6502.cpp1046
-rw-r--r--src/mame/audio/snk6502.h148
-rw-r--r--src/mame/drivers/snk6502.cpp287
-rw-r--r--src/mame/includes/snk6502.h44
-rw-r--r--src/mame/video/snk6502.cpp4
5 files changed, 872 insertions, 657 deletions
diff --git a/src/mame/audio/snk6502.cpp b/src/mame/audio/snk6502.cpp
index 96f4755c9ce..659deadd16d 100644
--- a/src/mame/audio/snk6502.cpp
+++ b/src/mame/audio/snk6502.cpp
@@ -15,6 +15,8 @@
#include "emu.h"
#include "audio/snk6502.h"
+#include "speaker.h"
+
#ifndef M_LN2
#define M_LN2 0.69314718055994530942
#endif
@@ -26,7 +28,7 @@
#define FRAC_ONE (1 << FRAC_BITS)
#define FRAC_MASK (FRAC_ONE - 1)
-const char *const sasuke_sample_names[] =
+static const char *const sasuke_sample_names[] =
{
"*sasuke",
@@ -39,7 +41,7 @@ const char *const sasuke_sample_names[] =
nullptr
};
-const char *const vanguard_sample_names[] =
+static const char *const vanguard_sample_names[] =
{
"*vanguard",
@@ -69,7 +71,7 @@ const char *const vanguard_sample_names[] =
};
-const char *const fantasy_sample_names[] =
+static const char *const fantasy_sample_names[] =
{
"*fantasy",
@@ -105,7 +107,7 @@ static const discrete_op_amp_filt_info fantasy_filter =
#define FANTASY_NOISE_STREAM_IN NODE_02
#define FANTASY_NOISE_LOGIC NODE_03
-DISCRETE_SOUND_START( fantasy_discrete )
+static DISCRETE_SOUND_START( fantasy_discrete )
DISCRETE_INPUT_LOGIC (FANTASY_BOMB_EN)
DISCRETE_INPUT_STREAM(FANTASY_NOISE_STREAM_IN, 0)
@@ -125,24 +127,28 @@ DISCRETE_SOUND_START( fantasy_discrete )
DISCRETE_SOUND_END
-DEFINE_DEVICE_TYPE(SNK6502, snk6502_sound_device, "snk6502_sound", "SNK6502 Custom Sound")
+DEFINE_DEVICE_TYPE(SNK6502_SOUND, snk6502_sound_device, "snk6502_sound", "SNK6502 Custom Sound")
+DEFINE_DEVICE_TYPE(VANGUARD_SOUND, vanguard_sound_device, "vanguard_sound", "SNK Vanguard Sound")
+DEFINE_DEVICE_TYPE(FANTASY_SOUND, fantasy_sound_device, "fantasy_sound", "SNK Fantasy Sound")
+DEFINE_DEVICE_TYPE(NIBBLER_SOUND, nibbler_sound_device, "nibbler_sound", "Rock-Ola Nibbler Sound")
+DEFINE_DEVICE_TYPE(PBALLOON_SOUND, pballoon_sound_device, "pballoon_sound", "SNK Pioneer Balloon Sound")
+DEFINE_DEVICE_TYPE(SASUKE_SOUND, sasuke_sound_device, "sasuke_sound", "SNK Sasuke Vs. Commander Sound")
+DEFINE_DEVICE_TYPE(SATANSAT_SOUND, satansat_sound_device, "satansat_sound", "SNK Satan of Saturn Sound")
+
snk6502_sound_device::snk6502_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, SNK6502, tag, owner, clock),
- device_sound_interface(mconfig, *this),
- m_tone_clock_expire(0),
- m_tone_clock(0),
- m_tone_stream(nullptr),
- m_sn76477_2(*this, ":sn76477.2"),
- m_discrete(*this, ":discrete"),
- m_samples(*this, ":samples"),
- m_rom(*this, ":snk6502"),
- m_sound0_stop_on_rollover(0),
- m_last_port1(0),
- m_hd38880_cmd(0),
- m_hd38880_addr(0),
- m_hd38880_data_bytes(0),
- m_hd38880_speed(0)
+ : device_t(mconfig, SNK6502_SOUND, tag, owner, clock)
+ , device_sound_interface(mconfig, *this)
+ , m_tone_clock_expire(0)
+ , m_tone_clock(0)
+ , m_tone_stream(nullptr)
+ , m_samples(*this, "^samples")
+ , m_rom(*this, DEVICE_SELF_OWNER)
+ , m_sound0_stop_on_rollover(0)
+ , m_hd38880_cmd(0)
+ , m_hd38880_addr(0)
+ , m_hd38880_data_bytes(0)
+ , m_hd38880_speed(0)
{
}
@@ -174,7 +180,6 @@ void snk6502_sound_device::device_start()
save_item(NAME(m_tone_clock));
save_item(NAME(m_sound0_stop_on_rollover));
- save_item(NAME(m_last_port1));
save_item(NAME(m_hd38880_cmd));
save_item(NAME(m_hd38880_addr));
save_item(NAME(m_hd38880_data_bytes));
@@ -244,7 +249,7 @@ void snk6502_sound_device::build_waveform(int channel, int mask)
bit3 = 8;
else if (BIT(mask, 2))
bit3 = 4;
- else if (BIT(mask, 8))
+ else if (BIT(mask, 3))
bit3 = 2;
// bit 2
@@ -283,7 +288,7 @@ void snk6502_sound_device::build_waveform(int channel, int mask)
}
else
{
- const int data = (bit0 & BIT(i, 0)) + (bit1 & BIT(i, 1)) + (bit2 & BIT(i, 2)) + (bit3 & BIT(i, 3));
+ const int data = (BIT(i, 0) ? bit0 : 0) + (BIT(i, 1) ? bit1 : 0) + (BIT(i, 2) ? bit2 : 0) + (BIT(i, 3) ? bit3 : 0);
m_tone_channels[channel].form[i] = data - base;
}
}
@@ -302,7 +307,7 @@ void snk6502_sound_device::set_music_freq(int freq)
m_tone_channels[i].mask = 0xff;
m_tone_channels[i].sample_step = 0;
m_tone_channels[i].sample_cur = 0;
- m_tone_channels[i].sample_rate = (double)(freq * 8) / SAMPLE_RATE * FRAC_ONE;
+ m_tone_channels[i].sample_rate = double(freq * 8) / SAMPLE_RATE * FRAC_ONE;
build_waveform(i, 1);
}
@@ -314,140 +319,259 @@ void snk6502_sound_device::set_music_clock(double clock_time)
m_tone_clock = 0;
}
-int snk6502_sound_device::music0_playing()
+CUSTOM_INPUT_MEMBER(snk6502_sound_device::music0_playing)
{
- return m_tone_channels[0].mute;
+ return m_tone_channels[0].mute ? 0x01 : 0x00;
}
+void snk6502_sound_device::set_channel_base(int channel, int base, int mask)
+{
+ m_tone_channels[channel].base = base;
+ m_tone_channels[channel].mask = mask;
+}
-WRITE8_MEMBER( snk6502_sound_device::sasuke_sound_w )
+void snk6502_sound_device::mute_channel(int channel)
{
- switch (offset)
- {
- case 0:
- /*
- bit description
+ m_tone_channels[channel].mute = 1;
+ m_tone_channels[channel].offset = 0;
+}
- 0 hit (ic52)
- 1 boss start (ic51)
- 2 shot
- 3 boss attack (ic48?)
- 4 ??
- 5
- 6
- 7 reset counter
- */
+void snk6502_sound_device::unmute_channel(int channel)
+{
+ m_tone_channels[channel].mute = 0;
+ m_tone_channels[channel].offset = 0;
+}
- if ((~data & 0x01) && (m_last_port1 & 0x01))
- m_samples->start(0, 0);
- if ((~data & 0x02) && (m_last_port1 & 0x02))
- m_samples->start(1, 1);
- if ((~data & 0x04) && (m_last_port1 & 0x04))
- m_samples->start(2, 2);
- if ((~data & 0x08) && (m_last_port1 & 0x08))
- m_samples->start(3, 3);
- if ((data & 0x80) && (~m_last_port1 & 0x80))
+/*
+ Hitachi HD38880 speech synthesizer chip
+
+ I heard that this chip uses PARCOR coefficients but I don't know ROM data format.
+ How do I generate samples?
+*/
+
+
+/* HD38880 command */
+#define HD38880_ADSET 2
+#define HD38880_READ 3
+#define HD38880_INT1 4
+#define HD38880_INT2 6
+#define HD38880_SYSPD 8
+#define HD38880_STOP 10
+#define HD38880_CONDT 11
+#define HD38880_START 12
+#define HD38880_SSTART 14
+
+/* HD38880 control bits */
+#define HD38880_CTP 0x10
+#define HD38880_CMV 0x20
+#define HD68880_SYBS 0x0f
+
+
+void snk6502_sound_device::speech_w(uint8_t data, const uint16_t *table, int start)
+{
+ /*
+ bit description
+ 0 SYBS1
+ 1 SYBS2
+ 2 SYBS3
+ 3 SYBS4
+ 4 CTP
+ 5 CMV
+ 6
+ 7
+ */
+
+ if ((data & HD38880_CTP) && (data & HD38880_CMV))
+ {
+ data &= HD68880_SYBS;
+
+ switch (m_hd38880_cmd)
{
- m_tone_channels[0].offset = 0;
- m_tone_channels[0].mute = 0;
- }
+ case 0:
+ switch (data)
+ {
+ case HD38880_START:
+ logerror("speech: START\n");
- if ((~data & 0x80) && (m_last_port1 & 0x80))
- m_tone_channels[0].mute = 1;
+ if (m_hd38880_data_bytes == 5 && !m_samples->playing(0))
+ {
+ for (int i = 0; i < 16; i++)
+ {
+ if (table[i] && table[i] == m_hd38880_addr)
+ {
+ m_samples->start(0, start + i);
+ break;
+ }
+ }
+ }
+ break;
- m_last_port1 = data;
- break;
+ case HD38880_SSTART:
+ logerror("speech: SSTART\n");
+ break;
- case 1:
- /*
- bit description
+ case HD38880_STOP:
+ m_samples->stop(0);
+ logerror("speech: STOP\n");
+ break;
- 0
- 1 wave form
- 2 wave form
- 3 wave form
- 4 MUSIC A8
- 5 MUSIC A9
- 6 MUSIC A10
- 7
- */
+ case HD38880_SYSPD:
+ m_hd38880_cmd = data;
+ break;
- /* select tune in ROM based on sound command byte */
- m_tone_channels[0].base = 0x0000 + ((data & 0x70) << 4);
- m_tone_channels[0].mask = 0xff;
+ case HD38880_CONDT:
+ logerror("speech: CONDT\n");
+ break;
- m_sound0_stop_on_rollover = 1;
+ case HD38880_ADSET:
+ m_hd38880_cmd = data;
+ m_hd38880_addr = 0;
+ m_hd38880_data_bytes = 0;
+ break;
- /* bit 1-3 sound0 waveform control */
- sasuke_build_waveform((data & 0x0e) >> 1);
- break;
- }
-}
+ case HD38880_READ:
+ logerror("speech: READ\n");
+ break;
-WRITE8_MEMBER( snk6502_sound_device::satansat_sound_w )
-{
- switch (offset)
- {
- case 0:
- /*
- bit description
+ case HD38880_INT1:
+ m_hd38880_cmd = data;
+ break;
- */
+ case HD38880_INT2:
+ m_hd38880_cmd = data;
+ break;
- /* bit 0 = analog sound trigger */
+ case 0:
+ // ignore it
+ break;
- /* bit 1 = to 76477 */
+ default:
+ logerror("speech: unknown command: 0x%x\n", data);
+ }
+ break;
- /* bit 2 = analog sound trigger */
- if (data & 0x04 && !(m_last_port1 & 0x04))
- m_samples->start(0, 1);
+ case HD38880_INT1:
+ logerror("speech: INT1: 0x%x\n", data);
- if (data & 0x08)
- {
- m_tone_channels[0].mute = 1;
- m_tone_channels[0].offset = 0;
+ if (data & 8)
+ logerror("speech: triangular waveform\n");
+ else
+ logerror("speech: impulse waveform\n");
+
+ logerror("speech: %sable losing effect of vocal tract\n", data & 4 ? "en" : "dis");
+
+ if ((data & 2) && (data & 8))
+ logerror("speech: use external pitch control\n");
+
+ m_hd38880_cmd = 0;
+ break;
+
+ case HD38880_INT2:
+ logerror("speech: INT2: 0x%x\n", data);
+
+ logerror("speech: %d bits / frame\n", data & 8 ? 48 : 96);
+ logerror("speech: %d ms / frame\n", data & 4 ? 20 : 10);
+ logerror("speech: %sable repeat\n", data & 2 ? "en" : "dis");
+ logerror("speech: %d operations\n", ((data & 8) == 0) || (data & 1) ? 10 : 8);
+
+ m_hd38880_cmd = 0;
+ break;
+
+ case HD38880_SYSPD:
+ m_hd38880_speed = ((double)(data + 1)) / 10.0;
+ logerror("speech: SYSPD: %1.1f\n", m_hd38880_speed);
+ m_hd38880_cmd = 0;
+ break;
+
+ case HD38880_ADSET:
+ m_hd38880_addr |= (data << (m_hd38880_data_bytes++ * 4));
+ if (m_hd38880_data_bytes == 5)
+ {
+ logerror("speech: ADSET: 0x%05x\n", m_hd38880_addr);
+ m_hd38880_cmd = 0;
+ }
+ break;
}
+ }
+}
- /* bit 4-6 sound0 waveform control */
- sasuke_build_waveform((data & 0x70) >> 4);
- /* bit 7 sound1 waveform control */
- satansat_build_waveform((data & 0x80) >> 7);
+/*
+ vanguard/fantasy speech
- m_last_port1 = data;
- break;
- case 1:
- /*
- bit description
+ ROM data format (INT2 = 0xf):
+ 48 bits / frame
+ 20 ms / frame
+ enable repeat
+ 10 operations
+*/
- */
+//-------------------------------------------------
+// sound_stream_update - handle a stream update
+//-------------------------------------------------
- /* select tune in ROM based on sound command byte */
- m_tone_channels[0].base = 0x0000 + ((data & 0x0e) << 7);
- m_tone_channels[0].mask = 0xff;
- m_tone_channels[1].base = 0x0800 + ((data & 0x60) << 4);
- m_tone_channels[1].mask = 0x1ff;
+void snk6502_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+{
+ stream_sample_t *buffer = outputs[0];
- m_sound0_stop_on_rollover = 1;
+ for (int i = 0; i < NUM_CHANNELS; i++)
+ validate_tone_channel(i);
- if (data & 0x01)
- m_tone_channels[0].mute = 0;
+ while (samples-- > 0)
+ {
+ int32_t data = 0;
- if (data & 0x10)
- m_tone_channels[1].mute = 0;
- else
+ for (tone_t &voice : m_tone_channels)
{
- m_tone_channels[1].mute = 1;
- m_tone_channels[1].offset = 0;
+ int16_t const *const form = voice.form;
+
+ if (!voice.mute && voice.sample_step)
+ {
+ const int cur_pos = voice.sample_cur + voice.sample_step;
+ const int prev = form[(voice.sample_cur >> FRAC_BITS) & 15];
+ const int cur = form[(cur_pos >> FRAC_BITS) & 15];
+
+ /* interpolate */
+ data += (int32_t(prev) * (FRAC_ONE - (cur_pos & FRAC_MASK))
+ + int32_t(cur) * (cur_pos & FRAC_MASK)) >> FRAC_BITS;
+
+ voice.sample_cur = cur_pos;
+ }
}
- /* bit 7 = ? */
- break;
+ *buffer++ = data;
+
+ m_tone_clock += FRAC_ONE;
+ if (m_tone_clock >= m_tone_clock_expire)
+ {
+ for (int i = 0; i < NUM_CHANNELS; i++)
+ {
+ m_tone_channels[i].offset++;
+ m_tone_channels[i].offset &= m_tone_channels[i].mask;
+
+ validate_tone_channel(i);
+ }
+
+ if (m_tone_channels[0].offset == 0 && m_sound0_stop_on_rollover)
+ m_tone_channels[0].mute = 1;
+
+ m_tone_clock -= m_tone_clock_expire;
+ }
}
}
-WRITE8_MEMBER( snk6502_sound_device::vanguard_sound_w )
+
+vanguard_sound_device::vanguard_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, VANGUARD_SOUND, tag, owner, clock)
+ , m_custom(*this, "custom")
+ , m_sn76477_2(*this, "sn76477.2")
+ , m_samples(*this, "samples")
+ , m_last_port1(0)
+{
+}
+
+WRITE8_MEMBER(vanguard_sound_device::sound_w)
{
switch (offset)
{
@@ -466,10 +590,9 @@ WRITE8_MEMBER( snk6502_sound_device::vanguard_sound_w )
*/
/* select musical tune in ROM based on sound command byte */
- m_tone_channels[0].base = ((data & 0x07) << 8);
- m_tone_channels[0].mask = 0xff;
+ m_custom->set_channel_base(0, (data & 0x07) << 8);
- m_sound0_stop_on_rollover = 1;
+ m_custom->set_sound0_stop_on_rollover(1);
/* play noise samples requested by sound command byte */
/* SHOT A */
@@ -483,21 +606,17 @@ WRITE8_MEMBER( snk6502_sound_device::vanguard_sound_w )
m_samples->start(2, 1);
if (data & 0x08)
- {
- m_tone_channels[0].mute = 1;
- m_tone_channels[0].offset = 0;
- }
+ m_custom->mute_channel(0);
if (data & 0x10)
- {
- m_tone_channels[0].mute = 0;
- }
+ m_custom->unmute_channel(0);
/* SHOT B */
m_sn76477_2->enable_w((data & 0x40) ? 0 : 1);
m_last_port1 = data;
break;
+
case 1:
/*
bit description
@@ -513,17 +632,14 @@ WRITE8_MEMBER( snk6502_sound_device::vanguard_sound_w )
*/
/* select tune in ROM based on sound command byte */
- m_tone_channels[1].base = 0x0800 + ((data & 0x07) << 8);
- m_tone_channels[1].mask = 0xff;
+ m_custom->set_channel_base(1, 0x0800 | ((data & 0x07) << 8));
if (data & 0x08)
- m_tone_channels[1].mute = 0;
+ m_custom->unmute_channel(1);
else
- {
- m_tone_channels[1].mute = 1;
- m_tone_channels[1].offset = 0;
- }
+ m_custom->mute_channel(1);
break;
+
case 2:
/*
bit description
@@ -538,12 +654,108 @@ WRITE8_MEMBER( snk6502_sound_device::vanguard_sound_w )
7 AS 8 (sound1 waveform)
*/
- build_waveform(0, (data & 0x3) | ((data & 4) << 1) | ((data & 8) >> 1));
- build_waveform(1, data >> 4);
+ m_custom->build_waveform(0, (data & 0x3) | ((data & 4) << 1) | ((data & 8) >> 1));
+ m_custom->build_waveform(1, data >> 4);
}
}
-WRITE8_MEMBER( snk6502_sound_device::fantasy_sound_w )
+WRITE8_MEMBER(vanguard_sound_device::speech_w)
+{
+ static const uint16_t vanguard_table[16] =
+ {
+ 0x04000,
+ 0x04325,
+ 0x044a2,
+ 0x045b7,
+ 0x046ee,
+ 0x04838,
+ 0x04984,
+ 0x04b01,
+ 0x04c38,
+ 0x04de6,
+ 0x04f43,
+ 0x05048,
+ 0x05160,
+ 0x05289,
+ 0x0539e,
+ 0x054ce
+ };
+
+ m_custom->speech_w(data, vanguard_table, 2);
+}
+
+MACHINE_CONFIG_START(vanguard_sound_device::device_add_mconfig)
+ SPEAKER(config, "mono").front_center();
+
+ MCFG_DEVICE_ADD(m_custom, SNK6502_SOUND, 0)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+
+ MCFG_DEVICE_ADD("samples", SAMPLES)
+ MCFG_SAMPLES_CHANNELS(3)
+ MCFG_SAMPLES_NAMES(vanguard_sample_names)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
+
+ MCFG_DEVICE_ADD("sn76477.1", SN76477)
+ // SHOT A GND: 2,9,26,27 +5V: 15,25
+ MCFG_SN76477_NOISE_PARAMS(RES_K(470), RES_M(1.5), CAP_P(220)) // noise + filter
+ MCFG_SN76477_DECAY_RES(0) // decay_res
+ MCFG_SN76477_ATTACK_PARAMS(0, 0) // attack_decay_cap + attack_res
+ MCFG_SN76477_AMP_RES(RES_K(47)) // amplitude_res
+ MCFG_SN76477_FEEDBACK_RES(RES_K(4.7)) // feedback_res
+ MCFG_SN76477_VCO_PARAMS(0, 0, 0) // VCO volt + cap + res
+ MCFG_SN76477_PITCH_VOLTAGE(0) // pitch_voltage
+ MCFG_SN76477_SLF_PARAMS(0, 0) // slf caps + res
+ MCFG_SN76477_ONESHOT_PARAMS(0, 0) // oneshot caps + res
+ MCFG_SN76477_VCO_MODE(0) // VCO mode
+ MCFG_SN76477_MIXER_PARAMS(0, 1, 0) // mixer A, B, C
+ MCFG_SN76477_ENVELOPE_PARAMS(1, 1) // envelope 1, 2
+ MCFG_SN76477_ENABLE(1) // enable
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+
+ MCFG_DEVICE_ADD("sn76477.2", SN76477)
+ // SHOT B GND: 1,2,26,27 +5V: 15,25,28
+ MCFG_SN76477_NOISE_PARAMS(RES_K(10), RES_K(30), 0) // noise + filter
+ MCFG_SN76477_DECAY_RES(0) // decay_res
+ MCFG_SN76477_ATTACK_PARAMS(0, 0) // attack_decay_cap + attack_res
+ MCFG_SN76477_AMP_RES(RES_K(47)) // amplitude_res
+ MCFG_SN76477_FEEDBACK_RES(RES_K(4.7)) // feedback_res
+ MCFG_SN76477_VCO_PARAMS(0, 0, 0) // VCO volt + cap + res
+ MCFG_SN76477_PITCH_VOLTAGE(0) // pitch_voltage
+ MCFG_SN76477_SLF_PARAMS(0, 0) // slf caps + res
+ MCFG_SN76477_ONESHOT_PARAMS(0, 0) // oneshot caps + res
+ MCFG_SN76477_VCO_MODE(0) // VCO mode
+ MCFG_SN76477_MIXER_PARAMS(0, 1, 0) // mixer A, B, C
+ MCFG_SN76477_ENVELOPE_PARAMS(0, 1) // envelope 1, 2
+ MCFG_SN76477_ENABLE(1) // enable
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
+MACHINE_CONFIG_END
+
+void vanguard_sound_device::device_start()
+{
+ save_item(NAME(m_last_port1));
+}
+
+void vanguard_sound_device::device_reset()
+{
+ // 41.6 Hz update (measured)
+ m_custom->set_music_clock(1 / 41.6);
+}
+
+
+fantasy_sound_device::fantasy_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : fantasy_sound_device(mconfig, FANTASY_SOUND, tag, owner, clock)
+{
+}
+
+fantasy_sound_device::fantasy_sound_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , m_custom(*this, "custom")
+ , m_discrete(*this, "discrete")
+ , m_last_port1(0)
+{
+}
+
+WRITE8_MEMBER(fantasy_sound_device::sound_w)
{
switch (offset)
{
@@ -562,32 +774,26 @@ WRITE8_MEMBER( snk6502_sound_device::fantasy_sound_w )
*/
/* select musical tune in ROM based on sound command byte */
- m_tone_channels[0].base = 0x0000 + ((data & 0x07) << 8);
- m_tone_channels[0].mask = 0xff;
+ m_custom->set_channel_base(0, 0x0000 | ((data & 0x07) << 8));
- m_sound0_stop_on_rollover = 0;
+ m_custom->set_sound0_stop_on_rollover(0);
if (data & 0x08)
- m_tone_channels[0].mute = 0;
+ m_custom->unmute_channel(0);
else
- {
- m_tone_channels[0].offset = m_tone_channels[0].base;
- m_tone_channels[0].mute = 1;
- }
+ m_custom->mute_channel(0);
if (data & 0x10)
- m_tone_channels[2].mute = 0;
+ m_custom->unmute_channel(2);
else
- {
- m_tone_channels[2].offset = 0;
- m_tone_channels[2].mute = 1;
- }
+ m_custom->mute_channel(2);
/* BOMB */
m_discrete->write(space, FANTASY_BOMB_EN, data & 0x80);
m_last_port1 = data;
break;
+
case 1:
/*
bit description
@@ -603,17 +809,14 @@ WRITE8_MEMBER( snk6502_sound_device::fantasy_sound_w )
*/
/* select tune in ROM based on sound command byte */
- m_tone_channels[1].base = 0x0800 + ((data & 0x07) << 8);
- m_tone_channels[1].mask = 0xff;
+ m_custom->set_channel_base(1, 0x0800 | ((data & 0x07) << 8));
if (data & 0x08)
- m_tone_channels[1].mute = 0;
+ m_custom->unmute_channel(1);
else
- {
- m_tone_channels[1].mute = 1;
- m_tone_channels[1].offset = 0;
- }
+ m_custom->mute_channel(1);
break;
+
case 2:
/*
bit description
@@ -628,9 +831,10 @@ WRITE8_MEMBER( snk6502_sound_device::fantasy_sound_w )
7 AS 8 (sound1 waveform)
*/
- build_waveform(0, (data & 0x9) | ((data & 2) << 1) | ((data & 4) >> 1));
- build_waveform(1, data >> 4);
+ m_custom->build_waveform(0, (data & 0x9) | ((data & 2) << 1) | ((data & 4) >> 1));
+ m_custom->build_waveform(1, data >> 4);
break;
+
case 3:
/*
bit description
@@ -646,279 +850,357 @@ WRITE8_MEMBER( snk6502_sound_device::fantasy_sound_w )
*/
/* select tune in ROM based on sound command byte */
- m_tone_channels[2].base = 0x1000 + ((data & 0x70) << 4);
- m_tone_channels[2].mask = 0xff;
+ m_custom->set_channel_base(2, 0x1000 | ((data & 0x70) << 4));
break;
}
}
+WRITE8_MEMBER(fantasy_sound_device::speech_w)
+{
+ static const uint16_t fantasy_table[16] =
+ {
+ 0x04000,
+ 0x04297,
+ 0x044b6,
+ 0x04682,
+ 0x04927,
+ 0x04be0,
+ 0x04cc2,
+ 0x04e36,
+ 0x05000,
+ 0x05163,
+ 0x052c9,
+ 0x053fd,
+ 0,
+ 0,
+ 0,
+ 0
+ };
-/*
- Hitachi HD38880 speech synthesizer chip
-
- I heard that this chip uses PARCOR coefficients but I don't know ROM data format.
- How do I generate samples?
-*/
-
-
-/* HD38880 command */
-#define HD38880_ADSET 2
-#define HD38880_READ 3
-#define HD38880_INT1 4
-#define HD38880_INT2 6
-#define HD38880_SYSPD 8
-#define HD38880_STOP 10
-#define HD38880_CONDT 11
-#define HD38880_START 12
-#define HD38880_SSTART 14
-
-/* HD38880 control bits */
-#define HD38880_CTP 0x10
-#define HD38880_CMV 0x20
-#define HD68880_SYBS 0x0f
-
+ m_custom->speech_w(data, fantasy_table, 0);
+}
-void snk6502_sound_device::speech_w(uint8_t data, const uint16_t *table, int start)
+MACHINE_CONFIG_START(fantasy_sound_device::device_add_mconfig)
+ SPEAKER(config, "mono").front_center();
+
+ MCFG_DEVICE_ADD(m_custom, SNK6502_SOUND, 0)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+
+ MCFG_DEVICE_ADD("samples", SAMPLES)
+ MCFG_SAMPLES_CHANNELS(1)
+ MCFG_SAMPLES_NAMES(fantasy_sample_names)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.5)
+
+ MCFG_DEVICE_ADD("sn76477.1", SN76477)
+ // BOMB GND: 2,9,26,27 +5V: 15,25
+ MCFG_SN76477_NOISE_PARAMS(RES_K(470), RES_M(1.5), CAP_P(220)) // noise + filter
+ MCFG_SN76477_DECAY_RES(0) // decay_res
+ MCFG_SN76477_ATTACK_PARAMS(0, 0) // attack_decay_cap + attack_res
+ MCFG_SN76477_AMP_RES(RES_K(470)) // amplitude_res
+ MCFG_SN76477_FEEDBACK_RES(RES_K(4.7)) // feedback_res
+ MCFG_SN76477_VCO_PARAMS(0, 0, 0) // VCO volt + cap + res
+ MCFG_SN76477_PITCH_VOLTAGE(0) // pitch_voltage
+ MCFG_SN76477_SLF_PARAMS(0, 0) // slf caps + res
+ MCFG_SN76477_ONESHOT_PARAMS(0, 0) // oneshot caps + res
+ MCFG_SN76477_VCO_MODE(0) // VCO mode
+ MCFG_SN76477_MIXER_PARAMS(0, 1, 0) // mixer A, B, C
+ // schematic does not show pin 1 grounded, but it must be.
+ // otherwise it is using the VCO for the envelope, but the VCO is not hooked up
+ MCFG_SN76477_ENVELOPE_PARAMS(0, 1) // envelope 1, 2
+ MCFG_SN76477_ENABLE(0) // enable
+ MCFG_SOUND_ROUTE(0, "discrete", 1.0, 0)
+
+ MCFG_DEVICE_ADD("discrete", DISCRETE, fantasy_discrete)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.5)
+MACHINE_CONFIG_END
+
+void fantasy_sound_device::device_start()
{
- /*
- bit description
- 0 SYBS1
- 1 SYBS2
- 2 SYBS3
- 3 SYBS4
- 4 CTP
- 5 CMV
- 6
- 7
- */
+ save_item(NAME(m_last_port1));
+}
- if ((data & HD38880_CTP) && (data & HD38880_CMV))
- {
- data &= HD68880_SYBS;
+void fantasy_sound_device::device_reset()
+{
+ // 41.6 Hz update (measured)
+ m_custom->set_music_clock(1 / 41.6);
+}
- switch (m_hd38880_cmd)
- {
- case 0:
- switch (data)
- {
- case HD38880_START:
- logerror("speech: START\n");
- if (m_hd38880_data_bytes == 5 && !m_samples->playing(0))
- {
- for (int i = 0; i < 16; i++)
- {
- if (table[i] && table[i] == m_hd38880_addr)
- {
- m_samples->start(0, start + i);
- break;
- }
- }
- }
- break;
+nibbler_sound_device::nibbler_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : fantasy_sound_device(mconfig, NIBBLER_SOUND, tag, owner, clock)
+{
+}
- case HD38880_SSTART:
- logerror("speech: SSTART\n");
- break;
+MACHINE_CONFIG_START(nibbler_sound_device::device_add_mconfig)
+ fantasy_sound_device::device_add_mconfig(config);
- case HD38880_STOP:
- m_samples->stop(0);
- logerror("speech: STOP\n");
- break;
+ MCFG_DEVICE_REMOVE("samples")
+MACHINE_CONFIG_END
- case HD38880_SYSPD:
- m_hd38880_cmd = data;
- break;
- case HD38880_CONDT:
- logerror("speech: CONDT\n");
- break;
+pballoon_sound_device::pballoon_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : fantasy_sound_device(mconfig, PBALLOON_SOUND, tag, owner, clock)
+{
+}
- case HD38880_ADSET:
- m_hd38880_cmd = data;
- m_hd38880_addr = 0;
- m_hd38880_data_bytes = 0;
- break;
+MACHINE_CONFIG_START(pballoon_sound_device::device_add_mconfig)
+ fantasy_sound_device::device_add_mconfig(config);
- case HD38880_READ:
- logerror("speech: READ\n");
- break;
+ MCFG_DEVICE_REMOVE("samples")
+MACHINE_CONFIG_END
- case HD38880_INT1:
- m_hd38880_cmd = data;
- break;
-
- case HD38880_INT2:
- m_hd38880_cmd = data;
- break;
+void pballoon_sound_device::device_reset()
+{
+ // 40.3 Hz update (measured)
+ m_custom->set_music_clock(1 / 40.3);
+}
- case 0:
- // ignore it
- break;
- default:
- logerror("speech: unknown command: 0x%x\n", data);
- }
- break;
+sasuke_sound_device::sasuke_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SASUKE_SOUND, tag, owner, clock)
+ , m_custom(*this, "custom")
+ , m_samples(*this, "samples")
+ , m_last_port1(0)
+{
+}
- case HD38880_INT1:
- logerror("speech: INT1: 0x%x\n", data);
+WRITE8_MEMBER(sasuke_sound_device::sound_w)
+{
+ switch (offset)
+ {
+ case 0:
+ /*
+ bit description
- if (data & 8)
- logerror("speech: triangular waveform\n");
- else
- logerror("speech: impulse waveform\n");
+ 0 hit (ic52)
+ 1 boss start (ic51)
+ 2 shot
+ 3 boss attack (ic48?)
+ 4 ??
+ 5
+ 6
+ 7 reset counter
+ */
- logerror("speech: %sable losing effect of vocal tract\n", data & 4 ? "en" : "dis");
+ if (BIT(~data & m_last_port1, 0))
+ m_samples->start(0, 0);
+ if (BIT(~data & m_last_port1, 1))
+ m_samples->start(1, 1);
+ if (BIT(~data & m_last_port1, 2))
+ m_samples->start(2, 2);
+ if (BIT(~data & m_last_port1, 3))
+ m_samples->start(3, 3);
- if ((data & 2) && (data & 8))
- logerror("speech: use external pitch control\n");
+ if (BIT(data & ~m_last_port1, 7))
+ m_custom->unmute_channel(0);
+ else if (BIT(~data & m_last_port1, 7))
+ m_custom->mute_channel(0);
- m_hd38880_cmd = 0;
- break;
+ m_last_port1 = data;
+ break;
- case HD38880_INT2:
- logerror("speech: INT2: 0x%x\n", data);
+ case 1:
+ /*
+ bit description
- logerror("speech: %d bits / frame\n", data & 8 ? 48 : 96);
- logerror("speech: %d ms / frame\n", data & 4 ? 20 : 10);
- logerror("speech: %sable repeat\n", data & 2 ? "en" : "dis");
- logerror("speech: %d operations\n", ((data & 8) == 0) || (data & 1) ? 10 : 8);
+ 0
+ 1 wave form
+ 2 wave form
+ 3 wave form
+ 4 MUSIC A8
+ 5 MUSIC A9
+ 6 MUSIC A10
+ 7
+ */
- m_hd38880_cmd = 0;
- break;
+ /* select tune in ROM based on sound command byte */
+ m_custom->set_channel_base(0, 0x0000 | ((data & 0x70) << 4));
- case HD38880_SYSPD:
- m_hd38880_speed = ((double)(data + 1)) / 10.0;
- logerror("speech: SYSPD: %1.1f\n", m_hd38880_speed);
- m_hd38880_cmd = 0;
- break;
+ m_custom->set_sound0_stop_on_rollover(1);
- case HD38880_ADSET:
- m_hd38880_addr |= (data << (m_hd38880_data_bytes++ * 4));
- if (m_hd38880_data_bytes == 5)
- {
- logerror("speech: ADSET: 0x%05x\n", m_hd38880_addr);
- m_hd38880_cmd = 0;
- }
- break;
- }
+ /* bit 1-3 sound0 waveform control */
+ m_custom->sasuke_build_waveform((data & 0x0e) >> 1);
+ break;
}
}
+MACHINE_CONFIG_START(sasuke_sound_device::device_add_mconfig)
+ SPEAKER(config, "mono").front_center();
+
+ MCFG_DEVICE_ADD(m_custom, SNK6502_SOUND, 0)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+
+ MCFG_DEVICE_ADD("samples", SAMPLES)
+ MCFG_SAMPLES_CHANNELS(4)
+ MCFG_SAMPLES_NAMES(sasuke_sample_names)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.12)
+
+ MCFG_DEVICE_ADD("sn76477.1", SN76477)
+ // ic48 GND: 2,22,26,27,28 +5V: 1,15,25
+ MCFG_SN76477_NOISE_PARAMS(RES_K(470), RES_K(150), CAP_P(4700)) // noise + filter
+ MCFG_SN76477_DECAY_RES(RES_K(22)) // decay_res
+ MCFG_SN76477_ATTACK_PARAMS(CAP_U(10), RES_K(10)) // attack_decay_cap + attack_res
+ MCFG_SN76477_AMP_RES(RES_K(100)) // amplitude_res
+ MCFG_SN76477_FEEDBACK_RES(RES_K(47)) // feedback_res
+ MCFG_SN76477_VCO_PARAMS(0, 0, 0) // VCO volt + cap + res: N/C
+ MCFG_SN76477_PITCH_VOLTAGE(0) // pitch_voltage: N/C
+ MCFG_SN76477_SLF_PARAMS(0, RES_K(10)) // slf caps + res
+ MCFG_SN76477_ONESHOT_PARAMS(CAP_U(2.2), RES_K(100)) // oneshot caps + res
+ MCFG_SN76477_VCO_MODE(0) // VCO mode
+ MCFG_SN76477_MIXER_PARAMS(0, 1, 0) // mixer A, B, C
+ MCFG_SN76477_ENVELOPE_PARAMS(1, 0) // envelope 1, 2
+ MCFG_SN76477_ENABLE(1) // enable
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+
+ MCFG_DEVICE_ADD("sn76477.2", SN76477)
+ // ic51 GND: 2,26,27 +5V: 1,15,22,25,28
+ MCFG_SN76477_NOISE_PARAMS(RES_K(340), RES_K(47), CAP_P(100)) // noise + filter
+ MCFG_SN76477_DECAY_RES(RES_K(470)) // decay_res
+ MCFG_SN76477_ATTACK_PARAMS(CAP_U(4.7), RES_K(10)) // attack_decay_cap + attack_res
+ MCFG_SN76477_AMP_RES(RES_K(100)) // amplitude_res
+ MCFG_SN76477_FEEDBACK_RES(RES_K(47)) // feedback_res
+ MCFG_SN76477_VCO_PARAMS(0, CAP_P(220), RES_K(1000)) // VCO volt + cap + res
+ MCFG_SN76477_PITCH_VOLTAGE(0) // pitch_voltage: N/C
+ MCFG_SN76477_SLF_PARAMS(0, RES_K(220)) // slf caps + res
+ MCFG_SN76477_ONESHOT_PARAMS(CAP_U(22), RES_K(47)) // oneshot caps + res
+ MCFG_SN76477_VCO_MODE(1) // VCO mode
+ MCFG_SN76477_MIXER_PARAMS(0, 1, 0) // mixer A, B, C
+ MCFG_SN76477_ENVELOPE_PARAMS(1, 1) // envelope 1, 2
+ MCFG_SN76477_ENABLE(1) // enable
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+
+ MCFG_DEVICE_ADD("sn76477.3", SN76477)
+ // ic52 GND: 2,22,27,28 +5V: 1,15,25,26
+ MCFG_SN76477_NOISE_PARAMS(RES_K(330), RES_K(47), CAP_P(100)) // noise + filter
+ MCFG_SN76477_DECAY_RES(RES_K(1)) // decay_res
+ MCFG_SN76477_ATTACK_PARAMS(0, RES_K(1)) // attack_decay_cap + attack_res
+ MCFG_SN76477_AMP_RES(RES_K(100)) // amplitude_res
+ MCFG_SN76477_FEEDBACK_RES(RES_K(47)) // feedback_res
+ MCFG_SN76477_VCO_PARAMS(0, CAP_P(1000), RES_K(1000)) // VCO volt + cap + res
+ MCFG_SN76477_PITCH_VOLTAGE(0) // pitch_voltage: N/C
+ MCFG_SN76477_SLF_PARAMS(CAP_U(1), RES_K(10)) // slf caps + res
+ MCFG_SN76477_ONESHOT_PARAMS(CAP_U(2.2), RES_K(150)) // oneshot caps + res
+ MCFG_SN76477_VCO_MODE(0) // VCO mode
+ MCFG_SN76477_MIXER_PARAMS(1, 1, 0) // mixer A, B, C
+ MCFG_SN76477_ENVELOPE_PARAMS(1, 0) // envelope 1, 2
+ MCFG_SN76477_ENABLE(1) // enable
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+MACHINE_CONFIG_END
+
+void sasuke_sound_device::device_start()
+{
+ save_item(NAME(m_last_port1));
+}
-/*
- vanguard/fantasy speech
+void sasuke_sound_device::device_reset()
+{
+ m_custom->set_music_clock(M_LN2 * (RES_K(18) + RES_K(1)) * CAP_U(1));
- ROM data format (INT2 = 0xf):
- 48 bits / frame
- 20 ms / frame
- enable repeat
- 10 operations
-*/
+ // adjusted (measured through audio recording of pcb)
+ m_custom->set_music_freq(35300);
+}
-WRITE8_MEMBER( snk6502_sound_device::vanguard_speech_w )
-{
- static const uint16_t vanguard_table[16] =
- {
- 0x04000,
- 0x04325,
- 0x044a2,
- 0x045b7,
- 0x046ee,
- 0x04838,
- 0x04984,
- 0x04b01,
- 0x04c38,
- 0x04de6,
- 0x04f43,
- 0x05048,
- 0x05160,
- 0x05289,
- 0x0539e,
- 0x054ce
- };
- speech_w(data, vanguard_table, 2);
+satansat_sound_device::satansat_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SATANSAT_SOUND, tag, owner, clock)
+ , m_custom(*this, "custom")
+ , m_samples(*this, "samples")
+ , m_last_port1(0)
+{
}
-WRITE8_MEMBER( snk6502_sound_device::fantasy_speech_w )
+WRITE8_MEMBER(satansat_sound_device::sound_w)
{
- static const uint16_t fantasy_table[16] =
+ switch (offset)
{
- 0x04000,
- 0x04297,
- 0x044b6,
- 0x04682,
- 0x04927,
- 0x04be0,
- 0x04cc2,
- 0x04e36,
- 0x05000,
- 0x05163,
- 0x052c9,
- 0x053fd,
- 0,
- 0,
- 0,
- 0
- };
+ case 0:
+ /*
+ bit description
- speech_w(data, fantasy_table, 0);
-}
+ */
-//-------------------------------------------------
-// sound_stream_update - handle a stream update
-//-------------------------------------------------
+ /* bit 0 = analog sound trigger */
-void snk6502_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
-{
- stream_sample_t *buffer = outputs[0];
+ /* bit 1 = to 76477 */
- for (int i = 0; i < NUM_CHANNELS; i++)
- validate_tone_channel(i);
+ /* bit 2 = analog sound trigger */
+ if (data & 0x04 && !(m_last_port1 & 0x04))
+ m_samples->start(0, 1);
- while (samples-- > 0)
- {
- int32_t data = 0;
+ if (data & 0x08)
+ m_custom->mute_channel(0);
- for (int i = 0; i < NUM_CHANNELS; i++)
- {
- tone_t &voice = m_tone_channels[i];
- int16_t *form = voice.form;
+ /* bit 4-6 sound0 waveform control */
+ m_custom->sasuke_build_waveform((data & 0x70) >> 4);
- if (!voice.mute && voice.sample_step)
- {
- int cur_pos = voice.sample_cur + voice.sample_step;
- int prev = form[(voice.sample_cur >> FRAC_BITS) & 15];
- int cur = form[(cur_pos >> FRAC_BITS) & 15];
+ /* bit 7 sound1 waveform control */
+ m_custom->satansat_build_waveform((data & 0x80) >> 7);
- /* interpolate */
- data += ((int32_t)prev * (FRAC_ONE - (cur_pos & FRAC_MASK))
- + (int32_t)cur * (cur_pos & FRAC_MASK)) >> FRAC_BITS;
+ m_last_port1 = data;
+ break;
- voice.sample_cur = cur_pos;
- }
- }
+ case 1:
+ /*
+ bit description
- *buffer++ = data;
+ */
- m_tone_clock += FRAC_ONE;
- if (m_tone_clock >= m_tone_clock_expire)
- {
- for (int i = 0; i < NUM_CHANNELS; i++)
- {
- m_tone_channels[i].offset++;
- m_tone_channels[i].offset &= m_tone_channels[i].mask;
+ /* select tune in ROM based on sound command byte */
+ m_custom->set_channel_base(0, 0x0000 | ((data & 0x0e) << 7));
+ m_custom->set_channel_base(1, 0x0800 | ((data & 0x60) << 4), 0x1ff);
- validate_tone_channel(i);
- }
+ m_custom->set_sound0_stop_on_rollover(1);
- if (m_tone_channels[0].offset == 0 && m_sound0_stop_on_rollover)
- m_tone_channels[0].mute = 1;
+ if (data & 0x01)
+ m_custom->unmute_channel(0);
- m_tone_clock -= m_tone_clock_expire;
- }
+ if (data & 0x10)
+ m_custom->unmute_channel(1);
+ else
+ m_custom->mute_channel(1);
+ /* bit 7 = ? */
+ break;
}
}
+
+MACHINE_CONFIG_START(satansat_sound_device::device_add_mconfig)
+ SPEAKER(config, "mono").front_center();
+
+ MCFG_DEVICE_ADD(m_custom, SNK6502_SOUND, 0)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+
+ MCFG_DEVICE_ADD("samples", SAMPLES)
+ MCFG_SAMPLES_CHANNELS(3)
+ MCFG_SAMPLES_NAMES(vanguard_sample_names)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
+
+ MCFG_DEVICE_ADD("sn76477.1", SN76477)
+ // ??? GND: 2,26,27 +5V: 15,25
+ MCFG_SN76477_NOISE_PARAMS(RES_K(470), RES_M(1.5), CAP_P(220)) // noise + filter
+ MCFG_SN76477_DECAY_RES(0) // decay_res
+ MCFG_SN76477_ATTACK_PARAMS(0, 0) // attack_decay_cap + attack_res
+ MCFG_SN76477_AMP_RES(RES_K(47)) // amplitude_res
+ MCFG_SN76477_FEEDBACK_RES(RES_K(47)) // feedback_res
+ MCFG_SN76477_VCO_PARAMS(0, 0, 0) // VCO volt + cap + res
+ MCFG_SN76477_PITCH_VOLTAGE(0) // pitch_voltage
+ MCFG_SN76477_SLF_PARAMS(0, 0) // slf caps + res
+ MCFG_SN76477_ONESHOT_PARAMS(0, 0) // oneshot caps + res
+ MCFG_SN76477_VCO_MODE(0) // VCO mode
+ MCFG_SN76477_MIXER_PARAMS(0, 1, 0) // mixer A, B, C
+ MCFG_SN76477_ENVELOPE_PARAMS(1, 1) // envelope 1, 2
+ MCFG_SN76477_ENABLE(1) // enable
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
+MACHINE_CONFIG_END
+
+void satansat_sound_device::device_start()
+{
+ save_item(NAME(m_last_port1));
+}
+
+void satansat_sound_device::device_reset()
+{
+ // same as sasuke (assumption?)
+ // NOTE: this was set before sasuke was adjusted to a lower freq, please don't modify until measured/confirmed on pcb
+ m_custom->set_music_freq(38000);
+}
diff --git a/src/mame/audio/snk6502.h b/src/mame/audio/snk6502.h
index 32869b1c5da..ce7be05119f 100644
--- a/src/mame/audio/snk6502.h
+++ b/src/mame/audio/snk6502.h
@@ -19,16 +19,20 @@ class snk6502_sound_device : public device_t, public device_sound_interface
public:
snk6502_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_WRITE8_MEMBER( sasuke_sound_w );
- DECLARE_WRITE8_MEMBER( satansat_sound_w );
- DECLARE_WRITE8_MEMBER( vanguard_sound_w );
- DECLARE_WRITE8_MEMBER( vanguard_speech_w );
- DECLARE_WRITE8_MEMBER( fantasy_sound_w );
- DECLARE_WRITE8_MEMBER( fantasy_speech_w );
+ DECLARE_CUSTOM_INPUT_MEMBER(music0_playing);
- void set_music_clock(double clock_time);
void set_music_freq(int freq);
- int music0_playing();
+ void set_music_clock(double clock_time);
+ void set_channel_base(int channel, int base, int mask = 0xff);
+ void mute_channel(int channel);
+ void unmute_channel(int channel);
+ void set_sound0_stop_on_rollover(int value) { m_sound0_stop_on_rollover = value; }
+
+ void speech_w(uint8_t data, const uint16_t *table, int start);
+
+ void build_waveform(int channel, int mask);
+ void sasuke_build_waveform(int mask);
+ void satansat_build_waveform(int mask);
protected:
// device-level overrides
@@ -58,31 +62,133 @@ private:
int32_t m_tone_clock;
sound_stream * m_tone_stream;
- optional_device<sn76477_device> m_sn76477_2;
- optional_device<discrete_device> m_discrete;
optional_device<samples_device> m_samples;
required_memory_region m_rom;
int m_sound0_stop_on_rollover;
- uint8_t m_last_port1;
int m_hd38880_cmd;
uint32_t m_hd38880_addr;
int m_hd38880_data_bytes;
double m_hd38880_speed;
- inline void validate_tone_channel(int channel);
- void sasuke_build_waveform(int mask);
- void satansat_build_waveform(int mask);
- void build_waveform(int channel, int mask);
- void speech_w(uint8_t data, const uint16_t *table, int start);
+ void validate_tone_channel(int channel);
+};
+
+
+class vanguard_sound_device : public device_t
+{
+public:
+ vanguard_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_WRITE8_MEMBER( sound_w );
+ DECLARE_WRITE8_MEMBER( speech_w );
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ required_device<snk6502_sound_device> m_custom;
+ required_device<sn76477_device> m_sn76477_2;
+ required_device<samples_device> m_samples;
+
+ uint8_t m_last_port1;
+};
+
+
+class fantasy_sound_device : public device_t
+{
+public:
+ fantasy_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_WRITE8_MEMBER( sound_w );
+ DECLARE_WRITE8_MEMBER( speech_w );
+
+protected:
+ fantasy_sound_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ required_device<snk6502_sound_device> m_custom;
+
+private:
+ required_device<discrete_device> m_discrete;
+
+ uint8_t m_last_port1;
+};
+
+
+class nibbler_sound_device : public fantasy_sound_device
+{
+public:
+ nibbler_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+
+class pballoon_sound_device : public fantasy_sound_device
+{
+public:
+ pballoon_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_reset() override;
+};
+
+
+class sasuke_sound_device : public device_t
+{
+public:
+ sasuke_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_WRITE8_MEMBER(sound_w);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ required_device<snk6502_sound_device> m_custom;
+ required_device<samples_device> m_samples;
+
+ uint8_t m_last_port1;
+};
+
+
+class satansat_sound_device : public device_t
+{
+public:
+ satansat_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_WRITE8_MEMBER(sound_w);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ required_device<snk6502_sound_device> m_custom;
+ required_device<samples_device> m_samples;
+
+ uint8_t m_last_port1;
};
-DECLARE_DEVICE_TYPE(SNK6502, snk6502_sound_device)
-DISCRETE_SOUND_EXTERN( fantasy_discrete );
+DECLARE_DEVICE_TYPE(SNK6502_SOUND, snk6502_sound_device)
-extern char const *const sasuke_sample_names[];
-extern char const *const vanguard_sample_names[];
-extern char const *const fantasy_sample_names[];
+DECLARE_DEVICE_TYPE(VANGUARD_SOUND, vanguard_sound_device)
+DECLARE_DEVICE_TYPE(FANTASY_SOUND, fantasy_sound_device)
+DECLARE_DEVICE_TYPE(NIBBLER_SOUND, nibbler_sound_device)
+DECLARE_DEVICE_TYPE(PBALLOON_SOUND, pballoon_sound_device)
+DECLARE_DEVICE_TYPE(SASUKE_SOUND, sasuke_sound_device)
+DECLARE_DEVICE_TYPE(SATANSAT_SOUND, satansat_sound_device)
#endif // MAME_AUDIO_SNK6502_H
diff --git a/src/mame/drivers/snk6502.cpp b/src/mame/drivers/snk6502.cpp
index a37d836fcfa..2fd8eeea006 100644
--- a/src/mame/drivers/snk6502.cpp
+++ b/src/mame/drivers/snk6502.cpp
@@ -330,11 +330,6 @@ void snk6502_state::sasuke_start_counter()
*
*************************************/
-CUSTOM_INPUT_MEMBER(snk6502_state::snk6502_music0_r)
-{
- return (m_sound->music0_playing() ? 0x01 : 0x00);
-}
-
CUSTOM_INPUT_MEMBER(snk6502_state::sasuke_count_r)
{
return (m_sasuke_counter >> 4);
@@ -357,7 +352,7 @@ void snk6502_state::sasuke_map(address_map &map)
map(0x3000, 0x3000).w("crtc", FUNC(mc6845_device::address_w));
map(0x3001, 0x3001).w("crtc", FUNC(mc6845_device::register_w));
map(0x4000, 0x8fff).rom();
- map(0xb000, 0xb001).w(m_sound, FUNC(snk6502_sound_device::sasuke_sound_w));
+ map(0xb000, 0xb001).w("snk6502", FUNC(sasuke_sound_device::sound_w));
map(0xb002, 0xb002).w(this, FUNC(snk6502_state::satansat_b002_w)); /* flip screen & irq enable */
map(0xb003, 0xb003).w(this, FUNC(snk6502_state::satansat_backcolor_w));
map(0xb004, 0xb004).portr("IN0");
@@ -377,7 +372,7 @@ void snk6502_state::satansat_map(address_map &map)
map(0x3000, 0x3000).w("crtc", FUNC(mc6845_device::address_w));
map(0x3001, 0x3001).w("crtc", FUNC(mc6845_device::register_w));
map(0x4000, 0x9fff).rom();
- map(0xb000, 0xb001).w(m_sound, FUNC(snk6502_sound_device::satansat_sound_w));
+ map(0xb000, 0xb001).w("snk6502", FUNC(satansat_sound_device::sound_w));
map(0xb002, 0xb002).w(this, FUNC(snk6502_state::satansat_b002_w)); /* flip screen & irq enable */
map(0xb003, 0xb003).w(this, FUNC(snk6502_state::satansat_backcolor_w));
map(0xb004, 0xb004).portr("IN0");
@@ -396,7 +391,7 @@ void snk6502_state::vanguard_map(address_map &map)
map(0x1000, 0x1fff).ram().w(this, FUNC(snk6502_state::charram_w)).share("charram");
map(0x3000, 0x3000).w("crtc", FUNC(mc6845_device::address_w));
map(0x3001, 0x3001).w("crtc", FUNC(mc6845_device::register_w));
- map(0x3100, 0x3102).w(m_sound, FUNC(snk6502_sound_device::vanguard_sound_w));
+ map(0x3100, 0x3102).w("snk6502", FUNC(vanguard_sound_device::sound_w));
map(0x3103, 0x3103).w(this, FUNC(snk6502_state::flipscreen_w));
map(0x3104, 0x3104).portr("IN0");
map(0x3105, 0x3105).portr("IN1");
@@ -404,51 +399,51 @@ void snk6502_state::vanguard_map(address_map &map)
map(0x3107, 0x3107).portr("IN2");
map(0x3200, 0x3200).w(this, FUNC(snk6502_state::scrollx_w));
map(0x3300, 0x3300).w(this, FUNC(snk6502_state::scrolly_w));
- map(0x3400, 0x3400).w(m_sound, FUNC(snk6502_sound_device::vanguard_speech_w)); // speech
+ map(0x3400, 0x3400).w("snk6502", FUNC(vanguard_sound_device::speech_w)); // speech
map(0x4000, 0xbfff).rom();
map(0xf000, 0xffff).rom(); /* for the reset / interrupt vectors */
}
-void snk6502_state::fantasy_map(address_map &map)
+void fantasy_state::fantasy_map(address_map &map)
{
map(0x0000, 0x03ff).ram();
- map(0x0400, 0x07ff).ram().w(this, FUNC(snk6502_state::videoram2_w)).share("videoram2");
- map(0x0800, 0x0bff).ram().w(this, FUNC(snk6502_state::videoram_w)).share("videoram");
- map(0x0c00, 0x0fff).ram().w(this, FUNC(snk6502_state::colorram_w)).share("colorram");
- map(0x1000, 0x1fff).ram().w(this, FUNC(snk6502_state::charram_w)).share("charram");
+ map(0x0400, 0x07ff).ram().w(this, FUNC(fantasy_state::videoram2_w)).share("videoram2");
+ map(0x0800, 0x0bff).ram().w(this, FUNC(fantasy_state::videoram_w)).share("videoram");
+ map(0x0c00, 0x0fff).ram().w(this, FUNC(fantasy_state::colorram_w)).share("colorram");
+ map(0x1000, 0x1fff).ram().w(this, FUNC(fantasy_state::charram_w)).share("charram");
map(0x2000, 0x2000).w("crtc", FUNC(mc6845_device::address_w));
map(0x2001, 0x2001).w("crtc", FUNC(mc6845_device::register_w));
- map(0x2100, 0x2102).w(m_sound, FUNC(snk6502_sound_device::fantasy_sound_w));
- map(0x2103, 0x2103).w(this, FUNC(snk6502_state::fantasy_flipscreen_w)); // affects both video and sound
+ map(0x2100, 0x2102).w("snk6502", FUNC(fantasy_sound_device::sound_w));
+ map(0x2103, 0x2103).w(this, FUNC(fantasy_state::fantasy_flipscreen_w)); // affects both video and sound
map(0x2104, 0x2104).portr("IN0");
map(0x2105, 0x2105).portr("IN1");
map(0x2106, 0x2106).portr("DSW");
map(0x2107, 0x2107).portr("IN2");
- map(0x2200, 0x2200).w(this, FUNC(snk6502_state::scrollx_w));
- map(0x2300, 0x2300).w(this, FUNC(snk6502_state::scrolly_w));
- map(0x2400, 0x2400).w(m_sound, FUNC(snk6502_sound_device::fantasy_speech_w)); // speech
+ map(0x2200, 0x2200).w(this, FUNC(fantasy_state::scrollx_w));
+ map(0x2300, 0x2300).w(this, FUNC(fantasy_state::scrolly_w));
+ map(0x2400, 0x2400).w("snk6502", FUNC(fantasy_sound_device::speech_w)); // speech
map(0x3000, 0xbfff).rom();
map(0xf000, 0xffff).rom();
}
-void snk6502_state::pballoon_map(address_map &map)
+void fantasy_state::pballoon_map(address_map &map)
{
map(0x0000, 0x03ff).ram();
- map(0x0400, 0x07ff).ram().w(this, FUNC(snk6502_state::videoram2_w)).share("videoram2");
- map(0x0800, 0x0bff).ram().w(this, FUNC(snk6502_state::videoram_w)).share("videoram");
- map(0x0c00, 0x0fff).ram().w(this, FUNC(snk6502_state::colorram_w)).share("colorram");
- map(0x1000, 0x1fff).ram().w(this, FUNC(snk6502_state::charram_w)).share("charram");
+ map(0x0400, 0x07ff).ram().w(this, FUNC(fantasy_state::videoram2_w)).share("videoram2");
+ map(0x0800, 0x0bff).ram().w(this, FUNC(fantasy_state::videoram_w)).share("videoram");
+ map(0x0c00, 0x0fff).ram().w(this, FUNC(fantasy_state::colorram_w)).share("colorram");
+ map(0x1000, 0x1fff).ram().w(this, FUNC(fantasy_state::charram_w)).share("charram");
map(0x3000, 0x9fff).rom();
map(0xb000, 0xb000).w("crtc", FUNC(mc6845_device::address_w));
map(0xb001, 0xb001).w("crtc", FUNC(mc6845_device::register_w));
- map(0xb100, 0xb102).w(m_sound, FUNC(snk6502_sound_device::fantasy_sound_w));
- map(0xb103, 0xb103).w(this, FUNC(snk6502_state::fantasy_flipscreen_w)); // affects both video and sound
+ map(0xb100, 0xb102).w("snk6502", FUNC(fantasy_sound_device::sound_w));
+ map(0xb103, 0xb103).w(this, FUNC(fantasy_state::fantasy_flipscreen_w)); // affects both video and sound
map(0xb104, 0xb104).portr("IN0");
map(0xb105, 0xb105).portr("IN1");
map(0xb106, 0xb106).portr("DSW");
map(0xb107, 0xb107).portr("IN2");
- map(0xb200, 0xb200).w(this, FUNC(snk6502_state::scrollx_w));
- map(0xb300, 0xb300).w(this, FUNC(snk6502_state::scrolly_w));
+ map(0xb200, 0xb200).w(this, FUNC(fantasy_state::scrollx_w));
+ map(0xb300, 0xb300).w(this, FUNC(fantasy_state::scrolly_w));
map(0xf000, 0xffff).rom();
}
@@ -534,7 +529,7 @@ static INPUT_PORTS_START( satansat )
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_START1 )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_START2 )
PORT_BIT( 0x7c, IP_ACTIVE_HIGH, IPT_UNKNOWN )
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(DEVICE_SELF, snk6502_state,snk6502_music0_r, nullptr) /* music0 playing */
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER("snk6502:custom", snk6502_sound_device,music0_playing, nullptr) /* music0 playing */
PORT_START("IN2")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_IMPULSE(1) PORT_CHANGED_MEMBER(DEVICE_SELF, snk6502_state,coin_inserted, 0)
@@ -599,7 +594,7 @@ static INPUT_PORTS_START( vanguard )
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_COCKTAIL /* fire left */
PORT_MODIFY("IN2")
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(DEVICE_SELF, snk6502_state,snk6502_music0_r, nullptr) /* music0 playing */
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER("snk6502:custom", snk6502_sound_device,music0_playing, nullptr) /* music0 playing */
INPUT_PORTS_END
static INPUT_PORTS_START( fantasy )
@@ -797,35 +792,9 @@ INTERRUPT_GEN_MEMBER(snk6502_state::snk6502_interrupt)
MACHINE_RESET_MEMBER(snk6502_state,sasuke)
{
- m_sound->set_music_clock(M_LN2 * (RES_K(18) + RES_K(1)) * CAP_U(1));
-
- // adjusted (measured through audio recording of pcb)
- m_sound->set_music_freq(35300);
-
- sasuke_start_counter();
-}
-
-MACHINE_RESET_MEMBER(snk6502_state,satansat)
-{
- // same as sasuke (assumption?)
- // NOTE: this was set before sasuke was adjusted to a lower freq, please don't modify until measured/confirmed on pcb
- m_sound->set_music_freq(38000);
-
sasuke_start_counter();
}
-MACHINE_RESET_MEMBER(snk6502_state,vanguard)
-{
- // 41.6 Hz update (measured)
- m_sound->set_music_clock(1 / 41.6);
-}
-
-MACHINE_RESET_MEMBER(snk6502_state,pballoon)
-{
- // 40.3 Hz update (measured)
- m_sound->set_music_clock(1 / 40.3);
-}
-
/*************************************
*
@@ -865,67 +834,7 @@ MACHINE_CONFIG_START(snk6502_state::sasuke)
MCFG_TIMER_DRIVER_ADD_PERIODIC("sasuke_timer", snk6502_state, sasuke_update_counter, attotime::from_hz(MASTER_CLOCK / 8))
// sound hardware
- SPEAKER(config, "mono").front_center();
-
- MCFG_DEVICE_ADD("snk6502", SNK6502, 0)
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
-
-
- MCFG_DEVICE_ADD("samples", SAMPLES)
- MCFG_SAMPLES_CHANNELS(4)
- MCFG_SAMPLES_NAMES(sasuke_sample_names)
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.12)
-
- MCFG_DEVICE_ADD("sn76477.1", SN76477)
- // ic48 GND: 2,22,26,27,28 +5V: 1,15,25
- MCFG_SN76477_NOISE_PARAMS(RES_K(470), RES_K(150), CAP_P(4700)) // noise + filter
- MCFG_SN76477_DECAY_RES(RES_K(22)) // decay_res
- MCFG_SN76477_ATTACK_PARAMS(CAP_U(10), RES_K(10)) // attack_decay_cap + attack_res
- MCFG_SN76477_AMP_RES(RES_K(100)) // amplitude_res
- MCFG_SN76477_FEEDBACK_RES(RES_K(47)) // feedback_res
- MCFG_SN76477_VCO_PARAMS(0, 0, 0) // VCO volt + cap + res: N/C
- MCFG_SN76477_PITCH_VOLTAGE(0) // pitch_voltage: N/C
- MCFG_SN76477_SLF_PARAMS(0, RES_K(10)) // slf caps + res
- MCFG_SN76477_ONESHOT_PARAMS(CAP_U(2.2), RES_K(100)) // oneshot caps + res
- MCFG_SN76477_VCO_MODE(0) // VCO mode
- MCFG_SN76477_MIXER_PARAMS(0, 1, 0) // mixer A, B, C
- MCFG_SN76477_ENVELOPE_PARAMS(1, 0) // envelope 1, 2
- MCFG_SN76477_ENABLE(1) // enable
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
-
- MCFG_DEVICE_ADD("sn76477.2", SN76477)
- // ic51 GND: 2,26,27 +5V: 1,15,22,25,28
- MCFG_SN76477_NOISE_PARAMS(RES_K(340), RES_K(47), CAP_P(100)) // noise + filter
- MCFG_SN76477_DECAY_RES(RES_K(470)) // decay_res
- MCFG_SN76477_ATTACK_PARAMS(CAP_U(4.7), RES_K(10)) // attack_decay_cap + attack_res
- MCFG_SN76477_AMP_RES(RES_K(100)) // amplitude_res
- MCFG_SN76477_FEEDBACK_RES(RES_K(47)) // feedback_res
- MCFG_SN76477_VCO_PARAMS(0, CAP_P(220), RES_K(1000)) // VCO volt + cap + res
- MCFG_SN76477_PITCH_VOLTAGE(0) // pitch_voltage: N/C
- MCFG_SN76477_SLF_PARAMS(0, RES_K(220)) // slf caps + res
- MCFG_SN76477_ONESHOT_PARAMS(CAP_U(22), RES_K(47)) // oneshot caps + res
- MCFG_SN76477_VCO_MODE(1) // VCO mode
- MCFG_SN76477_MIXER_PARAMS(0, 1, 0) // mixer A, B, C
- MCFG_SN76477_ENVELOPE_PARAMS(1, 1) // envelope 1, 2
- MCFG_SN76477_ENABLE(1) // enable
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
-
- MCFG_DEVICE_ADD("sn76477.3", SN76477)
- // ic52 GND: 2,22,27,28 +5V: 1,15,25,26
- MCFG_SN76477_NOISE_PARAMS(RES_K(330), RES_K(47), CAP_P(100)) // noise + filter
- MCFG_SN76477_DECAY_RES(RES_K(1)) // decay_res
- MCFG_SN76477_ATTACK_PARAMS(0, RES_K(1)) // attack_decay_cap + attack_res
- MCFG_SN76477_AMP_RES(RES_K(100)) // amplitude_res
- MCFG_SN76477_FEEDBACK_RES(RES_K(47)) // feedback_res
- MCFG_SN76477_VCO_PARAMS(0, CAP_P(1000), RES_K(1000)) // VCO volt + cap + res
- MCFG_SN76477_PITCH_VOLTAGE(0) // pitch_voltage: N/C
- MCFG_SN76477_SLF_PARAMS(CAP_U(1), RES_K(10)) // slf caps + res
- MCFG_SN76477_ONESHOT_PARAMS(CAP_U(2.2), RES_K(150)) // oneshot caps + res
- MCFG_SN76477_VCO_MODE(0) // VCO mode
- MCFG_SN76477_MIXER_PARAMS(1, 1, 0) // mixer A, B, C
- MCFG_SN76477_ENVELOPE_PARAMS(1, 0) // envelope 1, 2
- MCFG_SN76477_ENABLE(1) // enable
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+ MCFG_DEVICE_ADD("snk6502", SASUKE_SOUND, 0)
MACHINE_CONFIG_END
MACHINE_CONFIG_START(snk6502_state::satansat)
@@ -934,36 +843,11 @@ MACHINE_CONFIG_START(snk6502_state::satansat)
MCFG_DEVICE_MODIFY("maincpu")
MCFG_DEVICE_PROGRAM_MAP(satansat_map)
- MCFG_MACHINE_RESET_OVERRIDE(snk6502_state,satansat)
-
// video hardware
MCFG_GFXDECODE_MODIFY("gfxdecode", gfx_satansat)
// sound hardware
- MCFG_DEVICE_MODIFY("samples")
- MCFG_SAMPLES_CHANNELS(3)
- MCFG_SAMPLES_NAMES(vanguard_sample_names)
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
-
- MCFG_DEVICE_REPLACE("sn76477.1", SN76477)
- // ??? GND: 2,26,27 +5V: 15,25
- MCFG_SN76477_NOISE_PARAMS(RES_K(470), RES_M(1.5), CAP_P(220)) // noise + filter
- MCFG_SN76477_DECAY_RES(0) // decay_res
- MCFG_SN76477_ATTACK_PARAMS(0, 0) // attack_decay_cap + attack_res
- MCFG_SN76477_AMP_RES(RES_K(47)) // amplitude_res
- MCFG_SN76477_FEEDBACK_RES(RES_K(47)) // feedback_res
- MCFG_SN76477_VCO_PARAMS(0, 0, 0) // VCO volt + cap + res
- MCFG_SN76477_PITCH_VOLTAGE(0) // pitch_voltage
- MCFG_SN76477_SLF_PARAMS(0, 0) // slf caps + res
- MCFG_SN76477_ONESHOT_PARAMS(0, 0) // oneshot caps + res
- MCFG_SN76477_VCO_MODE(0) // VCO mode
- MCFG_SN76477_MIXER_PARAMS(0, 1, 0) // mixer A, B, C
- MCFG_SN76477_ENVELOPE_PARAMS(1, 1) // envelope 1, 2
- MCFG_SN76477_ENABLE(1) // enable
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
-
- MCFG_DEVICE_REMOVE("sn76477.2")
- MCFG_DEVICE_REMOVE("sn76477.3")
+ MCFG_DEVICE_REPLACE("snk6502", SATANSAT_SOUND, 0)
MACHINE_CONFIG_END
MACHINE_CONFIG_START(snk6502_state::vanguard)
@@ -974,10 +858,7 @@ MACHINE_CONFIG_START(snk6502_state::vanguard)
MCFG_DEVICE_PROGRAM_MAP(vanguard_map)
MCFG_DEVICE_VBLANK_INT_DRIVER("screen", snk6502_state, snk6502_interrupt)
- MCFG_MACHINE_RESET_OVERRIDE(snk6502_state,vanguard)
-
// video hardware
-
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_REFRESH_RATE((MASTER_CLOCK / 16) / (45 * 32 * 8))
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
@@ -997,104 +878,38 @@ MACHINE_CONFIG_START(snk6502_state::vanguard)
MCFG_MC6845_CHAR_WIDTH(8)
// sound hardware
- SPEAKER(config, "mono").front_center();
-
- MCFG_DEVICE_ADD("snk6502", SNK6502, 0)
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
-
- MCFG_DEVICE_ADD("samples", SAMPLES)
- MCFG_SAMPLES_CHANNELS(3)
- MCFG_SAMPLES_NAMES(vanguard_sample_names)
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
-
- MCFG_DEVICE_ADD("sn76477.1", SN76477)
- // SHOT A GND: 2,9,26,27 +5V: 15,25
- MCFG_SN76477_NOISE_PARAMS(RES_K(470), RES_M(1.5), CAP_P(220)) // noise + filter
- MCFG_SN76477_DECAY_RES(0) // decay_res
- MCFG_SN76477_ATTACK_PARAMS(0, 0) // attack_decay_cap + attack_res
- MCFG_SN76477_AMP_RES(RES_K(47)) // amplitude_res
- MCFG_SN76477_FEEDBACK_RES(RES_K(4.7)) // feedback_res
- MCFG_SN76477_VCO_PARAMS(0, 0, 0) // VCO volt + cap + res
- MCFG_SN76477_PITCH_VOLTAGE(0) // pitch_voltage
- MCFG_SN76477_SLF_PARAMS(0, 0) // slf caps + res
- MCFG_SN76477_ONESHOT_PARAMS(0, 0) // oneshot caps + res
- MCFG_SN76477_VCO_MODE(0) // VCO mode
- MCFG_SN76477_MIXER_PARAMS(0, 1, 0) // mixer A, B, C
- MCFG_SN76477_ENVELOPE_PARAMS(1, 1) // envelope 1, 2
- MCFG_SN76477_ENABLE(1) // enable
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
-
- MCFG_DEVICE_ADD("sn76477.2", SN76477)
- // SHOT B GND: 1,2,26,27 +5V: 15,25,28
- MCFG_SN76477_NOISE_PARAMS(RES_K(10), RES_K(30), 0) // noise + filter
- MCFG_SN76477_DECAY_RES(0) // decay_res
- MCFG_SN76477_ATTACK_PARAMS(0, 0) // attack_decay_cap + attack_res
- MCFG_SN76477_AMP_RES(RES_K(47)) // amplitude_res
- MCFG_SN76477_FEEDBACK_RES(RES_K(4.7)) // feedback_res
- MCFG_SN76477_VCO_PARAMS(0, 0, 0) // VCO volt + cap + res
- MCFG_SN76477_PITCH_VOLTAGE(0) // pitch_voltage
- MCFG_SN76477_SLF_PARAMS(0, 0) // slf caps + res
- MCFG_SN76477_ONESHOT_PARAMS(0, 0) // oneshot caps + res
- MCFG_SN76477_VCO_MODE(0) // VCO mode
- MCFG_SN76477_MIXER_PARAMS(0, 1, 0) // mixer A, B, C
- MCFG_SN76477_ENVELOPE_PARAMS(0, 1) // envelope 1, 2
- MCFG_SN76477_ENABLE(1) // enable
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
+ MCFG_DEVICE_ADD("snk6502", VANGUARD_SOUND, 0)
MACHINE_CONFIG_END
-MACHINE_CONFIG_START(snk6502_state::fantasy)
+MACHINE_CONFIG_START(fantasy_state::fantasy)
vanguard(config);
+
// basic machine hardware
MCFG_DEVICE_MODIFY("maincpu")
MCFG_DEVICE_PROGRAM_MAP(fantasy_map)
// sound hardware
- MCFG_DEVICE_MODIFY("samples")
- MCFG_SAMPLES_CHANNELS(1)
- MCFG_SAMPLES_NAMES(fantasy_sample_names)
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.5)
-
- MCFG_DEVICE_REPLACE("sn76477.1", SN76477)
- // BOMB GND: 2,9,26,27 +5V: 15,25
- MCFG_SN76477_NOISE_PARAMS(RES_K(470), RES_M(1.5), CAP_P(220)) // noise + filter
- MCFG_SN76477_DECAY_RES(0) // decay_res
- MCFG_SN76477_ATTACK_PARAMS(0, 0) // attack_decay_cap + attack_res
- MCFG_SN76477_AMP_RES(RES_K(470)) // amplitude_res
- MCFG_SN76477_FEEDBACK_RES(RES_K(4.7)) // feedback_res
- MCFG_SN76477_VCO_PARAMS(0, 0, 0) // VCO volt + cap + res
- MCFG_SN76477_PITCH_VOLTAGE(0) // pitch_voltage
- MCFG_SN76477_SLF_PARAMS(0, 0) // slf caps + res
- MCFG_SN76477_ONESHOT_PARAMS(0, 0) // oneshot caps + res
- MCFG_SN76477_VCO_MODE(0) // VCO mode
- MCFG_SN76477_MIXER_PARAMS(0, 1, 0) // mixer A, B, C
- // schematic does not show pin 1 grounded, but it must be.
- // otherwise it is using the VCO for the envelope, but the VCO is not hooked up
- MCFG_SN76477_ENVELOPE_PARAMS(0, 1) // envelope 1, 2
- MCFG_SN76477_ENABLE(0) // enable
- MCFG_SOUND_ROUTE(0, "discrete", 1.0, 0)
-
- MCFG_DEVICE_ADD("discrete", DISCRETE, fantasy_discrete)
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.5)
-
- MCFG_DEVICE_REMOVE("sn76477.2")
+ MCFG_DEVICE_REPLACE("snk6502", FANTASY_SOUND, 0)
MACHINE_CONFIG_END
-MACHINE_CONFIG_START(snk6502_state::nibbler)
+MACHINE_CONFIG_START(fantasy_state::nibbler)
fantasy(config);
// sound hardware
- MCFG_DEVICE_REMOVE("samples")
+ MCFG_DEVICE_REPLACE("snk6502", NIBBLER_SOUND, 0)
MACHINE_CONFIG_END
-MACHINE_CONFIG_START(snk6502_state::pballoon)
+MACHINE_CONFIG_START(fantasy_state::pballoon)
nibbler(config);
+
// basic machine hardware
MCFG_DEVICE_MODIFY("maincpu")
MCFG_DEVICE_PROGRAM_MAP(pballoon_map)
- MCFG_MACHINE_RESET_OVERRIDE(snk6502_state,pballoon)
+ MCFG_VIDEO_START_OVERRIDE(snk6502_state, pballoon)
- MCFG_VIDEO_START_OVERRIDE(snk6502_state, pballoon )
+ // sound hardware
+ MCFG_DEVICE_REPLACE("snk6502", PBALLOON_SOUND, 0)
MACHINE_CONFIG_END
@@ -1715,16 +1530,16 @@ GAME( 1981, satansatind, satansat, satansat, satansat, snk6502_state, empty_init
GAME( 1981, vanguard, 0, vanguard, vanguard, snk6502_state, empty_init, ROT90, "SNK", "Vanguard (SNK)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
GAME( 1981, vanguardc, vanguard, vanguard, vanguard, snk6502_state, empty_init, ROT90, "SNK (Centuri license)", "Vanguard (Centuri)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
GAME( 1981, vanguardj, vanguard, vanguard, vanguard, snk6502_state, empty_init, ROT90, "SNK", "Vanguard (Japan)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
-GAME( 1981, fantasyu, 0, fantasy, fantasyu, snk6502_state, empty_init, ROT90, "SNK (Rock-Ola license)", "Fantasy (US)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
-GAME( 1981, fantasyg, fantasyu, fantasy, fantasy, snk6502_state, empty_init, ROT90, "SNK", "Fantasy (Germany, set 1)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) // bootleg?
-GAME( 1981, fantasyg2, fantasyu, fantasy, fantasy, snk6502_state, empty_init, ROT90, "SNK", "Fantasy (Germany, set 2)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) // bootleg?
-GAME( 1981, fantasyj, fantasyu, fantasy, fantasyu, snk6502_state, empty_init, ROT90, "SNK", "Fantasy (Japan)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
-GAME( 1982, pballoon, 0, pballoon, pballoon, snk6502_state, empty_init, ROT90, "SNK", "Pioneer Balloon", MACHINE_SUPPORTS_SAVE )
-GAME( 1982, pballoonr, pballoon, pballoon, pballoon, snk6502_state, empty_init, ROT90, "SNK (Rock-Ola license)", "Pioneer Balloon (Rock-Ola license)", MACHINE_SUPPORTS_SAVE )
-GAME( 1982, nibbler, 0, nibbler, nibbler, snk6502_state, empty_init, ROT90, "Rock-Ola", "Nibbler (rev 9)", MACHINE_SUPPORTS_SAVE )
-GAME( 1982, nibblera, nibbler, nibbler, nibbler, snk6502_state, empty_init, ROT90, "Rock-Ola", "Nibbler (rev 9, alternate set)", MACHINE_SUPPORTS_SAVE )
-GAME( 1982, nibbler8, nibbler, nibbler, nibbler8, snk6502_state, empty_init, ROT90, "Rock-Ola", "Nibbler (rev 8)", MACHINE_SUPPORTS_SAVE )
-GAME( 1982, nibbler7, nibbler, nibbler, nibbler8, snk6502_state, empty_init, ROT90, "Rock-Ola", "Nibbler (rev 7)", MACHINE_SUPPORTS_SAVE )
-GAME( 1982, nibbler6, nibbler, nibbler, nibbler6, snk6502_state, empty_init, ROT90, "Rock-Ola", "Nibbler (rev 6)", MACHINE_SUPPORTS_SAVE )
-GAME( 1982, nibblerp, nibbler, nibbler, nibbler6, snk6502_state, empty_init, ROT90, "Rock-Ola", "Nibbler (Pioneer Balloon conversion - rev 6)", MACHINE_SUPPORTS_SAVE )
-GAME( 1983, nibblero, nibbler, nibbler, nibbler8, snk6502_state, empty_init, ROT90, "Rock-Ola (Olympia license)", "Nibbler (Olympia - rev 8)", MACHINE_SUPPORTS_SAVE )
+GAME( 1981, fantasyu, 0, fantasy, fantasyu, fantasy_state, empty_init, ROT90, "SNK (Rock-Ola license)", "Fantasy (US)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
+GAME( 1981, fantasyg, fantasyu, fantasy, fantasy, fantasy_state, empty_init, ROT90, "SNK", "Fantasy (Germany, set 1)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) // bootleg?
+GAME( 1981, fantasyg2, fantasyu, fantasy, fantasy, fantasy_state, empty_init, ROT90, "SNK", "Fantasy (Germany, set 2)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) // bootleg?
+GAME( 1981, fantasyj, fantasyu, fantasy, fantasyu, fantasy_state, empty_init, ROT90, "SNK", "Fantasy (Japan)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
+GAME( 1982, pballoon, 0, pballoon, pballoon, fantasy_state, empty_init, ROT90, "SNK", "Pioneer Balloon", MACHINE_SUPPORTS_SAVE )
+GAME( 1982, pballoonr, pballoon, pballoon, pballoon, fantasy_state, empty_init, ROT90, "SNK (Rock-Ola license)", "Pioneer Balloon (Rock-Ola license)", MACHINE_SUPPORTS_SAVE )
+GAME( 1982, nibbler, 0, nibbler, nibbler, fantasy_state, empty_init, ROT90, "Rock-Ola", "Nibbler (rev 9)", MACHINE_SUPPORTS_SAVE )
+GAME( 1982, nibblera, nibbler, nibbler, nibbler, fantasy_state, empty_init, ROT90, "Rock-Ola", "Nibbler (rev 9, alternate set)", MACHINE_SUPPORTS_SAVE )
+GAME( 1982, nibbler8, nibbler, nibbler, nibbler8, fantasy_state, empty_init, ROT90, "Rock-Ola", "Nibbler (rev 8)", MACHINE_SUPPORTS_SAVE )
+GAME( 1982, nibbler7, nibbler, nibbler, nibbler8, fantasy_state, empty_init, ROT90, "Rock-Ola", "Nibbler (rev 7)", MACHINE_SUPPORTS_SAVE )
+GAME( 1982, nibbler6, nibbler, nibbler, nibbler6, fantasy_state, empty_init, ROT90, "Rock-Ola", "Nibbler (rev 6)", MACHINE_SUPPORTS_SAVE )
+GAME( 1982, nibblerp, nibbler, nibbler, nibbler6, fantasy_state, empty_init, ROT90, "Rock-Ola", "Nibbler (Pioneer Balloon conversion - rev 6)", MACHINE_SUPPORTS_SAVE )
+GAME( 1983, nibblero, nibbler, nibbler, nibbler8, fantasy_state, empty_init, ROT90, "Rock-Ola (Olympia license)", "Nibbler (Olympia - rev 8)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/includes/snk6502.h b/src/mame/includes/snk6502.h
index 2e3b338ea8a..90612a1e5a1 100644
--- a/src/mame/includes/snk6502.h
+++ b/src/mame/includes/snk6502.h
@@ -12,24 +12,23 @@
#include "machine/timer.h"
-class snk6502_sound_device;
+class fantasy_sound_device;
class snk6502_state : public driver_device
{
public:
- snk6502_state(const machine_config &mconfig, device_type type, const char *tag)
- : driver_device(mconfig, type, tag),
+ snk6502_state(const machine_config &mconfig, device_type type, const char *tag) :
+ driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
- m_sound(*this, "snk6502"),
m_gfxdecode(*this, "gfxdecode"),
m_palette(*this, "palette"),
m_videoram(*this, "videoram"),
m_videoram2(*this, "videoram2"),
m_colorram(*this, "colorram"),
- m_charram(*this, "charram") { }
+ m_charram(*this, "charram")
+ { }
required_device<cpu_device> m_maincpu;
- required_device<snk6502_sound_device> m_sound;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
@@ -55,11 +54,9 @@ public:
DECLARE_WRITE8_MEMBER(scrollx_w);
DECLARE_WRITE8_MEMBER(scrolly_w);
DECLARE_WRITE8_MEMBER(flipscreen_w);
- DECLARE_WRITE8_MEMBER(fantasy_flipscreen_w);
DECLARE_WRITE8_MEMBER(satansat_b002_w);
DECLARE_WRITE8_MEMBER(satansat_backcolor_w);
- DECLARE_CUSTOM_INPUT_MEMBER(snk6502_music0_r);
DECLARE_CUSTOM_INPUT_MEMBER(sasuke_count_r);
DECLARE_INPUT_CHANGED_MEMBER(coin_inserted);
@@ -72,11 +69,8 @@ public:
DECLARE_MACHINE_RESET(sasuke);
DECLARE_VIDEO_START(satansat);
DECLARE_PALETTE_INIT(satansat);
- DECLARE_MACHINE_RESET(vanguard);
DECLARE_VIDEO_START(snk6502);
DECLARE_PALETTE_INIT(snk6502);
- DECLARE_MACHINE_RESET(satansat);
- DECLARE_MACHINE_RESET(pballoon);
DECLARE_VIDEO_START(pballoon);
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
@@ -87,17 +81,35 @@ public:
void sasuke_start_counter();
void postload();
- void pballoon(machine_config &config);
- void nibbler(machine_config &config);
void satansat(machine_config &config);
- void fantasy(machine_config &config);
void vanguard(machine_config &config);
void sasuke(machine_config &config);
- void fantasy_map(address_map &map);
- void pballoon_map(address_map &map);
void sasuke_map(address_map &map);
void satansat_map(address_map &map);
void vanguard_map(address_map &map);
};
+class fantasy_state : public snk6502_state
+{
+public:
+ fantasy_state(const machine_config &mconfig, device_type type, const char *tag) :
+ snk6502_state(mconfig, type, tag),
+ m_sound(*this, "snk6502")
+ {
+ }
+
+ void fantasy(machine_config &config);
+ void nibbler(machine_config &config);
+ void pballoon(machine_config &config);
+
+protected:
+ DECLARE_WRITE8_MEMBER(fantasy_flipscreen_w);
+
+ void fantasy_map(address_map &map);
+ void pballoon_map(address_map &map);
+
+private:
+ required_device<fantasy_sound_device> m_sound;
+};
+
#endif // MAME_INCLUDES_SNK6502_H
diff --git a/src/mame/video/snk6502.cpp b/src/mame/video/snk6502.cpp
index 46f6a8107a8..4a4cb13058a 100644
--- a/src/mame/video/snk6502.cpp
+++ b/src/mame/video/snk6502.cpp
@@ -137,9 +137,9 @@ WRITE8_MEMBER(snk6502_state::flipscreen_w)
}
}
-WRITE8_MEMBER(snk6502_state::fantasy_flipscreen_w)
+WRITE8_MEMBER(fantasy_state::fantasy_flipscreen_w)
{
- m_sound->fantasy_sound_w(space, offset | 0x03, data, mem_mask);
+ m_sound->sound_w(space, offset | 0x03, data, mem_mask);
flipscreen_w(space, offset, data, mem_mask);
}