diff options
author | Vas Crabb <vas@vastheman.com> | 2018-07-29 18:01:48 +1000 |
---|---|---|
committer | Vas Crabb <vas@vastheman.com> | 2018-07-29 18:01:48 +1000 |
commit | 51cebe3f60aa2584d02eac8c67455c8691fce934 (patch) | |
tree | 9d90a7485bc1adfef10b736c91d21038d660b3d2 | |
parent | 7bd14bedf6fd824853c406248dd4a36db17ecb7b (diff) |
qsoundhle: Saturate ROM offsets [superctr]
qsound: Apply ADPCM sample bank [superctr]
-rw-r--r-- | src/devices/sound/qsound.cpp | 26 | ||||
-rw-r--r-- | src/devices/sound/qsoundhle.cpp | 29 | ||||
-rw-r--r-- | src/devices/sound/qsoundhle.h | 9 |
3 files changed, 31 insertions, 33 deletions
diff --git a/src/devices/sound/qsound.cpp b/src/devices/sound/qsound.cpp index 0c49495427a..31d4f08ac6c 100644 --- a/src/devices/sound/qsound.cpp +++ b/src/devices/sound/qsound.cpp @@ -283,7 +283,7 @@ READ16_MEMBER(qsound_device::dsp_sample_r) // FIXME: DSP16 doesn't like bytes, only signed words - should this zero-pad or byte-smear? u8 const byte(read_byte((u32(m_rom_bank) << 16) | m_rom_offset)); if (!machine().side_effects_disabled()) - m_rom_bank = offset; + m_rom_bank = (m_rom_bank & 0x8000U) | offset; return (u16(byte) << 8) | u16(byte); } @@ -331,25 +331,11 @@ WRITE_LINE_MEMBER(qsound_device::dsp_ock_w) WRITE16_MEMBER(qsound_device::dsp_pio_w) { - /* - * FIXME: what does this do when PDX is high? - * There are seemingly two significant points where the program writes PDX1 every sample interval. - * - * Before writing the right-channel sample to SDX - this causes the PSEL 0->1 transition: - * 0:5d4: 996e if true a0 = rnd(a0) - * 0:5d5: 51e0 0000 pdx1 = 0x0000 - * 0:5d7: 49a0 move sdx = a0 - * - * This curious code where it writes out the a word from RAM@0x00f1 - this value seems significant: - * 0:335: 18f1 set r0 = 0x00f1 - * 0:336: 3cd0 nop, a0 = *r0 - * 0:337: d850 p = x*y, y = a1, x = *pt++i - * 0:338: 49e0 move pdx1 = a0 - */ - if (offset) - LOG("QSound: DSP PDX1 = %04X\n", data); - else - m_rom_offset = data; + // PDX0 is used for QSound ROM offset, and PDX1 is used for ADPCM ROM offset + // this prevents spurious PSEL transitions between sending samples to the DAC + // it could still be used to have separate QSound/ADPCM ROM banks + m_rom_bank = (m_rom_bank & 0x7fffU) | u16(offset << 15); + m_rom_offset = data; } diff --git a/src/devices/sound/qsoundhle.cpp b/src/devices/sound/qsoundhle.cpp index 5a57f098454..8d182bb4b1a 100644 --- a/src/devices/sound/qsoundhle.cpp +++ b/src/devices/sound/qsoundhle.cpp @@ -29,6 +29,19 @@ #include "emu.h" #include "qsoundhle.h" +#include <algorithm> +#include <limits> + + +namespace { + +constexpr u32 saturate(s64 val) +{ + return std::min<s64>(std::max<s64>(val, std::numeric_limits<s32>::min()), std::numeric_limits<s32>::max()); +} + +} // anonymous namespace + // device type definition DEFINE_DEVICE_TYPE(QSOUND_HLE, qsound_hle_device, "qsound_hle", "QSound (HLE)") @@ -41,7 +54,7 @@ DEFINE_DEVICE_TYPE(QSOUND_HLE, qsound_hle_device, "qsound_hle", "QSound (HLE)") // qsound_hle_device - constructor //------------------------------------------------- -qsound_hle_device::qsound_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) +qsound_hle_device::qsound_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : device_t(mconfig, QSOUND_HLE, tag, owner, clock) , device_sound_interface(mconfig, *this) , device_rom_interface(mconfig, *this, 24) @@ -124,14 +137,14 @@ void qsound_hle_device::sound_stream_update(sound_stream &stream, stream_sample_ offs_t const addr(ch.reg[1] | (bank << 16)); // update based on playback rate - uint32_t updated(uint32_t(ch.reg[2] << 4) + ((uint32_t(ch.reg[1]) << 16) | ch.reg[3])); - ch.reg[3] = uint16_t(updated); - if (updated >= (uint32_t(ch.reg[5]) << 16)) - updated -= uint32_t(ch.reg[4]) << 16; - ch.reg[1] = uint16_t(updated >> 16); + s64 updated(s32(u32(ch.reg[2]) << 4) + s32((u32(ch.reg[1]) << 16) | ch.reg[3])); + ch.reg[3] = u16(saturate(updated)); + if (updated >= s32(u32(ch.reg[5]) << 16)) + updated -= s32(u32(ch.reg[4]) << 16); + ch.reg[1] = u16(saturate(updated) >> 16); // get the scaled sample - int32_t const scaled(int32_t(int16_t(ch.reg[6])) * read_sample(addr)); + s32 const scaled(s32(s16(ch.reg[6])) * read_sample(addr)); // apply simple panning *lmix++ += (((scaled >> 8) * ch.lvol) >> 14); @@ -172,7 +185,7 @@ READ8_MEMBER(qsound_hle_device::qsound_r) } -void qsound_hle_device::write_data(uint8_t address, uint16_t data) +void qsound_hle_device::write_data(u8 address, u16 data) { int ch = 0, reg; diff --git a/src/devices/sound/qsoundhle.h b/src/devices/sound/qsoundhle.h index 8f4def443a0..498343ba6cb 100644 --- a/src/devices/sound/qsoundhle.h +++ b/src/devices/sound/qsoundhle.h @@ -34,13 +34,12 @@ protected: virtual void rom_bank_updated() override; private: - // MAME resources sound_stream *m_stream; struct qsound_channel { - uint16_t reg[8]; // channel control registers + u16 reg[8]; // channel control registers // work variables int lvol; // left volume @@ -48,10 +47,10 @@ private: } m_channel[16]; int m_pan_table[33]; // pan volume table - uint16_t m_data; // register latch data + u16 m_data; // register latch data - inline int16_t read_sample(uint32_t offset) { return uint16_t(read_byte(offset)) << 8; } - void write_data(uint8_t address, uint16_t data); + inline s16 read_sample(u32 offset) { return u16(read_byte(offset)) << 8; } + void write_data(u8 address, u16 data); }; DECLARE_DEVICE_TYPE(QSOUND_HLE, qsound_hle_device) |