From e64244db48c2778c7fb6a2f69bab5fc13f63b524 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Sat, 2 Jun 2018 15:01:03 +1000 Subject: 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 --- src/mame/audio/snk6502.cpp | 1144 ++++++++++++++++++++++++++---------------- src/mame/audio/snk6502.h | 148 +++++- src/mame/drivers/snk6502.cpp | 287 ++--------- src/mame/includes/snk6502.h | 44 +- src/mame/video/snk6502.cpp | 4 +- 5 files changed, 921 insertions(+), 706 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,216 +319,327 @@ 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; } - -WRITE8_MEMBER( snk6502_sound_device::sasuke_sound_w ) +void snk6502_sound_device::set_channel_base(int channel, int base, int mask) { - switch (offset) - { - case 0: - /* - bit description - - 0 hit (ic52) - 1 boss start (ic51) - 2 shot - 3 boss attack (ic48?) - 4 ?? - 5 - 6 - 7 reset counter - */ + m_tone_channels[channel].base = base; + m_tone_channels[channel].mask = mask; +} - 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); +void snk6502_sound_device::mute_channel(int channel) +{ + m_tone_channels[channel].mute = 1; + m_tone_channels[channel].offset = 0; +} - if ((data & 0x80) && (~m_last_port1 & 0x80)) - { - m_tone_channels[0].offset = 0; - m_tone_channels[0].mute = 0; - } +void snk6502_sound_device::unmute_channel(int channel) +{ + m_tone_channels[channel].mute = 0; + m_tone_channels[channel].offset = 0; +} - if ((~data & 0x80) && (m_last_port1 & 0x80)) - m_tone_channels[0].mute = 1; - m_last_port1 = data; - break; +/* + Hitachi HD38880 speech synthesizer chip - case 1: - /* - bit description + I heard that this chip uses PARCOR coefficients but I don't know ROM data format. + How do I generate samples? +*/ - 0 - 1 wave form - 2 wave form - 3 wave form - 4 MUSIC A8 - 5 MUSIC A9 - 6 MUSIC A10 - 7 - */ - /* select tune in ROM based on sound command byte */ - m_tone_channels[0].base = 0x0000 + ((data & 0x70) << 4); - m_tone_channels[0].mask = 0xff; +/* 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 - m_sound0_stop_on_rollover = 1; +/* HD38880 control bits */ +#define HD38880_CTP 0x10 +#define HD38880_CMV 0x20 +#define HD68880_SYBS 0x0f - /* bit 1-3 sound0 waveform control */ - sasuke_build_waveform((data & 0x0e) >> 1); - break; - } -} -WRITE8_MEMBER( snk6502_sound_device::satansat_sound_w ) +void snk6502_sound_device::speech_w(uint8_t data, const uint16_t *table, int start) { - switch (offset) + /* + bit description + 0 SYBS1 + 1 SYBS2 + 2 SYBS3 + 3 SYBS4 + 4 CTP + 5 CMV + 6 + 7 + */ + + if ((data & HD38880_CTP) && (data & HD38880_CMV)) { - case 0: - /* - bit description + data &= HD68880_SYBS; - */ + switch (m_hd38880_cmd) + { + case 0: + switch (data) + { + case HD38880_START: + logerror("speech: START\n"); - /* bit 0 = analog sound trigger */ + 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; - /* bit 1 = to 76477 */ + case HD38880_SSTART: + logerror("speech: SSTART\n"); + break; - /* bit 2 = analog sound trigger */ - if (data & 0x04 && !(m_last_port1 & 0x04)) - m_samples->start(0, 1); + case HD38880_STOP: + m_samples->stop(0); + logerror("speech: STOP\n"); + break; - if (data & 0x08) - { - m_tone_channels[0].mute = 1; - m_tone_channels[0].offset = 0; - } + case HD38880_SYSPD: + m_hd38880_cmd = data; + break; - /* bit 4-6 sound0 waveform control */ - sasuke_build_waveform((data & 0x70) >> 4); + case HD38880_CONDT: + logerror("speech: CONDT\n"); + break; - /* bit 7 sound1 waveform control */ - satansat_build_waveform((data & 0x80) >> 7); + case HD38880_ADSET: + m_hd38880_cmd = data; + m_hd38880_addr = 0; + m_hd38880_data_bytes = 0; + break; - m_last_port1 = data; - break; - case 1: - /* - bit description + case HD38880_READ: + logerror("speech: READ\n"); + break; - */ + case HD38880_INT1: + m_hd38880_cmd = data; + break; - /* 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; + case HD38880_INT2: + m_hd38880_cmd = data; + break; - m_sound0_stop_on_rollover = 1; + case 0: + // ignore it + break; - if (data & 0x01) - m_tone_channels[0].mute = 0; + default: + logerror("speech: unknown command: 0x%x\n", data); + } + break; - if (data & 0x10) - m_tone_channels[1].mute = 0; - else - { - m_tone_channels[1].mute = 1; - m_tone_channels[1].offset = 0; - } + case HD38880_INT1: + logerror("speech: INT1: 0x%x\n", data); - /* bit 7 = ? */ - break; - } -} + if (data & 8) + logerror("speech: triangular waveform\n"); + else + logerror("speech: impulse waveform\n"); -WRITE8_MEMBER( snk6502_sound_device::vanguard_sound_w ) -{ - switch (offset) - { - case 0: - /* - bit description + logerror("speech: %sable losing effect of vocal tract\n", data & 4 ? "en" : "dis"); - 0 MUSIC A10 - 1 MUSIC A9 - 2 MUSIC A8 - 3 LS05 PORT 1 - 4 LS04 PORT 2 - 5 SHOT A - 6 SHOT B - 7 BOMB - */ + if ((data & 2) && (data & 8)) + logerror("speech: use external pitch control\n"); - /* 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_hd38880_cmd = 0; + break; - m_sound0_stop_on_rollover = 1; + case HD38880_INT2: + logerror("speech: INT2: 0x%x\n", data); - /* play noise samples requested by sound command byte */ - /* SHOT A */ - if (data & 0x20 && !(m_last_port1 & 0x20)) - m_samples->start(1, 0); - else if (!(data & 0x20) && m_last_port1 & 0x20) - m_samples->stop(1); + 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); - /* BOMB */ - if (data & 0x80 && !(m_last_port1 & 0x80)) - m_samples->start(2, 1); + m_hd38880_cmd = 0; + break; - if (data & 0x08) - { - m_tone_channels[0].mute = 1; - m_tone_channels[0].offset = 0; - } + 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; - if (data & 0x10) - { - m_tone_channels[0].mute = 0; + 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; } + } +} - /* SHOT B */ - m_sn76477_2->enable_w((data & 0x40) ? 0 : 1); - m_last_port1 = data; - break; - case 1: - /* - bit description +/* + vanguard/fantasy speech - 0 MUSIC A10 - 1 MUSIC A9 - 2 MUSIC A8 - 3 LS04 PORT 3 - 4 EXTP A (HD38880 external pitch control A) - 5 EXTP B (HD38880 external pitch control B) - 6 - 7 - */ + ROM data format (INT2 = 0xf): + 48 bits / frame + 20 ms / frame + enable repeat + 10 operations +*/ - /* select tune in ROM based on sound command byte */ - m_tone_channels[1].base = 0x0800 + ((data & 0x07) << 8); - m_tone_channels[1].mask = 0xff; +//------------------------------------------------- +// sound_stream_update - handle a stream update +//------------------------------------------------- - if (data & 0x08) - m_tone_channels[1].mute = 0; - else +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]; + + for (int i = 0; i < NUM_CHANNELS; i++) + validate_tone_channel(i); + + while (samples-- > 0) + { + int32_t data = 0; + + 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; + } } + + *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; + } + } +} + + +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) + { + case 0: + /* + bit description + + 0 MUSIC A10 + 1 MUSIC A9 + 2 MUSIC A8 + 3 LS05 PORT 1 + 4 LS04 PORT 2 + 5 SHOT A + 6 SHOT B + 7 BOMB + */ + + /* select musical tune in ROM based on sound command byte */ + m_custom->set_channel_base(0, (data & 0x07) << 8); + + m_custom->set_sound0_stop_on_rollover(1); + + /* play noise samples requested by sound command byte */ + /* SHOT A */ + if (data & 0x20 && !(m_last_port1 & 0x20)) + m_samples->start(1, 0); + else if (!(data & 0x20) && m_last_port1 & 0x20) + m_samples->stop(1); + + /* BOMB */ + if (data & 0x80 && !(m_last_port1 & 0x80)) + m_samples->start(2, 1); + + if (data & 0x08) + m_custom->mute_channel(0); + + if (data & 0x10) + 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 + + 0 MUSIC A10 + 1 MUSIC A9 + 2 MUSIC A8 + 3 LS04 PORT 3 + 4 EXTP A (HD38880 external pitch control A) + 5 EXTP B (HD38880 external pitch control B) + 6 + 7 + */ + + /* select tune in ROM based on sound command byte */ + m_custom->set_channel_base(1, 0x0800 | ((data & 0x07) << 8)); + + if (data & 0x08) + m_custom->unmute_channel(1); + else + 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 - */ - - if ((data & HD38880_CTP) && (data & HD38880_CMV)) - { - data &= HD68880_SYBS; + save_item(NAME(m_last_port1)); +} - switch (m_hd38880_cmd) - { - case 0: - switch (data) - { - case HD38880_START: - logerror("speech: START\n"); +void fantasy_sound_device::device_reset() +{ + // 41.6 Hz update (measured) + m_custom->set_music_clock(1 / 41.6); +} - 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; - case HD38880_SSTART: - logerror("speech: SSTART\n"); - 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_STOP: - m_samples->stop(0); - logerror("speech: STOP\n"); - break; +MACHINE_CONFIG_START(nibbler_sound_device::device_add_mconfig) + fantasy_sound_device::device_add_mconfig(config); - case HD38880_SYSPD: - m_hd38880_cmd = data; - break; + MCFG_DEVICE_REMOVE("samples") +MACHINE_CONFIG_END - case HD38880_CONDT: - logerror("speech: CONDT\n"); - break; - case HD38880_ADSET: - m_hd38880_cmd = data; - m_hd38880_addr = 0; - m_hd38880_data_bytes = 0; - 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_READ: - logerror("speech: READ\n"); - break; +MACHINE_CONFIG_START(pballoon_sound_device::device_add_mconfig) + fantasy_sound_device::device_add_mconfig(config); - case HD38880_INT1: - m_hd38880_cmd = data; - break; + MCFG_DEVICE_REMOVE("samples") +MACHINE_CONFIG_END - 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 m_sn76477_2; - optional_device m_discrete; optional_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 m_custom; + required_device m_sn76477_2; + required_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 m_custom; + +private: + required_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 m_custom; + required_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 m_custom; + required_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 m_maincpu; - required_device m_sound; required_device m_gfxdecode; required_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 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); } -- cgit v1.2.3