cbus/pc9801_86.cpp: attempt to resolve DAC FIFO under/overflows

This commit is contained in:
angelosa 2024-11-12 21:23:03 +01:00
parent 878d70d975
commit d566c8f76b
2 changed files with 52 additions and 29 deletions

View File

@ -20,6 +20,7 @@
TODO: TODO:
- Test all pcm modes; - Test all pcm modes;
- Fix PCM overflow bug properly (CPUENB signal yield host CPU until DAC catches up?)
- Make volume work; - Make volume work;
- Recording; - Recording;
- SpeakBoard: no idea about software that uses this, also board shows a single YM2608B? - SpeakBoard: no idea about software that uses this, also board shows a single YM2608B?
@ -368,14 +369,21 @@ void pc9801_86_device::io_map(address_map &map)
return 0; return 0;
}), }),
NAME([this] (u8 data) { NAME([this] (u8 data) {
// HACK: on overflow make sure to single step the FIFO enough to claim some space back
// os2warp3 initializes the full buffer with 0x00 then quickly pretends
// that DAC already catched up by the time the actual startup/shutdown chimes are sent.
if (queue_count() == QUEUE_SIZE)
{
dac_transfer();
logerror("Warning: $a46c write with FIFO overflow %02x\n", m_pcm_mode);
}
if(queue_count() < QUEUE_SIZE) if(queue_count() < QUEUE_SIZE)
{ {
m_queue[m_head++] = data; m_queue[m_head++] = data;
m_head %= QUEUE_SIZE; m_head %= QUEUE_SIZE;
m_count++; m_count++;
} }
// TODO: what should happen on overflow?
// os2warp3 startup / shutdown chimes do this already
}) })
); );
} }
@ -424,12 +432,8 @@ u8 pc9801_86_device::queue_pop()
return ret; return ret;
} }
TIMER_CALLBACK_MEMBER(pc9801_86_device::dac_tick) void pc9801_86_device::dac_transfer()
{ {
m_pcm_clk = !m_pcm_clk;
if((m_pcm_ctrl & 0x40) || !(m_pcm_ctrl & 0x80))
return;
switch(m_pcm_mode & 0x70) switch(m_pcm_mode & 0x70)
{ {
case 0x70: // 8bit stereo case 0x70: // 8bit stereo
@ -461,6 +465,20 @@ TIMER_CALLBACK_MEMBER(pc9801_86_device::dac_tick)
m_rdac->write(rsample); m_rdac->write(rsample);
} break; } break;
} }
}
TIMER_CALLBACK_MEMBER(pc9801_86_device::dac_tick)
{
m_pcm_clk = !m_pcm_clk;
if((m_pcm_ctrl & 0x40) || !(m_pcm_ctrl & 0x80))
return;
// TODO: verify underflow
// should leave the DACs in whatever state they are or ...?
if (!queue_count())
return;
dac_transfer();
if((queue_count() < m_irq_rate) && (m_pcm_ctrl & 0x20)) if((queue_count() < m_irq_rate) && (m_pcm_ctrl & 0x20))
{ {
m_pcmirq = true; m_pcmirq = true;

View File

@ -31,6 +31,9 @@ public:
pc9801_86_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); pc9801_86_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
pc9801_86_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); pc9801_86_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
static constexpr feature_type unemulated_features() { return feature::MICROPHONE; }
static constexpr feature_type imperfect_features() { return feature::SOUND; }
protected: protected:
void io_map(address_map &map) ATTR_COLD; void io_map(address_map &map) ATTR_COLD;
u8 pcm_control_r(); u8 pcm_control_r();
@ -74,6 +77,8 @@ private:
required_device<dac_16bit_r2r_twos_complement_device> m_rdac; required_device<dac_16bit_r2r_twos_complement_device> m_rdac;
std::vector<u8> m_queue; std::vector<u8> m_queue;
emu_timer *m_dac_timer; emu_timer *m_dac_timer;
void dac_transfer();
}; };
class pc9801_speakboard_device : public pc9801_86_device class pc9801_speakboard_device : public pc9801_86_device