Merge pull request #5440 from ligfx/axhledelayinterrupt
AX-HLE: delay sending interrupt when done processing command list
This commit is contained in:
commit
3a2ec8c8a1
|
@ -3,16 +3,9 @@
|
|||
[Core]
|
||||
# Values set here will override the main Dolphin settings.
|
||||
MMU = 1
|
||||
# LLE audio enabled by default for a listenable output
|
||||
DSPHLE = False
|
||||
|
||||
[DSP]
|
||||
# Ensure the LLE recompiler gets selected and not interpreter.
|
||||
EnableJIT = True
|
||||
|
||||
[EmuState]
|
||||
# The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||
EmulationIssues = Needs LLE audio for proper sound.
|
||||
EmulationStateId = 4
|
||||
|
||||
[OnLoad]
|
||||
|
|
|
@ -408,15 +408,14 @@ static void GenerateDSPInterrupt(u64 DSPIntType, s64 cyclesLate)
|
|||
// DSP_CONTROL - we mask by (INT_DSP | INT_ARAM | INT_AID) just to ensure people
|
||||
// don't call this with bogus values.
|
||||
s_dspState.Hex |= (DSPIntType & (INT_DSP | INT_ARAM | INT_AID));
|
||||
|
||||
UpdateInterrupts();
|
||||
}
|
||||
|
||||
// CALLED FROM DSP EMULATOR, POSSIBLY THREADED
|
||||
void GenerateDSPInterruptFromDSPEmu(DSPInterruptType type)
|
||||
void GenerateDSPInterruptFromDSPEmu(DSPInterruptType type, int cycles_into_future)
|
||||
{
|
||||
// TODO: Maybe rethink this? The timing is unpredictable.
|
||||
CoreTiming::ScheduleEvent(0, s_et_GenerateDSPInterrupt, type, CoreTiming::FromThread::ANY);
|
||||
CoreTiming::ScheduleEvent(cycles_into_future, s_et_GenerateDSPInterrupt, type,
|
||||
CoreTiming::FromThread::ANY);
|
||||
}
|
||||
|
||||
// called whenever SystemTimers thinks the DSP deserves a few more cycles
|
||||
|
|
|
@ -69,7 +69,8 @@ DSPEmulator* GetDSPEmulator();
|
|||
|
||||
void DoState(PointerWrap& p);
|
||||
|
||||
void GenerateDSPInterruptFromDSPEmu(DSPInterruptType type);
|
||||
// TODO: Maybe rethink this? The timing is unpredictable.
|
||||
void GenerateDSPInterruptFromDSPEmu(DSPInterruptType type, int cycles_into_future = 0);
|
||||
|
||||
// Audio/DSP Helper
|
||||
u8 ReadARAM(u32 address);
|
||||
|
|
|
@ -22,21 +22,21 @@ CMailHandler::~CMailHandler()
|
|||
Clear();
|
||||
}
|
||||
|
||||
void CMailHandler::PushMail(u32 _Mail, bool interrupt)
|
||||
void CMailHandler::PushMail(u32 mail, bool interrupt, int cycles_into_future)
|
||||
{
|
||||
if (interrupt)
|
||||
{
|
||||
if (m_Mails.empty())
|
||||
{
|
||||
DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);
|
||||
DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP, cycles_into_future);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Mails.front().second = true;
|
||||
}
|
||||
}
|
||||
m_Mails.emplace(_Mail, false);
|
||||
DEBUG_LOG(DSP_MAIL, "DSP writes 0x%08x", _Mail);
|
||||
m_Mails.emplace(mail, false);
|
||||
DEBUG_LOG(DSP_MAIL, "DSP writes 0x%08x", mail);
|
||||
}
|
||||
|
||||
u16 CMailHandler::ReadDSPMailboxHigh()
|
||||
|
|
|
@ -21,7 +21,8 @@ public:
|
|||
CMailHandler();
|
||||
~CMailHandler();
|
||||
|
||||
void PushMail(u32 _Mail, bool interrupt = false);
|
||||
// TODO: figure out correct timing for interrupts rather than defaulting to "immediately."
|
||||
void PushMail(u32 mail, bool interrupt = false, int cycles_into_future = 0);
|
||||
void Clear();
|
||||
void Halt(bool _Halt);
|
||||
void DoState(PointerWrap& p);
|
||||
|
|
|
@ -77,7 +77,22 @@ void AXUCode::LoadResamplingCoefficients()
|
|||
void AXUCode::SignalWorkEnd()
|
||||
{
|
||||
// Signal end of processing
|
||||
m_mail_handler.PushMail(DSP_YIELD, true);
|
||||
// TODO: figure out how many cycles this is actually supposed to take
|
||||
|
||||
// The Clone Wars hangs upon initial boot if this interrupt happens too quickly after submitting a
|
||||
// command list. When played in DSP-LLE, the interrupt lags by about 160,000 cycles, though any
|
||||
// value greater than or equal to 814 will work here. In other games, the lag can be as small as
|
||||
// 50,000 cycles (in Metroid Prime) and as large as 718,092 cycles (in Tales of Symphonia!).
|
||||
|
||||
// On the PowerPC side, hthh_ discovered that The Clone Wars tracks a "AXCommandListCycles"
|
||||
// variable which matches the aforementioned 160,000 cycles. It's initialized to ~2500 cycles for
|
||||
// a minimal, empty command list, so that should be a safe number for pretty much anything a game
|
||||
// does.
|
||||
|
||||
// For more information, see https://bugs.dolphin-emu.org/issues/10265.
|
||||
constexpr int AX_EMPTY_COMMAND_LIST_CYCLES = 2500;
|
||||
|
||||
m_mail_handler.PushMail(DSP_YIELD, true, AX_EMPTY_COMMAND_LIST_CYCLES);
|
||||
}
|
||||
|
||||
void AXUCode::HandleCommandList()
|
||||
|
|
Loading…
Reference in New Issue