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:
Shawn Hoffman 2010-03-23 03:32:19 +00:00
parent cf7101ef08
commit f6db5b7d8d
7 changed files with 165 additions and 281 deletions

View file

@ -16,6 +16,8 @@
// http://code.google.com/p/dolphin-emu/
#include <map>
#include <queue>
#include <vector>
#include "Common.h"
#include "ChunkFile.h"
@ -91,23 +93,16 @@ struct CtrlRegister
};
// STATE_TO_SAVE
u32 ppc_msg;
u32 arm_msg;
CtrlRegister ctrl;
static u32 ppc_msg;
static u32 arm_msg;
static CtrlRegister ctrl;
u32 ppc_irq_flags;
u32 ppc_irq_masks;
u32 arm_irq_flags;
u32 arm_irq_masks;
static u32 ppc_irq_flags;
static u32 ppc_irq_masks;
static u32 arm_irq_flags;
static u32 arm_irq_masks;
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];
static u32 sensorbar_power; // do we need to care about this?
void DoState(PointerWrap &p)
{
@ -119,17 +114,10 @@ void DoState(PointerWrap &p)
p.Do(arm_irq_flags);
p.Do(arm_irq_masks);
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()
{
cmd_active = false;
ctrl = CtrlRegister();
ppc_msg =
arm_msg =
@ -139,12 +127,7 @@ void Init()
arm_irq_flags =
arm_irq_masks =
sensorbar_power =
g_ReplyHead =
g_ReplyTail =
g_ReplyNum = 0;
memset(g_ReplyFifo, 0, REPLY_FIFO_DEPTH);
sensorbar_power = 0;
ppc_irq_masks |= INT_CAUSE_IPC_BROADWAY;
}
@ -166,7 +149,7 @@ void Read32(u32& _rReturnValue, const u32 _Address)
{
case IPC_PPCCTRL:
_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);
// 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
_rReturnValue = arm_msg;
INFO_LOG(WII_IPC, "r32 IPC_ARMMSG %08x ", _rReturnValue);
DEBUG_LOG(WII_IPC, "r32 IPC_ARMMSG %08x ", _rReturnValue);
break;
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
{
ppc_msg = _Value;
INFO_LOG(WII_IPC, "IPC_PPCMSG = %08x", ppc_msg);
DEBUG_LOG(WII_IPC, "IPC_PPCMSG = %08x", ppc_msg);
}
break;
case IPC_PPCCTRL:
{
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);
if (ctrl.X1) // seems like we should just be able to use X1 directly, but it doesn't work...why?!
cmd_active = true;
if (ctrl.X1)
{
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;
case PPC_IRQFLAG: // ACR REGISTER IT IS CALLED IN DEBUG
{
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;
@ -221,7 +208,7 @@ void Write32(const u32 _Value, const u32 _Address)
ppc_irq_masks = _Value;
if (ppc_irq_masks & INT_CAUSE_IPC_BROADWAY) // wtf?
Reset();
INFO_LOG(WII_IPC, "w32 PPC_IRQMASK %08x", ppc_irq_masks);
DEBUG_LOG(WII_IPC, "w32 PPC_IRQMASK %08x", ppc_irq_masks);
}
break;
@ -253,21 +240,12 @@ void UpdateInterrupts()
ProcessorInterface::SetInterrupt(ProcessorInterface::INT_CAUSE_WII_IPC, !!(ppc_irq_flags & ppc_irq_masks));
}
// The rest is for IOS HLE
bool IsReady()
void GenerateAck(u32 _Address)
{
return ((ctrl.Y1 == 0) && (ctrl.Y2 == 0) && ((ppc_irq_flags & INT_CAUSE_IPC_BROADWAY) == 0));
}
u32 GetAddress()
{
return (cmd_active ? ppc_msg : 0);
}
void GenerateAck()
{
cmd_active = false;
arm_msg = _Address; // dunno if it's really set here, but HLE needs to stay in context
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();
}
@ -275,40 +253,14 @@ void GenerateReply(u32 _Address)
{
arm_msg = _Address;
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();
}
void EnqReply(u32 _Address)
bool IsReady()
{
if (g_ReplyNum < REPLY_FIFO_DEPTH)
{
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;
return ((ctrl.Y1 == 0) && (ctrl.Y2 == 0) && ((ppc_irq_flags & INT_CAUSE_IPC_BROADWAY) == 0));
}
}

View file

@ -44,9 +44,6 @@ enum StarletInterruptCause
INT_CAUSE_IPC_STARLET = 0x80000000
};
#define REPLY_FIFO_DEPTH (unsigned)8
#define REPLY_FIFO_MASK (REPLY_FIFO_DEPTH - 1)
void Init();
void Reset();
void Shutdown();
@ -55,14 +52,10 @@ void DoState(PointerWrap &p);
void Read32(u32& _rReturnValue, 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 GenerateAck(u32 _Address);
void GenerateReply(u32 _Address);
bool IsReady();
}

View file

@ -15,30 +15,23 @@
// Official SVN repository and contact information can be found at
// 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):
// =======================================================
// File description
// -------------
/* 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
Close: 0
Read: Bytes read
Write: Bytes written
Seek: Seek position
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)
They will also generate a true or false return for UpdateInterrupts() in WII_IPC.cpp. */
// =============
Return values for file handles: All IPC calls will generate a return value to 0x04,
in case of success they are
Open: DeviceID
Close: 0
Read: Bytes read
Write: Bytes written
Seek: Seek position
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)
They will also generate a true or false return for UpdateInterrupts() in WII_IPC.cpp.
*/
#include <map>
#include <string>
@ -78,6 +71,10 @@ typedef std::map<u32, std::string> TFileNameMap;
TFileNameMap g_FileNameMap;
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
void Init()
{
@ -125,6 +122,9 @@ void Reset(bool _bHard)
g_DeviceMap.erase(itr, g_DeviceMap.end());
g_FileNameMap.clear();
request_queue = std::queue<u32>();
reply_queue = std::queue<u32>();
g_LastDeviceID = IPC_FIRST_FILEIO_ID;
}
@ -133,7 +133,6 @@ void Shutdown()
Reset(true);
}
// Set default content file
void SetDefaultContentFile(const std::string& _rFilename)
{
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);
}
// 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)
{
// 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;
}
// 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)
{
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
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()))
{
@ -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)
{
bool CmdSuccess = false;
@ -284,7 +276,8 @@ void ExecuteCommand(u32 _Address)
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
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);
DeviceID = GetDeviceIDByName(DeviceName);
@ -332,9 +325,9 @@ void ExecuteCommand(u32 _Address)
INFO_LOG(WII_IPC_FILEIO, "IOP: ReOpen (Device=%s, DeviceID=%08x, Mode=%i)",
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)
// 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
// 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.
if(pDevice->ReturnFileHandle())
if (pDevice->ReturnFileHandle())
Memory::Write_U32(DeviceID, _Address + 4);
else
pDevice->Open(_Address, Mode);
@ -368,110 +361,102 @@ void ExecuteCommand(u32 _Address)
break;
case COMMAND_CLOSE_DEVICE:
{
if (pDevice)
{
pDevice->Close(_Address);
// Don't delete hardware
if (!pDevice->IsHardware())
DeleteDeviceByID(DeviceID);
CmdSuccess = true;
}
}
if (pDevice)
{
pDevice->Close(_Address);
// Don't delete hardware
if (!pDevice->IsHardware())
DeleteDeviceByID(DeviceID);
CmdSuccess = true;
}
break;
case COMMAND_READ:
{
if (pDevice != NULL)
CmdSuccess = pDevice->Read(_Address);
}
if (pDevice != NULL)
CmdSuccess = pDevice->Read(_Address);
break;
case COMMAND_WRITE:
{
if (pDevice != NULL)
CmdSuccess = pDevice->Write(_Address);
}
if (pDevice != NULL)
CmdSuccess = pDevice->Write(_Address);
break;
case COMMAND_SEEK:
{
if (pDevice != NULL)
CmdSuccess = pDevice->Seek(_Address);
}
if (pDevice != NULL)
CmdSuccess = pDevice->Seek(_Address);
break;
case COMMAND_IOCTL:
{
if (pDevice != NULL)
CmdSuccess = pDevice->IOCtl(_Address);
}
if (pDevice != NULL)
CmdSuccess = pDevice->IOCtl(_Address);
break;
case COMMAND_IOCTLV:
{
if (pDevice)
CmdSuccess = pDevice->IOCtlV(_Address);
}
if (pDevice)
CmdSuccess = pDevice->IOCtlV(_Address);
break;
default:
_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;
}
// It seems that the original hardware overwrites the command after it has been
// executed. We write 8 which is not any valid command.
//
// AyuanX: Is this really necessary?
// My experiment says no, so I'm just commenting this out
//
//Memory::Write_U32(8, _Address);
// 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
Memory::Write_U32(Command, _Address + 8);
if (CmdSuccess)
{
// Generate a reply to the IPC command
WII_IPCInterface::EnqReply(_Address);
EnqReply(_Address);
}
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);
}
// ===================================================
// This is called continuously from SystemTimers.cpp
// ---------------------------------------------------
// Called when IOS module has some reply
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()
{
if (WII_IPCInterface::IsReady() == false)
if (!WII_IPCInterface::IsReady())
return;
UpdateDevices();
// if we have a reply to send
u32 _Reply = WII_IPCInterface::DeqReply();
if (_Reply)
if (reply_queue.size())
{
WII_IPCInterface::GenerateReply(_Reply);
INFO_LOG(WII_IPC_HLE, "<<-- Reply to Command Address: 0x%08x", _Reply);
WII_IPCInterface::GenerateReply(reply_queue.front());
INFO_LOG(WII_IPC_HLE, "<<-- Reply to IPC Request @ 0x%08x", reply_queue.front());
reply_queue.pop();
return;
}
// If there is a a new command
u32 _Address = WII_IPCInterface::GetAddress();
if (_Address)
if (request_queue.size())
{
WII_IPCInterface::GenerateAck();
INFO_LOG(WII_IPC_HLE, "||-- Acknowledge Command Address: 0x%08x", _Address);
WII_IPCInterface::GenerateAck(request_queue.front());
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
Debugger::PrintCallstack(LogTypes::WII_IPC_HLE, LogTypes::LDEBUG);
#if MAX_LOGLEVEL >= DEBUG_LEVEL
Dolphin_Debugger::PrintCallstack(LogTypes::WII_IPC_HLE, LogTypes::LDEBUG);
#endif
}
}
@ -488,4 +473,4 @@ void UpdateDevices()
}
} // end of namespace IPC
} // end of namespace WII_IPC_HLE_Interface

View file

@ -61,6 +61,9 @@ void UpdateDevices();
void ExecuteCommand(u32 _Address);
void EnqRequest(u32 _Address);
void EnqReply(u32 _Address);
enum ECommandType
{
COMMAND_OPEN_DEVICE = 1,

View file

@ -77,17 +77,15 @@ protected:
bool m_Hardware;
bool m_Active;
// ===================================================
/* A struct for IOS ioctlv calls */
// ----------------
// A struct for IOS ioctlv calls
struct SIOCtlVBuffer
{
SIOCtlVBuffer(u32 _Address)
: m_Address(_Address)
{
/* 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
stored. */
// 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
// stored.
Parameter = Memory::Read_U32(m_Address + 0x0C); // command 3, arg0
NumberInBuffer = Memory::Read_U32(m_Address + 0x10); // 4, arg1
NumberPayloadBuffer = Memory::Read_U32(m_Address + 0x14); // 5, arg2
@ -144,11 +142,8 @@ protected:
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,
LogTypes::LOG_TYPE LogType = LogTypes::WII_IPC_HLE,
LogTypes::LOG_LEVELS Verbosity = LogTypes::LDEBUG)
@ -161,7 +156,6 @@ protected:
Memory::Read_U32(_CommandAddress + i*4));
}
}
void DumpAsync(u32 BufferVector, u32 NumberInBuffer, u32 NumberOutBuffer,
LogTypes::LOG_TYPE LogType = LogTypes::WII_IPC_HLE,
@ -175,7 +169,8 @@ protected:
u32 InBuffer = 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;
for (u32 j = 0; j < InBufferSize; j++)
@ -188,22 +183,21 @@ protected:
GENERIC_LOG(LogType, LogTypes::LDEBUG, " Buffer: %s", Temp.c_str());
}
for (u32 i = 0; i < NumberOutBuffer; i++)
{
u32 OutBuffer = 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, " OutBuffer: 0x%08x (0x%x):", OutBuffer, OutBufferSize);
GENERIC_LOG(LogType, LogTypes::LINFO, "%s - IOCtlV OutBuffer[%i]:",
GetDeviceName().c_str(), i);
GENERIC_LOG(LogType, LogTypes::LINFO, " OutBuffer: 0x%08x (0x%x):",
OutBuffer, OutBufferSize);
#if defined(MAX_LOGLEVEL) && MAX_LOGLEVEL >= INFO_LEVEL
DumpCommands(OutBuffer, OutBufferSize, LogType, Verbosity);
#endif
}
}
};
#endif

View file

@ -37,10 +37,7 @@ enum
IOCTL_STM_READDDRREG2 = 0x4002,
};
// =======================================================
// The /device/stm/immediate class
// -------------
// The /dev/stm/immediate
class CWII_IPC_HLE_Device_stm_immediate : public IWII_IPC_HLE_Device
{
public:
@ -71,11 +68,11 @@ public:
virtual bool IOCtl(u32 _CommandAddress)
{
u32 Parameter = Memory::Read_U32(_CommandAddress +0x0C);
u32 BufferIn = Memory::Read_U32(_CommandAddress +0x10);
u32 BufferInSize = Memory::Read_U32(_CommandAddress +0x14);
u32 BufferOut = Memory::Read_U32(_CommandAddress +0x18);
u32 BufferOutSize = Memory::Read_U32(_CommandAddress +0x1C);
u32 Parameter = Memory::Read_U32(_CommandAddress + 0x0C);
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14);
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C);
// Prepare the out buffer(s) with zeroes as a safety precaution
// to avoid returning bad values
@ -123,16 +120,11 @@ public:
// Write return value to the IPC call
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
// Generate true or false reply for the main UpdateInterrupts() function
return true;
}
};
// =======================================================
// The /device/stm/eventhook class
// -------------
// The /dev/stm/eventhook
class CWII_IPC_HLE_Device_stm_eventhook : public IWII_IPC_HLE_Device
{
public:
@ -165,13 +157,13 @@ public:
virtual bool IOCtl(u32 _CommandAddress)
{
u32 Parameter = Memory::Read_U32(_CommandAddress +0x0C);
u32 BufferIn = Memory::Read_U32(_CommandAddress +0x10);
u32 BufferInSize = Memory::Read_U32(_CommandAddress +0x14);
u32 BufferOut = Memory::Read_U32(_CommandAddress +0x18);
u32 BufferOutSize = Memory::Read_U32(_CommandAddress +0x1C);
u32 Parameter = Memory::Read_U32(_CommandAddress + 0x0C);
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14);
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
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
Memory::Memset(BufferOut, 0, BufferOutSize);
u32 ReturnValue = 0;
@ -184,42 +176,29 @@ public:
m_EventHookAddress = _CommandAddress;
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, " 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);
DEBUG_LOG(WII_IPC_STM, "0x1000 - IOCTL_STM_EVENTHOOK", 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);
DumpCommands(BufferIn, BufferInSize/4, LogTypes::WII_IPC_STM);
return false;
}
break;
default:
{
_dbg_assert_msg_(WII_IPC_STM, 0, "CWII_IPC_HLE_Device_stm_eventhook: 0x%x", 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);
}
_dbg_assert_msg_(WII_IPC_STM, 0, "unknown %s ioctl %x",
GetDeviceName().c_str(), Parameter);
break;
}
// Write return value to the IPC call, 0 means success
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
// Generate true or false reply for the main UpdateInterrupts() function
return false;
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
return true;
}
// STATE_TO_SAVE
u32 m_EventHookAddress;
};
#endif

View file

@ -316,16 +316,11 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::IOCtlV(u32 _CommandAddress)
// write return value
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)
{
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);
}
// ================
// ===================================================
// 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.
// ---------------------------------------------------
// AyuanX: Basically, our WII_IPC_HLE is efficient enough to send the packet immediately
// rather than enqueue it to some other memory
// 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)
{
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);
// 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
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
// 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
//
void CWII_IPC_HLE_Device_usb_oh1_57e_305::PurgeACLPool()
{
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
Memory::Write_U32(sizeof(UACLHeader) + ((UACLHeader*)_Address)->Size, m_ACLBuffer.m_address + 0x4);
// 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
m_ACLBuffer.m_address = 0;
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()
{
// Check if HCI Pool is not purged
@ -437,7 +423,7 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
{
PurgeHCIPool();
if (m_HCIPool.m_number == 0)
WII_IPCInterface::EnqReply(m_CtrlSetup.m_Address);
WII_IPC_HLE_Interface::EnqReply(m_CtrlSetup.m_Address);
return true;
}
@ -453,23 +439,22 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
{
PurgeACLPool();
if (m_ACLPool.m_number == 0)
WII_IPCInterface::EnqReply(m_ACLSetup);
WII_IPC_HLE_Interface::EnqReply(m_ACLSetup);
return true;
}
// --------------------------------------------------------------------
/* We wait for ScanEnable to be sent from the game through HCI_CMD_WRITE_SCAN_ENABLE
before we initiate the connection.
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
this new method of not waiting at all if there are no real Wiimotes. Please let me know
if it doesn't work. */
// AyuanX: I don't know the Real Wiimote behavior, so I'll leave it here untouched
//
// Initiate ACL connection
static int counter = (Core::GetRealWiimote() ? 1000 : 0);
if (m_HCIBuffer.m_address && (m_ScanEnable & 0x2))
@ -537,17 +522,13 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
return false;
}
// Events
// -----------------
// These messages are sent from the Wiimote to the game, for example RequestConnection()
// or ConnectionComplete().
//
// 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
//
void CWII_IPC_HLE_Device_usb_oh1_57e_305::AddEventToQueue(const SQueuedEvent& _event)
{
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);
// 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
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
// 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
//
void CWII_IPC_HLE_Device_usb_oh1_57e_305::PurgeHCIPool()
{
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
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
WII_IPCInterface::EnqReply(m_HCIBuffer.m_address);
WII_IPC_HLE_Interface::EnqReply(m_HCIBuffer.m_address);
// Invalidate ACL buffer
m_HCIBuffer.m_address = 0;
m_HCIBuffer.m_buffer = NULL;
@ -714,7 +694,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventConnectionComplete(const bdad
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)
{
SQueuedEvent Event(sizeof(SHCIEventRequestConnection), 0);
@ -1137,8 +1117,6 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventConPacketTypeChange(u16 _conn
// Command dispatcher
// -----------------
// This is called from the USB_IOCTL_HCI_COMMAND_MESSAGE Ioctlv
//
//
void CWII_IPC_HLE_Device_usb_oh1_57e_305::ExecuteHCICommandMessage(const SHCICommandMessage& _rHCICommandMessage)
{
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 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);
}
}