From 1e1369c02b191bb201f093b5b9517f4fc732bc40 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Fri, 16 Mar 2018 04:26:46 +1100 Subject: qsound: clean up host and DAC comms a bit, hopefully fix desync ie15: fix shortname conflict (nw) Motorola naming M68000 = family, MC68000 = main production implementation, XC68LC040 = pre-main production implementation. The M prefix should only be used for devices representing a family in the abstract, like the M6805 device that represents the PMOS 6805 core but not a particular implementation with onboard peripherals and memory. (nw) --- src/devices/cpu/ie15/ie15.cpp | 2 +- src/devices/cpu/m68000/m68kcpu.cpp | 30 +++++++-------- src/devices/sound/qsound.cpp | 79 +++++++++++++++++++++----------------- src/devices/sound/qsound.h | 7 +--- src/devices/sound/qsoundhle.cpp | 2 +- 5 files changed, 62 insertions(+), 58 deletions(-) diff --git a/src/devices/cpu/ie15/ie15.cpp b/src/devices/cpu/ie15/ie15.cpp index 23e69cadd45..80c0fecdbe7 100644 --- a/src/devices/cpu/ie15/ie15.cpp +++ b/src/devices/cpu/ie15/ie15.cpp @@ -22,7 +22,7 @@ //************************************************************************** // device type definition -DEFINE_DEVICE_TYPE(IE15_CPU, ie15_cpu_device, "ie15", "ie15 CPU") +DEFINE_DEVICE_TYPE(IE15_CPU, ie15_cpu_device, "ie15_cpu", "ie15 CPU") //************************************************************************** // DEVICE INTERFACE diff --git a/src/devices/cpu/m68000/m68kcpu.cpp b/src/devices/cpu/m68000/m68kcpu.cpp index c8a13cadb4e..bf8a92a600b 100644 --- a/src/devices/cpu/m68000/m68kcpu.cpp +++ b/src/devices/cpu/m68000/m68kcpu.cpp @@ -2464,21 +2464,21 @@ device_memory_interface::space_config_vector m68000_base_device::memory_space_co -DEFINE_DEVICE_TYPE(M68000, m68000_device, "m68000", "Motorola M68000") -DEFINE_DEVICE_TYPE(M68301, m68301_device, "m68301", "Motorola M68301") -DEFINE_DEVICE_TYPE(M68008, m68008_device, "m68008", "Motorola M68008") -DEFINE_DEVICE_TYPE(M68008PLCC, m68008plcc_device, "m68008plcc", "Motorola M68008PLCC") -DEFINE_DEVICE_TYPE(M68010, m68010_device, "m68010", "Motorola M68010") -DEFINE_DEVICE_TYPE(M68EC020, m68ec020_device, "m68ec020", "Motorola M68EC020") -DEFINE_DEVICE_TYPE(M68020, m68020_device, "m68020", "Motorola M68020") -DEFINE_DEVICE_TYPE(M68020FPU, m68020fpu_device, "m68020fpu", "Motorola M68020FPU") -DEFINE_DEVICE_TYPE(M68020PMMU, m68020pmmu_device, "m68020pmmu", "Motorola M68020PMMU") -DEFINE_DEVICE_TYPE(M68020HMMU, m68020hmmu_device, "m68020hmmu", "Motorola M68020HMMU") -DEFINE_DEVICE_TYPE(M68EC030, m68ec030_device, "m68ec030", "Motorola M68EC030") -DEFINE_DEVICE_TYPE(M68030, m68030_device, "m68030", "Motorola M68030") -DEFINE_DEVICE_TYPE(M68EC040, m68ec040_device, "m68ec040", "Motorola M68EC040") -DEFINE_DEVICE_TYPE(M68LC040, m68lc040_device, "m68lc040", "Motorola M68LC040") -DEFINE_DEVICE_TYPE(M68040, m68040_device, "m68040", "Motorola M68040") +DEFINE_DEVICE_TYPE(M68000, m68000_device, "m68000", "Motorola MC68000") +DEFINE_DEVICE_TYPE(M68301, m68301_device, "m68301", "Motorola MC68301") +DEFINE_DEVICE_TYPE(M68008, m68008_device, "m68008", "Motorola MC68008") +DEFINE_DEVICE_TYPE(M68008PLCC, m68008plcc_device, "m68008plcc", "Motorola MC68008PLCC") +DEFINE_DEVICE_TYPE(M68010, m68010_device, "m68010", "Motorola MC68010") +DEFINE_DEVICE_TYPE(M68EC020, m68ec020_device, "m68ec020", "Motorola MC68EC020") +DEFINE_DEVICE_TYPE(M68020, m68020_device, "m68020", "Motorola MC68020") +DEFINE_DEVICE_TYPE(M68020FPU, m68020fpu_device, "m68020fpu", "Motorola MC68020FPU") +DEFINE_DEVICE_TYPE(M68020PMMU, m68020pmmu_device, "m68020pmmu", "Motorola MC68020PMMU") +DEFINE_DEVICE_TYPE(M68020HMMU, m68020hmmu_device, "m68020hmmu", "Motorola MC68020HMMU") +DEFINE_DEVICE_TYPE(M68EC030, m68ec030_device, "m68ec030", "Motorola MC68EC030") +DEFINE_DEVICE_TYPE(M68030, m68030_device, "m68030", "Motorola MC68030") +DEFINE_DEVICE_TYPE(M68EC040, m68ec040_device, "m68ec040", "Motorola MC68EC040") +DEFINE_DEVICE_TYPE(M68LC040, m68lc040_device, "m68lc040", "Motorola MC68LC040") +DEFINE_DEVICE_TYPE(M68040, m68040_device, "m68040", "Motorola MC68040") DEFINE_DEVICE_TYPE(SCC68070, scc68070_device, "scc68070", "Philips SCC68070") DEFINE_DEVICE_TYPE(FSCPU32, fscpu32_device, "fscpu32", "Freescale CPU32 Core") DEFINE_DEVICE_TYPE(MCF5206E, mcf5206e_device, "mcf5206e", "Freescale MCF5206E") diff --git a/src/devices/sound/qsound.cpp b/src/devices/sound/qsound.cpp index f5411dfa94b..402c7c80a02 100644 --- a/src/devices/sound/qsound.cpp +++ b/src/devices/sound/qsound.cpp @@ -42,12 +42,13 @@ are 16-bit signed values, but Capcom only has 8-bit ROMs connected. I'm assuming byte smearing, but it may be zero-padded in the LSBs. - The DSP sends out 16-bit samples on its SIO port clocked at 2.5 MHz. + The DSP sends out 16-bit samples on its SIO port clocked at 5 MHz. The stereo samples aren't loaded fast enough for consecutive frames so there's an empty frame between them. Sample pairs are loaded every 1,248 machine cycles, giving a sample rate of 24.03846 kHz - (60 MHz / 2 / 1248). It's unknown how the real hardware identifies - left/right samples - I'm using a massive hack at the moment. + (60 MHz / 2 / 1248). The glue logic seems to generate the WS signal + for the DAC from the PSEL line and the SIO control lines, but it + isn't clear exactly how this is achieved. The DSP writes values to pdx1 every sample cycle (alternating between zero and non-zero values). This may be for the volume @@ -93,7 +94,7 @@ #define LOG_COMMAND (1U << 1) #define LOG_SAMPLE (1U << 2) -//#define VERBOSE (LOG_GENERAL | LOG_SAMPLE) +//#define VERBOSE (LOG_GENERAL | LOG_COMMAND | LOG_SAMPLE) //#define LOG_OUTPUT_STREAM std::cout #include "logmacro.h" @@ -122,8 +123,8 @@ qsound_device::qsound_device(machine_config const &mconfig, char const *tag, dev , device_sound_interface(mconfig, *this) , device_rom_interface(mconfig, *this, 24) , m_dsp(*this, "dsp"), m_stream(nullptr) - , m_rom_bank(0U), m_rom_offset(0U), m_cmd_addr(0U), m_cmd_data(0U), m_cmd_pending(0U), m_dsp_ready(1U) - , m_last_time(0U), m_samples{ 0, 0 }, m_sr(0U), m_fsr(0U), m_ock(1U), m_old(1U), m_ready(0U), m_channel(0U) + , m_rom_bank(0U), m_rom_offset(0U), m_cmd_addr(0U), m_cmd_data(0U), m_new_data(0U), m_cmd_pending(0U), m_dsp_ready(1U) + , m_samples{ 0, 0 }, m_sr(0U), m_fsr(0U), m_ock(1U), m_old(1U), m_ready(0U), m_channel(0U) { } @@ -133,14 +134,22 @@ WRITE8_MEMBER(qsound_device::qsound_w) switch (offset) { case 0: - machine().scheduler().synchronize(timer_expired_delegate(FUNC(qsound_device::set_cmd_data_high), this), unsigned(data)); + LOGCOMMAND( + "QSound: set command data[h] = %02X (%04X -> %04X)\n", + data, m_new_data, (m_new_data & 0x00ffU) | (u16(data) << 8)); + m_new_data = (m_new_data & 0x00ffU) | (u16(data) << 8); break; case 1: - machine().scheduler().synchronize(timer_expired_delegate(FUNC(qsound_device::set_cmd_data_low), this), unsigned(data)); + LOGCOMMAND( + "QSound: set command data[l] = %02X (%04X -> %04X)\n", + data, m_new_data, (m_new_data & 0xff00U) | data); + m_new_data = (m_new_data & 0xff00U) | data; break; case 2: m_dsp_ready = 0U; - machine().scheduler().synchronize(timer_expired_delegate(FUNC(qsound_device::set_cmd_addr), this), unsigned(data)); + machine().scheduler().synchronize( + timer_expired_delegate(FUNC(qsound_device::set_cmd), this), + (unsigned(data) << 16) | m_new_data); break; default: logerror("QSound: host write to unknown register %01X = %02X (%s)\n", offset, data, machine().describe_context()); @@ -192,11 +201,11 @@ void qsound_device::device_start() save_item(NAME(m_rom_offset)); save_item(NAME(m_cmd_addr)); save_item(NAME(m_cmd_data)); + save_item(NAME(m_new_data)); save_item(NAME(m_cmd_pending)); save_item(NAME(m_dsp_ready)); // save serial sample recovery state - save_item(NAME(m_last_time)); save_item(NAME(m_samples)); save_item(NAME(m_sr)); save_item(NAME(m_fsr)); @@ -251,7 +260,7 @@ void qsound_device::dsp_io_map(address_map &map) READ16_MEMBER(qsound_device::dsp_sample_r) { - // TODO: 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)); if (!machine().side_effects_disabled()) m_rom_bank = offset; @@ -269,7 +278,11 @@ WRITE_LINE_MEMBER(qsound_device::dsp_ock_w) // detect start of word if (m_ready && !m_fsr && !m_dsp->ose_r()) + { + // FIXME: PSEL at beginning of word seems to select channel, but how does the logic derive WS from the DSP outputs? + m_channel = m_dsp->psel_r(); m_fsr = 0xffffU; + } // shift in data if (m_fsr) @@ -278,16 +291,10 @@ WRITE_LINE_MEMBER(qsound_device::dsp_ock_w) m_fsr >>= 1; if (!m_fsr) { - // FIXME: this is an epic hack, but I don't know how the hardware actually identifies channels - u64 const now(m_dsp->total_cycles()); - if ((now - m_last_time) > 500) - m_channel = 0U; - m_last_time = now; LOGSAMPLE("QSound: recovered channel %u sample %04X\n", m_channel, m_sr); if (!m_channel) m_stream->update(); m_samples[m_channel] = m_sr; - m_channel = m_channel ? 0U : 1U; #if 0 // enable to log PCM to a file - can be imported with "ffmpeg -f s16be -ar 24038 -ac 2 -i qsound.pcm qsound.wav" static std::ofstream logfile("qsound.pcm", std::ios::binary); logfile.put(u8(m_sr >> 8)); @@ -304,6 +311,21 @@ 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 @@ -334,26 +356,11 @@ void qsound_device::set_dsp_ready(void *ptr, s32 param) m_dsp_ready = 1U; } -void qsound_device::set_cmd_addr(void *ptr, s32 param) +void qsound_device::set_cmd(void *ptr, s32 param) { - LOGCOMMAND("QSound: DSP command @%02X = %04X\n", param, m_cmd_data); - m_cmd_addr = u16(u32(param)); + LOGCOMMAND("QSound: DSP command @%02X = %04X\n", u32(param) >> 16, u16(u32(param))); + m_cmd_addr = u16(u32(param) >> 16); + m_cmd_data = u16(u32(param)); m_cmd_pending = 1U; m_dsp->set_input_line(DSP16_INT_LINE, ASSERT_LINE); } - -void qsound_device::set_cmd_data_high(void *ptr, s32 param) -{ - LOGCOMMAND( - "QSound: set command data[h] = %02X (%04X -> %04X)\n", - param, m_cmd_data, (m_cmd_data & 0x00ffU) | (u32(param) << 8)); - m_cmd_data = u16((m_cmd_data & 0x00ffU) | (u32(param) << 8)); -} - -void qsound_device::set_cmd_data_low(void *ptr, s32 param) -{ - LOGCOMMAND( - "QSound: set command data[l] = %02X (%04X -> %04X)\n", - param, m_cmd_data, (m_cmd_data & 0xff00U) | u32(param)); - m_cmd_data = u16((m_cmd_data & 0xff00U) | u32(param)); -} diff --git a/src/devices/sound/qsound.h b/src/devices/sound/qsound.h index 53966e8b701..9bdbdc5716e 100644 --- a/src/devices/sound/qsound.h +++ b/src/devices/sound/qsound.h @@ -47,9 +47,7 @@ private: DECLARE_WRITE_LINE_MEMBER(dsp_ock_w); DECLARE_READ16_MEMBER(dsp_pio_r); void set_dsp_ready(void *ptr, s32 param); - void set_cmd_addr(void *ptr, s32 param); - void set_cmd_data_high(void *ptr, s32 param); - void set_cmd_data_low(void *ptr, s32 param); + void set_cmd(void *ptr, s32 param); // MAME resources required_device m_dsp; @@ -57,11 +55,10 @@ private: // DSP communication u16 m_rom_bank, m_rom_offset; - u16 m_cmd_addr, m_cmd_data; + u16 m_cmd_addr, m_cmd_data, m_new_data; u8 m_cmd_pending, m_dsp_ready; // serial sample recovery - u64 m_last_time; s16 m_samples[2]; u16 m_sr, m_fsr; u8 m_ock, m_old, m_ready, m_channel; diff --git a/src/devices/sound/qsoundhle.cpp b/src/devices/sound/qsoundhle.cpp index 31b28b36e49..e310fb98090 100644 --- a/src/devices/sound/qsoundhle.cpp +++ b/src/devices/sound/qsoundhle.cpp @@ -27,7 +27,7 @@ ***************************************************************************/ #include "emu.h" -#include "qsound.h" +#include "qsoundhle.h" // device type definition DEFINE_DEVICE_TYPE(QSOUND_HLE, qsound_hle_device, "qsound_hle", "QSound (HLE)") -- cgit v1.2.3