Merge pull request #230 from Parlane/libogc_ios_fix
Fixes Wiimotes for libogc.
This commit is contained in:
commit
2e119af086
|
@ -82,6 +82,9 @@ static int enque_reply;
|
|||
|
||||
static u64 last_reply_time;
|
||||
|
||||
// NOTE: Only call this if you have correctly handled
|
||||
// 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);
|
||||
|
@ -347,7 +350,7 @@ void ExecuteCommand(u32 _Address)
|
|||
{
|
||||
bool CmdSuccess = false;
|
||||
|
||||
ECommandType Command = static_cast<ECommandType>(Memory::Read_U32(_Address));
|
||||
IPCCommandType Command = static_cast<IPCCommandType>(Memory::Read_U32(_Address));
|
||||
volatile s32 DeviceID = Memory::Read_U32(_Address + 8);
|
||||
|
||||
IWII_IPC_HLE_Device* pDevice = (DeviceID >= 0 && DeviceID < IPC_MAX_FDS) ? g_FdMap[DeviceID] : nullptr;
|
||||
|
@ -356,7 +359,7 @@ void ExecuteCommand(u32 _Address)
|
|||
|
||||
switch (Command)
|
||||
{
|
||||
case COMMAND_OPEN_DEVICE:
|
||||
case IPC_CMD_OPEN:
|
||||
{
|
||||
u32 Mode = Memory::Read_U32(_Address + 0x10);
|
||||
DeviceID = getFreeDeviceId();
|
||||
|
@ -431,7 +434,7 @@ void ExecuteCommand(u32 _Address)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case COMMAND_CLOSE_DEVICE:
|
||||
case IPC_CMD_CLOSE:
|
||||
{
|
||||
if (pDevice)
|
||||
{
|
||||
|
@ -461,7 +464,7 @@ void ExecuteCommand(u32 _Address)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case COMMAND_READ:
|
||||
case IPC_CMD_READ:
|
||||
{
|
||||
if (pDevice)
|
||||
{
|
||||
|
@ -474,7 +477,7 @@ void ExecuteCommand(u32 _Address)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case COMMAND_WRITE:
|
||||
case IPC_CMD_WRITE:
|
||||
{
|
||||
if (pDevice)
|
||||
{
|
||||
|
@ -487,7 +490,7 @@ void ExecuteCommand(u32 _Address)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case COMMAND_SEEK:
|
||||
case IPC_CMD_SEEK:
|
||||
{
|
||||
if (pDevice)
|
||||
{
|
||||
|
@ -500,7 +503,7 @@ void ExecuteCommand(u32 _Address)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case COMMAND_IOCTL:
|
||||
case IPC_CMD_IOCTL:
|
||||
{
|
||||
if (pDevice)
|
||||
{
|
||||
|
@ -508,7 +511,7 @@ void ExecuteCommand(u32 _Address)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case COMMAND_IOCTLV:
|
||||
case IPC_CMD_IOCTLV:
|
||||
{
|
||||
if (pDevice)
|
||||
{
|
||||
|
@ -526,10 +529,9 @@ void ExecuteCommand(u32 _Address)
|
|||
|
||||
if (CmdSuccess)
|
||||
{
|
||||
// It seems that the original hardware overwrites the command after it has been
|
||||
// executed. We write 8 which is not any valid command, and what IOS does
|
||||
Memory::Write_U32(8, _Address);
|
||||
// IOS seems to write back the command that was responded to
|
||||
// The original hardware overwrites the command type with the async reply type.
|
||||
Memory::Write_U32(IPC_REP_ASYNC, _Address);
|
||||
// IOS also seems to write back the command that was responded to in the FD field.
|
||||
Memory::Write_U32(Command, _Address + 8);
|
||||
|
||||
// Ensure replies happen in order, fairly ugly
|
||||
|
@ -557,6 +559,9 @@ void EnqRequest(u32 _Address)
|
|||
}
|
||||
|
||||
// Called when IOS module has some reply
|
||||
// NOTE: Only call this if you have correctly handled
|
||||
// CommandAddress+0 and CommandAddress+8.
|
||||
// Please search for examples of this being called elsewhere.
|
||||
void EnqReply(u32 _Address, int cycles_in_future)
|
||||
{
|
||||
CoreTiming::ScheduleEvent(cycles_in_future, enque_reply, _Address);
|
||||
|
|
|
@ -8,6 +8,21 @@
|
|||
|
||||
class IWII_IPC_HLE_Device;
|
||||
|
||||
enum IPCCommandType : u32
|
||||
{
|
||||
IPC_CMD_OPEN = 1,
|
||||
IPC_CMD_CLOSE = 2,
|
||||
IPC_CMD_READ = 3,
|
||||
IPC_CMD_WRITE = 4,
|
||||
IPC_CMD_SEEK = 5,
|
||||
IPC_CMD_IOCTL = 6,
|
||||
IPC_CMD_IOCTLV = 7,
|
||||
// IPC_REP_ASYNC is used for messages that are automatically
|
||||
// sent to an IOS queue when an asynchronous syscall completes.
|
||||
// Reference: http://wiibrew.org/wiki/IOS
|
||||
IPC_REP_ASYNC = 8
|
||||
};
|
||||
|
||||
namespace WII_IPC_HLE_Interface
|
||||
{
|
||||
|
||||
|
@ -52,15 +67,4 @@ void ExecuteCommand(u32 _Address);
|
|||
void EnqRequest(u32 _Address);
|
||||
void EnqReply(u32 _Address, int cycles_in_future = 0);
|
||||
|
||||
enum ECommandType
|
||||
{
|
||||
COMMAND_OPEN_DEVICE = 1,
|
||||
COMMAND_CLOSE_DEVICE = 2,
|
||||
COMMAND_READ = 3,
|
||||
COMMAND_WRITE = 4,
|
||||
COMMAND_SEEK = 5,
|
||||
COMMAND_IOCTL = 6,
|
||||
COMMAND_IOCTLV = 7,
|
||||
};
|
||||
|
||||
} // end of namespace WII_IPC_HLE_Interface
|
||||
|
|
|
@ -991,11 +991,10 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
|||
|
||||
// This is necessary because Reset(true) above deleted this object. Ew.
|
||||
|
||||
// It seems that the original hardware overwrites the command after it has been
|
||||
// executed. We write 8 which is not any valid command, and what IOS does
|
||||
Memory::Write_U32(8, _CommandAddress);
|
||||
// IOS seems to write back the command that was responded to
|
||||
Memory::Write_U32(7, _CommandAddress + 8);
|
||||
// The original hardware overwrites the command type with the async reply type.
|
||||
Memory::Write_U32(IPC_REP_ASYNC, _CommandAddress);
|
||||
// IOS also seems to write back the command that was responded to in the FD field.
|
||||
Memory::Write_U32(IPC_CMD_IOCTLV, _CommandAddress + 8);
|
||||
|
||||
// Generate a reply to the IPC command
|
||||
WII_IPC_HLE_Interface::EnqReply(_CommandAddress, 0);
|
||||
|
|
|
@ -29,9 +29,10 @@ void CWII_IPC_HLE_Device_hid::checkUsbUpdates(CWII_IPC_HLE_Device_hid* hid)
|
|||
if (hid->deviceCommandAddress != 0){
|
||||
hid->FillOutDevices(Memory::Read_U32(hid->deviceCommandAddress + 0x18), Memory::Read_U32(hid->deviceCommandAddress + 0x1C));
|
||||
|
||||
Memory::Write_U32(8, hid->deviceCommandAddress);
|
||||
// IOS seems to write back the command that was responded to
|
||||
Memory::Write_U32(/*COMMAND_IOCTL*/ 6, hid->deviceCommandAddress + 8);
|
||||
// The original hardware overwrites the command type with the async reply type.
|
||||
Memory::Write_U32(IPC_REP_ASYNC, hid->deviceCommandAddress);
|
||||
// IOS also seems to write back the command that was responded to in the FD field.
|
||||
Memory::Write_U32(IPC_CMD_IOCTL, hid->deviceCommandAddress + 8);
|
||||
|
||||
// Return value
|
||||
Memory::Write_U32(0, hid->deviceCommandAddress + 4);
|
||||
|
@ -56,9 +57,10 @@ void CWII_IPC_HLE_Device_hid::handleUsbUpdates(struct libusb_transfer *transfer)
|
|||
ret = transfer->length;
|
||||
}
|
||||
|
||||
Memory::Write_U32(8, replyAddress);
|
||||
// IOS seems to write back the command that was responded to
|
||||
Memory::Write_U32(/*COMMAND_IOCTL*/ 6, replyAddress + 8);
|
||||
// The original hardware overwrites the command type with the async reply type.
|
||||
Memory::Write_U32(IPC_REP_ASYNC, replyAddress);
|
||||
// IOS also seems to write back the command that was responded to in the FD field.
|
||||
Memory::Write_U32(IPC_CMD_IOCTL, replyAddress + 8);
|
||||
|
||||
// Return value
|
||||
Memory::Write_U32(ret, replyAddress + 4);
|
||||
|
@ -247,9 +249,10 @@ bool CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
|
|||
if (deviceCommandAddress != 0){
|
||||
Memory::Write_U32(0xFFFFFFFF, Memory::Read_U32(deviceCommandAddress + 0x18));
|
||||
|
||||
Memory::Write_U32(8, deviceCommandAddress);
|
||||
// IOS seems to write back the command that was responded to
|
||||
Memory::Write_U32(/*COMMAND_IOCTL*/ 6, deviceCommandAddress + 8);
|
||||
// The original hardware overwrites the command type with the async reply type.
|
||||
Memory::Write_U32(IPC_REP_ASYNC, deviceCommandAddress);
|
||||
// IOS also seems to write back the command that was responded to in the FD field.
|
||||
Memory::Write_U32(IPC_CMD_IOCTL, deviceCommandAddress + 8);
|
||||
|
||||
// Return value
|
||||
Memory::Write_U32(-1, deviceCommandAddress + 4);
|
||||
|
|
|
@ -12,6 +12,18 @@
|
|||
#include "Core/IPC_HLE/WII_IPC_HLE.h"
|
||||
#include "Core/IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.h"
|
||||
|
||||
void CWII_IPC_HLE_Device_sdio_slot0::EnqueueReply(u32 CommandAddress, u32 ReturnValue)
|
||||
{
|
||||
// IOS seems to write back the command that was responded to, this class does not
|
||||
// overwrite the command so it is safe to read.
|
||||
Memory::Write_U32(Memory::Read_U32(CommandAddress), CommandAddress + 8);
|
||||
// The original hardware overwrites the command type with the async reply type.
|
||||
Memory::Write_U32(IPC_REP_ASYNC, CommandAddress);
|
||||
|
||||
Memory::Write_U32(ReturnValue, CommandAddress + 4);
|
||||
|
||||
WII_IPC_HLE_Interface::EnqReply(CommandAddress);
|
||||
}
|
||||
|
||||
CWII_IPC_HLE_Device_sdio_slot0::CWII_IPC_HLE_Device_sdio_slot0(u32 _DeviceID, const std::string& _rDeviceName)
|
||||
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
|
||||
|
@ -39,8 +51,7 @@ void CWII_IPC_HLE_Device_sdio_slot0::EventNotify()
|
|||
if ((SConfig::GetInstance().m_WiiSDCard && m_event.type == EVENT_INSERT) ||
|
||||
(!SConfig::GetInstance().m_WiiSDCard && m_event.type == EVENT_REMOVE))
|
||||
{
|
||||
Memory::Write_U32(m_event.type, m_event.addr + 4);
|
||||
WII_IPC_HLE_Interface::EnqReply(m_event.addr);
|
||||
EnqueueReply(m_event.addr, m_event.type);
|
||||
m_event.addr = 0;
|
||||
m_event.type = EVENT_NONE;
|
||||
}
|
||||
|
@ -222,8 +233,7 @@ bool CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
|
|||
// release returns 0
|
||||
// unknown sd int
|
||||
// technically we do it out of order, oh well
|
||||
Memory::Write_U32(EVENT_INVALID, m_event.addr + 4);
|
||||
WII_IPC_HLE_Interface::EnqReply(m_event.addr);
|
||||
EnqueueReply(m_event.addr, EVENT_INVALID);
|
||||
m_event.addr = 0;
|
||||
m_event.type = EVENT_NONE;
|
||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
||||
|
|
|
@ -21,6 +21,7 @@ public:
|
|||
bool IOCtl(u32 _CommandAddress) override;
|
||||
bool IOCtlV(u32 _CommandAddress) override;
|
||||
|
||||
static void EnqueueReply(u32 CommandAddress, u32 ReturnValue);
|
||||
void EventNotify();
|
||||
|
||||
private:
|
||||
|
|
|
@ -14,6 +14,19 @@
|
|||
#include "Core/IPC_HLE/WII_IPC_HLE.h"
|
||||
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h"
|
||||
|
||||
|
||||
|
||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::EnqueueReply(u32 CommandAddress)
|
||||
{
|
||||
// IOS seems to write back the command that was responded to in the FD field, this
|
||||
// class does not overwrite the command so it is safe to read back.
|
||||
Memory::Write_U32(Memory::Read_U32(CommandAddress), CommandAddress + 8);
|
||||
// The original hardware overwrites the command type with the async reply type.
|
||||
Memory::Write_U32(IPC_REP_ASYNC, CommandAddress);
|
||||
|
||||
WII_IPC_HLE_Interface::EnqReply(CommandAddress);
|
||||
}
|
||||
|
||||
// The device class
|
||||
CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(u32 _DeviceID, const std::string& _rDeviceName)
|
||||
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
|
||||
|
@ -340,7 +353,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 _ConnectionHandle, u
|
|||
memcpy((u8*)pHeader + sizeof(hci_acldata_hdr_t), _pData, pHeader->length);
|
||||
|
||||
m_ACLEndpoint.SetRetVal(sizeof(hci_acldata_hdr_t) + _Size);
|
||||
WII_IPC_HLE_Interface::EnqReply(m_ACLEndpoint.m_address);
|
||||
EnqueueReply(m_ACLEndpoint.m_address);
|
||||
m_ACLEndpoint.Invalidate();
|
||||
}
|
||||
else
|
||||
|
@ -367,7 +380,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::AddEventToQueue(const SQueuedEvent& _e
|
|||
m_HCIEndpoint.FillBuffer(_event.m_buffer, _event.m_size);
|
||||
m_HCIEndpoint.SetRetVal(_event.m_size);
|
||||
// Send a reply to indicate HCI buffer is filled
|
||||
WII_IPC_HLE_Interface::EnqReply(m_HCIEndpoint.m_address);
|
||||
EnqueueReply(m_HCIEndpoint.m_address);
|
||||
m_HCIEndpoint.Invalidate();
|
||||
}
|
||||
else // push new one, pop oldest
|
||||
|
@ -385,7 +398,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::AddEventToQueue(const SQueuedEvent& _e
|
|||
m_HCIEndpoint.FillBuffer(event.m_buffer, event.m_size);
|
||||
m_HCIEndpoint.SetRetVal(event.m_size);
|
||||
// Send a reply to indicate HCI buffer is filled
|
||||
WII_IPC_HLE_Interface::EnqReply(m_HCIEndpoint.m_address);
|
||||
EnqueueReply(m_HCIEndpoint.m_address);
|
||||
m_HCIEndpoint.Invalidate();
|
||||
m_EventQueue.pop_front();
|
||||
}
|
||||
|
@ -415,7 +428,7 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
|||
m_HCIEndpoint.FillBuffer(event.m_buffer, event.m_size);
|
||||
m_HCIEndpoint.SetRetVal(event.m_size);
|
||||
// Send a reply to indicate HCI buffer is filled
|
||||
WII_IPC_HLE_Interface::EnqReply(m_HCIEndpoint.m_address);
|
||||
EnqueueReply(m_HCIEndpoint.m_address);
|
||||
m_HCIEndpoint.Invalidate();
|
||||
m_EventQueue.pop_front();
|
||||
packet_transferred = true;
|
||||
|
@ -517,7 +530,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::ACLPool::WriteToEndpoint(CtrlBuffer& e
|
|||
|
||||
m_queue.pop_front();
|
||||
|
||||
WII_IPC_HLE_Interface::EnqReply(endpoint.m_address);
|
||||
EnqueueReply(endpoint.m_address);
|
||||
endpoint.Invalidate();
|
||||
}
|
||||
|
||||
|
@ -1214,7 +1227,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::ExecuteHCICommandMessage(const SHCICom
|
|||
}
|
||||
|
||||
// HCI command is finished, send a reply to command
|
||||
WII_IPC_HLE_Interface::EnqReply(_rHCICommandMessage.m_Address);
|
||||
EnqueueReply(_rHCICommandMessage.m_Address);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -58,6 +58,8 @@ public:
|
|||
|
||||
virtual u32 Update() override;
|
||||
|
||||
static void EnqueueReply(u32 CommandAddress);
|
||||
|
||||
// Send ACL data back to bt stack
|
||||
void SendACLPacket(u16 _ConnectionHandle, u8* _pData, u32 _Size);
|
||||
|
||||
|
|
|
@ -8,11 +8,6 @@
|
|||
#include "Core/IPC_HLE/WII_IPC_HLE_Device.h"
|
||||
#include "Core/IPC_HLE/WII_Socket.h" // No Wii socket support while using NetPlay or TAS
|
||||
|
||||
|
||||
using WII_IPC_HLE_Interface::ECommandType;
|
||||
using WII_IPC_HLE_Interface::COMMAND_IOCTL;
|
||||
using WII_IPC_HLE_Interface::COMMAND_IOCTLV;
|
||||
|
||||
#ifdef _WIN32
|
||||
#define ERRORCODE(name) WSA ## name
|
||||
#define EITHER(win32, posix) win32
|
||||
|
@ -180,8 +175,8 @@ void WiiSocket::Update(bool read, bool write, bool except)
|
|||
{
|
||||
s32 ReturnValue = 0;
|
||||
bool forceNonBlock = false;
|
||||
ECommandType ct = static_cast<ECommandType>(Memory::Read_U32(it->_CommandAddress));
|
||||
if (!it->is_ssl && ct == COMMAND_IOCTL)
|
||||
IPCCommandType ct = static_cast<IPCCommandType>(Memory::Read_U32(it->_CommandAddress));
|
||||
if (!it->is_ssl && ct == IPC_CMD_IOCTL)
|
||||
{
|
||||
u32 BufferIn = Memory::Read_U32(it->_CommandAddress + 0x10);
|
||||
u32 BufferInSize = Memory::Read_U32(it->_CommandAddress + 0x14);
|
||||
|
@ -267,7 +262,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (ct == COMMAND_IOCTLV)
|
||||
else if (ct == IPC_CMD_IOCTLV)
|
||||
{
|
||||
SIOCtlVBuffer CommandBuffer(it->_CommandAddress);
|
||||
u32 BufferIn = 0, BufferIn2 = 0;
|
||||
|
@ -523,7 +518,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
|
|||
DEBUG_LOG(WII_IPC_NET,
|
||||
"IOCTL(V) Sock: %08x ioctl/v: %d returned: %d nonBlock: %d forceNonBlock: %d",
|
||||
fd, it->is_ssl ? (int) it->ssl_type : (int) it->net_type, ReturnValue, nonBlock, forceNonBlock);
|
||||
WiiSockMan::EnqueueReply(it->_CommandAddress, ReturnValue);
|
||||
WiiSockMan::EnqueueReply(it->_CommandAddress, ReturnValue, ct);
|
||||
it = pending_sockops.erase(it);
|
||||
}
|
||||
else
|
||||
|
@ -625,11 +620,12 @@ void WiiSockMan::Update()
|
|||
}
|
||||
}
|
||||
|
||||
void WiiSockMan::EnqueueReply(u32 CommandAddress, s32 ReturnValue)
|
||||
void WiiSockMan::EnqueueReply(u32 CommandAddress, s32 ReturnValue, IPCCommandType CommandType)
|
||||
{
|
||||
Memory::Write_U32(8, CommandAddress);
|
||||
// IOS seems to write back the command that was responded to
|
||||
Memory::Write_U32(Memory::Read_U32(CommandAddress), CommandAddress + 8);
|
||||
// The original hardware overwrites the command type with the async reply type.
|
||||
Memory::Write_U32(IPC_REP_ASYNC, CommandAddress);
|
||||
// IOS also seems to write back the command that was responded to in the FD field.
|
||||
Memory::Write_U32(CommandType, CommandAddress + 8);
|
||||
|
||||
// Return value
|
||||
Memory::Write_U32(ReturnValue, CommandAddress + 4);
|
||||
|
|
|
@ -204,7 +204,7 @@ public:
|
|||
return instance; // Instantiated on first use.
|
||||
}
|
||||
void Update();
|
||||
static void EnqueueReply(u32 CommandAddress, s32 ReturnValue);
|
||||
static void EnqueueReply(u32 CommandAddress, s32 ReturnValue, IPCCommandType CommandType);
|
||||
static void Convert(WiiSockAddrIn const & from, sockaddr_in& to);
|
||||
static void Convert(sockaddr_in const & from, WiiSockAddrIn& to, s32 addrlen=-1);
|
||||
// NON-BLOCKING FUNCTIONS
|
||||
|
@ -224,10 +224,11 @@ public:
|
|||
{
|
||||
if (WiiSockets.find(sock) == WiiSockets.end())
|
||||
{
|
||||
IPCCommandType ct = static_cast<IPCCommandType>(Memory::Read_U32(CommandAddress));
|
||||
ERROR_LOG(WII_IPC_NET,
|
||||
"DoSock: Error, fd not found (%08x, %08X, %08X)",
|
||||
sock, CommandAddress, type);
|
||||
EnqueueReply(CommandAddress, -SO_EBADF);
|
||||
EnqueueReply(CommandAddress, -SO_EBADF, ct);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue