Use different reply delays for various DI commands.

Fixes issue 5983.
This commit is contained in:
Jordan Woyak 2013-02-08 16:20:15 -06:00
parent 95d08db46f
commit a11827cdf0
3 changed files with 55 additions and 6 deletions

View File

@ -84,6 +84,8 @@ static ipc_msg_queue reply_queue; // arm -> ppc
static int enque_reply;
static u64 last_reply_time;
void EnqueReplyCallback(u64 userdata, int)
{
reply_queue.push_back(userdata);
@ -163,6 +165,7 @@ void Reset(bool _bHard)
}
request_queue.clear();
reply_queue.clear();
last_reply_time = 0;
}
void Shutdown()
@ -246,6 +249,7 @@ void DoState(PointerWrap &p)
{
p.Do(request_queue);
p.Do(reply_queue);
p.Do(last_reply_time);
TDeviceMap::const_iterator itr;
@ -518,8 +522,18 @@ void ExecuteCommand(u32 _Address)
if (CmdSuccess)
{
// Ensure replies happen in order, fairly ugly
// Without this, tons of games fail now that DI commads have different reply delays
int reply_delay = pDevice ? pDevice->GetCmdDelay(_Address) : 0;
const s64 ticks_til_last_reply = last_reply_time - CoreTiming::GetTicks();
if (ticks_til_last_reply > 0)
reply_delay = ticks_til_last_reply;
last_reply_time = CoreTiming::GetTicks() + reply_delay;
// Generate a reply to the IPC command
int const reply_delay = pDevice ? pDevice->GetCmdDelay(_Address) : 0;
EnqReply(_Address, reply_delay);
}
else

View File

@ -462,8 +462,43 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32
return 1;
}
int CWII_IPC_HLE_Device_di::GetCmdDelay(u32)
int CWII_IPC_HLE_Device_di::GetCmdDelay(u32 _CommandAddress)
{
// Less than ~1/150th of a second hangs Oregon Trail at "loading wheel".
return SystemTimers::GetTicksPerSecond() / 100;
}
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
u32 Command = Memory::Read_U32(BufferIn) >> 24;
// Hacks below
switch (Command)
{
case DVDLowRead:
case DVDLowUnencryptedRead:
{
u32 const Size = Memory::Read_U32(BufferIn + 0x04);
// Delay depends on size of read, that makes sense, right?
// More than ~1150K "bytes / sec" hangs NSMBWii on boot.
// Less than ~800K "bytes / sec" hangs DKCR randomly.
return SystemTimers::GetTicksPerSecond() / 975000 * Size;
break;
}
case DVDLowClearCoverInterrupt:
// Less than ~1/155th of a second hangs Oregon Trail at "loading wheel".
// More than ~1/140th of a second hangs Resident Evil Archives: Resident Evil Zero.
return SystemTimers::GetTicksPerSecond() / 146;
break;
// case DVDLowAudioBufferConfig:
// case DVDLowInquiry:
// case DVDLowReadDiskID:
// case DVDLowWaitForCoverClose:
// case DVDLowGetCoverReg:
// case DVDLowGetCoverStatus:
// case DVDLowReset:
// case DVDLowClosePartition:
default:
// ranom numbers here!
return SystemTimers::GetTicksPerSecond() / 1500;
break;
}
}

View File

@ -71,7 +71,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
static std::thread g_save_thread;
// Don't forget to increase this after doing changes on the savestate system
static const u32 STATE_VERSION = 11;
static const u32 STATE_VERSION = 12;
struct StateHeader
{