summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
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
commit51cebe3f60aa2584d02eac8c67455c8691fce934 (patch)
tree9d90a7485bc1adfef10b736c91d21038d660b3d2
parent7bd14bedf6fd824853c406248dd4a36db17ecb7b (diff)
qsoundhle: Saturate ROM offsets [superctr]
qsound: Apply ADPCM sample bank [superctr]
-rw-r--r--src/devices/sound/qsound.cpp26
-rw-r--r--src/devices/sound/qsoundhle.cpp29
-rw-r--r--src/devices/sound/qsoundhle.h9
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)