Simulate ARAM DMAState correctly and check for external exceptions after
MTMSR is executed. This commits fixes issue 617. WWE Day of Reckoning 1 and 2 are now playable with Dolphin. The changes are not implemented for JitIL yet.
This commit is contained in:
parent
227580d1a5
commit
da4141aa9f
|
@ -436,10 +436,6 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
if (tmpControl.ARAM) g_dspState.DSPControl.ARAM = 0;
|
if (tmpControl.ARAM) g_dspState.DSPControl.ARAM = 0;
|
||||||
if (tmpControl.DSP) g_dspState.DSPControl.DSP = 0;
|
if (tmpControl.DSP) g_dspState.DSPControl.DSP = 0;
|
||||||
|
|
||||||
// Tracking DMAState fixes Knockout Kings 2003 in DSP HLE mode
|
|
||||||
if (GetDSPEmulator()->IsLLE())
|
|
||||||
g_dspState.DSPControl.DMAState = 0; // keep g_ARAM DMA State zero
|
|
||||||
|
|
||||||
// unknown
|
// unknown
|
||||||
g_dspState.DSPControl.unk3 = tmpControl.unk3;
|
g_dspState.DSPControl.unk3 = tmpControl.unk3;
|
||||||
g_dspState.DSPControl.pad = tmpControl.pad;
|
g_dspState.DSPControl.pad = tmpControl.pad;
|
||||||
|
@ -701,8 +697,8 @@ void Do_ARAM_DMA()
|
||||||
// seems like a good estimate
|
// seems like a good estimate
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(g_arDMA.Cnt.count >> 1, et_GenerateDSPInterrupt, INT_ARAM | (1<<16));
|
CoreTiming::ScheduleEvent_Threadsafe(g_arDMA.Cnt.count >> 1, et_GenerateDSPInterrupt, INT_ARAM | (1<<16));
|
||||||
|
|
||||||
// Emulating the DMA wait time fixes Knockout Kings 2003 in DSP HLE mode
|
// Set the "DMA in progress" flag. It will be cleared when the interrupt will
|
||||||
if (!GetDSPEmulator()->IsLLE())
|
// be triggered, after the simulated delay.
|
||||||
g_dspState.DSPControl.DMAState = 1;
|
g_dspState.DSPControl.DMAState = 1;
|
||||||
|
|
||||||
// Real hardware DMAs in 32byte chunks, but we can get by with 8byte chunks
|
// Real hardware DMAs in 32byte chunks, but we can get by with 8byte chunks
|
||||||
|
|
|
@ -234,6 +234,7 @@ void Interpreter::mtmsr(UGeckoInstruction _inst)
|
||||||
{
|
{
|
||||||
// Privileged?
|
// Privileged?
|
||||||
MSR = m_GPR[_inst.RS];
|
MSR = m_GPR[_inst.RS];
|
||||||
|
PowerPC::CheckExceptions();
|
||||||
m_EndBlock = true;
|
m_EndBlock = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -300,10 +300,15 @@ void Jit64::Cleanup()
|
||||||
ABI_CallFunctionCCC((void *)&PowerPC::UpdatePerformanceMonitor, js.downcountAmount, jit->js.numLoadStoreInst, jit->js.numFloatingPointInst);
|
ABI_CallFunctionCCC((void *)&PowerPC::UpdatePerformanceMonitor, js.downcountAmount, jit->js.numLoadStoreInst, jit->js.numFloatingPointInst);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Jit64::WriteExit(u32 destination, int exit_num)
|
void Jit64::WriteExit(u32 destination, int exit_num, bool force_ee_check)
|
||||||
{
|
{
|
||||||
Cleanup();
|
Cleanup();
|
||||||
|
|
||||||
|
// External exceptions are checked when the following instruction sets the <= 0 flag.
|
||||||
|
// If we need to force the check, execute a useless SUB EAX, EAX
|
||||||
SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
|
SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
|
||||||
|
if (force_ee_check)
|
||||||
|
SUB(32, R(EAX), R(EAX));
|
||||||
|
|
||||||
//If nobody has taken care of this yet (this can be removed when all branches are done)
|
//If nobody has taken care of this yet (this can be removed when all branches are done)
|
||||||
JitBlock *b = js.curBlock;
|
JitBlock *b = js.curBlock;
|
||||||
|
@ -312,7 +317,7 @@ void Jit64::WriteExit(u32 destination, int exit_num)
|
||||||
|
|
||||||
// Link opportunity!
|
// Link opportunity!
|
||||||
int block = blocks.GetBlockNumberFromStartAddress(destination);
|
int block = blocks.GetBlockNumberFromStartAddress(destination);
|
||||||
if (block >= 0 && jo.enableBlocklink)
|
if (!force_ee_check && block >= 0 && jo.enableBlocklink)
|
||||||
{
|
{
|
||||||
// It exists! Joy of joy!
|
// It exists! Joy of joy!
|
||||||
JMP(blocks.GetBlock(block)->checkedEntry, true);
|
JMP(blocks.GetBlock(block)->checkedEntry, true);
|
||||||
|
|
|
@ -112,7 +112,7 @@ public:
|
||||||
|
|
||||||
// Utilities for use by opcodes
|
// Utilities for use by opcodes
|
||||||
|
|
||||||
void WriteExit(u32 destination, int exit_num);
|
void WriteExit(u32 destination, int exit_num, bool force_ee_check = false);
|
||||||
void WriteExitDestInEAX();
|
void WriteExitDestInEAX();
|
||||||
void WriteExceptionExit();
|
void WriteExceptionExit();
|
||||||
void WriteExternalExceptionExit();
|
void WriteExternalExceptionExit();
|
||||||
|
|
|
@ -122,7 +122,10 @@ void Jit64::mtmsr(UGeckoInstruction inst)
|
||||||
gpr.UnlockAll();
|
gpr.UnlockAll();
|
||||||
gpr.Flush(FLUSH_ALL);
|
gpr.Flush(FLUSH_ALL);
|
||||||
fpr.Flush(FLUSH_ALL);
|
fpr.Flush(FLUSH_ALL);
|
||||||
WriteExit(js.compilerPC + 4, 0);
|
|
||||||
|
// Force an external exception when going out of mtmsr in order to check
|
||||||
|
// immediately for interrupts that were delayed because of MSR.EE=0.
|
||||||
|
WriteExit(js.compilerPC + 4, 0, true);
|
||||||
js.firstFPInstructionFound = false;
|
js.firstFPInstructionFound = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue