mirror of
https://github.com/holub/mame
synced 2025-06-07 13:23:50 +03:00
qsoundhle: Saturate ROM offsets [superctr]
qsound: Apply ADPCM sample bank [superctr]
This commit is contained in:
parent
7bd14bedf6
commit
51cebe3f60
@ -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?
|
// 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));
|
u8 const byte(read_byte((u32(m_rom_bank) << 16) | m_rom_offset));
|
||||||
if (!machine().side_effects_disabled())
|
if (!machine().side_effects_disabled())
|
||||||
m_rom_bank = offset;
|
m_rom_bank = (m_rom_bank & 0x8000U) | offset;
|
||||||
return (u16(byte) << 8) | u16(byte);
|
return (u16(byte) << 8) | u16(byte);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,24 +331,10 @@ WRITE_LINE_MEMBER(qsound_device::dsp_ock_w)
|
|||||||
|
|
||||||
WRITE16_MEMBER(qsound_device::dsp_pio_w)
|
WRITE16_MEMBER(qsound_device::dsp_pio_w)
|
||||||
{
|
{
|
||||||
/*
|
// PDX0 is used for QSound ROM offset, and PDX1 is used for ADPCM ROM offset
|
||||||
* FIXME: what does this do when PDX is high?
|
// this prevents spurious PSEL transitions between sending samples to the DAC
|
||||||
* There are seemingly two significant points where the program writes PDX1 every sample interval.
|
// it could still be used to have separate QSound/ADPCM ROM banks
|
||||||
*
|
m_rom_bank = (m_rom_bank & 0x7fffU) | u16(offset << 15);
|
||||||
* 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;
|
m_rom_offset = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,19 @@
|
|||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "qsoundhle.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
|
// device type definition
|
||||||
DEFINE_DEVICE_TYPE(QSOUND_HLE, qsound_hle_device, "qsound_hle", "QSound (HLE)")
|
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 - 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_t(mconfig, QSOUND_HLE, tag, owner, clock)
|
||||||
, device_sound_interface(mconfig, *this)
|
, device_sound_interface(mconfig, *this)
|
||||||
, device_rom_interface(mconfig, *this, 24)
|
, 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));
|
offs_t const addr(ch.reg[1] | (bank << 16));
|
||||||
|
|
||||||
// update based on playback rate
|
// update based on playback rate
|
||||||
uint32_t updated(uint32_t(ch.reg[2] << 4) + ((uint32_t(ch.reg[1]) << 16) | ch.reg[3]));
|
s64 updated(s32(u32(ch.reg[2]) << 4) + s32((u32(ch.reg[1]) << 16) | ch.reg[3]));
|
||||||
ch.reg[3] = uint16_t(updated);
|
ch.reg[3] = u16(saturate(updated));
|
||||||
if (updated >= (uint32_t(ch.reg[5]) << 16))
|
if (updated >= s32(u32(ch.reg[5]) << 16))
|
||||||
updated -= uint32_t(ch.reg[4]) << 16;
|
updated -= s32(u32(ch.reg[4]) << 16);
|
||||||
ch.reg[1] = uint16_t(updated >> 16);
|
ch.reg[1] = u16(saturate(updated) >> 16);
|
||||||
|
|
||||||
// get the scaled sample
|
// 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
|
// apply simple panning
|
||||||
*lmix++ += (((scaled >> 8) * ch.lvol) >> 14);
|
*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;
|
int ch = 0, reg;
|
||||||
|
|
||||||
|
@ -34,13 +34,12 @@ protected:
|
|||||||
virtual void rom_bank_updated() override;
|
virtual void rom_bank_updated() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// MAME resources
|
// MAME resources
|
||||||
sound_stream *m_stream;
|
sound_stream *m_stream;
|
||||||
|
|
||||||
struct qsound_channel
|
struct qsound_channel
|
||||||
{
|
{
|
||||||
uint16_t reg[8]; // channel control registers
|
u16 reg[8]; // channel control registers
|
||||||
|
|
||||||
// work variables
|
// work variables
|
||||||
int lvol; // left volume
|
int lvol; // left volume
|
||||||
@ -48,10 +47,10 @@ private:
|
|||||||
} m_channel[16];
|
} m_channel[16];
|
||||||
|
|
||||||
int m_pan_table[33]; // pan volume table
|
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; }
|
inline s16 read_sample(u32 offset) { return u16(read_byte(offset)) << 8; }
|
||||||
void write_data(uint8_t address, uint16_t data);
|
void write_data(u8 address, u16 data);
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_DEVICE_TYPE(QSOUND_HLE, qsound_hle_device)
|
DECLARE_DEVICE_TYPE(QSOUND_HLE, qsound_hle_device)
|
||||||
|
Loading…
Reference in New Issue
Block a user