Merge pull request #230 from Parlane/libogc_ios_fix

Fixes Wiimotes for libogc.
This commit is contained in:
Matthew Parlane 2014-03-30 12:07:02 +13:00
commit 2e119af086
10 changed files with 96 additions and 62 deletions

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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:

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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
{