summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/rf5c68.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/sound/rf5c68.cpp')
-rw-r--r--src/devices/sound/rf5c68.cpp129
1 files changed, 73 insertions, 56 deletions
diff --git a/src/devices/sound/rf5c68.cpp b/src/devices/sound/rf5c68.cpp
index 56661d9a6d4..09fd397d4fb 100644
--- a/src/devices/sound/rf5c68.cpp
+++ b/src/devices/sound/rf5c68.cpp
@@ -3,8 +3,8 @@
/*********************************************************/
/* ricoh RF5C68(or clone) PCM controller */
/* */
-/* TODO : RF5C164 (Sega CD/Mega CD) */
-/* has difference? */
+/* TODO: Verify RF5C105,164 (Sega CD/Mega CD) */
+/* differences */
/*********************************************************/
#include "emu.h"
@@ -12,8 +12,24 @@
// device type definition
-DEFINE_DEVICE_TYPE(RF5C68, rf5c68_device, "rf5c68", "Ricoh RF5C68")
-DEFINE_DEVICE_TYPE(RF5C164, rf5c164_device, "rf5c164", "Ricoh RF5C164")
+DEFINE_DEVICE_TYPE(RF5C68, rf5c68_device, "rf5c68", "Ricoh RF5C68")
+DEFINE_DEVICE_TYPE(RF5C164, rf5c164_device, "rf5c164", "Ricoh RF5C164") // or Sega 315-5476A
+
+
+void rf5c68_device::map(address_map &map)
+{
+ // TODO: Mirroring is sega arcade boards only?
+ map(0x0000, 0x0008).mirror(0x0ff0).w(FUNC(rf5c68_device::rf5c68_w)); // A12 = 0 : Register
+ map(0x1000, 0x1fff).rw(FUNC(rf5c68_device::rf5c68_mem_r), FUNC(rf5c68_device::rf5c68_mem_w)); // A12 = 1 : Waveform data
+}
+
+void rf5c164_device::rf5c164_map(address_map &map)
+{
+ // TODO: Not mirrored?
+ map(0x0000, 0x0008).w(FUNC(rf5c68_device::rf5c68_w)); // A12 = 0 : Register
+ map(0x0010, 0x001f).r(FUNC(rf5c68_device::rf5c68_r));
+ map(0x1000, 0x1fff).rw(FUNC(rf5c68_device::rf5c68_mem_r), FUNC(rf5c68_device::rf5c68_mem_w)); // A12 = 1 : Waveform data
+}
//**************************************************************************
@@ -24,7 +40,7 @@ DEFINE_DEVICE_TYPE(RF5C164, rf5c164_device, "rf5c164", "Ricoh RF5C164")
// rf5c68_device - constructor
//-------------------------------------------------
-rf5c68_device::rf5c68_device(const machine_config & mconfig, device_type type, const char * tag, device_t * owner, u32 clock)
+rf5c68_device::rf5c68_device(const machine_config & mconfig, device_type type, const char * tag, device_t * owner, u32 clock, int output_bits)
: device_t(mconfig, type, tag, owner, clock)
, device_sound_interface(mconfig, *this)
, device_memory_interface(mconfig, *this)
@@ -33,22 +49,23 @@ rf5c68_device::rf5c68_device(const machine_config & mconfig, device_type type, c
, m_cbank(0)
, m_wbank(0)
, m_enable(0)
+ , m_output_bits(output_bits)
, m_sample_end_cb(*this)
{
}
-rf5c68_device::rf5c68_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : rf5c68_device(mconfig, RF5C68, tag, owner, clock)
+rf5c68_device::rf5c68_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : rf5c68_device(mconfig, RF5C68, tag, owner, clock, 10)
{
}
//-------------------------------------------------
-// rf5c68_device - constructor
+// rf5c164_device - constructor
//-------------------------------------------------
-rf5c164_device::rf5c164_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : rf5c68_device(mconfig, RF5C164, tag, owner, clock)
+rf5c164_device::rf5c164_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : rf5c68_device(mconfig, RF5C164, tag, owner, clock, 16)
{
}
@@ -59,24 +76,21 @@ rf5c164_device::rf5c164_device(const machine_config &mconfig, const char *tag, d
void rf5c68_device::device_start()
{
- m_data = &space(0);
// Find our direct access
- m_cache = space().cache<0, 0, ENDIANNESS_LITTLE>();
+ space(0).cache(m_cache);
m_sample_end_cb.resolve();
/* allocate the stream */
m_stream = stream_alloc(0, 2, clock() / 384);
- for (int ch = 0; ch < NUM_CHANNELS; ch++)
- {
- save_item(NAME(m_chan[ch].enable), ch);
- save_item(NAME(m_chan[ch].env), ch);
- save_item(NAME(m_chan[ch].pan), ch);
- save_item(NAME(m_chan[ch].start), ch);
- save_item(NAME(m_chan[ch].addr), ch);
- save_item(NAME(m_chan[ch].step), ch);
- save_item(NAME(m_chan[ch].loopst), ch);
- }
+ save_item(STRUCT_MEMBER(m_chan, enable));
+ save_item(STRUCT_MEMBER(m_chan, env));
+ save_item(STRUCT_MEMBER(m_chan, pan));
+ save_item(STRUCT_MEMBER(m_chan, start));
+ save_item(STRUCT_MEMBER(m_chan, addr));
+ save_item(STRUCT_MEMBER(m_chan, step));
+ save_item(STRUCT_MEMBER(m_chan, loopst));
+
save_item(NAME(m_cbank));
save_item(NAME(m_wbank));
save_item(NAME(m_enable));
@@ -105,18 +119,26 @@ device_memory_interface::space_config_vector rf5c68_device::memory_space_config(
// sound_stream_update - handle a stream update
//-------------------------------------------------
-void rf5c68_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+void rf5c68_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
{
- stream_sample_t *left = outputs[0];
- stream_sample_t *right = outputs[1];
-
- /* start with clean buffers */
- memset(left, 0, samples * sizeof(*left));
- memset(right, 0, samples * sizeof(*right));
+ auto &left = outputs[0];
+ auto &right = outputs[1];
/* bail if not enabled */
if (!m_enable)
+ {
+ left.fill(0);
+ right.fill(0);
return;
+ }
+
+ if (m_mixleft.size() < left.samples())
+ m_mixleft.resize(left.samples());
+ if (m_mixright.size() < right.samples())
+ m_mixright.resize(right.samples());
+
+ std::fill_n(&m_mixleft[0], left.samples(), 0);
+ std::fill_n(&m_mixright[0], right.samples(), 0);
/* loop over channels */
for (pcm_channel &chan : m_chan)
@@ -128,7 +150,7 @@ void rf5c68_device::sound_stream_update(sound_stream &stream, stream_sample_t **
int rv = ((chan.pan >> 4) & 0x0f) * chan.env;
/* loop over the sample buffer */
- for (int j = 0; j < samples; j++)
+ for (int j = 0; j < left.samples(); j++)
{
int sample;
@@ -140,11 +162,11 @@ void rf5c68_device::sound_stream_update(sound_stream &stream, stream_sample_t **
}
/* fetch the sample and handle looping */
- sample = m_cache->read_byte((chan.addr >> 11) & 0xffff);
+ sample = m_cache.read_byte((chan.addr >> 11) & 0xffff);
if (sample == 0xff)
{
chan.addr = chan.loopst << 11;
- sample = m_cache->read_byte((chan.addr >> 11) & 0xffff);
+ sample = m_cache.read_byte((chan.addr >> 11) & 0xffff);
/* if we loop to a loop point, we're effectively dead */
if (sample == 0xff)
@@ -156,32 +178,28 @@ void rf5c68_device::sound_stream_update(sound_stream &stream, stream_sample_t **
if (sample & 0x80)
{
sample &= 0x7f;
- left[j] += (sample * lv) >> 5;
- right[j] += (sample * rv) >> 5;
+ m_mixleft[j] += (sample * lv) >> 5;
+ m_mixright[j] += (sample * rv) >> 5;
}
else
{
- left[j] -= (sample * lv) >> 5;
- right[j] -= (sample * rv) >> 5;
+ m_mixleft[j] -= (sample * lv) >> 5;
+ m_mixright[j] -= (sample * rv) >> 5;
}
}
}
}
- /* now clamp and shift the result (output is only 10 bits) */
- for (int j = 0; j < samples; j++)
+ /*
+ now clamp and shift the result (output is only 10 bits for RF5C68, 16 bits for RF5C164)
+ reference: Mega CD hardware manual, RF5C68 datasheet
+ */
+ const u8 output_shift = (m_output_bits > 16) ? 0 : (16 - m_output_bits);
+ const s32 output_nandmask = (1 << output_shift) - 1;
+ for (int j = 0; j < left.samples(); j++)
{
- stream_sample_t temp;
-
- temp = left[j];
- if (temp > 32767) temp = 32767;
- else if (temp < -32768) temp = -32768;
- left[j] = temp & ~0x3f;
-
- temp = right[j];
- if (temp > 32767) temp = 32767;
- else if (temp < -32768) temp = -32768;
- right[j] = temp & ~0x3f;
+ left.put_int_clamp(j, m_mixleft[j] & ~output_nandmask, 32768);
+ right.put_int_clamp(j, m_mixright[j] & ~output_nandmask, 32768);
}
}
@@ -190,12 +208,11 @@ void rf5c68_device::sound_stream_update(sound_stream &stream, stream_sample_t **
// RF5C68 write register
//-------------------------------------------------
+// TODO: RF5C164 only?
u8 rf5c68_device::rf5c68_r(offs_t offset)
{
- uint8_t shift;
-
m_stream->update();
- shift = (offset & 1) ? 11 + 8 : 11;
+ u8 shift = (offset & 1) ? 11 + 8 : 11;
// printf("%08x\n",(m_chan[(offset & 0x0e) >> 1].addr));
@@ -205,7 +222,6 @@ u8 rf5c68_device::rf5c68_r(offs_t offset)
void rf5c68_device::rf5c68_w(offs_t offset, u8 data)
{
pcm_channel &chan = m_chan[m_cbank];
- int i;
/* force the stream to update first */
m_stream->update();
@@ -252,7 +268,7 @@ void rf5c68_device::rf5c68_w(offs_t offset, u8 data)
break;
case 0x08: /* channel on/off reg */
- for (i = 0; i < 8; i++)
+ for (int i = 0; i < 8; i++)
{
m_chan[i].enable = (~data >> i) & 1;
if (!m_chan[i].enable)
@@ -269,7 +285,7 @@ void rf5c68_device::rf5c68_w(offs_t offset, u8 data)
u8 rf5c68_device::rf5c68_mem_r(offs_t offset)
{
- return m_cache->read_byte(m_wbank | offset);
+ return m_cache.read_byte(m_wbank | offset);
}
@@ -279,5 +295,6 @@ u8 rf5c68_device::rf5c68_mem_r(offs_t offset)
void rf5c68_device::rf5c68_mem_w(offs_t offset, u8 data)
{
- m_data->write_byte(m_wbank | offset, data);
+ m_stream->update();
+ m_cache.write_byte(m_wbank | offset, data);
}