mirror of
https://github.com/holub/mame
synced 2025-06-03 11:26:56 +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?
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user