summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/k051649.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/sound/k051649.cpp')
-rw-r--r--src/devices/sound/k051649.cpp178
1 files changed, 71 insertions, 107 deletions
diff --git a/src/devices/sound/k051649.cpp b/src/devices/sound/k051649.cpp
index 29287ba63f9..c4dd31c1ba7 100644
--- a/src/devices/sound/k051649.cpp
+++ b/src/devices/sound/k051649.cpp
@@ -1,6 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Bryan McPhail
-/***************************************************************************
+/*******************************************************************************
Konami 051649 - SCC1 sound as used in Haunted Castle, City Bomber
@@ -12,25 +12,30 @@
waveform from RAM (32 bytes per waveform, 8 bit signed data).
This sound chip is the same as the sound chip in some Konami
- megaROM cartridges for the MSX. It is actually well researched
- and documented:
+ megaROM cartridges for the MSX. This device only emulates the
+ sound portion, not the memory mapper.
- http://bifi.msxnet.org/msxnet/tech/scc.html
+ 052539 is more or less equivalent to this chip except channel 5
+ does not share waveram with channel 4.
- Thanks to Sean Young (sean@mess.org) for some bugfixes.
+ References:
+ - http://bifi.msxnet.org/msxnet/tech/scc.html
+ - http://bifi.msxnet.org/msxnet/tech/soundcartridge
- K052539 is more or less equivalent to this chip except channel 5
- does not share waveram with channel 4.
+ TODO:
+ - make 052539 a subdevice
+ - bus conflicts on 051649 (not 052539). When the CPU accesses waveform RAM
+ and the SCC is reading it at the same time, it can cause audible spikes.
+ A similar thing happens internally when the shared ch4/ch5 do a read at
+ the same time.
+ - test register bits 0-4, not used in any software
-***************************************************************************/
+*******************************************************************************/
#include "emu.h"
#include "k051649.h"
#include <algorithm>
-#define FREQ_BITS 16
-#define DEF_GAIN 8
-
void k051649_device::scc_map(address_map &map)
{
map(0x00, 0x7f).rw(FUNC(k051649_device::k051649_waveform_r), FUNC(k051649_device::k051649_waveform_w));
@@ -44,9 +49,9 @@ void k051649_device::scc_map(address_map &map)
DEFINE_DEVICE_TYPE(K051649, k051649_device, "k051649", "K051649 SCC1")
-//**************************************************************************
+//******************************************************************************
// LIVE DEVICE
-//**************************************************************************
+//******************************************************************************
//-------------------------------------------------
// k051649_device - constructor
@@ -56,10 +61,6 @@ k051649_device::k051649_device(const machine_config &mconfig, const char *tag, d
: device_t(mconfig, K051649, tag, owner, clock)
, device_sound_interface(mconfig, *this)
, m_stream(nullptr)
- , m_mclock(0)
- , m_rate(0)
- , m_mixer_table(nullptr)
- , m_mixer_lookup(nullptr)
, m_test(0)
{
}
@@ -72,25 +73,16 @@ k051649_device::k051649_device(const machine_config &mconfig, const char *tag, d
void k051649_device::device_start()
{
// get stream channels
- m_rate = clock()/16;
- m_stream = stream_alloc(0, 1, m_rate);
- m_mclock = clock();
-
- // allocate a buffer to mix into - 1 second's worth should be more than enough
- m_mixer_buffer.resize(2 * m_rate);
-
- // build the mixer table
- make_mixer_table(5);
+ m_stream = stream_alloc(0, 1, clock());
// save states
- for (int voice = 0; voice < 5; voice++)
- {
- save_item(NAME(m_channel_list[voice].counter), voice);
- save_item(NAME(m_channel_list[voice].frequency), voice);
- save_item(NAME(m_channel_list[voice].volume), voice);
- save_item(NAME(m_channel_list[voice].key), voice);
- save_item(NAME(m_channel_list[voice].waveram), voice);
- }
+ save_item(STRUCT_MEMBER(m_channel_list, counter));
+ save_item(STRUCT_MEMBER(m_channel_list, clock));
+ save_item(STRUCT_MEMBER(m_channel_list, frequency));
+ save_item(STRUCT_MEMBER(m_channel_list, volume));
+ save_item(STRUCT_MEMBER(m_channel_list, sample));
+ save_item(STRUCT_MEMBER(m_channel_list, key));
+ save_item(STRUCT_MEMBER(m_channel_list, waveram));
save_item(NAME(m_test));
}
@@ -107,6 +99,7 @@ void k051649_device::device_reset()
voice.frequency = 0;
voice.volume = 0xf;
voice.counter = 0;
+ voice.clock = 0;
voice.key = false;
}
@@ -132,15 +125,7 @@ void k051649_device::device_post_load()
void k051649_device::device_clock_changed()
{
- const u32 old_rate = m_rate;
- m_rate = clock()/16;
- m_mclock = clock();
-
- if (old_rate < m_rate)
- {
- m_mixer_buffer.resize(2 * m_rate, 0);
- }
- m_stream->set_sample_rate(m_rate);
+ m_stream->set_sample_rate(clock());
}
@@ -148,41 +133,34 @@ void k051649_device::device_clock_changed()
// sound_stream_update - handle a stream update
//-------------------------------------------------
-void k051649_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+void k051649_device::sound_stream_update(sound_stream &stream)
{
- // zap the contents of the mixer buffer
- std::fill(m_mixer_buffer.begin(), m_mixer_buffer.end(), 0);
-
- for (sound_channel &voice : m_channel_list)
+ for (int i = 0; i < stream.samples(); i++)
{
- // channel is halted for freq < 9
- if (voice.frequency > 8)
+ for (sound_channel &voice : m_channel_list)
{
- const int v = voice.volume * voice.key;
- int c = voice.counter;
- const int step = ((s64(m_mclock) << FREQ_BITS) / float((voice.frequency + 1) * 16 * (m_rate / 32))) + 0.5f;
-
- // add our contribution
- for (int i = 0; i < samples; i++)
+ // channel is halted for freq < 9
+ if (voice.frequency > 8)
{
- c += step;
- const int offs = (c >> FREQ_BITS) & 0x1f;
- m_mixer_buffer[i] += (voice.waveram[offs] * v) >> 3;
+ if (++voice.clock > voice.frequency)
+ {
+ voice.counter = (voice.counter + 1) & 0x1f;
+ voice.clock = 0;
+ }
+ if (voice.clock == 0)
+ {
+ voice.sample = (voice.key ? voice.waveram[voice.counter] : 0) * voice.volume;
+ }
}
- // update the counter for this voice
- voice.counter = c;
+ // scale to 11 bit digital output on chip
+ stream.add_int(0, i, voice.sample >> 4, 1024);
}
}
-
- // mix it down
- stream_sample_t *buffer = outputs[0];
- for (int i = 0; i < samples; i++)
- *buffer++ = m_mixer_lookup[m_mixer_buffer[i]];
}
-/********************************************************************************/
+/******************************************************************************/
void k051649_device::k051649_waveform_w(offs_t offset, u8 data)
@@ -206,17 +184,19 @@ void k051649_device::k051649_waveform_w(offs_t offset, u8 data)
u8 k051649_device::k051649_waveform_r(offs_t offset)
{
- // test-register bits 6/7 expose the internal counter
+ u8 counter = 0;
+
+ // test register bits 6/7 expose the internal counter
if (m_test & 0xc0)
{
m_stream->update();
- if (offset >= 0x60)
- offset += (m_channel_list[3 + (m_test >> 6 & 1)].counter >> FREQ_BITS);
+ if (offset >= 0x60 && (m_test & 0xc0) != 0xc0)
+ counter = m_channel_list[3 + (m_test >> 6 & 1)].counter;
else if (m_test & 0x40)
- offset += (m_channel_list[offset >> 5].counter >> FREQ_BITS);
+ counter = m_channel_list[offset >> 5].counter;
}
- return m_channel_list[offset >> 5].waveram[offset & 0x1f];
+ return m_channel_list[offset >> 5].waveram[(offset + counter) & 0x1f];
}
@@ -233,20 +213,22 @@ void k051649_device::k052539_waveform_w(offs_t offset, u8 data)
u8 k051649_device::k052539_waveform_r(offs_t offset)
{
- // test-register bit 6 exposes the internal counter
+ u8 counter = 0;
+
+ // test register bit 6 exposes the internal counter
if (m_test & 0x40)
{
m_stream->update();
- offset += (m_channel_list[offset >> 5].counter >> FREQ_BITS);
+ counter = m_channel_list[offset >> 5].counter;
}
- return m_channel_list[offset >> 5].waveram[offset & 0x1f];
+ return m_channel_list[offset >> 5].waveram[(offset + counter) & 0x1f];
}
void k051649_device::k051649_volume_w(offs_t offset, u8 data)
{
m_stream->update();
- m_channel_list[offset & 0x7].volume = data & 0xf;
+ m_channel_list[offset].volume = data & 0xf;
}
@@ -257,17 +239,18 @@ void k051649_device::k051649_frequency_w(offs_t offset, u8 data)
m_stream->update();
- // test-register bit 5 resets the internal counter
- if (m_test & 0x20)
- m_channel_list[offset].counter = ~0;
- else if (m_channel_list[offset].frequency < 9)
- m_channel_list[offset].counter |= ((1 << FREQ_BITS) - 1);
-
// update frequency
if (freq_hi)
m_channel_list[offset].frequency = (m_channel_list[offset].frequency & 0x0ff) | (data << 8 & 0xf00);
else
m_channel_list[offset].frequency = (m_channel_list[offset].frequency & 0xf00) | data;
+
+ // test register bit 5 resets the internal counter
+ if (m_test & 0x20)
+ m_channel_list[offset].counter = 0;
+
+ // sample reload pending
+ m_channel_list[offset].clock = -1;
}
@@ -288,32 +271,13 @@ void k051649_device::k051649_test_w(u8 data)
}
-u8 k051649_device::k051649_test_r()
-{
- // reading the test register sets it to $ff!
- if (!machine().side_effects_disabled())
- k051649_test_w(0xff);
- return 0xff;
-}
-
-
-//-------------------------------------------------
-// build a table to divide by the number of voices
-//-------------------------------------------------
-
-void k051649_device::make_mixer_table(int voices)
+u8 k051649_device::k051649_test_r(address_space &space)
{
- // allocate memory
- m_mixer_table = std::make_unique<s16[]>(512 * voices);
+ u8 data = space.unmap();
- // find the middle of the table
- m_mixer_lookup = m_mixer_table.get() + (256 * voices);
+ // reading the test register triggers a write
+ if (!machine().side_effects_disabled())
+ k051649_test_w(data);
- // fill in the table - 16 bit case
- for (int i = 0; i < (voices * 256); i++)
- {
- const int val = std::min(32767, i * DEF_GAIN * 16 / voices);
- m_mixer_lookup[ i] = val;
- m_mixer_lookup[-i] = -val;
- }
+ return data;
}