diff --git a/src/devices/cpu/dsp16/dsp16dis.cpp b/src/devices/cpu/dsp16/dsp16dis.cpp index 7574c1c868c..85391ed6c43 100644 --- a/src/devices/cpu/dsp16/dsp16dis.cpp +++ b/src/devices/cpu/dsp16/dsp16dis.cpp @@ -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; } diff --git a/src/devices/sound/qsound.cpp b/src/devices/sound/qsound.cpp index dd4960b1211..0197304c53c 100644 --- a/src/devices/sound/qsound.cpp +++ b/src/devices/sound/qsound.cpp @@ -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 diff --git a/src/devices/sound/qsoundhle.cpp b/src/devices/sound/qsoundhle.cpp index 19634e5c062..5a57f098454 100644 --- a/src/devices/sound/qsoundhle.cpp +++ b/src/devices/sound/qsoundhle.cpp @@ -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; } } diff --git a/src/devices/sound/qsoundhle.h b/src/devices/sound/qsoundhle.h index 6bb081ae4fb..f723fa0a89b 100644 --- a/src/devices/sound/qsoundhle.h +++ b/src/devices/sound/qsoundhle.h @@ -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); };