diff options
Diffstat (limited to 'src/mame/audio/wswan.cpp')
-rw-r--r-- | src/mame/audio/wswan.cpp | 135 |
1 files changed, 75 insertions, 60 deletions
diff --git a/src/mame/audio/wswan.cpp b/src/mame/audio/wswan.cpp index f86afd635af..e8638bbc850 100644 --- a/src/mame/audio/wswan.cpp +++ b/src/mame/audio/wswan.cpp @@ -32,6 +32,7 @@ DEFINE_DEVICE_TYPE(WSWAN_SND, wswan_sound_device, "wswan_sound", "WonderSwan Cus wswan_sound_device::wswan_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, WSWAN_SND, tag, owner, clock), device_sound_interface(mconfig, *this), + device_rom_interface(mconfig, *this, 14), m_channel(nullptr), m_sweep_step(0), m_sweep_time(0), @@ -39,12 +40,12 @@ wswan_sound_device::wswan_sound_device(const machine_config &mconfig, const char m_noise_type(0), m_noise_reset(0), m_noise_enable(0), + m_noise_output(0), m_sample_address(0), m_audio2_voice(0), m_audio3_sweep(0), m_audio4_noise(0), m_mono(0), - m_voice_data(0), m_output_volume(0), m_external_stereo(0), m_external_speaker(0), @@ -53,6 +54,7 @@ wswan_sound_device::wswan_sound_device(const machine_config &mconfig, const char { } +constexpr int clk_div = 64; //------------------------------------------------- // device_start - device-specific startup @@ -60,7 +62,7 @@ wswan_sound_device::wswan_sound_device(const machine_config &mconfig, const char void wswan_sound_device::device_start() { - m_channel = stream_alloc(0, 2, machine().sample_rate()); + m_channel = stream_alloc(0, 2, clock() / clk_div); save_item(NAME(m_sweep_step)); save_item(NAME(m_sweep_time)); @@ -73,7 +75,6 @@ void wswan_sound_device::device_start() save_item(NAME(m_audio3_sweep)); save_item(NAME(m_audio4_noise)); save_item(NAME(m_mono)); - save_item(NAME(m_voice_data)); save_item(NAME(m_output_volume)); save_item(NAME(m_external_stereo)); save_item(NAME(m_external_speaker)); @@ -86,6 +87,7 @@ void wswan_sound_device::device_start() save_item(NAME(m_audio1.vol_left)); save_item(NAME(m_audio1.vol_right)); save_item(NAME(m_audio1.on)); + save_item(NAME(m_audio1.offset)); save_item(NAME(m_audio1.signal)); save_item(NAME(m_audio2.freq)); @@ -94,6 +96,7 @@ void wswan_sound_device::device_start() save_item(NAME(m_audio2.vol_left)); save_item(NAME(m_audio2.vol_right)); save_item(NAME(m_audio2.on)); + save_item(NAME(m_audio2.offset)); save_item(NAME(m_audio2.signal)); save_item(NAME(m_audio3.freq)); @@ -102,6 +105,7 @@ void wswan_sound_device::device_start() save_item(NAME(m_audio3.vol_left)); save_item(NAME(m_audio3.vol_right)); save_item(NAME(m_audio3.on)); + save_item(NAME(m_audio3.offset)); save_item(NAME(m_audio3.signal)); save_item(NAME(m_audio4.freq)); @@ -110,9 +114,19 @@ void wswan_sound_device::device_start() save_item(NAME(m_audio4.vol_left)); save_item(NAME(m_audio4.vol_right)); save_item(NAME(m_audio4.on)); + save_item(NAME(m_audio4.offset)); save_item(NAME(m_audio4.signal)); } +void wswan_sound_device::device_clock_changed() +{ + m_channel->set_sample_rate(clock() / clk_div); +} + +void wswan_sound_device::rom_bank_updated() +{ + m_channel->update(); +} //------------------------------------------------- // device_reset @@ -121,19 +135,33 @@ void wswan_sound_device::device_start() void wswan_sound_device::device_reset() { m_audio1.on = 0; - m_audio1.signal = 16; + m_audio1.signal = 0; + m_audio1.offset = 0; m_audio1.pos = 0; m_audio2.on = 0; - m_audio2.signal = 16; + m_audio2.signal = 0; + m_audio2.offset = 0; m_audio2.pos = 0; m_audio3.on = 0; - m_audio3.signal = 16; + m_audio3.signal = 0; + m_audio3.offset = 0; m_audio3.pos = 0; m_audio4.on = 0; - m_audio4.signal = 16; + m_audio4.signal = 0; + m_audio4.offset = 0; m_audio4.pos = 0; + m_noise_output = 0; } +int wswan_sound_device::fetch_sample(int channel, int offset) +{ + uint8_t b = read_byte(m_sample_address + ((channel & 3) << 4) + ((offset & 0x1f) >> 1)); + + if (offset & 1) + return b >> 4; + else + return b & 0xf; +} //------------------------------------------------- // sound_stream_update - handle a stream update @@ -150,11 +178,11 @@ void wswan_sound_device::sound_stream_update(sound_stream &stream, stream_sample if ( m_audio1.on ) { sample = m_audio1.signal; - m_audio1.pos++; - if ( m_audio1.pos >= m_audio1.period / 2 ) + m_audio1.pos += clk_div; + if (m_audio1.pos >= m_audio1.period) { - m_audio1.pos = 0; - m_audio1.signal = -m_audio1.signal; + m_audio1.pos -= m_audio1.period; + m_audio1.signal = fetch_sample(0, m_audio1.offset++); } left += m_audio1.vol_left * sample; right += m_audio1.vol_right * sample; @@ -164,17 +192,18 @@ void wswan_sound_device::sound_stream_update(sound_stream &stream, stream_sample { if ( m_audio2_voice ) { - left += (m_voice_data - 128)*(m_master_volume & 0x0f); - right += (m_voice_data - 128)*(m_master_volume & 0x0f); + uint8_t voice_data = m_audio2.vol_left << 4 | m_audio2.vol_right; + left += voice_data * (m_master_volume & 0x0f); + right += voice_data * (m_master_volume & 0x0f); } else { sample = m_audio2.signal; - m_audio2.pos++; - if ( m_audio2.pos >= m_audio2.period / 2 ) + m_audio2.pos += clk_div; + if (m_audio2.pos >= m_audio2.period) { - m_audio2.pos = 0; - m_audio2.signal = -m_audio2.signal; + m_audio2.pos -= m_audio2.period; + m_audio2.signal = fetch_sample(1, m_audio2.offset++); } left += m_audio2.vol_left * sample; right += m_audio2.vol_right * sample; @@ -184,20 +213,21 @@ void wswan_sound_device::sound_stream_update(sound_stream &stream, stream_sample if ( m_audio3.on ) { sample = m_audio3.signal; - m_audio3.pos++; - if ( m_audio3.pos >= m_audio3.period / 2 ) + m_audio3.pos += clk_div; + if (m_audio3.pos >= m_audio3.period) { - m_audio3.pos = 0; - m_audio3.signal = -m_audio3.signal; + m_audio3.pos -= m_audio3.period; + m_audio3.signal = fetch_sample(2, m_audio3.offset++); } if ( m_audio3_sweep && m_sweep_time ) { - m_sweep_count++; + m_sweep_count += clk_div; if ( m_sweep_count >= m_sweep_time ) { - m_sweep_count = 0; + m_sweep_count -= m_sweep_time; m_audio3.freq += m_sweep_step; - m_audio3.period = machine().sample_rate() / (3072000 / ((2048 - (m_audio3.freq & 0x7ff)) << 5)); + m_audio3.freq &= 0x7ff; + m_audio3.period = 2048 - m_audio3.freq; } } left += m_audio3.vol_left * sample; @@ -207,39 +237,29 @@ void wswan_sound_device::sound_stream_update(sound_stream &stream, stream_sample if ( m_audio4.on ) { sample = m_audio4.signal; - m_audio4.pos++; - if ( m_audio4.pos >= m_audio4.period / 2 ) + m_audio4.pos += clk_div; + if (m_audio4.pos >= m_audio4.period) { - m_audio4.signal = -m_audio4.signal; - m_audio4.pos = 0; + if (m_audio4_noise) + m_audio4.signal = m_noise_output ? 0xf : 0; + else + m_audio4.signal = fetch_sample(3, m_audio4.offset++); + + m_audio4.pos -= m_audio4.period; + + if (m_noise_reset) + { + m_noise_reset = 0; + m_noise_shift = 0; + m_noise_output = 0; + } if (m_noise_enable) { - uint16_t new_bit = 0; - - if (m_noise_type == 0) - { - new_bit = (m_noise_shift ^ (m_noise_shift >> 5) ^ (m_noise_shift >> 8)) & 1; - } - else - { - static int shift_bit[] = { 0, 10, 13, 4, 8, 6, 9, 11 }; - - new_bit = (1 ^ (m_noise_shift >> 7) ^ (m_noise_shift >> shift_bit[m_noise_type])) & 1; - } - m_noise_shift = (m_noise_shift << 1) | new_bit; - - if (m_audio4_noise) - { - m_audio4.signal = (m_noise_shift & 0x8000) ? 16 : -16; - } - - m_noise_shift &= 0x7fff; - - if (m_noise_shift == 0x7fff) - { - m_noise_shift = (m_noise_type == 0) ? 0x80 : 0; - } + static int shift_bit[] = { 14, 10, 13, 4, 8, 6, 9, 11 }; + + m_noise_output = (1 ^ (m_noise_shift >> 7) ^ (m_noise_shift >> shift_bit[m_noise_type])) & 1; + m_noise_shift = m_noise_shift << 1 | m_noise_output; } } left += m_audio4.vol_left * sample; @@ -259,7 +279,7 @@ void wswan_sound_device::wswan_ch_set_freq( CHAN *ch, uint16_t freq ) { freq &= 0x7ff; // docs say freq is 11bits and a few games (Morita Shougi, World Stadium + others) write 0x800 causing a divide by 0 crash ch->freq = freq; - ch->period = machine().sample_rate() / (3072000 / ((2048 - freq) << 5)); + ch->period = 2048 - freq; } WRITE8_MEMBER( wswan_sound_device::port_w ) @@ -306,7 +326,6 @@ WRITE8_MEMBER( wswan_sound_device::port_w ) break; case 0x89: /* Audio 2 volume */ - m_voice_data = data; m_audio2.vol_left = ( data & 0xF0 ) >> 4; m_audio2.vol_right = data & 0x0F; break; @@ -326,17 +345,13 @@ WRITE8_MEMBER( wswan_sound_device::port_w ) break; case 0x8D: /* Sweep time */ - m_sweep_time = machine().sample_rate() / ( 3072000 / ( 8192 * (data + 1) ) ); + m_sweep_time = 8192 * (data + 1); break; case 0x8E: /* Noise control */ m_noise_type = data & 0x07; m_noise_reset = ( data & 0x08 ) >> 3; m_noise_enable = ( data & 0x10 ) >> 4; - if (m_noise_reset) - { - m_noise_shift = (m_noise_type == 0) ? 0x80 : 0; - } break; case 0x8F: /* Sample location */ |