Play-/Source/iop/Iop_PadMan.cpp

276 lines
6.7 KiB
C++

#include <assert.h>
#include <stdio.h>
#include "Iop_PadMan.h"
#include "../Log.h"
#include "../RegisterStateFile.h"
#include "placeholder_def.h"
using namespace Iop;
using namespace PS2;
#define PADNUM (1)
#define MODE (0x7) //DUAL SHOCK
//#define MODE (0x4) //DIGITAL
#define LOG_NAME "iop_padman"
#define STATE_PADDATA ("iop_padman/paddata.xml")
#define STATE_PADDATA_ADDRESS ("address")
#define STATE_PADDATA_TYPE ("type")
CPadMan::CPadMan(CSifMan& sif)
: m_nPadDataAddress(0)
, m_nPadDataType(PAD_DATA_STD)
{
sif.RegisterModule(MODULE_ID_1, this);
sif.RegisterModule(MODULE_ID_2, this);
sif.RegisterModule(MODULE_ID_3, this);
sif.RegisterModule(MODULE_ID_4, this);
}
std::string CPadMan::GetId() const
{
return "padman";
}
std::string CPadMan::GetFunctionName(unsigned int) const
{
return "unknown";
}
void CPadMan::Invoke(CMIPS& context, unsigned int functionId)
{
throw std::runtime_error("Not implemented.");
}
bool CPadMan::Invoke(uint32 method, uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, uint8* ram)
{
assert(method == 1);
method = args[0];
switch(method)
{
case 0x00000001:
case 0x80000100:
Open(args, argsSize, ret, retSize, ram);
break;
case 0x00000008:
SetActuatorAlign(args, argsSize, ret, retSize, ram);
break;
case 0x00000010:
Init(args, argsSize, ret, retSize, ram);
break;
case 0x00000012:
GetModuleVersion(args, argsSize, ret, retSize, ram);
break;
default:
CLog::GetInstance().Print(LOG_NAME, "Unknown method invoked (0x%0.8X).\r\n", method);
break;
}
return true;
}
void CPadMan::SaveState(Framework::CZipArchiveWriter& archive)
{
CRegisterStateFile* registerFile = new CRegisterStateFile(STATE_PADDATA);
registerFile->SetRegister32(STATE_PADDATA_ADDRESS, m_nPadDataAddress);
registerFile->SetRegister32(STATE_PADDATA_TYPE, m_nPadDataType);
archive.InsertFile(registerFile);
}
void CPadMan::LoadState(Framework::CZipArchiveReader& archive)
{
CRegisterStateFile registerFile(*archive.BeginReadFile(STATE_PADDATA));
m_nPadDataAddress = registerFile.GetRegister32(STATE_PADDATA_ADDRESS);
m_nPadDataType = static_cast<PAD_DATA_TYPE>(registerFile.GetRegister32(STATE_PADDATA_TYPE));
}
void CPadMan::SetButtonState(unsigned int nPadNumber, CControllerInfo::BUTTON nButton, bool nPressed, uint8* ram)
{
if(m_nPadDataAddress == 0) return;
ExecutePadDataFunction(bind(&CPadMan::PDF_SetButtonState, PLACEHOLDER_1, nButton, nPressed),
ram + m_nPadDataAddress, PADNUM);
}
void CPadMan::SetAxisState(unsigned int padNumber, CControllerInfo::BUTTON button, uint8 axisValue, uint8* ram)
{
if(m_nPadDataAddress == 0) return;
ExecutePadDataFunction(std::bind(&CPadMan::PDF_SetAxisState, std::placeholders::_1, button, axisValue),
ram + m_nPadDataAddress, PADNUM);
}
void CPadMan::Open(uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, uint8* ram)
{
uint32 nPort = args[1];
uint32 nSlot = args[2];
uint32 nAddress = args[4];
CLog::GetInstance().Print(LOG_NAME, "Opening device on port %i and slot %i.\r\n", nPort, nSlot);
if(nPort == 0)
{
m_nPadDataAddress = nAddress;
m_nPadDataType = GetDataType(ram + m_nPadDataAddress);
CLog::GetInstance().Print(LOG_NAME, "Detected data type %d.\r\n", m_nPadDataType);
ExecutePadDataFunction(&CPadMan::PDF_InitializeStruct0, ram + m_nPadDataAddress, 0);
ExecutePadDataFunction(&CPadMan::PDF_InitializeStruct1, ram + m_nPadDataAddress, 1);
}
//Returns 0 on error
ret[3] = 0x00000001;
}
void CPadMan::SetActuatorAlign(uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, uint8* ram)
{
assert(retSize >= 24);
ret[5] = 1;
}
void CPadMan::Init(uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, uint8* ram)
{
assert(retSize >= 0x10);
CLog::GetInstance().Print(LOG_NAME, "Init();\r\n");
ret[3] = 1;
}
void CPadMan::GetModuleVersion(uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, uint8* ram)
{
assert(retSize >= 0x10);
CLog::GetInstance().Print(LOG_NAME, "GetModuleVersion();\r\n");
ret[3] = 0x00000400;
}
void CPadMan::ExecutePadDataFunction(const PadDataFunction& func, void* pBase, size_t nOffset)
{
switch(m_nPadDataType)
{
case PAD_DATA_STD:
{
CPadDataHandler<PADDATA> padData(reinterpret_cast<PADDATA*>(pBase) + nOffset);
func(&padData);
}
break;
case PAD_DATA_STD80:
{
CPadDataHandler<PADDATA80> padData(reinterpret_cast<PADDATA80*>(pBase) + nOffset);
func(&padData);
}
break;
case PAD_DATA_EX:
{
CPadDataHandler<PADDATAEX> padData(reinterpret_cast<PADDATAEX*>(pBase) + nOffset);
func(&padData);
}
break;
}
}
CPadMan::PAD_DATA_TYPE CPadMan::GetDataType(uint8* dataAddress)
{
PAD_DATA_TYPE result = PAD_DATA_STD;
if((dataAddress[0x08] == 0xFF) && (dataAddress[0x48] == 0xFF))
{
result = PAD_DATA_STD;
}
if((dataAddress[0x08] == 0xFF) && (dataAddress[0x88] == 0xFF))
{
result = PAD_DATA_STD80;
}
if((dataAddress[0x00] == 0xFF) && (dataAddress[0x80] == 0xFF))
{
result = PAD_DATA_EX;
}
return result;
}
void CPadMan::PDF_InitializeStruct0(CPadDataInterface* pPadData)
{
pPadData->SetFrame(0);
pPadData->SetState(6);
pPadData->SetReqState(0);
pPadData->SetLength(32);
pPadData->SetOk(1);
//Reset analog sticks
for(unsigned int i = 0; i < 4; i++)
{
pPadData->SetData(4 + i, 0x7F);
}
}
void CPadMan::PDF_InitializeStruct1(CPadDataInterface* pPadData)
{
pPadData->SetFrame(1);
pPadData->SetState(6);
pPadData->SetReqState(0);
pPadData->SetLength(32);
pPadData->SetOk(1);
//Reset analog sticks
for(unsigned int i = 0; i < 4; i++)
{
pPadData->SetData(4 + i, 0x7F);
}
//EX struct initialization
pPadData->SetModeCurId(MODE << 4);
pPadData->SetModeCurOffset(0);
pPadData->SetModeTable(0, MODE);
pPadData->SetNumberOfModes(4);
}
void CPadMan::PDF_SetButtonState(CPadDataInterface* pPadData, CControllerInfo::BUTTON nButton, bool nPressed)
{
uint16 nStatus = (pPadData->GetData(2) << 8) | (pPadData->GetData(3));
uint32 buttonMask = GetButtonMask(nButton);
nStatus &= ~buttonMask;
if(!nPressed)
{
nStatus |= buttonMask;
}
pPadData->SetReqState(0);
pPadData->SetData(2, static_cast<uint8>(nStatus >> 8));
pPadData->SetData(3, static_cast<uint8>(nStatus >> 0));
pPadData->SetData(0, 0);
pPadData->SetData(1, MODE << 4);
}
void CPadMan::PDF_SetAxisState(CPadDataInterface* padData, CControllerInfo::BUTTON axis, uint8 axisValue)
{
//rjoy_h 4;
//rjoy_v 5;
//ljoy_h 6;
//ljoy_v 7;
assert(axis < 4);
unsigned int axisIndex[4] =
{
6,
7,
4,
5
};
padData->SetReqState(0);
padData->SetData(axisIndex[axis], axisValue);
padData->SetData(0, 0);
padData->SetData(1, MODE << 4);
}