qsoundhle: Saturate ROM offsets [superctr]

qsound: Apply ADPCM sample bank [superctr]
This commit is contained in:
Vas Crabb 2018-07-29 18:01:48 +10:00
parent 7bd14bedf6
commit 51cebe3f60
3 changed files with 31 additions and 33 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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)