Merge pull request #432 from magumagu/ipchle-timing
IPC-HLE event handling improvements
This commit is contained in:
commit
a6395ae5b3
|
@ -165,7 +165,7 @@ void IPC_HLE_UpdateCallback(u64 userdata, int cyclesLate)
|
||||||
{
|
{
|
||||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
|
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
|
||||||
{
|
{
|
||||||
WII_IPC_HLE_Interface::Update();
|
WII_IPC_HLE_Interface::UpdateDevices();
|
||||||
CoreTiming::ScheduleEvent(IPC_HLE_PERIOD - cyclesLate, et_IPC_HLE);
|
CoreTiming::ScheduleEvent(IPC_HLE_PERIOD - cyclesLate, et_IPC_HLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,7 +158,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||||
MMIO::ComplexWrite<u32>([](u32, u32 val) {
|
MMIO::ComplexWrite<u32>([](u32, u32 val) {
|
||||||
ctrl.ppc(val);
|
ctrl.ppc(val);
|
||||||
if (ctrl.X1)
|
if (ctrl.X1)
|
||||||
WII_IPC_HLE_Interface::EnqRequest(ppc_msg);
|
WII_IPC_HLE_Interface::EnqueueRequest(ppc_msg);
|
||||||
WII_IPC_HLE_Interface::Update();
|
WII_IPC_HLE_Interface::Update();
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(0, updateInterrupts, 0);
|
CoreTiming::ScheduleEvent_Threadsafe(0, updateInterrupts, 0);
|
||||||
})
|
})
|
||||||
|
|
|
@ -76,19 +76,22 @@ IWII_IPC_HLE_Device* es_handles[ES_MAX_COUNT];
|
||||||
typedef std::deque<u32> ipc_msg_queue;
|
typedef std::deque<u32> ipc_msg_queue;
|
||||||
static ipc_msg_queue request_queue; // ppc -> arm
|
static ipc_msg_queue request_queue; // ppc -> arm
|
||||||
static ipc_msg_queue reply_queue; // arm -> ppc
|
static ipc_msg_queue reply_queue; // arm -> ppc
|
||||||
static std::mutex s_reply_queue;
|
|
||||||
|
|
||||||
static int enque_reply;
|
static int event_enqueue_reply;
|
||||||
|
static int event_enqueue_request;
|
||||||
|
|
||||||
static u64 last_reply_time;
|
static u64 last_reply_time;
|
||||||
|
|
||||||
// NOTE: Only call this if you have correctly handled
|
static void EnqueueReplyCallback(u64 userdata, int)
|
||||||
// CommandAddress+0 and CommandAddress+8.
|
|
||||||
// Please search for examples of this being called elsewhere.
|
|
||||||
void EnqueReplyCallback(u64 userdata, int)
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(s_reply_queue);
|
|
||||||
reply_queue.push_back((u32)userdata);
|
reply_queue.push_back((u32)userdata);
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EnqueueRequestCallback(u64 userdata, int)
|
||||||
|
{
|
||||||
|
request_queue.push_back((u32)userdata);
|
||||||
|
Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
|
@ -133,12 +136,14 @@ void Init()
|
||||||
g_DeviceMap[i] = new CWII_IPC_HLE_Device_stub(i, "/dev/usb/oh1"); i++;
|
g_DeviceMap[i] = new CWII_IPC_HLE_Device_stub(i, "/dev/usb/oh1"); i++;
|
||||||
g_DeviceMap[i] = new IWII_IPC_HLE_Device(i, "_Unimplemented_Device_"); i++;
|
g_DeviceMap[i] = new IWII_IPC_HLE_Device(i, "_Unimplemented_Device_"); i++;
|
||||||
|
|
||||||
enque_reply = CoreTiming::RegisterEvent("IPCReply", EnqueReplyCallback);
|
event_enqueue_reply = CoreTiming::RegisterEvent("IPCReply", EnqueueReplyCallback);
|
||||||
|
event_enqueue_request = CoreTiming::RegisterEvent("IPCRequest", EnqueueRequestCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset(bool _bHard)
|
void Reset(bool _bHard)
|
||||||
{
|
{
|
||||||
CoreTiming::RemoveAllEvents(enque_reply);
|
CoreTiming::RemoveAllEvents(event_enqueue_reply);
|
||||||
|
CoreTiming::RemoveAllEvents(event_enqueue_request);
|
||||||
|
|
||||||
for (IWII_IPC_HLE_Device*& dev : g_FdMap)
|
for (IWII_IPC_HLE_Device*& dev : g_FdMap)
|
||||||
{
|
{
|
||||||
|
@ -175,12 +180,8 @@ void Reset(bool _bHard)
|
||||||
g_DeviceMap.erase(g_DeviceMap.begin(), g_DeviceMap.end());
|
g_DeviceMap.erase(g_DeviceMap.begin(), g_DeviceMap.end());
|
||||||
}
|
}
|
||||||
request_queue.clear();
|
request_queue.clear();
|
||||||
|
reply_queue.clear();
|
||||||
|
|
||||||
// lock due to using reply_queue
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lk(s_reply_queue);
|
|
||||||
reply_queue.clear();
|
|
||||||
}
|
|
||||||
last_reply_time = 0;
|
last_reply_time = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,8 +265,6 @@ IWII_IPC_HLE_Device* CreateFileIO(u32 _DeviceID, const std::string& _rDeviceName
|
||||||
|
|
||||||
void DoState(PointerWrap &p)
|
void DoState(PointerWrap &p)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(s_reply_queue);
|
|
||||||
|
|
||||||
p.Do(request_queue);
|
p.Do(request_queue);
|
||||||
p.Do(reply_queue);
|
p.Do(reply_queue);
|
||||||
p.Do(last_reply_time);
|
p.Do(last_reply_time);
|
||||||
|
@ -537,6 +536,11 @@ void ExecuteCommand(u32 _Address)
|
||||||
// Ensure replies happen in order, fairly ugly
|
// Ensure replies happen in order, fairly ugly
|
||||||
// Without this, tons of games fail now that DI commands have different reply delays
|
// Without this, tons of games fail now that DI commands have different reply delays
|
||||||
int reply_delay = pDevice ? pDevice->GetCmdDelay(_Address) : 0;
|
int reply_delay = pDevice ? pDevice->GetCmdDelay(_Address) : 0;
|
||||||
|
if (!reply_delay)
|
||||||
|
{
|
||||||
|
int delay_us = 250;
|
||||||
|
reply_delay = SystemTimers::GetTicksPerSecond() / 1000000 * delay_us;
|
||||||
|
}
|
||||||
|
|
||||||
const s64 ticks_til_last_reply = last_reply_time - CoreTiming::GetTicks();
|
const s64 ticks_til_last_reply = last_reply_time - CoreTiming::GetTicks();
|
||||||
|
|
||||||
|
@ -548,23 +552,28 @@ void ExecuteCommand(u32 _Address)
|
||||||
last_reply_time = CoreTiming::GetTicks() + reply_delay;
|
last_reply_time = CoreTiming::GetTicks() + reply_delay;
|
||||||
|
|
||||||
// Generate a reply to the IPC command
|
// Generate a reply to the IPC command
|
||||||
EnqReply(_Address, reply_delay);
|
EnqueueReply(_Address, reply_delay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Happens AS SOON AS IPC gets a new pointer!
|
// Happens AS SOON AS IPC gets a new pointer!
|
||||||
void EnqRequest(u32 _Address)
|
void EnqueueRequest(u32 address)
|
||||||
{
|
{
|
||||||
request_queue.push_back(_Address);
|
CoreTiming::ScheduleEvent(1000, event_enqueue_request, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when IOS module has some reply
|
// Called when IOS module has some reply
|
||||||
// NOTE: Only call this if you have correctly handled
|
// NOTE: Only call this if you have correctly handled
|
||||||
// CommandAddress+0 and CommandAddress+8.
|
// CommandAddress+0 and CommandAddress+8.
|
||||||
// Please search for examples of this being called elsewhere.
|
// Please search for examples of this being called elsewhere.
|
||||||
void EnqReply(u32 _Address, int cycles_in_future)
|
void EnqueueReply(u32 address, int cycles_in_future)
|
||||||
{
|
{
|
||||||
CoreTiming::ScheduleEvent(cycles_in_future, enque_reply, _Address);
|
CoreTiming::ScheduleEvent(cycles_in_future, event_enqueue_reply, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnqueueReply_Threadsafe(u32 address, int cycles_in_future)
|
||||||
|
{
|
||||||
|
CoreTiming::ScheduleEvent_Threadsafe(cycles_in_future, event_enqueue_reply, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is called every IPC_HLE_PERIOD from SystemTimers.cpp
|
// This is called every IPC_HLE_PERIOD from SystemTimers.cpp
|
||||||
|
@ -574,8 +583,6 @@ void Update()
|
||||||
if (!WII_IPCInterface::IsReady())
|
if (!WII_IPCInterface::IsReady())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UpdateDevices();
|
|
||||||
|
|
||||||
if (request_queue.size())
|
if (request_queue.size())
|
||||||
{
|
{
|
||||||
WII_IPCInterface::GenerateAck(request_queue.front());
|
WII_IPCInterface::GenerateAck(request_queue.front());
|
||||||
|
@ -583,21 +590,15 @@ void Update()
|
||||||
u32 command = request_queue.front();
|
u32 command = request_queue.front();
|
||||||
request_queue.pop_front();
|
request_queue.pop_front();
|
||||||
ExecuteCommand(command);
|
ExecuteCommand(command);
|
||||||
|
return;
|
||||||
#if MAX_LOGLEVEL >= DEBUG_LEVEL
|
|
||||||
Dolphin_Debugger::PrintCallstack(LogTypes::WII_IPC_HLE, LogTypes::LDEBUG);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// lock due to using reply_queue
|
if (reply_queue.size())
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(s_reply_queue);
|
WII_IPCInterface::GenerateReply(reply_queue.front());
|
||||||
if (reply_queue.size())
|
INFO_LOG(WII_IPC_HLE, "<<-- Reply to IPC Request @ 0x%08x", reply_queue.front());
|
||||||
{
|
reply_queue.pop_front();
|
||||||
WII_IPCInterface::GenerateReply(reply_queue.front());
|
return;
|
||||||
INFO_LOG(WII_IPC_HLE, "<<-- Reply to IPC Request @ 0x%08x", reply_queue.front());
|
|
||||||
reply_queue.pop_front();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -606,9 +607,9 @@ void UpdateDevices()
|
||||||
// Check if a hardware device must be updated
|
// Check if a hardware device must be updated
|
||||||
for (const auto& entry : g_DeviceMap)
|
for (const auto& entry : g_DeviceMap)
|
||||||
{
|
{
|
||||||
if (entry.second->IsOpened() && entry.second->Update())
|
if (entry.second->IsOpened())
|
||||||
{
|
{
|
||||||
break;
|
entry.second->Update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,6 @@ namespace WII_IPC_HLE_Interface
|
||||||
#define IPC_FIRST_ID 0x00 // First IPC device ID
|
#define IPC_FIRST_ID 0x00 // First IPC device ID
|
||||||
#define IPC_MAX_FILES 0x10 // First IPC file ID
|
#define IPC_MAX_FILES 0x10 // First IPC file ID
|
||||||
|
|
||||||
void EnqueReplyCallback(u64 userdata, int =0);
|
|
||||||
|
|
||||||
// Init
|
// Init
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
|
@ -64,7 +62,8 @@ void UpdateDevices();
|
||||||
|
|
||||||
void ExecuteCommand(u32 _Address);
|
void ExecuteCommand(u32 _Address);
|
||||||
|
|
||||||
void EnqRequest(u32 _Address);
|
void EnqueueRequest(u32 address);
|
||||||
void EnqReply(u32 _Address, int cycles_in_future = 0);
|
void EnqueueReply(u32 address, int cycles_in_future = 0);
|
||||||
|
void EnqueueReply_Threadsafe(u32 address, int cycles_in_future = 0);
|
||||||
|
|
||||||
} // end of namespace WII_IPC_HLE_Interface
|
} // end of namespace WII_IPC_HLE_Interface
|
||||||
|
|
|
@ -998,7 +998,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
Memory::Write_U32(IPC_CMD_IOCTLV, _CommandAddress + 8);
|
Memory::Write_U32(IPC_CMD_IOCTLV, _CommandAddress + 8);
|
||||||
|
|
||||||
// Generate a reply to the IPC command
|
// Generate a reply to the IPC command
|
||||||
WII_IPC_HLE_Interface::EnqReply(_CommandAddress, 0);
|
WII_IPC_HLE_Interface::EnqueueReply(_CommandAddress, 0);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ void CWII_IPC_HLE_Device_hid::checkUsbUpdates(CWII_IPC_HLE_Device_hid* hid)
|
||||||
// Return value
|
// Return value
|
||||||
Memory::Write_U32(0, hid->deviceCommandAddress + 4);
|
Memory::Write_U32(0, hid->deviceCommandAddress + 4);
|
||||||
|
|
||||||
WII_IPC_HLE_Interface::EnqueReplyCallback(hid->deviceCommandAddress);
|
WII_IPC_HLE_Interface::EnqueueReply_Threadsafe(hid->deviceCommandAddress);
|
||||||
hid->deviceCommandAddress = 0;
|
hid->deviceCommandAddress = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ void CWII_IPC_HLE_Device_hid::handleUsbUpdates(struct libusb_transfer *transfer)
|
||||||
// Return value
|
// Return value
|
||||||
Memory::Write_U32(ret, replyAddress + 4);
|
Memory::Write_U32(ret, replyAddress + 4);
|
||||||
|
|
||||||
WII_IPC_HLE_Interface::EnqueReplyCallback(replyAddress);
|
WII_IPC_HLE_Interface::EnqueueReply_Threadsafe(replyAddress);
|
||||||
//DEBUG_LOG(WII_IPC_HID, "OMG OMG OMG I GOT A CALLBACK, IMMA BE FAMOUS %d %d %d", transfer->actual_length, transfer->length, transfer->status);
|
//DEBUG_LOG(WII_IPC_HID, "OMG OMG OMG I GOT A CALLBACK, IMMA BE FAMOUS %d %d %d", transfer->actual_length, transfer->length, transfer->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,13 +124,6 @@ bool CWII_IPC_HLE_Device_hid::Close(u32 _CommandAddress, bool _bForce)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 CWII_IPC_HLE_Device_hid::Update()
|
|
||||||
{
|
|
||||||
|
|
||||||
u32 work_done = 0;
|
|
||||||
return work_done;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
|
bool CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
|
||||||
{
|
{
|
||||||
u32 Parameter = Memory::Read_U32(_CommandAddress + 0xC);
|
u32 Parameter = Memory::Read_U32(_CommandAddress + 0xC);
|
||||||
|
@ -256,7 +249,7 @@ bool CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
|
||||||
|
|
||||||
// Return value
|
// Return value
|
||||||
Memory::Write_U32(-1, deviceCommandAddress + 4);
|
Memory::Write_U32(-1, deviceCommandAddress + 4);
|
||||||
WII_IPC_HLE_Interface::EnqueReplyCallback(deviceCommandAddress);
|
WII_IPC_HLE_Interface::EnqueueReply(deviceCommandAddress);
|
||||||
deviceCommandAddress = 0;
|
deviceCommandAddress = 0;
|
||||||
}
|
}
|
||||||
DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Shutdown) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
|
DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Shutdown) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
|
||||||
|
|
|
@ -27,7 +27,6 @@ public:
|
||||||
|
|
||||||
virtual bool Open(u32 _CommandAddress, u32 _Mode) override;
|
virtual bool Open(u32 _CommandAddress, u32 _Mode) override;
|
||||||
virtual bool Close(u32 _CommandAddress, bool _bForce) override;
|
virtual bool Close(u32 _CommandAddress, bool _bForce) override;
|
||||||
virtual u32 Update() override;
|
|
||||||
|
|
||||||
virtual bool IOCtlV(u32 _CommandAddress) override;
|
virtual bool IOCtlV(u32 _CommandAddress) override;
|
||||||
virtual bool IOCtl(u32 _CommandAddress) override;
|
virtual bool IOCtl(u32 _CommandAddress) override;
|
||||||
|
|
|
@ -22,7 +22,7 @@ void CWII_IPC_HLE_Device_sdio_slot0::EnqueueReply(u32 CommandAddress, u32 Return
|
||||||
|
|
||||||
Memory::Write_U32(ReturnValue, CommandAddress + 4);
|
Memory::Write_U32(ReturnValue, CommandAddress + 4);
|
||||||
|
|
||||||
WII_IPC_HLE_Interface::EnqReply(CommandAddress);
|
WII_IPC_HLE_Interface::EnqueueReply(CommandAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
CWII_IPC_HLE_Device_sdio_slot0::CWII_IPC_HLE_Device_sdio_slot0(u32 _DeviceID, const std::string& _rDeviceName)
|
CWII_IPC_HLE_Device_sdio_slot0::CWII_IPC_HLE_Device_sdio_slot0(u32 _DeviceID, const std::string& _rDeviceName)
|
||||||
|
|
|
@ -24,7 +24,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::EnqueueReply(u32 CommandAddress)
|
||||||
// The original hardware overwrites the command type with the async reply type.
|
// The original hardware overwrites the command type with the async reply type.
|
||||||
Memory::Write_U32(IPC_REP_ASYNC, CommandAddress);
|
Memory::Write_U32(IPC_REP_ASYNC, CommandAddress);
|
||||||
|
|
||||||
WII_IPC_HLE_Interface::EnqReply(CommandAddress);
|
WII_IPC_HLE_Interface::EnqueueReply(CommandAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The device class
|
// The device class
|
||||||
|
|
|
@ -632,7 +632,7 @@ void WiiSockMan::EnqueueReply(u32 CommandAddress, s32 ReturnValue, IPCCommandTyp
|
||||||
// Return value
|
// Return value
|
||||||
Memory::Write_U32(ReturnValue, CommandAddress + 4);
|
Memory::Write_U32(ReturnValue, CommandAddress + 4);
|
||||||
|
|
||||||
WII_IPC_HLE_Interface::EnqReply(CommandAddress);
|
WII_IPC_HLE_Interface::EnqueueReply(CommandAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue