Merge pull request #5440 from ligfx/axhledelayinterrupt

AX-HLE: delay sending interrupt when done processing command list
This commit is contained in:
Markus Wick 2017-05-23 14:29:45 +02:00 committed by GitHub
commit 3a2ec8c8a1
6 changed files with 27 additions and 18 deletions

View File

@ -3,16 +3,9 @@
[Core] [Core]
# Values set here will override the main Dolphin settings. # Values set here will override the main Dolphin settings.
MMU = 1 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] [EmuState]
# The Emulation State. 1 is worst, 5 is best, 0 is not set. # The Emulation State. 1 is worst, 5 is best, 0 is not set.
EmulationIssues = Needs LLE audio for proper sound.
EmulationStateId = 4 EmulationStateId = 4
[OnLoad] [OnLoad]

View File

@ -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 // DSP_CONTROL - we mask by (INT_DSP | INT_ARAM | INT_AID) just to ensure people
// don't call this with bogus values. // don't call this with bogus values.
s_dspState.Hex |= (DSPIntType & (INT_DSP | INT_ARAM | INT_AID)); s_dspState.Hex |= (DSPIntType & (INT_DSP | INT_ARAM | INT_AID));
UpdateInterrupts(); UpdateInterrupts();
} }
// CALLED FROM DSP EMULATOR, POSSIBLY THREADED // 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(cycles_into_future, s_et_GenerateDSPInterrupt, type,
CoreTiming::ScheduleEvent(0, s_et_GenerateDSPInterrupt, type, CoreTiming::FromThread::ANY); CoreTiming::FromThread::ANY);
} }
// called whenever SystemTimers thinks the DSP deserves a few more cycles // called whenever SystemTimers thinks the DSP deserves a few more cycles

View File

@ -69,7 +69,8 @@ DSPEmulator* GetDSPEmulator();
void DoState(PointerWrap& p); 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 // Audio/DSP Helper
u8 ReadARAM(u32 address); u8 ReadARAM(u32 address);

View File

@ -22,21 +22,21 @@ CMailHandler::~CMailHandler()
Clear(); Clear();
} }
void CMailHandler::PushMail(u32 _Mail, bool interrupt) void CMailHandler::PushMail(u32 mail, bool interrupt, int cycles_into_future)
{ {
if (interrupt) if (interrupt)
{ {
if (m_Mails.empty()) if (m_Mails.empty())
{ {
DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP); DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP, cycles_into_future);
} }
else else
{ {
m_Mails.front().second = true; m_Mails.front().second = true;
} }
} }
m_Mails.emplace(_Mail, false); m_Mails.emplace(mail, false);
DEBUG_LOG(DSP_MAIL, "DSP writes 0x%08x", _Mail); DEBUG_LOG(DSP_MAIL, "DSP writes 0x%08x", mail);
} }
u16 CMailHandler::ReadDSPMailboxHigh() u16 CMailHandler::ReadDSPMailboxHigh()

View File

@ -21,7 +21,8 @@ public:
CMailHandler(); CMailHandler();
~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 Clear();
void Halt(bool _Halt); void Halt(bool _Halt);
void DoState(PointerWrap& p); void DoState(PointerWrap& p);

View File

@ -77,7 +77,22 @@ void AXUCode::LoadResamplingCoefficients()
void AXUCode::SignalWorkEnd() void AXUCode::SignalWorkEnd()
{ {
// Signal end of processing // 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() void AXUCode::HandleCommandList()