Revert merges of aram-dma-fixes and memcard-delay
These merges, while in theory improving emulation accuracy, cause issues in other parts of the emulator based on invalid assumptions. memcard-delay fixed some of these issues in the EXI memcard code, but several other problems still exist and I don't have the time to debug that right now.
This commit is contained in:
parent
1ffb9ce47e
commit
208d25c3f5
|
@ -436,6 +436,10 @@ 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;
|
||||||
|
@ -697,9 +701,9 @@ 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));
|
||||||
|
|
||||||
// Set the "DMA in progress" flag. It will be cleared when the interrupt will
|
// Emulating the DMA wait time fixes Knockout Kings 2003 in DSP HLE mode
|
||||||
// be triggered, after the simulated delay.
|
if (!GetDSPEmulator()->IsLLE())
|
||||||
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
|
||||||
if (g_arDMA.Cnt.dir)
|
if (g_arDMA.Cnt.dir)
|
||||||
|
|
|
@ -47,22 +47,13 @@ void CEXIMemoryCard::FlushCallback(u64 userdata, int cyclesLate)
|
||||||
pThis->Flush();
|
pThis->Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEXIMemoryCard::CmdDoneCallback(u64 userdata, int cyclesLate)
|
|
||||||
{
|
|
||||||
int card_index = (int)userdata;
|
|
||||||
CEXIMemoryCard* pThis = (CEXIMemoryCard*)ExpansionInterface::FindDevice(EXIDEVICE_MEMORYCARD, card_index);
|
|
||||||
if (pThis)
|
|
||||||
pThis->CmdDone();
|
|
||||||
}
|
|
||||||
|
|
||||||
CEXIMemoryCard::CEXIMemoryCard(const int index)
|
CEXIMemoryCard::CEXIMemoryCard(const int index)
|
||||||
: card_index(index)
|
: card_index(index)
|
||||||
, m_bDirty(false)
|
, m_bDirty(false)
|
||||||
{
|
{
|
||||||
m_strFilename = (card_index == 0) ? SConfig::GetInstance().m_strMemoryCardA : SConfig::GetInstance().m_strMemoryCardB;
|
m_strFilename = (card_index == 0) ? SConfig::GetInstance().m_strMemoryCardA : SConfig::GetInstance().m_strMemoryCardB;
|
||||||
// we're potentially leaking events here, since there's no UnregisterEvent until emu shutdown, but I guess it's inconsequential
|
// we're potentially leaking events here, since there's no UnregisterEvent until emu shutdown, but I guess it's inconsequential
|
||||||
et_this_card = CoreTiming::RegisterEvent((card_index == 0) ? "memcardFlushA" : "memcardFlushB", FlushCallback);
|
et_this_card = CoreTiming::RegisterEvent((card_index == 0) ? "memcardA" : "memcardB", FlushCallback);
|
||||||
et_cmd_done = CoreTiming::RegisterEvent((card_index == 0) ? "memcardDoneA" : "memcardDoneB", CmdDoneCallback);
|
|
||||||
|
|
||||||
interruptSwitch = 0;
|
interruptSwitch = 0;
|
||||||
m_bInterruptSet = 0;
|
m_bInterruptSet = 0;
|
||||||
|
@ -184,21 +175,6 @@ bool CEXIMemoryCard::IsPresent()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEXIMemoryCard::CmdDone()
|
|
||||||
{
|
|
||||||
status |= MC_STATUS_READY;
|
|
||||||
status &= ~MC_STATUS_BUSY;
|
|
||||||
|
|
||||||
m_bInterruptSet = 1;
|
|
||||||
m_bDirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CEXIMemoryCard::CmdDoneLater(u64 cycles)
|
|
||||||
{
|
|
||||||
CoreTiming::RemoveEvent(et_cmd_done);
|
|
||||||
CoreTiming::ScheduleEvent(cycles, et_cmd_done, (u64)card_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CEXIMemoryCard::SetCS(int cs)
|
void CEXIMemoryCard::SetCS(int cs)
|
||||||
{
|
{
|
||||||
// So that memory card won't be invalidated during flushing
|
// So that memory card won't be invalidated during flushing
|
||||||
|
@ -222,7 +198,11 @@ void CEXIMemoryCard::SetCS(int cs)
|
||||||
|
|
||||||
//???
|
//???
|
||||||
|
|
||||||
CmdDoneLater(5000);
|
status |= MC_STATUS_READY;
|
||||||
|
status &= ~MC_STATUS_BUSY;
|
||||||
|
|
||||||
|
m_bInterruptSet = 1;
|
||||||
|
m_bDirty = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -249,7 +229,11 @@ void CEXIMemoryCard::SetCS(int cs)
|
||||||
address = (address & ~0x1FF) | ((address+1) & 0x1FF);
|
address = (address & ~0x1FF) | ((address+1) & 0x1FF);
|
||||||
}
|
}
|
||||||
|
|
||||||
CmdDoneLater(5000);
|
status |= MC_STATUS_READY;
|
||||||
|
status &= ~MC_STATUS_BUSY;
|
||||||
|
|
||||||
|
m_bInterruptSet = 1;
|
||||||
|
m_bDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Page written to memory card, not just to buffer - let's schedule a flush 0.5b cycles into the future (1 sec)
|
// Page written to memory card, not just to buffer - let's schedule a flush 0.5b cycles into the future (1 sec)
|
||||||
|
|
|
@ -47,18 +47,9 @@ private:
|
||||||
// through the userdata parameter, so that it can then call Flush on the right card.
|
// through the userdata parameter, so that it can then call Flush on the right card.
|
||||||
static void FlushCallback(u64 userdata, int cyclesLate);
|
static void FlushCallback(u64 userdata, int cyclesLate);
|
||||||
|
|
||||||
// Scheduled when a command that required delayed end signaling is done.
|
|
||||||
static void CmdDoneCallback(u64 userdata, int cyclesLate);
|
|
||||||
|
|
||||||
// Flushes the memory card contents to disk.
|
// Flushes the memory card contents to disk.
|
||||||
void Flush(bool exiting = false);
|
void Flush(bool exiting = false);
|
||||||
|
|
||||||
// Signals that the command that was previously executed is now done.
|
|
||||||
void CmdDone();
|
|
||||||
|
|
||||||
// Variant of CmdDone which schedules an event later in the future to complete the command.
|
|
||||||
void CmdDoneLater(u64 cycles);
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
cmdNintendoID = 0x00,
|
cmdNintendoID = 0x00,
|
||||||
|
@ -80,7 +71,7 @@ private:
|
||||||
|
|
||||||
std::string m_strFilename;
|
std::string m_strFilename;
|
||||||
int card_index;
|
int card_index;
|
||||||
int et_this_card, et_cmd_done;
|
int et_this_card;
|
||||||
//! memory card state
|
//! memory card state
|
||||||
|
|
||||||
// STATE_TO_SAVE
|
// STATE_TO_SAVE
|
||||||
|
|
|
@ -234,7 +234,6 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -303,8 +303,7 @@ void Jit64::Cleanup()
|
||||||
void Jit64::WriteExit(u32 destination, int exit_num)
|
void Jit64::WriteExit(u32 destination, int exit_num)
|
||||||
{
|
{
|
||||||
Cleanup();
|
Cleanup();
|
||||||
|
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 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;
|
||||||
|
|
|
@ -122,25 +122,7 @@ 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);
|
||||||
|
|
||||||
// If some exceptions are pending and EE are now enabled, force checking
|
|
||||||
// external exceptions when going out of mtmsr in order to execute delayed
|
|
||||||
// interrupts as soon as possible.
|
|
||||||
MOV(32, R(EAX), M(&MSR));
|
|
||||||
TEST(32, R(EAX), Imm32(0x8000));
|
|
||||||
FixupBranch eeDisabled = J_CC(CC_Z);
|
|
||||||
|
|
||||||
MOV(32, R(EAX), M((void*)&PowerPC::ppcState.Exceptions));
|
|
||||||
TEST(32, R(EAX), R(EAX));
|
|
||||||
FixupBranch noExceptionsPending = J_CC(CC_Z);
|
|
||||||
|
|
||||||
MOV(32, M(&PC), Imm32(js.compilerPC + 4));
|
|
||||||
WriteExternalExceptionExit();
|
|
||||||
|
|
||||||
SetJumpTarget(eeDisabled);
|
|
||||||
SetJumpTarget(noExceptionsPending);
|
|
||||||
WriteExit(js.compilerPC + 4, 0);
|
WriteExit(js.compilerPC + 4, 0);
|
||||||
|
|
||||||
js.firstFPInstructionFound = false;
|
js.firstFPInstructionFound = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -276,8 +276,8 @@ public:
|
||||||
InstLoc EmitLoadMSR() {
|
InstLoc EmitLoadMSR() {
|
||||||
return FoldZeroOp(LoadMSR, 0);
|
return FoldZeroOp(LoadMSR, 0);
|
||||||
}
|
}
|
||||||
InstLoc EmitStoreMSR(InstLoc val, InstLoc pc) {
|
InstLoc EmitStoreMSR(InstLoc val) {
|
||||||
return FoldBiOp(StoreMSR, val, pc);
|
return FoldUOp(StoreMSR, val);
|
||||||
}
|
}
|
||||||
InstLoc EmitStoreFPRF(InstLoc value) {
|
InstLoc EmitStoreFPRF(InstLoc value) {
|
||||||
return FoldUOp(StoreFPRF, value);
|
return FoldUOp(StoreFPRF, value);
|
||||||
|
|
|
@ -994,26 +994,8 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case StoreMSR: {
|
case StoreMSR: {
|
||||||
unsigned InstLoc = ibuild->GetImmValue(getOp2(I));
|
|
||||||
regStoreInstToConstLoc(RI, 32, getOp1(I), &MSR);
|
regStoreInstToConstLoc(RI, 32, getOp1(I), &MSR);
|
||||||
regNormalRegClear(RI, I);
|
regNormalRegClear(RI, I);
|
||||||
|
|
||||||
// If some exceptions are pending and EE are now enabled, force checking
|
|
||||||
// external exceptions when going out of mtmsr in order to execute delayed
|
|
||||||
// interrupts as soon as possible.
|
|
||||||
Jit->MOV(32, R(EAX), M(&MSR));
|
|
||||||
Jit->TEST(32, R(EAX), Imm32(0x8000));
|
|
||||||
FixupBranch eeDisabled = Jit->J_CC(CC_Z);
|
|
||||||
|
|
||||||
Jit->MOV(32, R(EAX), M((void*)&PowerPC::ppcState.Exceptions));
|
|
||||||
Jit->TEST(32, R(EAX), R(EAX));
|
|
||||||
FixupBranch noExceptionsPending = Jit->J_CC(CC_Z);
|
|
||||||
|
|
||||||
Jit->MOV(32, M(&PC), Imm32(InstLoc + 4));
|
|
||||||
Jit->WriteExceptionExit(); // TODO: Implement WriteExternalExceptionExit for JitIL
|
|
||||||
|
|
||||||
Jit->SetJumpTarget(eeDisabled);
|
|
||||||
Jit->SetJumpTarget(noExceptionsPending);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case StoreGQR: {
|
case StoreGQR: {
|
||||||
|
|
|
@ -106,7 +106,7 @@ void JitIL::mfspr(UGeckoInstruction inst)
|
||||||
// --------------
|
// --------------
|
||||||
void JitIL::mtmsr(UGeckoInstruction inst)
|
void JitIL::mtmsr(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
ibuild.EmitStoreMSR(ibuild.EmitLoadGReg(inst.RS), ibuild.EmitIntConst(js.compilerPC));
|
ibuild.EmitStoreMSR(ibuild.EmitLoadGReg(inst.RS));
|
||||||
ibuild.EmitBranchUncond(ibuild.EmitIntConst(js.compilerPC + 4));
|
ibuild.EmitBranchUncond(ibuild.EmitIntConst(js.compilerPC + 4));
|
||||||
}
|
}
|
||||||
// ==============
|
// ==============
|
||||||
|
|
Loading…
Reference in New Issue