diff options
Diffstat (limited to 'src/devices/sound/rf5c68.cpp')
-rw-r--r-- | src/devices/sound/rf5c68.cpp | 129 |
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); } |