mirror of
https://github.com/libretro/Play-.git
synced 2025-02-26 22:45:29 +00:00
276 lines
6.7 KiB
C++
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);
|
|
}
|