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)
This commit is contained in:
Vas Crabb 2018-03-16 04:26:46 +11:00
parent bb11fbd2bd
commit 1e1369c02b
5 changed files with 62 additions and 58 deletions

View File

@ -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

View File

@ -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")

View File

@ -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));
}

View File

@ -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<dsp16_device_base> 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;

View File

@ -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)")