mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-09-21 11:51:48 +02:00
make WII_IPC_HLEInterface manage the IPC message queue instead of the "lle" portion.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5224 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
cf7101ef08
commit
f6db5b7d8d
7 changed files with 165 additions and 281 deletions
|
@ -16,6 +16,8 @@
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <queue>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "ChunkFile.h"
|
#include "ChunkFile.h"
|
||||||
|
@ -91,23 +93,16 @@ struct CtrlRegister
|
||||||
};
|
};
|
||||||
|
|
||||||
// STATE_TO_SAVE
|
// STATE_TO_SAVE
|
||||||
u32 ppc_msg;
|
static u32 ppc_msg;
|
||||||
u32 arm_msg;
|
static u32 arm_msg;
|
||||||
CtrlRegister ctrl;
|
static CtrlRegister ctrl;
|
||||||
|
|
||||||
u32 ppc_irq_flags;
|
static u32 ppc_irq_flags;
|
||||||
u32 ppc_irq_masks;
|
static u32 ppc_irq_masks;
|
||||||
u32 arm_irq_flags;
|
static u32 arm_irq_flags;
|
||||||
u32 arm_irq_masks;
|
static u32 arm_irq_masks;
|
||||||
|
|
||||||
u32 sensorbar_power; // do we need to care about this?
|
static u32 sensorbar_power; // do we need to care about this?
|
||||||
|
|
||||||
// not actual registers:
|
|
||||||
bool cmd_active;
|
|
||||||
u32 g_ReplyHead;
|
|
||||||
u32 g_ReplyTail;
|
|
||||||
u32 g_ReplyNum;
|
|
||||||
u32 g_ReplyFifo[REPLY_FIFO_DEPTH];
|
|
||||||
|
|
||||||
void DoState(PointerWrap &p)
|
void DoState(PointerWrap &p)
|
||||||
{
|
{
|
||||||
|
@ -119,17 +114,10 @@ void DoState(PointerWrap &p)
|
||||||
p.Do(arm_irq_flags);
|
p.Do(arm_irq_flags);
|
||||||
p.Do(arm_irq_masks);
|
p.Do(arm_irq_masks);
|
||||||
p.Do(sensorbar_power);
|
p.Do(sensorbar_power);
|
||||||
p.Do(cmd_active);
|
|
||||||
p.Do(g_ReplyHead);
|
|
||||||
p.Do(g_ReplyTail);
|
|
||||||
p.Do(g_ReplyNum);
|
|
||||||
p.DoArray(g_ReplyFifo, REPLY_FIFO_DEPTH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
cmd_active = false;
|
|
||||||
ctrl = CtrlRegister();
|
ctrl = CtrlRegister();
|
||||||
ppc_msg =
|
ppc_msg =
|
||||||
arm_msg =
|
arm_msg =
|
||||||
|
@ -139,12 +127,7 @@ void Init()
|
||||||
arm_irq_flags =
|
arm_irq_flags =
|
||||||
arm_irq_masks =
|
arm_irq_masks =
|
||||||
|
|
||||||
sensorbar_power =
|
sensorbar_power = 0;
|
||||||
|
|
||||||
g_ReplyHead =
|
|
||||||
g_ReplyTail =
|
|
||||||
g_ReplyNum = 0;
|
|
||||||
memset(g_ReplyFifo, 0, REPLY_FIFO_DEPTH);
|
|
||||||
|
|
||||||
ppc_irq_masks |= INT_CAUSE_IPC_BROADWAY;
|
ppc_irq_masks |= INT_CAUSE_IPC_BROADWAY;
|
||||||
}
|
}
|
||||||
|
@ -166,7 +149,7 @@ void Read32(u32& _rReturnValue, const u32 _Address)
|
||||||
{
|
{
|
||||||
case IPC_PPCCTRL:
|
case IPC_PPCCTRL:
|
||||||
_rReturnValue = ctrl.ppc();
|
_rReturnValue = ctrl.ppc();
|
||||||
INFO_LOG(WII_IPC, "r32 IPC_PPCCTRL %03x [R:%i A:%i E:%i]",
|
DEBUG_LOG(WII_IPC, "r32 IPC_PPCCTRL %03x [R:%i A:%i E:%i]",
|
||||||
ctrl.ppc(), ctrl.Y1, ctrl.Y2, ctrl.X1);
|
ctrl.ppc(), ctrl.Y1, ctrl.Y2, ctrl.X1);
|
||||||
|
|
||||||
// if ((REASON_REG & 0x14) == 0x14) CALL IPCReplayHandler
|
// if ((REASON_REG & 0x14) == 0x14) CALL IPCReplayHandler
|
||||||
|
@ -175,7 +158,7 @@ void Read32(u32& _rReturnValue, const u32 _Address)
|
||||||
|
|
||||||
case IPC_ARMMSG: // looks a little bit like a callback function
|
case IPC_ARMMSG: // looks a little bit like a callback function
|
||||||
_rReturnValue = arm_msg;
|
_rReturnValue = arm_msg;
|
||||||
INFO_LOG(WII_IPC, "r32 IPC_ARMMSG %08x ", _rReturnValue);
|
DEBUG_LOG(WII_IPC, "r32 IPC_ARMMSG %08x ", _rReturnValue);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GPIOB_OUT:
|
case GPIOB_OUT:
|
||||||
|
@ -195,24 +178,28 @@ void Write32(const u32 _Value, const u32 _Address)
|
||||||
case IPC_PPCMSG: // __ios_Ipc2 ... a value from __responses is loaded
|
case IPC_PPCMSG: // __ios_Ipc2 ... a value from __responses is loaded
|
||||||
{
|
{
|
||||||
ppc_msg = _Value;
|
ppc_msg = _Value;
|
||||||
INFO_LOG(WII_IPC, "IPC_PPCMSG = %08x", ppc_msg);
|
DEBUG_LOG(WII_IPC, "IPC_PPCMSG = %08x", ppc_msg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IPC_PPCCTRL:
|
case IPC_PPCCTRL:
|
||||||
{
|
{
|
||||||
ctrl.ppc(_Value);
|
ctrl.ppc(_Value);
|
||||||
INFO_LOG(WII_IPC, "w32 %08x IPC_PPCCTRL = %03x [R:%i A:%i E:%i]",
|
DEBUG_LOG(WII_IPC, "w32 %08x IPC_PPCCTRL = %03x [R:%i A:%i E:%i]",
|
||||||
_Value, ctrl.ppc(), ctrl.Y1, ctrl.Y2, ctrl.X1);
|
_Value, ctrl.ppc(), ctrl.Y1, ctrl.Y2, ctrl.X1);
|
||||||
if (ctrl.X1) // seems like we should just be able to use X1 directly, but it doesn't work...why?!
|
if (ctrl.X1)
|
||||||
cmd_active = true;
|
{
|
||||||
|
INFO_LOG(WII_IPC, "new pointer available: %08x", ppc_msg);
|
||||||
|
// Let the HLE handle the request on it's own time
|
||||||
|
WII_IPC_HLE_Interface::EnqRequest(ppc_msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PPC_IRQFLAG: // ACR REGISTER IT IS CALLED IN DEBUG
|
case PPC_IRQFLAG: // ACR REGISTER IT IS CALLED IN DEBUG
|
||||||
{
|
{
|
||||||
ppc_irq_flags &= ~_Value;
|
ppc_irq_flags &= ~_Value;
|
||||||
INFO_LOG(WII_IPC, "w32 PPC_IRQFLAG %08x (%08x)", _Value, ppc_irq_flags);
|
DEBUG_LOG(WII_IPC, "w32 PPC_IRQFLAG %08x (%08x)", _Value, ppc_irq_flags);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -221,7 +208,7 @@ void Write32(const u32 _Value, const u32 _Address)
|
||||||
ppc_irq_masks = _Value;
|
ppc_irq_masks = _Value;
|
||||||
if (ppc_irq_masks & INT_CAUSE_IPC_BROADWAY) // wtf?
|
if (ppc_irq_masks & INT_CAUSE_IPC_BROADWAY) // wtf?
|
||||||
Reset();
|
Reset();
|
||||||
INFO_LOG(WII_IPC, "w32 PPC_IRQMASK %08x", ppc_irq_masks);
|
DEBUG_LOG(WII_IPC, "w32 PPC_IRQMASK %08x", ppc_irq_masks);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -253,21 +240,12 @@ void UpdateInterrupts()
|
||||||
ProcessorInterface::SetInterrupt(ProcessorInterface::INT_CAUSE_WII_IPC, !!(ppc_irq_flags & ppc_irq_masks));
|
ProcessorInterface::SetInterrupt(ProcessorInterface::INT_CAUSE_WII_IPC, !!(ppc_irq_flags & ppc_irq_masks));
|
||||||
}
|
}
|
||||||
|
|
||||||
// The rest is for IOS HLE
|
void GenerateAck(u32 _Address)
|
||||||
bool IsReady()
|
|
||||||
{
|
{
|
||||||
return ((ctrl.Y1 == 0) && (ctrl.Y2 == 0) && ((ppc_irq_flags & INT_CAUSE_IPC_BROADWAY) == 0));
|
arm_msg = _Address; // dunno if it's really set here, but HLE needs to stay in context
|
||||||
}
|
|
||||||
|
|
||||||
u32 GetAddress()
|
|
||||||
{
|
|
||||||
return (cmd_active ? ppc_msg : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GenerateAck()
|
|
||||||
{
|
|
||||||
cmd_active = false;
|
|
||||||
ctrl.Y2 = 1;
|
ctrl.Y2 = 1;
|
||||||
|
INFO_LOG(WII_IPC, "GenerateAck: %08x | %08x [R:%i A:%i E:%i]",
|
||||||
|
ppc_msg,_Address, ctrl.Y1, ctrl.Y2, ctrl.X1);
|
||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,40 +253,14 @@ void GenerateReply(u32 _Address)
|
||||||
{
|
{
|
||||||
arm_msg = _Address;
|
arm_msg = _Address;
|
||||||
ctrl.Y1 = 1;
|
ctrl.Y1 = 1;
|
||||||
|
INFO_LOG(WII_IPC, "GenerateReply: %08x | %08x [R:%i A:%i E:%i]",
|
||||||
|
ppc_msg,_Address, ctrl.Y1, ctrl.Y2, ctrl.X1);
|
||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnqReply(u32 _Address)
|
bool IsReady()
|
||||||
{
|
{
|
||||||
if (g_ReplyNum < REPLY_FIFO_DEPTH)
|
return ((ctrl.Y1 == 0) && (ctrl.Y2 == 0) && ((ppc_irq_flags & INT_CAUSE_IPC_BROADWAY) == 0));
|
||||||
{
|
|
||||||
g_ReplyFifo[g_ReplyTail++] = _Address;
|
|
||||||
g_ReplyTail &= REPLY_FIFO_MASK;
|
|
||||||
g_ReplyNum++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ERROR_LOG(WII_IPC, "Reply FIFO is full, something must be wrong!");
|
|
||||||
PanicAlert("WII_IPC: Reply FIFO is full, something must be wrong!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 DeqReply()
|
|
||||||
{
|
|
||||||
u32 _Address;
|
|
||||||
|
|
||||||
if (g_ReplyNum)
|
|
||||||
{
|
|
||||||
_Address = g_ReplyFifo[g_ReplyHead++];
|
|
||||||
g_ReplyHead &= REPLY_FIFO_MASK;
|
|
||||||
g_ReplyNum--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_Address = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _Address;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,9 +44,6 @@ enum StarletInterruptCause
|
||||||
INT_CAUSE_IPC_STARLET = 0x80000000
|
INT_CAUSE_IPC_STARLET = 0x80000000
|
||||||
};
|
};
|
||||||
|
|
||||||
#define REPLY_FIFO_DEPTH (unsigned)8
|
|
||||||
#define REPLY_FIFO_MASK (REPLY_FIFO_DEPTH - 1)
|
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void Reset();
|
void Reset();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
@ -55,14 +52,10 @@ void DoState(PointerWrap &p);
|
||||||
void Read32(u32& _rReturnValue, const u32 _Address);
|
void Read32(u32& _rReturnValue, const u32 _Address);
|
||||||
void Write32(const u32 _Value, const u32 _Address);
|
void Write32(const u32 _Value, const u32 _Address);
|
||||||
|
|
||||||
u32 GetAddress();
|
|
||||||
void GenerateAck();
|
|
||||||
void GenerateReply(u32 _Address);
|
|
||||||
void InsertReply(u32 _Address);
|
|
||||||
void EnqReply(u32 _Address);
|
|
||||||
u32 DeqReply();
|
|
||||||
|
|
||||||
void UpdateInterrupts();
|
void UpdateInterrupts();
|
||||||
|
void GenerateAck(u32 _Address);
|
||||||
|
void GenerateReply(u32 _Address);
|
||||||
|
|
||||||
bool IsReady();
|
bool IsReady();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,18 +15,14 @@
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
/*
|
||||||
|
This is the main Wii IPC file that handles all incoming IPC calls and directs them
|
||||||
|
to the right function.
|
||||||
|
|
||||||
|
IPC basics (IOS' usage):
|
||||||
|
|
||||||
// =======================================================
|
Return values for file handles: All IPC calls will generate a return value to 0x04,
|
||||||
// File description
|
in case of success they are
|
||||||
// -------------
|
|
||||||
/* This is the main Wii IPC file that handles all incoming IPC calls and directs them
|
|
||||||
to the right function.
|
|
||||||
|
|
||||||
IPC basics:
|
|
||||||
|
|
||||||
Return values for file handles: All IPC calls will generate a return value to 0x04,
|
|
||||||
in case of success they are
|
|
||||||
Open: DeviceID
|
Open: DeviceID
|
||||||
Close: 0
|
Close: 0
|
||||||
Read: Bytes read
|
Read: Bytes read
|
||||||
|
@ -34,11 +30,8 @@
|
||||||
Seek: Seek position
|
Seek: Seek position
|
||||||
Ioctl: 0 (in addition to that there may be messages to the out buffers)
|
Ioctl: 0 (in addition to that there may be messages to the out buffers)
|
||||||
Ioctlv: 0 (in addition to that there may be messages to the out buffers)
|
Ioctlv: 0 (in addition to that there may be messages to the out buffers)
|
||||||
They will also generate a true or false return for UpdateInterrupts() in WII_IPC.cpp. */
|
They will also generate a true or false return for UpdateInterrupts() in WII_IPC.cpp.
|
||||||
// =============
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -78,6 +71,10 @@ typedef std::map<u32, std::string> TFileNameMap;
|
||||||
TFileNameMap g_FileNameMap;
|
TFileNameMap g_FileNameMap;
|
||||||
u32 g_LastDeviceID;
|
u32 g_LastDeviceID;
|
||||||
|
|
||||||
|
typedef std::queue<u32> ipc_msg_queue;
|
||||||
|
static ipc_msg_queue request_queue; // ppc -> arm
|
||||||
|
static ipc_msg_queue reply_queue; // arm -> ppc
|
||||||
|
|
||||||
// General IPC functions
|
// General IPC functions
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
|
@ -125,6 +122,9 @@ void Reset(bool _bHard)
|
||||||
g_DeviceMap.erase(itr, g_DeviceMap.end());
|
g_DeviceMap.erase(itr, g_DeviceMap.end());
|
||||||
g_FileNameMap.clear();
|
g_FileNameMap.clear();
|
||||||
|
|
||||||
|
request_queue = std::queue<u32>();
|
||||||
|
reply_queue = std::queue<u32>();
|
||||||
|
|
||||||
g_LastDeviceID = IPC_FIRST_FILEIO_ID;
|
g_LastDeviceID = IPC_FIRST_FILEIO_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +133,6 @@ void Shutdown()
|
||||||
Reset(true);
|
Reset(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set default content file
|
|
||||||
void SetDefaultContentFile(const std::string& _rFilename)
|
void SetDefaultContentFile(const std::string& _rFilename)
|
||||||
{
|
{
|
||||||
CWII_IPC_HLE_Device_es* pDevice = (CWII_IPC_HLE_Device_es*)AccessDeviceByID(GetDeviceIDByName(std::string("/dev/es")));
|
CWII_IPC_HLE_Device_es* pDevice = (CWII_IPC_HLE_Device_es*)AccessDeviceByID(GetDeviceIDByName(std::string("/dev/es")));
|
||||||
|
@ -172,7 +171,7 @@ void DeleteDeviceByID(u32 ID)
|
||||||
g_FileNameMap.erase(ID);
|
g_FileNameMap.erase(ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is called from COMMAND_OPEN_DEVICE. Here we either create a new file handle
|
// This is called from ExecuteCommand() COMMAND_OPEN_DEVICE
|
||||||
IWII_IPC_HLE_Device* CreateFileIO(u32 _DeviceID, const std::string& _rDeviceName)
|
IWII_IPC_HLE_Device* CreateFileIO(u32 _DeviceID, const std::string& _rDeviceName)
|
||||||
{
|
{
|
||||||
// scan device name and create the right one
|
// scan device name and create the right one
|
||||||
|
@ -184,7 +183,7 @@ IWII_IPC_HLE_Device* CreateFileIO(u32 _DeviceID, const std::string& _rDeviceName
|
||||||
return pDevice;
|
return pDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let the game read the setting.txt file
|
// Try to make sure the game is always reading the setting.txt file we provide
|
||||||
void CopySettingsFile(std::string& DeviceName)
|
void CopySettingsFile(std::string& DeviceName)
|
||||||
{
|
{
|
||||||
std::string Source = File::GetSysDirectory() + WII_SYS_DIR + DIR_SEP;
|
std::string Source = File::GetSysDirectory() + WII_SYS_DIR + DIR_SEP;
|
||||||
|
@ -197,7 +196,8 @@ void CopySettingsFile(std::string& DeviceName)
|
||||||
|
|
||||||
// Check if the target dir exists, otherwise create it
|
// Check if the target dir exists, otherwise create it
|
||||||
std::string TargetDir = Target.substr(0, Target.find_last_of(DIR_SEP));
|
std::string TargetDir = Target.substr(0, Target.find_last_of(DIR_SEP));
|
||||||
if(!File::IsDirectory(TargetDir.c_str())) File::CreateFullPath(Target.c_str());
|
if (!File::IsDirectory(TargetDir.c_str()))
|
||||||
|
File::CreateFullPath(Target.c_str());
|
||||||
|
|
||||||
if (File::Copy(Source.c_str(), Target.c_str()))
|
if (File::Copy(Source.c_str(), Target.c_str()))
|
||||||
{
|
{
|
||||||
|
@ -256,14 +256,6 @@ void DoState(PointerWrap &p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===================================================
|
|
||||||
/* This generates an acknowledgment to IPC calls. This function is called from
|
|
||||||
IPC_CONTROL_REGISTER requests in WII_IPC.cpp. The acknowledgment _Address will
|
|
||||||
start with 0x033e...., it will be for the _CommandAddress 0x133e...., from
|
|
||||||
debugging I also noticed that the Ioctl arguments are stored temporarily in
|
|
||||||
0x933e.... with the same .... as in the _CommandAddress. */
|
|
||||||
// ----------------
|
|
||||||
|
|
||||||
void ExecuteCommand(u32 _Address)
|
void ExecuteCommand(u32 _Address)
|
||||||
{
|
{
|
||||||
bool CmdSuccess = false;
|
bool CmdSuccess = false;
|
||||||
|
@ -284,7 +276,8 @@ void ExecuteCommand(u32 _Address)
|
||||||
Memory::GetString(DeviceName, Memory::Read_U32(_Address + 0xC));
|
Memory::GetString(DeviceName, Memory::Read_U32(_Address + 0xC));
|
||||||
|
|
||||||
// The game may try to read setting.txt here, in that case copy it so it can read it
|
// The game may try to read setting.txt here, in that case copy it so it can read it
|
||||||
if(DeviceName.find("setting.txt") != std::string::npos) CopySettingsFile(DeviceName);
|
if (DeviceName.find("setting.txt") != std::string::npos)
|
||||||
|
CopySettingsFile(DeviceName);
|
||||||
|
|
||||||
u32 Mode = Memory::Read_U32(_Address + 0x10);
|
u32 Mode = Memory::Read_U32(_Address + 0x10);
|
||||||
DeviceID = GetDeviceIDByName(DeviceName);
|
DeviceID = GetDeviceIDByName(DeviceName);
|
||||||
|
@ -332,9 +325,9 @@ void ExecuteCommand(u32 _Address)
|
||||||
INFO_LOG(WII_IPC_FILEIO, "IOP: ReOpen (Device=%s, DeviceID=%08x, Mode=%i)",
|
INFO_LOG(WII_IPC_FILEIO, "IOP: ReOpen (Device=%s, DeviceID=%08x, Mode=%i)",
|
||||||
pDevice->GetDeviceName().c_str(), DeviceID, Mode);
|
pDevice->GetDeviceName().c_str(), DeviceID, Mode);
|
||||||
|
|
||||||
if(pDevice->IsHardware())
|
if (pDevice->IsHardware())
|
||||||
{
|
{
|
||||||
if(pDevice->IsOpened())
|
if (pDevice->IsOpened())
|
||||||
{
|
{
|
||||||
if (pDevice->GetDeviceName().find("/dev/net/kd/request") != std::string::npos)
|
if (pDevice->GetDeviceName().find("/dev/net/kd/request") != std::string::npos)
|
||||||
// AyuanX: /dev/net/kd/request is more like event which doesn't need close so it can be reopened
|
// AyuanX: /dev/net/kd/request is more like event which doesn't need close so it can be reopened
|
||||||
|
@ -358,7 +351,7 @@ void ExecuteCommand(u32 _Address)
|
||||||
// Open > Failed > ... other stuff > ReOpen call sequence, in that case
|
// Open > Failed > ... other stuff > ReOpen call sequence, in that case
|
||||||
// we have no file and no file handle, so we call Open again to basically
|
// we have no file and no file handle, so we call Open again to basically
|
||||||
// get a -106 error so that the game call CreateFile and then ReOpen again.
|
// get a -106 error so that the game call CreateFile and then ReOpen again.
|
||||||
if(pDevice->ReturnFileHandle())
|
if (pDevice->ReturnFileHandle())
|
||||||
Memory::Write_U32(DeviceID, _Address + 4);
|
Memory::Write_U32(DeviceID, _Address + 4);
|
||||||
else
|
else
|
||||||
pDevice->Open(_Address, Mode);
|
pDevice->Open(_Address, Mode);
|
||||||
|
@ -368,7 +361,6 @@ void ExecuteCommand(u32 _Address)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COMMAND_CLOSE_DEVICE:
|
case COMMAND_CLOSE_DEVICE:
|
||||||
{
|
|
||||||
if (pDevice)
|
if (pDevice)
|
||||||
{
|
{
|
||||||
pDevice->Close(_Address);
|
pDevice->Close(_Address);
|
||||||
|
@ -377,101 +369,94 @@ void ExecuteCommand(u32 _Address)
|
||||||
DeleteDeviceByID(DeviceID);
|
DeleteDeviceByID(DeviceID);
|
||||||
CmdSuccess = true;
|
CmdSuccess = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COMMAND_READ:
|
case COMMAND_READ:
|
||||||
{
|
|
||||||
if (pDevice != NULL)
|
if (pDevice != NULL)
|
||||||
CmdSuccess = pDevice->Read(_Address);
|
CmdSuccess = pDevice->Read(_Address);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COMMAND_WRITE:
|
case COMMAND_WRITE:
|
||||||
{
|
|
||||||
if (pDevice != NULL)
|
if (pDevice != NULL)
|
||||||
CmdSuccess = pDevice->Write(_Address);
|
CmdSuccess = pDevice->Write(_Address);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COMMAND_SEEK:
|
case COMMAND_SEEK:
|
||||||
{
|
|
||||||
if (pDevice != NULL)
|
if (pDevice != NULL)
|
||||||
CmdSuccess = pDevice->Seek(_Address);
|
CmdSuccess = pDevice->Seek(_Address);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COMMAND_IOCTL:
|
case COMMAND_IOCTL:
|
||||||
{
|
|
||||||
if (pDevice != NULL)
|
if (pDevice != NULL)
|
||||||
CmdSuccess = pDevice->IOCtl(_Address);
|
CmdSuccess = pDevice->IOCtl(_Address);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COMMAND_IOCTLV:
|
case COMMAND_IOCTLV:
|
||||||
{
|
|
||||||
if (pDevice)
|
if (pDevice)
|
||||||
CmdSuccess = pDevice->IOCtlV(_Address);
|
CmdSuccess = pDevice->IOCtlV(_Address);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
_dbg_assert_msg_(WII_IPC_HLE, 0, "Unknown IPC Command %i (0x%08x)", Command, _Address);
|
_dbg_assert_msg_(WII_IPC_HLE, 0, "Unknown IPC Command %i (0x%08x)", Command, _Address);
|
||||||
// Break on the same terms as the _dbg_assert_msg_, if LOGGING was defined
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// It seems that the original hardware overwrites the command after it has been
|
// It seems that the original hardware overwrites the command after it has been
|
||||||
// executed. We write 8 which is not any valid command.
|
// executed. We write 8 which is not any valid command, and what IOS does
|
||||||
//
|
Memory::Write_U32(8, _Address);
|
||||||
// AyuanX: Is this really necessary?
|
// IOS seems to write back the command that was responded to
|
||||||
// My experiment says no, so I'm just commenting this out
|
Memory::Write_U32(Command, _Address + 8);
|
||||||
//
|
|
||||||
//Memory::Write_U32(8, _Address);
|
|
||||||
|
|
||||||
if (CmdSuccess)
|
if (CmdSuccess)
|
||||||
{
|
{
|
||||||
// Generate a reply to the IPC command
|
// Generate a reply to the IPC command
|
||||||
WII_IPCInterface::EnqReply(_Address);
|
EnqReply(_Address);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//INFO_LOG(WII_IPC_HLE, "<<-- Failed or Not Ready to Reply to Command Address: 0x%08x ", _Address);
|
ERROR_LOG(WII_IPC_HLE, "<<-- Failed or Not Ready to Reply to IPC Request @ 0x%08x ", _Address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Happens AS SOON AS IPC gets a new pointer!
|
||||||
|
void EnqRequest(u32 _Address)
|
||||||
|
{
|
||||||
|
request_queue.push(_Address);
|
||||||
|
}
|
||||||
|
|
||||||
// ===================================================
|
// Called when IOS module has some reply
|
||||||
// This is called continuously from SystemTimers.cpp
|
void EnqReply(u32 _Address)
|
||||||
// ---------------------------------------------------
|
{
|
||||||
|
reply_queue.push(_Address);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is called every IPC_HLE_PERIOD from SystemTimers.cpp
|
||||||
|
// Takes care of routing ipc <-> ipc HLE
|
||||||
void Update()
|
void Update()
|
||||||
{
|
{
|
||||||
if (WII_IPCInterface::IsReady() == false)
|
if (!WII_IPCInterface::IsReady())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UpdateDevices();
|
UpdateDevices();
|
||||||
|
|
||||||
// if we have a reply to send
|
if (reply_queue.size())
|
||||||
u32 _Reply = WII_IPCInterface::DeqReply();
|
|
||||||
if (_Reply)
|
|
||||||
{
|
{
|
||||||
WII_IPCInterface::GenerateReply(_Reply);
|
WII_IPCInterface::GenerateReply(reply_queue.front());
|
||||||
INFO_LOG(WII_IPC_HLE, "<<-- Reply to Command Address: 0x%08x", _Reply);
|
INFO_LOG(WII_IPC_HLE, "<<-- Reply to IPC Request @ 0x%08x", reply_queue.front());
|
||||||
|
reply_queue.pop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is a a new command
|
if (request_queue.size())
|
||||||
u32 _Address = WII_IPCInterface::GetAddress();
|
|
||||||
if (_Address)
|
|
||||||
{
|
{
|
||||||
WII_IPCInterface::GenerateAck();
|
WII_IPCInterface::GenerateAck(request_queue.front());
|
||||||
INFO_LOG(WII_IPC_HLE, "||-- Acknowledge Command Address: 0x%08x", _Address);
|
INFO_LOG(WII_IPC_HLE, "||-- Acknowledge IPC Request @ 0x%08x", request_queue.front());
|
||||||
|
|
||||||
ExecuteCommand(_Address);
|
ExecuteCommand(request_queue.front());
|
||||||
|
request_queue.pop();
|
||||||
|
|
||||||
#if MAX_LOG_LEVEL >= DEBUG_LEVEL
|
#if MAX_LOGLEVEL >= DEBUG_LEVEL
|
||||||
Debugger::PrintCallstack(LogTypes::WII_IPC_HLE, LogTypes::LDEBUG);
|
Dolphin_Debugger::PrintCallstack(LogTypes::WII_IPC_HLE, LogTypes::LDEBUG);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -488,4 +473,4 @@ void UpdateDevices()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // end of namespace IPC
|
} // end of namespace WII_IPC_HLE_Interface
|
||||||
|
|
|
@ -61,6 +61,9 @@ void UpdateDevices();
|
||||||
|
|
||||||
void ExecuteCommand(u32 _Address);
|
void ExecuteCommand(u32 _Address);
|
||||||
|
|
||||||
|
void EnqRequest(u32 _Address);
|
||||||
|
void EnqReply(u32 _Address);
|
||||||
|
|
||||||
enum ECommandType
|
enum ECommandType
|
||||||
{
|
{
|
||||||
COMMAND_OPEN_DEVICE = 1,
|
COMMAND_OPEN_DEVICE = 1,
|
||||||
|
|
|
@ -77,17 +77,15 @@ protected:
|
||||||
bool m_Hardware;
|
bool m_Hardware;
|
||||||
bool m_Active;
|
bool m_Active;
|
||||||
|
|
||||||
// ===================================================
|
// A struct for IOS ioctlv calls
|
||||||
/* A struct for IOS ioctlv calls */
|
|
||||||
// ----------------
|
|
||||||
struct SIOCtlVBuffer
|
struct SIOCtlVBuffer
|
||||||
{
|
{
|
||||||
SIOCtlVBuffer(u32 _Address)
|
SIOCtlVBuffer(u32 _Address)
|
||||||
: m_Address(_Address)
|
: m_Address(_Address)
|
||||||
{
|
{
|
||||||
/* These are the Ioctlv parameters in the IOS communication. The BufferVector
|
// These are the Ioctlv parameters in the IOS communication. The BufferVector
|
||||||
is a memory address offset at where the in and out buffer addresses are
|
// is a memory address offset at where the in and out buffer addresses are
|
||||||
stored. */
|
// stored.
|
||||||
Parameter = Memory::Read_U32(m_Address + 0x0C); // command 3, arg0
|
Parameter = Memory::Read_U32(m_Address + 0x0C); // command 3, arg0
|
||||||
NumberInBuffer = Memory::Read_U32(m_Address + 0x10); // 4, arg1
|
NumberInBuffer = Memory::Read_U32(m_Address + 0x10); // 4, arg1
|
||||||
NumberPayloadBuffer = Memory::Read_U32(m_Address + 0x14); // 5, arg2
|
NumberPayloadBuffer = Memory::Read_U32(m_Address + 0x14); // 5, arg2
|
||||||
|
@ -144,11 +142,8 @@ protected:
|
||||||
std::vector<SBuffer> PayloadBuffer;
|
std::vector<SBuffer> PayloadBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Write out the IPC struct from _CommandAddress to _NumberOfCommands numbers
|
||||||
// ===================================================
|
// of 4 byte commands.
|
||||||
/* Write out the IPC struct from _CommandAddress to _NumberOfCommands numbers
|
|
||||||
of 4 byte commands. */
|
|
||||||
// ----------------
|
|
||||||
void DumpCommands(u32 _CommandAddress, size_t _NumberOfCommands = 8,
|
void DumpCommands(u32 _CommandAddress, size_t _NumberOfCommands = 8,
|
||||||
LogTypes::LOG_TYPE LogType = LogTypes::WII_IPC_HLE,
|
LogTypes::LOG_TYPE LogType = LogTypes::WII_IPC_HLE,
|
||||||
LogTypes::LOG_LEVELS Verbosity = LogTypes::LDEBUG)
|
LogTypes::LOG_LEVELS Verbosity = LogTypes::LDEBUG)
|
||||||
|
@ -162,7 +157,6 @@ protected:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DumpAsync(u32 BufferVector, u32 NumberInBuffer, u32 NumberOutBuffer,
|
void DumpAsync(u32 BufferVector, u32 NumberInBuffer, u32 NumberOutBuffer,
|
||||||
LogTypes::LOG_TYPE LogType = LogTypes::WII_IPC_HLE,
|
LogTypes::LOG_TYPE LogType = LogTypes::WII_IPC_HLE,
|
||||||
LogTypes::LOG_LEVELS Verbosity = LogTypes::LDEBUG)
|
LogTypes::LOG_LEVELS Verbosity = LogTypes::LDEBUG)
|
||||||
|
@ -175,7 +169,8 @@ protected:
|
||||||
u32 InBuffer = Memory::Read_U32(BufferOffset); BufferOffset += 4;
|
u32 InBuffer = Memory::Read_U32(BufferOffset); BufferOffset += 4;
|
||||||
u32 InBufferSize = Memory::Read_U32(BufferOffset); BufferOffset += 4;
|
u32 InBufferSize = Memory::Read_U32(BufferOffset); BufferOffset += 4;
|
||||||
|
|
||||||
GENERIC_LOG(LogType, LogTypes::LINFO, "%s - IOCtlV InBuffer[%i]:", GetDeviceName().c_str(), i);
|
GENERIC_LOG(LogType, LogTypes::LINFO, "%s - IOCtlV InBuffer[%i]:",
|
||||||
|
GetDeviceName().c_str(), i);
|
||||||
|
|
||||||
std::string Temp;
|
std::string Temp;
|
||||||
for (u32 j = 0; j < InBufferSize; j++)
|
for (u32 j = 0; j < InBufferSize; j++)
|
||||||
|
@ -188,22 +183,21 @@ protected:
|
||||||
GENERIC_LOG(LogType, LogTypes::LDEBUG, " Buffer: %s", Temp.c_str());
|
GENERIC_LOG(LogType, LogTypes::LDEBUG, " Buffer: %s", Temp.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (u32 i = 0; i < NumberOutBuffer; i++)
|
for (u32 i = 0; i < NumberOutBuffer; i++)
|
||||||
{
|
{
|
||||||
u32 OutBuffer = Memory::Read_U32(BufferOffset); BufferOffset += 4;
|
u32 OutBuffer = Memory::Read_U32(BufferOffset); BufferOffset += 4;
|
||||||
u32 OutBufferSize = Memory::Read_U32(BufferOffset); BufferOffset += 4;
|
u32 OutBufferSize = Memory::Read_U32(BufferOffset); BufferOffset += 4;
|
||||||
|
|
||||||
GENERIC_LOG(LogType, LogTypes::LINFO, "%s - IOCtlV OutBuffer[%i]:", GetDeviceName().c_str(), i);
|
GENERIC_LOG(LogType, LogTypes::LINFO, "%s - IOCtlV OutBuffer[%i]:",
|
||||||
GENERIC_LOG(LogType, LogTypes::LINFO, " OutBuffer: 0x%08x (0x%x):", OutBuffer, OutBufferSize);
|
GetDeviceName().c_str(), i);
|
||||||
|
GENERIC_LOG(LogType, LogTypes::LINFO, " OutBuffer: 0x%08x (0x%x):",
|
||||||
|
OutBuffer, OutBufferSize);
|
||||||
|
|
||||||
#if defined(MAX_LOGLEVEL) && MAX_LOGLEVEL >= INFO_LEVEL
|
#if defined(MAX_LOGLEVEL) && MAX_LOGLEVEL >= INFO_LEVEL
|
||||||
DumpCommands(OutBuffer, OutBufferSize, LogType, Verbosity);
|
DumpCommands(OutBuffer, OutBufferSize, LogType, Verbosity);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -37,10 +37,7 @@ enum
|
||||||
IOCTL_STM_READDDRREG2 = 0x4002,
|
IOCTL_STM_READDDRREG2 = 0x4002,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The /dev/stm/immediate
|
||||||
// =======================================================
|
|
||||||
// The /device/stm/immediate class
|
|
||||||
// -------------
|
|
||||||
class CWII_IPC_HLE_Device_stm_immediate : public IWII_IPC_HLE_Device
|
class CWII_IPC_HLE_Device_stm_immediate : public IWII_IPC_HLE_Device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -71,11 +68,11 @@ public:
|
||||||
|
|
||||||
virtual bool IOCtl(u32 _CommandAddress)
|
virtual bool IOCtl(u32 _CommandAddress)
|
||||||
{
|
{
|
||||||
u32 Parameter = Memory::Read_U32(_CommandAddress +0x0C);
|
u32 Parameter = Memory::Read_U32(_CommandAddress + 0x0C);
|
||||||
u32 BufferIn = Memory::Read_U32(_CommandAddress +0x10);
|
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
|
||||||
u32 BufferInSize = Memory::Read_U32(_CommandAddress +0x14);
|
u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14);
|
||||||
u32 BufferOut = Memory::Read_U32(_CommandAddress +0x18);
|
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
|
||||||
u32 BufferOutSize = Memory::Read_U32(_CommandAddress +0x1C);
|
u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C);
|
||||||
|
|
||||||
// Prepare the out buffer(s) with zeroes as a safety precaution
|
// Prepare the out buffer(s) with zeroes as a safety precaution
|
||||||
// to avoid returning bad values
|
// to avoid returning bad values
|
||||||
|
@ -123,16 +120,11 @@ public:
|
||||||
|
|
||||||
// Write return value to the IPC call
|
// Write return value to the IPC call
|
||||||
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
|
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
|
||||||
|
|
||||||
// Generate true or false reply for the main UpdateInterrupts() function
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The /dev/stm/eventhook
|
||||||
// =======================================================
|
|
||||||
// The /device/stm/eventhook class
|
|
||||||
// -------------
|
|
||||||
class CWII_IPC_HLE_Device_stm_eventhook : public IWII_IPC_HLE_Device
|
class CWII_IPC_HLE_Device_stm_eventhook : public IWII_IPC_HLE_Device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -165,13 +157,13 @@ public:
|
||||||
|
|
||||||
virtual bool IOCtl(u32 _CommandAddress)
|
virtual bool IOCtl(u32 _CommandAddress)
|
||||||
{
|
{
|
||||||
u32 Parameter = Memory::Read_U32(_CommandAddress +0x0C);
|
u32 Parameter = Memory::Read_U32(_CommandAddress + 0x0C);
|
||||||
u32 BufferIn = Memory::Read_U32(_CommandAddress +0x10);
|
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
|
||||||
u32 BufferInSize = Memory::Read_U32(_CommandAddress +0x14);
|
u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14);
|
||||||
u32 BufferOut = Memory::Read_U32(_CommandAddress +0x18);
|
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
|
||||||
u32 BufferOutSize = Memory::Read_U32(_CommandAddress +0x1C);
|
u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C);
|
||||||
|
|
||||||
// Prepare the out buffer(s) with zeroes as a safety precaution
|
// Prepare the out buffer(s) with zeros as a safety precaution
|
||||||
// to avoid returning bad values
|
// to avoid returning bad values
|
||||||
Memory::Memset(BufferOut, 0, BufferOutSize);
|
Memory::Memset(BufferOut, 0, BufferOutSize);
|
||||||
u32 ReturnValue = 0;
|
u32 ReturnValue = 0;
|
||||||
|
@ -184,42 +176,29 @@ public:
|
||||||
m_EventHookAddress = _CommandAddress;
|
m_EventHookAddress = _CommandAddress;
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_STM, "%s registers event hook:", GetDeviceName().c_str());
|
INFO_LOG(WII_IPC_STM, "%s registers event hook:", GetDeviceName().c_str());
|
||||||
DEBUG_LOG(WII_IPC_STM, " 0x1000 - IOCTL_STM_EVENTHOOK", Parameter);
|
DEBUG_LOG(WII_IPC_STM, "0x1000 - IOCTL_STM_EVENTHOOK", Parameter);
|
||||||
DEBUG_LOG(WII_IPC_STM, " BufferIn: 0x%08x", BufferIn);
|
DEBUG_LOG(WII_IPC_STM, "BufferIn: 0x%08x", BufferIn);
|
||||||
DEBUG_LOG(WII_IPC_STM, " BufferInSize: 0x%08x", BufferInSize);
|
DEBUG_LOG(WII_IPC_STM, "BufferInSize: 0x%08x", BufferInSize);
|
||||||
DEBUG_LOG(WII_IPC_STM, " BufferOut: 0x%08x", BufferOut);
|
DEBUG_LOG(WII_IPC_STM, "BufferOut: 0x%08x", BufferOut);
|
||||||
DEBUG_LOG(WII_IPC_STM, " BufferOutSize: 0x%08x", BufferOutSize);
|
DEBUG_LOG(WII_IPC_STM, "BufferOutSize: 0x%08x", BufferOutSize);
|
||||||
|
|
||||||
DumpCommands(BufferIn, BufferInSize/4, LogTypes::WII_IPC_STM);
|
DumpCommands(BufferIn, BufferInSize/4, LogTypes::WII_IPC_STM);
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
_dbg_assert_msg_(WII_IPC_STM, 0, "unknown %s ioctl %x",
|
||||||
_dbg_assert_msg_(WII_IPC_STM, 0, "CWII_IPC_HLE_Device_stm_eventhook: 0x%x", Parameter);
|
GetDeviceName().c_str(), Parameter);
|
||||||
INFO_LOG(WII_IPC_STM, "%s registers event hook:", GetDeviceName().c_str());
|
|
||||||
DEBUG_LOG(WII_IPC_STM, " Parameter: 0x%x", Parameter);
|
|
||||||
DEBUG_LOG(WII_IPC_STM, " BufferIn: 0x%08x", BufferIn);
|
|
||||||
DEBUG_LOG(WII_IPC_STM, " BufferInSize: 0x%08x", BufferInSize);
|
|
||||||
DEBUG_LOG(WII_IPC_STM, " BufferOut: 0x%08x", BufferOut);
|
|
||||||
DEBUG_LOG(WII_IPC_STM, " BufferOutSize: 0x%08x", BufferOutSize);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write return value to the IPC call, 0 means success
|
// Write return value to the IPC call, 0 means success
|
||||||
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
|
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
|
||||||
|
return true;
|
||||||
// Generate true or false reply for the main UpdateInterrupts() function
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// STATE_TO_SAVE
|
// STATE_TO_SAVE
|
||||||
u32 m_EventHookAddress;
|
u32 m_EventHookAddress;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -316,16 +316,11 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::IOCtlV(u32 _CommandAddress)
|
||||||
|
|
||||||
// write return value
|
// write return value
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
Memory::Write_U32(0, _CommandAddress + 0x4);
|
||||||
return (_SendReply);
|
return _SendReply;
|
||||||
}
|
}
|
||||||
// ================
|
|
||||||
|
|
||||||
|
|
||||||
|
// Here we handle the USB_IOCTL_BLKMSG Ioctlv
|
||||||
// ===================================================
|
|
||||||
/* Here we handle the USB_IOCTL_BLKMSG Ioctlv */
|
|
||||||
// ----------------
|
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendToDevice(u16 _ConnectionHandle, u8* _pData, u32 _Size)
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendToDevice(u16 _ConnectionHandle, u8* _pData, u32 _Size)
|
||||||
{
|
{
|
||||||
CWII_IPC_HLE_WiiMote* pWiiMote = AccessWiiMote(_ConnectionHandle);
|
CWII_IPC_HLE_WiiMote* pWiiMote = AccessWiiMote(_ConnectionHandle);
|
||||||
|
@ -337,18 +332,12 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendToDevice(u16 _ConnectionHandle, u8
|
||||||
pWiiMote->ExecuteL2capCmd(_pData, _Size);
|
pWiiMote->ExecuteL2capCmd(_pData, _Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ================
|
|
||||||
|
|
||||||
|
|
||||||
// ===================================================
|
|
||||||
// Here we send ACL pakcets to CPU. They will consist of header + data.
|
// Here we send ACL pakcets to CPU. They will consist of header + data.
|
||||||
// The header is for example 07 00 41 00 which means size 0x0007 and channel 0x0041.
|
// The header is for example 07 00 41 00 which means size 0x0007 and channel 0x0041.
|
||||||
// ---------------------------------------------------
|
// ---------------------------------------------------
|
||||||
|
|
||||||
// AyuanX: Basically, our WII_IPC_HLE is efficient enough to send the packet immediately
|
// AyuanX: Basically, our WII_IPC_HLE is efficient enough to send the packet immediately
|
||||||
// rather than enqueue it to some other memory
|
// rather than enqueue it to some other memory
|
||||||
// But...the only exception comes from the Wiimote_Plugin
|
// But...the only exception comes from the Wiimote_Plugin
|
||||||
//
|
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 _ConnectionHandle, u8* _pData, u32 _Size)
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 _ConnectionHandle, u8* _pData, u32 _Size)
|
||||||
{
|
{
|
||||||
if(m_ACLBuffer.m_address != 0)
|
if(m_ACLBuffer.m_address != 0)
|
||||||
|
@ -368,7 +357,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 _ConnectionHandle, u
|
||||||
Memory::Write_U32(sizeof(UACLHeader) + _Size, m_ACLBuffer.m_address + 0x4);
|
Memory::Write_U32(sizeof(UACLHeader) + _Size, m_ACLBuffer.m_address + 0x4);
|
||||||
|
|
||||||
// Send a reply to indicate ACL buffer is sent
|
// Send a reply to indicate ACL buffer is sent
|
||||||
WII_IPCInterface::EnqReply(m_ACLBuffer.m_address);
|
WII_IPC_HLE_Interface::EnqReply(m_ACLBuffer.m_address);
|
||||||
|
|
||||||
// Invalidate ACL buffer
|
// Invalidate ACL buffer
|
||||||
m_ACLBuffer.m_address = 0;
|
m_ACLBuffer.m_address = 0;
|
||||||
|
@ -403,7 +392,6 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 _ConnectionHandle, u
|
||||||
// but current implementation of WiiMote_Plugin doesn't comply with this rule
|
// but current implementation of WiiMote_Plugin doesn't comply with this rule
|
||||||
// It acts like sending all the 3 packets in one cycle and idling around in the other two cycles
|
// It acts like sending all the 3 packets in one cycle and idling around in the other two cycles
|
||||||
// that's why we need this contingent ACL pool
|
// that's why we need this contingent ACL pool
|
||||||
//
|
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::PurgeACLPool()
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305::PurgeACLPool()
|
||||||
{
|
{
|
||||||
if(m_ACLBuffer.m_address == 0)
|
if(m_ACLBuffer.m_address == 0)
|
||||||
|
@ -420,16 +408,14 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::PurgeACLPool()
|
||||||
// Write the packet size as return value
|
// Write the packet size as return value
|
||||||
Memory::Write_U32(sizeof(UACLHeader) + ((UACLHeader*)_Address)->Size, m_ACLBuffer.m_address + 0x4);
|
Memory::Write_U32(sizeof(UACLHeader) + ((UACLHeader*)_Address)->Size, m_ACLBuffer.m_address + 0x4);
|
||||||
// Send a reply to indicate ACL buffer is sent
|
// Send a reply to indicate ACL buffer is sent
|
||||||
WII_IPCInterface::EnqReply(m_ACLBuffer.m_address);
|
WII_IPC_HLE_Interface::EnqReply(m_ACLBuffer.m_address);
|
||||||
// Invalidate ACL buffer
|
// Invalidate ACL buffer
|
||||||
m_ACLBuffer.m_address = 0;
|
m_ACLBuffer.m_address = 0;
|
||||||
m_ACLBuffer.m_buffer = NULL;
|
m_ACLBuffer.m_buffer = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===================================================
|
// See IPC_HLE_PERIOD in SystemTimers.cpp for a documentation of this update.
|
||||||
/* See IPC_HLE_PERIOD in SystemTimers.cpp for a documentation of this update. */
|
|
||||||
// ----------------
|
|
||||||
u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
||||||
{
|
{
|
||||||
// Check if HCI Pool is not purged
|
// Check if HCI Pool is not purged
|
||||||
|
@ -437,7 +423,7 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
||||||
{
|
{
|
||||||
PurgeHCIPool();
|
PurgeHCIPool();
|
||||||
if (m_HCIPool.m_number == 0)
|
if (m_HCIPool.m_number == 0)
|
||||||
WII_IPCInterface::EnqReply(m_CtrlSetup.m_Address);
|
WII_IPC_HLE_Interface::EnqReply(m_CtrlSetup.m_Address);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,23 +439,22 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
||||||
{
|
{
|
||||||
PurgeACLPool();
|
PurgeACLPool();
|
||||||
if (m_ACLPool.m_number == 0)
|
if (m_ACLPool.m_number == 0)
|
||||||
WII_IPCInterface::EnqReply(m_ACLSetup);
|
WII_IPC_HLE_Interface::EnqReply(m_ACLSetup);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
/* We wait for ScanEnable to be sent from the game through HCI_CMD_WRITE_SCAN_ENABLE
|
/* We wait for ScanEnable to be sent from the game through HCI_CMD_WRITE_SCAN_ENABLE
|
||||||
before we initiate the connection.
|
before we initiate the connection.
|
||||||
|
|
||||||
FiRES: TODO find a good solution to do this
|
FiRES: TODO find a good solution to do this
|
||||||
|
|
||||||
/* Why do we need this? 0 worked with the emulated wiimote in all games I tried. Do we have to
|
Why do we need this? 0 worked with the emulated wiimote in all games I tried. Do we have to
|
||||||
wait for wiiuse_init() and wiiuse_find() for a real Wiimote here? I'm testing
|
wait for wiiuse_init() and wiiuse_find() for a real Wiimote here? I'm testing
|
||||||
this new method of not waiting at all if there are no real Wiimotes. Please let me know
|
this new method of not waiting at all if there are no real Wiimotes. Please let me know
|
||||||
if it doesn't work. */
|
if it doesn't work. */
|
||||||
|
|
||||||
// AyuanX: I don't know the Real Wiimote behavior, so I'll leave it here untouched
|
// AyuanX: I don't know the Real Wiimote behavior, so I'll leave it here untouched
|
||||||
//
|
|
||||||
// Initiate ACL connection
|
// Initiate ACL connection
|
||||||
static int counter = (Core::GetRealWiimote() ? 1000 : 0);
|
static int counter = (Core::GetRealWiimote() ? 1000 : 0);
|
||||||
if (m_HCIBuffer.m_address && (m_ScanEnable & 0x2))
|
if (m_HCIBuffer.m_address && (m_ScanEnable & 0x2))
|
||||||
|
@ -537,17 +522,13 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
// -----------------
|
// -----------------
|
||||||
// These messages are sent from the Wiimote to the game, for example RequestConnection()
|
// These messages are sent from the Wiimote to the game, for example RequestConnection()
|
||||||
// or ConnectionComplete().
|
// or ConnectionComplete().
|
||||||
//
|
//
|
||||||
|
|
||||||
// Our WII_IPC_HLE is so efficient that we could fill the buffer immediately
|
// Our WII_IPC_HLE is so efficient that we could fill the buffer immediately
|
||||||
// rather than enqueue it to some other memory and this will do good for StateSave
|
// rather than enqueue it to some other memory and this will do good for StateSave
|
||||||
//
|
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::AddEventToQueue(const SQueuedEvent& _event)
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305::AddEventToQueue(const SQueuedEvent& _event)
|
||||||
{
|
{
|
||||||
if (m_HCIBuffer.m_address != 0)
|
if (m_HCIBuffer.m_address != 0)
|
||||||
|
@ -560,7 +541,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::AddEventToQueue(const SQueuedEvent& _e
|
||||||
Memory::Write_U32((u32)_event.m_size, m_HCIBuffer.m_address + 0x4);
|
Memory::Write_U32((u32)_event.m_size, m_HCIBuffer.m_address + 0x4);
|
||||||
|
|
||||||
// Send a reply to indicate HCI buffer is filled
|
// Send a reply to indicate HCI buffer is filled
|
||||||
WII_IPCInterface::EnqReply(m_HCIBuffer.m_address);
|
WII_IPC_HLE_Interface::EnqReply(m_HCIBuffer.m_address);
|
||||||
|
|
||||||
// Invalidate HCI buffer
|
// Invalidate HCI buffer
|
||||||
m_HCIBuffer.m_address = 0;
|
m_HCIBuffer.m_address = 0;
|
||||||
|
@ -590,7 +571,6 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::AddEventToQueue(const SQueuedEvent& _e
|
||||||
// so when IPC is running too fast that CPU can't catch up
|
// so when IPC is running too fast that CPU can't catch up
|
||||||
// then CPU(actually it is the usb driver) sometimes throws out a command before sending us a HCI buffer
|
// then CPU(actually it is the usb driver) sometimes throws out a command before sending us a HCI buffer
|
||||||
// So I put this contingent HCI Pool here until we figure out the true reason
|
// So I put this contingent HCI Pool here until we figure out the true reason
|
||||||
//
|
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::PurgeHCIPool()
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305::PurgeHCIPool()
|
||||||
{
|
{
|
||||||
if(m_HCIBuffer.m_address == 0)
|
if(m_HCIBuffer.m_address == 0)
|
||||||
|
@ -607,7 +587,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::PurgeHCIPool()
|
||||||
// Write the packet size as return value
|
// Write the packet size as return value
|
||||||
Memory::Write_U32(m_HCIPool.m_size[m_HCIPool.m_number], m_HCIBuffer.m_address + 0x4);
|
Memory::Write_U32(m_HCIPool.m_size[m_HCIPool.m_number], m_HCIBuffer.m_address + 0x4);
|
||||||
// Send a reply to indicate ACL buffer is sent
|
// Send a reply to indicate ACL buffer is sent
|
||||||
WII_IPCInterface::EnqReply(m_HCIBuffer.m_address);
|
WII_IPC_HLE_Interface::EnqReply(m_HCIBuffer.m_address);
|
||||||
// Invalidate ACL buffer
|
// Invalidate ACL buffer
|
||||||
m_HCIBuffer.m_address = 0;
|
m_HCIBuffer.m_address = 0;
|
||||||
m_HCIBuffer.m_buffer = NULL;
|
m_HCIBuffer.m_buffer = NULL;
|
||||||
|
@ -714,7 +694,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventConnectionComplete(const bdad
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is called from Update() after ScanEnable has been enabled. */
|
// This is called from Update() after ScanEnable has been enabled.
|
||||||
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventRequestConnection(CWII_IPC_HLE_WiiMote& _rWiiMote)
|
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventRequestConnection(CWII_IPC_HLE_WiiMote& _rWiiMote)
|
||||||
{
|
{
|
||||||
SQueuedEvent Event(sizeof(SHCIEventRequestConnection), 0);
|
SQueuedEvent Event(sizeof(SHCIEventRequestConnection), 0);
|
||||||
|
@ -1137,8 +1117,6 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventConPacketTypeChange(u16 _conn
|
||||||
// Command dispatcher
|
// Command dispatcher
|
||||||
// -----------------
|
// -----------------
|
||||||
// This is called from the USB_IOCTL_HCI_COMMAND_MESSAGE Ioctlv
|
// This is called from the USB_IOCTL_HCI_COMMAND_MESSAGE Ioctlv
|
||||||
//
|
|
||||||
//
|
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::ExecuteHCICommandMessage(const SHCICommandMessage& _rHCICommandMessage)
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305::ExecuteHCICommandMessage(const SHCICommandMessage& _rHCICommandMessage)
|
||||||
{
|
{
|
||||||
u8* pInput = Memory::GetPointer(_rHCICommandMessage.m_PayLoadAddr + 3);
|
u8* pInput = Memory::GetPointer(_rHCICommandMessage.m_PayLoadAddr + 3);
|
||||||
|
@ -1329,7 +1307,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::ExecuteHCICommandMessage(const SHCICom
|
||||||
if ((m_LastCmd == 0) && (m_HCIPool.m_number == 0))
|
if ((m_LastCmd == 0) && (m_HCIPool.m_number == 0))
|
||||||
{
|
{
|
||||||
// If HCI command is finished and HCI pool is empty, send a reply to command
|
// If HCI command is finished and HCI pool is empty, send a reply to command
|
||||||
WII_IPCInterface::EnqReply(_rHCICommandMessage.m_Address);
|
WII_IPC_HLE_Interface::EnqReply(_rHCICommandMessage.m_Address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue