Simulate a small delay on GC Memcard operations
This was not needed for most games before because the external exception was itself delayed. aram-dma-fixes changed that and made the external exception happen a lot quicker, breaking games that relied on the memcard operations delay. Fixes issue 5583.
This commit is contained in:
parent
76a13604ef
commit
760f777f5a
|
@ -47,13 +47,22 @@ 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) ? "memcardA" : "memcardB", FlushCallback);
|
et_this_card = CoreTiming::RegisterEvent((card_index == 0) ? "memcardFlushA" : "memcardFlushB", FlushCallback);
|
||||||
|
et_cmd_done = CoreTiming::RegisterEvent((card_index == 0) ? "memcardDoneA" : "memcardDoneB", CmdDoneCallback);
|
||||||
|
|
||||||
interruptSwitch = 0;
|
interruptSwitch = 0;
|
||||||
m_bInterruptSet = 0;
|
m_bInterruptSet = 0;
|
||||||
|
@ -175,6 +184,21 @@ 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
|
||||||
|
@ -198,11 +222,7 @@ void CEXIMemoryCard::SetCS(int cs)
|
||||||
|
|
||||||
//???
|
//???
|
||||||
|
|
||||||
status |= MC_STATUS_READY;
|
CmdDoneLater(5000);
|
||||||
status &= ~MC_STATUS_BUSY;
|
|
||||||
|
|
||||||
m_bInterruptSet = 1;
|
|
||||||
m_bDirty = true;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -229,11 +249,7 @@ void CEXIMemoryCard::SetCS(int cs)
|
||||||
address = (address & ~0x1FF) | ((address+1) & 0x1FF);
|
address = (address & ~0x1FF) | ((address+1) & 0x1FF);
|
||||||
}
|
}
|
||||||
|
|
||||||
status |= MC_STATUS_READY;
|
CmdDoneLater(5000);
|
||||||
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,9 +47,18 @@ 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,
|
||||||
|
@ -71,7 +80,7 @@ private:
|
||||||
|
|
||||||
std::string m_strFilename;
|
std::string m_strFilename;
|
||||||
int card_index;
|
int card_index;
|
||||||
int et_this_card;
|
int et_this_card, et_cmd_done;
|
||||||
//! memory card state
|
//! memory card state
|
||||||
|
|
||||||
// STATE_TO_SAVE
|
// STATE_TO_SAVE
|
||||||
|
|
Loading…
Reference in New Issue