mirror of
https://github.com/holub/mame
synced 2025-04-22 08:22:15 +03:00
dsp16: fix disassembler bugs (nw)
qsound_hle: simplify sample fetch/scale and register writes
This commit is contained in:
parent
30193541de
commit
deaa08b3b2
@ -395,7 +395,7 @@ dsp16_disassembler::result dsp16_disassembler::dasm_f1(u16 op)
|
||||
case 0x02: return result{ false, false, util::string_format("p = x*y") };
|
||||
case 0x03: return result{ false, false, util::string_format("a%u = a%u-p, p = x*y", d, s) };
|
||||
case 0x04: return result{ false, true, util::string_format("a%u = p", d) };
|
||||
case 0x05: return result{ false, false, util::string_format("a%u = a%u+p", d, d) };
|
||||
case 0x05: return result{ false, false, util::string_format("a%u = a%u+p", d, s) };
|
||||
case 0x06: return result{ true, false, util::string_format("nop") };
|
||||
case 0x07: return result{ false, false, util::string_format("a%u = a%u-p", d, s) };
|
||||
case 0x08: return result{ false, false, util::string_format("a%u = a%u|y", d, s) };
|
||||
@ -404,8 +404,8 @@ dsp16_disassembler::result dsp16_disassembler::dasm_f1(u16 op)
|
||||
case 0x0b: return result{ false, false, util::string_format("a%u-y", s) };
|
||||
case 0x0c: return result{ false, true, util::string_format("a%u = y", d) };
|
||||
case 0x0d: return result{ false, false, util::string_format("a%u = a%u+y", d, s) };
|
||||
case 0x0e: return result{ false, false, util::string_format("a%u = a%u&y", s, s) };
|
||||
case 0x0f: return result{ false, false, util::string_format("a%u = a%u-y", s, s) };
|
||||
case 0x0e: return result{ false, false, util::string_format("a%u = a%u&y", d, s) };
|
||||
case 0x0f: return result{ false, false, util::string_format("a%u = a%u-y", d, s) };
|
||||
}
|
||||
throw false;
|
||||
}
|
||||
|
@ -68,7 +68,7 @@
|
||||
(((ch - 1) << 3) & 0x78 sample bank
|
||||
(ch << 3) | 0x01 current/starting sample offset
|
||||
(ch << 3) | 0x02 rate (zero for key-off)
|
||||
(ch << 3) | 0x03 key-on
|
||||
(ch << 3) | 0x03 channel sample period counter
|
||||
(ch << 3) | 0x04 loop offset (relative to end)
|
||||
(ch << 3) | 0x05 end sample offset
|
||||
(ch << 3) | 0x06 channel volume
|
||||
|
@ -76,28 +76,30 @@ void qsound_hle_device::device_start()
|
||||
// init sound regs
|
||||
memset(m_channel, 0, sizeof(m_channel));
|
||||
|
||||
for (int adr = 0x7f; adr >= 0; adr--)
|
||||
write_data(adr, 0);
|
||||
for (int adr = 0x80; adr < 0x90; adr++)
|
||||
write_data(adr, 0x120);
|
||||
|
||||
// state save
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
save_item(NAME(m_channel[i].bank), i);
|
||||
save_item(NAME(m_channel[i].address), i);
|
||||
save_item(NAME(m_channel[i].freq), i);
|
||||
save_item(NAME(m_channel[i].loop), i);
|
||||
save_item(NAME(m_channel[i].end), i);
|
||||
save_item(NAME(m_channel[i].vol), i);
|
||||
save_item(NAME(m_channel[i].enabled), i);
|
||||
save_item(NAME(m_channel[i].reg), i);
|
||||
save_item(NAME(m_channel[i].lvol), i);
|
||||
save_item(NAME(m_channel[i].rvol), i);
|
||||
save_item(NAME(m_channel[i].step_ptr), i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void qsound_hle_device::device_reset()
|
||||
{
|
||||
for (qsound_channel &ch : m_channel)
|
||||
std::fill(std::begin(ch.reg), std::end(ch.reg), 0U);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// sound_stream_update - handle a stream update
|
||||
//-------------------------------------------------
|
||||
@ -108,45 +110,32 @@ void qsound_hle_device::sound_stream_update(sound_stream &stream, stream_sample_
|
||||
memset(outputs[0], 0, samples * sizeof(*outputs[0]));
|
||||
memset(outputs[1], 0, samples * sizeof(*outputs[1]));
|
||||
|
||||
for (auto & elem : m_channel)
|
||||
for (unsigned n = 0; ARRAY_LENGTH(m_channel) > n; ++n)
|
||||
{
|
||||
if (elem.enabled)
|
||||
qsound_channel &ch(m_channel[n]);
|
||||
stream_sample_t *lmix(outputs[0]);
|
||||
stream_sample_t *rmix(outputs[1]);
|
||||
|
||||
// Go through the buffer and add voice contributions
|
||||
offs_t const bank(m_channel[(n + ARRAY_LENGTH(m_channel) - 1) & (ARRAY_LENGTH(m_channel) - 1)].reg[0] & 0x7fff);
|
||||
for (int i = 0; i < samples; i++)
|
||||
{
|
||||
stream_sample_t *lmix=outputs[0];
|
||||
stream_sample_t *rmix=outputs[1];
|
||||
// current sample address (bank comes from previous channel)
|
||||
offs_t const addr(ch.reg[1] | (bank << 16));
|
||||
|
||||
// Go through the buffer and add voice contributions
|
||||
for (int i = 0; i < samples; i++)
|
||||
{
|
||||
elem.address += (elem.step_ptr >> 12);
|
||||
elem.step_ptr &= 0xfff;
|
||||
elem.step_ptr += elem.freq;
|
||||
// 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);
|
||||
|
||||
if (elem.address >= elem.end)
|
||||
{
|
||||
if (elem.loop)
|
||||
{
|
||||
// Reached the end, restart the loop
|
||||
elem.address -= elem.loop;
|
||||
// get the scaled sample
|
||||
int32_t const scaled(int32_t(int16_t(ch.reg[6])) * read_sample(addr));
|
||||
|
||||
// Make sure we don't overflow (what does the real chip do in this case?)
|
||||
if (elem.address >= elem.end)
|
||||
elem.address = elem.end - elem.loop;
|
||||
|
||||
elem.address &= 0xffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reached the end of a non-looped sample
|
||||
elem.enabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int8_t sample = read_sample(elem.bank | elem.address);
|
||||
*lmix++ += ((sample * elem.lvol * elem.vol) >> 14);
|
||||
*rmix++ += ((sample * elem.rvol * elem.vol) >> 14);
|
||||
}
|
||||
// apply simple panning
|
||||
*lmix++ += (((scaled >> 8) * ch.lvol) >> 14);
|
||||
*rmix++ += (((scaled >> 8) * ch.rvol) >> 14);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -187,14 +176,11 @@ void qsound_hle_device::write_data(uint8_t address, uint16_t data)
|
||||
{
|
||||
int ch = 0, reg;
|
||||
|
||||
// direct sound reg
|
||||
if (address < 0x80)
|
||||
{
|
||||
ch = address >> 3;
|
||||
reg = address & 7;
|
||||
}
|
||||
|
||||
// >= 0x80 is probably for the dsp?
|
||||
else if (address < 0x90)
|
||||
{
|
||||
ch = address & 0xf;
|
||||
@ -213,73 +199,38 @@ void qsound_hle_device::write_data(uint8_t address, uint16_t data)
|
||||
|
||||
switch (reg)
|
||||
{
|
||||
case 0:
|
||||
// bank, high bits unknown
|
||||
ch = (ch + 1) & 0xf; // strange ...
|
||||
m_channel[ch].bank = data << 16;
|
||||
break;
|
||||
case 0: // bank
|
||||
case 1: // current sample
|
||||
case 2: // playback rate
|
||||
case 3: // sample interval counter
|
||||
case 4: // loop offset
|
||||
case 5: // end sample
|
||||
case 6: // channel volume
|
||||
case 7: // unused
|
||||
m_channel[ch].reg[reg] = data;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// start/cur address
|
||||
m_channel[ch].address = data;
|
||||
break;
|
||||
case 8:
|
||||
{
|
||||
// panning (left=0x0110, centre=0x0120, right=0x0130)
|
||||
// looks like it doesn't write other values than that
|
||||
int pan = (data & 0x3f) - 0x10;
|
||||
if (pan > 0x20)
|
||||
pan = 0x20;
|
||||
if (pan < 0)
|
||||
pan = 0;
|
||||
|
||||
case 2:
|
||||
// frequency
|
||||
m_channel[ch].freq = data;
|
||||
if (data == 0)
|
||||
{
|
||||
// key off
|
||||
m_channel[ch].enabled = false;
|
||||
}
|
||||
break;
|
||||
m_channel[ch].rvol = m_pan_table[pan];
|
||||
m_channel[ch].lvol = m_pan_table[0x20 - pan];
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
// key on (does the value matter? it always writes 0x8000)
|
||||
m_channel[ch].enabled = true;
|
||||
m_channel[ch].step_ptr = 0;
|
||||
break;
|
||||
case 9:
|
||||
// unknown
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// loop address
|
||||
m_channel[ch].loop = data;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
// end address
|
||||
m_channel[ch].end = data;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
// master volume
|
||||
m_channel[ch].vol = data;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
// unused?
|
||||
break;
|
||||
|
||||
case 8:
|
||||
{
|
||||
// panning (left=0x0110, centre=0x0120, right=0x0130)
|
||||
// looks like it doesn't write other values than that
|
||||
int pan = (data & 0x3f) - 0x10;
|
||||
if (pan > 0x20)
|
||||
pan = 0x20;
|
||||
if (pan < 0)
|
||||
pan = 0;
|
||||
|
||||
m_channel[ch].rvol = m_pan_table[pan];
|
||||
m_channel[ch].lvol = m_pan_table[0x20 - pan];
|
||||
break;
|
||||
}
|
||||
|
||||
case 9:
|
||||
// unknown
|
||||
break;
|
||||
|
||||
default:
|
||||
//logerror("%s: write_data %02x = %04x\n", machine().describe_context(), address, data);
|
||||
break;
|
||||
default:
|
||||
//logerror("%s: write_data %02x = %04x\n", machine().describe_context(), address, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ public:
|
||||
protected:
|
||||
// device_t implementation
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// device_sound_interface implementation
|
||||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
|
||||
@ -48,24 +49,17 @@ private:
|
||||
|
||||
struct qsound_channel
|
||||
{
|
||||
uint32_t bank; // bank
|
||||
uint32_t address; // start/cur address
|
||||
uint16_t loop; // loop address
|
||||
uint16_t end; // end address
|
||||
uint32_t freq; // frequency
|
||||
uint16_t vol; // master volume
|
||||
uint16_t reg[8]; // channel control registers
|
||||
|
||||
// work variables
|
||||
bool enabled; // key on / key off
|
||||
int lvol; // left volume
|
||||
int rvol; // right volume
|
||||
uint32_t step_ptr; // current offset counter
|
||||
} m_channel[16];
|
||||
|
||||
int m_pan_table[33]; // pan volume table
|
||||
uint16_t m_data; // register latch data
|
||||
uint16_t m_data; // register latch data
|
||||
|
||||
inline int8_t read_sample(uint32_t offset) { return (int8_t)read_byte(offset); }
|
||||
inline int16_t read_sample(uint32_t offset) { return uint16_t(read_byte(offset)) << 8; }
|
||||
void write_data(uint8_t address, uint16_t data);
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user