DSPHLE: Return last mail with top bit cleared if there is no new mail

This is an accuracy improvement, though I don't think it matters for anything in practice.
This commit is contained in:
Pokechu22 2022-06-16 14:51:59 -07:00
parent bdbb23fa1a
commit 3aeafcc70b
2 changed files with 15 additions and 7 deletions

View File

@ -41,10 +41,9 @@ u16 CMailHandler::ReadDSPMailboxHigh()
// check if we have a mail for the CPU core
if (!m_pending_mails.empty())
{
u16 result = (m_pending_mails.front().first >> 16) & 0xFFFF;
return result;
m_last_mail = m_pending_mails.front().first;
}
return 0x00;
return u16(m_last_mail >> 0x10);
}
u16 CMailHandler::ReadDSPMailboxLow()
@ -52,18 +51,22 @@ u16 CMailHandler::ReadDSPMailboxLow()
// check if we have a mail for the CPU core
if (!m_pending_mails.empty())
{
u16 result = m_pending_mails.front().first & 0xFFFF;
m_last_mail = m_pending_mails.front().first;
const bool generate_interrupt = m_pending_mails.front().second;
m_pending_mails.pop_front();
if (generate_interrupt)
{
DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);
}
return result;
}
return 0x00;
// Clear the top bit of the high mail word after the mail has been read.
// The remaining bits read back the same as the previous mail, until new mail sent.
// (The CPU reads the high word first, and then the low word; since this function returns the low
// word, this means that the next read of the high word will have the top bit cleared.)
m_last_mail &= ~0x8000'0000;
return u16(m_last_mail & 0xffff);
}
void CMailHandler::ClearPending()

View File

@ -27,6 +27,8 @@ public:
// Clear any pending mail from the current uCode. This is called by DSPHLE::SetUCode and
// DSPHLE::SwapUCode. Since pending mail is an abstraction for DSPHLE and not something that
// actually exists on real hardware, HLE implementations do not need to call this directly.
// Note that this function does not reset m_last_mail, which will continue to read the same value
// until the new uCode sends mail.
void ClearPending();
u16 ReadDSPMailboxHigh();
@ -37,5 +39,8 @@ private:
// mails. But for HLE, it's a lot easier to write all the mails that will be read ahead of time,
// and then give them to the CPU in the requested order.
std::deque<std::pair<u32, bool>> m_pending_mails;
// If no pending mail exists, the last mail that was read is returned,
// but with the top bit (0x80000000) cleared.
u32 m_last_mail = 0;
};
} // namespace DSP::HLE