commit
d9d0e285c9
|
@ -64,68 +64,18 @@ void GetStatus(u8 _numPAD, GCPadStatus* _pPADStatus)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we are on the next input cycle, update output and input
|
|
||||||
// if we can get a lock
|
|
||||||
static int _last_numPAD = 4;
|
|
||||||
if (_numPAD <= _last_numPAD)
|
|
||||||
{
|
|
||||||
g_controller_interface.UpdateOutput();
|
|
||||||
g_controller_interface.UpdateInput();
|
|
||||||
}
|
|
||||||
_last_numPAD = _numPAD;
|
|
||||||
|
|
||||||
// get input
|
// get input
|
||||||
((GCPad*)s_config.controllers[_numPAD])->GetInput(_pPADStatus);
|
((GCPad*)s_config.controllers[_numPAD])->GetInput(_pPADStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
// __________________________________________________________________________________________________
|
void Rumble(u8 _numPAD, const ControlState strength)
|
||||||
// Function: Rumble
|
|
||||||
// Purpose: Pad rumble!
|
|
||||||
// input: _numPad - Which pad to rumble.
|
|
||||||
// _uType - Command type (Stop=0, Rumble=1, Stop Hard=2).
|
|
||||||
// _uStrength - Strength of the Rumble
|
|
||||||
// output: none
|
|
||||||
//
|
|
||||||
void Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength)
|
|
||||||
{
|
{
|
||||||
std::unique_lock<std::recursive_mutex> lk(s_config.controls_lock, std::try_to_lock);
|
std::unique_lock<std::recursive_mutex> lk(s_config.controls_lock, std::try_to_lock);
|
||||||
|
|
||||||
if (lk.owns_lock())
|
if (!lk.owns_lock())
|
||||||
{
|
return;
|
||||||
// TODO: this has potential to not stop rumble if user is messing with GUI at the perfect time
|
|
||||||
// set rumble
|
|
||||||
if (1 == _uType && _uStrength > 2)
|
|
||||||
{
|
|
||||||
((GCPad*)s_config.controllers[ _numPAD ])->SetOutput(255);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
((GCPad*)s_config.controllers[ _numPAD ])->SetOutput(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// __________________________________________________________________________________________________
|
((GCPad*)s_config.controllers[ _numPAD ])->SetOutput(strength);
|
||||||
// Function: Motor
|
|
||||||
// Purpose: For devices with constant Force feedback
|
|
||||||
// input: _numPAD - The pad to operate on
|
|
||||||
// _uType - 06 = Motor On, 04 = Motor Off
|
|
||||||
// _uStrength - 00 = Left Strong, 127 = Left Weak, 128 = Right Weak, 255 = Right Strong
|
|
||||||
// output: none
|
|
||||||
//
|
|
||||||
void Motor(u8 _numPAD, unsigned int _uType, unsigned int _uStrength)
|
|
||||||
{
|
|
||||||
std::unique_lock<std::recursive_mutex> lk(s_config.controls_lock, std::try_to_lock);
|
|
||||||
|
|
||||||
if (lk.owns_lock())
|
|
||||||
{
|
|
||||||
// TODO: this has potential to not stop rumble if user is messing with GUI at the perfect time
|
|
||||||
// set rumble
|
|
||||||
if (_uType == 6)
|
|
||||||
{
|
|
||||||
((GCPad*)s_config.controllers[ _numPAD ])->SetMotor(_uStrength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetMicButton(u8 pad)
|
bool GetMicButton(u8 pad)
|
||||||
|
|
|
@ -17,8 +17,7 @@ void Initialize(void* const hwnd);
|
||||||
InputConfig* GetConfig();
|
InputConfig* GetConfig();
|
||||||
|
|
||||||
void GetStatus(u8 _numPAD, GCPadStatus* _pPADStatus);
|
void GetStatus(u8 _numPAD, GCPadStatus* _pPADStatus);
|
||||||
void Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength);
|
void Rumble(u8 _numPAD, const ControlState strength);
|
||||||
void Motor(u8 _numPAD, unsigned int _uType, unsigned int _uStrength);
|
|
||||||
|
|
||||||
bool GetMicButton(u8 pad);
|
bool GetMicButton(u8 pad);
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,16 +120,9 @@ void GCPad::GetInput(GCPadStatus* const pad)
|
||||||
pad->triggerRight = static_cast<u8>(triggers[1] * 0xFF);
|
pad->triggerRight = static_cast<u8>(triggers[1] * 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCPad::SetMotor(const u8 on)
|
void GCPad::SetOutput(const ControlState strength)
|
||||||
{
|
{
|
||||||
// map 0..255 to -1.0..1.0
|
m_rumble->controls[0]->control_ref->State(strength);
|
||||||
ControlState force = on / 127.5 - 1;
|
|
||||||
m_rumble->controls[0]->control_ref->State(force);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GCPad::SetOutput(const u8 on)
|
|
||||||
{
|
|
||||||
m_rumble->controls[0]->control_ref->State(on);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCPad::LoadDefaults(const ControllerInterface& ciface)
|
void GCPad::LoadDefaults(const ControllerInterface& ciface)
|
||||||
|
|
|
@ -14,8 +14,7 @@ public:
|
||||||
|
|
||||||
GCPad(const unsigned int index);
|
GCPad(const unsigned int index);
|
||||||
void GetInput(GCPadStatus* const pad);
|
void GetInput(GCPadStatus* const pad);
|
||||||
void SetOutput(const u8 on);
|
void SetOutput(const ControlState strength);
|
||||||
void SetMotor(const u8 on);
|
|
||||||
|
|
||||||
bool GetMicButton() const;
|
bool GetMicButton() const;
|
||||||
|
|
||||||
|
|
|
@ -2,250 +2,40 @@
|
||||||
// Licensed under GPLv2
|
// Licensed under GPLv2
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "Core/Core.h"
|
|
||||||
#include "Core/CoreTiming.h"
|
|
||||||
#include "Core/Movie.h"
|
|
||||||
#include "Core/HW/EXI_Device.h"
|
|
||||||
#include "Core/HW/EXI_DeviceMic.h"
|
|
||||||
#include "Core/HW/GCPad.h"
|
|
||||||
#include "Core/HW/ProcessorInterface.h"
|
|
||||||
#include "Core/HW/SI.h"
|
|
||||||
#include "Core/HW/SI_Device.h"
|
|
||||||
#include "Core/HW/SI_DeviceDanceMat.h"
|
#include "Core/HW/SI_DeviceDanceMat.h"
|
||||||
#include "Core/HW/SystemTimers.h"
|
|
||||||
|
|
||||||
// --- Dance mat GameCube controller ---
|
|
||||||
CSIDevice_DanceMat::CSIDevice_DanceMat(SIDevices device, int _iDeviceNumber)
|
CSIDevice_DanceMat::CSIDevice_DanceMat(SIDevices device, int _iDeviceNumber)
|
||||||
: ISIDevice(device, _iDeviceNumber)
|
: CSIDevice_GCController(device, _iDeviceNumber) {}
|
||||||
, m_TButtonComboStart(0)
|
|
||||||
, m_TButtonCombo(0)
|
|
||||||
, m_LastButtonCombo(COMBO_NONE)
|
|
||||||
{
|
|
||||||
memset(&m_Origin, 0, sizeof(SOrigin));
|
|
||||||
m_Origin.uCommand = CMD_ORIGIN;
|
|
||||||
m_Origin.uOriginStickX = 0x80; // center
|
|
||||||
m_Origin.uOriginStickY = 0x80;
|
|
||||||
m_Origin.uSubStickStickX = 0x80;
|
|
||||||
m_Origin.uSubStickStickY = 0x80;
|
|
||||||
m_Origin.uTrigger_L = 0x00;
|
|
||||||
m_Origin.uTrigger_R = 0x00;
|
|
||||||
|
|
||||||
// Dunno if we need to do this, game/lib should set it?
|
u32 CSIDevice_DanceMat::MapPadStatus(const GCPadStatus& pad_status)
|
||||||
m_Mode = 0x03;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CSIDevice_DanceMat::RunBuffer(u8* _pBuffer, int _iLength)
|
|
||||||
{
|
{
|
||||||
// For debug logging only
|
|
||||||
ISIDevice::RunBuffer(_pBuffer, _iLength);
|
|
||||||
|
|
||||||
// Read the command
|
|
||||||
EBufferCommands command = static_cast<EBufferCommands>(_pBuffer[3]);
|
|
||||||
|
|
||||||
// Handle it
|
|
||||||
switch (command)
|
|
||||||
{
|
|
||||||
case CMD_RESET:
|
|
||||||
*(u32*)&_pBuffer[0] = SI_DANCEMAT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CMD_DIRECT:
|
|
||||||
{
|
|
||||||
INFO_LOG(SERIALINTERFACE, "PAD - Direct (Length: %d)", _iLength);
|
|
||||||
u32 high, low;
|
|
||||||
GetData(high, low);
|
|
||||||
for (int i = 0; i < (_iLength - 1) / 2; i++)
|
|
||||||
{
|
|
||||||
_pBuffer[i + 0] = (high >> (i * 8)) & 0xff;
|
|
||||||
_pBuffer[i + 4] = (low >> (i * 8)) & 0xff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CMD_ORIGIN:
|
|
||||||
{
|
|
||||||
INFO_LOG(SERIALINTERFACE, "PAD - Get Origin");
|
|
||||||
u8* pCalibration = reinterpret_cast<u8*>(&m_Origin);
|
|
||||||
for (int i = 0; i < (int)sizeof(SOrigin); i++)
|
|
||||||
{
|
|
||||||
_pBuffer[i ^ 3] = *pCalibration++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Recalibrate (FiRES: i am not 100 percent sure about this)
|
|
||||||
case CMD_RECALIBRATE:
|
|
||||||
{
|
|
||||||
INFO_LOG(SERIALINTERFACE, "PAD - Recalibrate");
|
|
||||||
u8* pCalibration = reinterpret_cast<u8*>(&m_Origin);
|
|
||||||
for (int i = 0; i < (int)sizeof(SOrigin); i++)
|
|
||||||
{
|
|
||||||
_pBuffer[i ^ 3] = *pCalibration++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// DEFAULT
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
ERROR_LOG(SERIALINTERFACE, "Unknown SI command (0x%x)", command);
|
|
||||||
PanicAlert("SI: Unknown command (0x%x)", command);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _iLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// GetData
|
|
||||||
|
|
||||||
// Return true on new data (max 7 Bytes and 6 bits ;)
|
|
||||||
// [00?SYXBA] [1LRZUDRL] [x] [y] [cx] [cy] [l] [r]
|
|
||||||
// |\_ ERR_LATCH (error latched - check SISR)
|
|
||||||
// |_ ERR_STATUS (error on last GetData or SendCmd?)
|
|
||||||
bool CSIDevice_DanceMat::GetData(u32& _Hi, u32& _Low)
|
|
||||||
{
|
|
||||||
GCPadStatus PadStatus;
|
|
||||||
memset(&PadStatus, 0, sizeof(PadStatus));
|
|
||||||
|
|
||||||
Pad::GetStatus(ISIDevice::m_iDeviceNumber, &PadStatus);
|
|
||||||
Movie::CallGCInputManip(&PadStatus, ISIDevice::m_iDeviceNumber);
|
|
||||||
|
|
||||||
Movie::SetPolledDevice();
|
|
||||||
if (NetPlay_GetInput(ISIDevice::m_iDeviceNumber, &PadStatus))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else if (Movie::IsPlayingInput())
|
|
||||||
{
|
|
||||||
Movie::PlayController(&PadStatus, ISIDevice::m_iDeviceNumber);
|
|
||||||
Movie::InputUpdate();
|
|
||||||
}
|
|
||||||
else if (Movie::IsRecordingInput())
|
|
||||||
{
|
|
||||||
Movie::RecordInput(&PadStatus, ISIDevice::m_iDeviceNumber);
|
|
||||||
Movie::InputUpdate();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Movie::CheckPadStatus(&PadStatus, ISIDevice::m_iDeviceNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map the dpad to the blue arrows, the buttons to the orange arrows
|
// Map the dpad to the blue arrows, the buttons to the orange arrows
|
||||||
// Z = + button, Start = - button
|
// Z = + button, Start = - button
|
||||||
u16 map = 0;
|
u16 map = 0;
|
||||||
if (PadStatus.button & PAD_BUTTON_UP)
|
if (pad_status.button & PAD_BUTTON_UP)
|
||||||
map |= 0x1000;
|
map |= 0x1000;
|
||||||
if (PadStatus.button & PAD_BUTTON_DOWN)
|
if (pad_status.button & PAD_BUTTON_DOWN)
|
||||||
map |= 0x2;
|
map |= 0x2;
|
||||||
if (PadStatus.button & PAD_BUTTON_LEFT)
|
if (pad_status.button & PAD_BUTTON_LEFT)
|
||||||
map |= 0x8;
|
map |= 0x8;
|
||||||
if (PadStatus.button & PAD_BUTTON_RIGHT)
|
if (pad_status.button & PAD_BUTTON_RIGHT)
|
||||||
map |= 0x4;
|
map |= 0x4;
|
||||||
if (PadStatus.button & PAD_BUTTON_Y)
|
if (pad_status.button & PAD_BUTTON_Y)
|
||||||
map |= 0x200;
|
map |= 0x200;
|
||||||
if (PadStatus.button & PAD_BUTTON_A)
|
if (pad_status.button & PAD_BUTTON_A)
|
||||||
map |= 0x10;
|
map |= 0x10;
|
||||||
if (PadStatus.button & PAD_BUTTON_B)
|
if (pad_status.button & PAD_BUTTON_B)
|
||||||
map |= 0x100;
|
map |= 0x100;
|
||||||
if (PadStatus.button & PAD_BUTTON_X)
|
if (pad_status.button & PAD_BUTTON_X)
|
||||||
map |= 0x800;
|
map |= 0x800;
|
||||||
if (PadStatus.button & PAD_TRIGGER_Z)
|
if (pad_status.button & PAD_TRIGGER_Z)
|
||||||
map |= 0x400;
|
map |= 0x400;
|
||||||
if (PadStatus.button & PAD_BUTTON_START)
|
if (pad_status.button & PAD_BUTTON_START)
|
||||||
map |= 0x1;
|
map |= 0x1;
|
||||||
|
|
||||||
_Hi = (u32)(map << 16) | 0x8080;
|
return (u32)(map << 16) | 0x8080;
|
||||||
|
|
||||||
// Low bits are packed differently per mode
|
|
||||||
if (m_Mode == 0 || m_Mode == 5 || m_Mode == 6 || m_Mode == 7)
|
|
||||||
{
|
|
||||||
_Low = (u8)(PadStatus.analogB >> 4); // Top 4 bits
|
|
||||||
_Low |= (u32)((u8)(PadStatus.analogA >> 4) << 4); // Top 4 bits
|
|
||||||
_Low |= (u32)((u8)(PadStatus.triggerRight >> 4) << 8); // Top 4 bits
|
|
||||||
_Low |= (u32)((u8)(PadStatus.triggerLeft >> 4) << 12); // Top 4 bits
|
|
||||||
_Low |= (u32)((u8)(PadStatus.substickY) << 16); // All 8 bits
|
|
||||||
_Low |= (u32)((u8)(PadStatus.substickX) << 24); // All 8 bits
|
|
||||||
}
|
|
||||||
else if (m_Mode == 1)
|
|
||||||
{
|
|
||||||
_Low = (u8)(PadStatus.analogB >> 4); // Top 4 bits
|
|
||||||
_Low |= (u32)((u8)(PadStatus.analogA >> 4) << 4); // Top 4 bits
|
|
||||||
_Low |= (u32)((u8)PadStatus.triggerRight << 8); // All 8 bits
|
|
||||||
_Low |= (u32)((u8)PadStatus.triggerLeft << 16); // All 8 bits
|
|
||||||
_Low |= (u32)((u8)PadStatus.substickY << 24); // Top 4 bits
|
|
||||||
_Low |= (u32)((u8)PadStatus.substickX << 28); // Top 4 bits
|
|
||||||
}
|
|
||||||
else if (m_Mode == 2)
|
|
||||||
{
|
|
||||||
// Identifies the dance mat
|
|
||||||
_Low = 0x8080ffff;
|
|
||||||
}
|
|
||||||
else if (m_Mode == 3)
|
|
||||||
{
|
|
||||||
// Analog A/B are always 0
|
|
||||||
_Low = (u8)PadStatus.triggerRight; // All 8 bits
|
|
||||||
_Low |= (u32)((u8)PadStatus.triggerLeft << 8); // All 8 bits
|
|
||||||
_Low |= (u32)((u8)PadStatus.substickY << 16); // All 8 bits
|
|
||||||
_Low |= (u32)((u8)PadStatus.substickX << 24); // All 8 bits
|
|
||||||
}
|
|
||||||
else if (m_Mode == 4)
|
|
||||||
{
|
|
||||||
_Low = (u8)(PadStatus.analogB); // All 8 bits
|
|
||||||
_Low |= (u32)((u8)(PadStatus.analogA) << 8); // All 8 bits
|
|
||||||
// triggerLeft/Right are always 0
|
|
||||||
_Low |= (u32)((u8)PadStatus.substickY << 16); // All 8 bits
|
|
||||||
_Low |= (u32)((u8)PadStatus.substickX << 24); // All 8 bits
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSIDevice_DanceMat::HandleButtonCombos(const GCPadStatus& pad_status)
|
||||||
// SendCommand
|
|
||||||
void CSIDevice_DanceMat::SendCommand(u32 _Cmd, u8 _Poll)
|
|
||||||
{
|
{
|
||||||
UCommand command(_Cmd);
|
|
||||||
|
|
||||||
switch (command.Command)
|
|
||||||
{
|
|
||||||
// Costis sent it in some demos :)
|
|
||||||
case 0x00:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CMD_WRITE:
|
|
||||||
{
|
|
||||||
unsigned int uType = command.Parameter1; // 0 = stop, 1 = rumble, 2 = stop hard
|
|
||||||
unsigned int uStrength = command.Parameter2;
|
|
||||||
|
|
||||||
// get the correct pad number that should rumble locally when using netplay
|
|
||||||
const u8 numPAD = NetPlay_InGamePadToLocalPad(ISIDevice::m_iDeviceNumber);
|
|
||||||
|
|
||||||
if (numPAD < 4)
|
|
||||||
Pad::Rumble(numPAD, uType, uStrength);
|
|
||||||
|
|
||||||
if (!_Poll)
|
|
||||||
{
|
|
||||||
m_Mode = command.Parameter2;
|
|
||||||
INFO_LOG(SERIALINTERFACE, "PAD %i set to mode %i", ISIDevice::m_iDeviceNumber, m_Mode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
ERROR_LOG(SERIALINTERFACE, "Unknown direct command (0x%x)", _Cmd);
|
|
||||||
PanicAlert("SI: Unknown direct command");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Savestate support
|
|
||||||
void CSIDevice_DanceMat::DoState(PointerWrap& p)
|
|
||||||
{
|
|
||||||
p.Do(m_Origin);
|
|
||||||
p.Do(m_Mode);
|
|
||||||
p.Do(m_TButtonComboStart);
|
|
||||||
p.Do(m_TButtonCombo);
|
|
||||||
p.Do(m_LastButtonCombo);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,98 +4,12 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Core/HW/SI_Device.h"
|
#include "Core/HW/SI_DeviceGCController.h"
|
||||||
#include "InputCommon/GCPadStatus.h"
|
|
||||||
|
|
||||||
// standard GameCube controller
|
class CSIDevice_DanceMat : public CSIDevice_GCController
|
||||||
class CSIDevice_DanceMat : public ISIDevice
|
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
|
|
||||||
// Commands
|
|
||||||
enum EBufferCommands
|
|
||||||
{
|
|
||||||
CMD_RESET = 0x00,
|
|
||||||
CMD_DIRECT = 0x40,
|
|
||||||
CMD_ORIGIN = 0x41,
|
|
||||||
CMD_RECALIBRATE = 0x42,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SOrigin
|
|
||||||
{
|
|
||||||
u8 uCommand;// Maybe should be button bits?
|
|
||||||
u8 unk_1; // ..and this would be the other half
|
|
||||||
u8 uOriginStickX;
|
|
||||||
u8 uOriginStickY;
|
|
||||||
u8 uSubStickStickX;
|
|
||||||
u8 uSubStickStickY;
|
|
||||||
u8 uTrigger_L;
|
|
||||||
u8 uTrigger_R;
|
|
||||||
u8 unk_4;
|
|
||||||
u8 unk_5;
|
|
||||||
u8 unk_6;
|
|
||||||
u8 unk_7;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum EDirectCommands
|
|
||||||
{
|
|
||||||
CMD_WRITE = 0x40
|
|
||||||
};
|
|
||||||
|
|
||||||
union UCommand
|
|
||||||
{
|
|
||||||
u32 Hex;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
u32 Parameter1 : 8;
|
|
||||||
u32 Parameter2 : 8;
|
|
||||||
u32 Command : 8;
|
|
||||||
u32 : 8;
|
|
||||||
};
|
|
||||||
UCommand() {Hex = 0;}
|
|
||||||
UCommand(u32 _iValue) {Hex = _iValue;}
|
|
||||||
};
|
|
||||||
|
|
||||||
enum EButtonCombo
|
|
||||||
{
|
|
||||||
COMBO_NONE = 0,
|
|
||||||
COMBO_ORIGIN,
|
|
||||||
COMBO_RESET
|
|
||||||
};
|
|
||||||
|
|
||||||
// struct to compare input against
|
|
||||||
// Set on connection and (standard pad only) on button combo
|
|
||||||
SOrigin m_Origin;
|
|
||||||
|
|
||||||
// PADAnalogMode
|
|
||||||
u8 m_Mode;
|
|
||||||
|
|
||||||
// Timer to track special button combos:
|
|
||||||
// y, X, start for 3 seconds updates origin with current status
|
|
||||||
// Technically, the above is only on standard pad, wavebird does not support it for example
|
|
||||||
// b, x, start for 3 seconds triggers reset (PI reset button interrupt)
|
|
||||||
u64 m_TButtonComboStart, m_TButtonCombo;
|
|
||||||
// Type of button combo from the last/current poll
|
|
||||||
EButtonCombo m_LastButtonCombo;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Constructor
|
|
||||||
CSIDevice_DanceMat(SIDevices device, int _iDeviceNumber);
|
CSIDevice_DanceMat(SIDevices device, int _iDeviceNumber);
|
||||||
|
virtual u32 MapPadStatus(const GCPadStatus& pad_status) override;
|
||||||
// Run the SI Buffer
|
virtual void HandleButtonCombos(const GCPadStatus& pad_status) override;
|
||||||
virtual int RunBuffer(u8* _pBuffer, int _iLength) override;
|
|
||||||
|
|
||||||
// Send and Receive pad input from network
|
|
||||||
static bool NetPlay_GetInput(u8 numPAD, GCPadStatus* status);
|
|
||||||
static u8 NetPlay_InGamePadToLocalPad(u8 numPAD);
|
|
||||||
|
|
||||||
// Return true on new data
|
|
||||||
virtual bool GetData(u32& _Hi, u32& _Low) override;
|
|
||||||
|
|
||||||
// Send a command directly
|
|
||||||
virtual void SendCommand(u32 _Cmd, u8 _Poll) override;
|
|
||||||
|
|
||||||
// Savestate support
|
|
||||||
virtual void DoState(PointerWrap& p) override;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -131,10 +131,7 @@ bool CSIDevice_GCController::GetData(u32& _Hi, u32& _Low)
|
||||||
Movie::CheckPadStatus(&PadStatus, ISIDevice::m_iDeviceNumber);
|
Movie::CheckPadStatus(&PadStatus, ISIDevice::m_iDeviceNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Thankfully changing mode does not change the high bits ;)
|
_Hi = MapPadStatus(PadStatus);
|
||||||
_Hi = (u32)((u8)PadStatus.stickY);
|
|
||||||
_Hi |= (u32)((u8)PadStatus.stickX << 8);
|
|
||||||
_Hi |= (u32)((u16)(PadStatus.button | PAD_USE_ORIGIN) << 16);
|
|
||||||
|
|
||||||
// Low bits are packed differently per mode
|
// Low bits are packed differently per mode
|
||||||
if (m_Mode == 0 || m_Mode == 5 || m_Mode == 6 || m_Mode == 7)
|
if (m_Mode == 0 || m_Mode == 5 || m_Mode == 6 || m_Mode == 7)
|
||||||
|
@ -181,11 +178,27 @@ bool CSIDevice_GCController::GetData(u32& _Hi, u32& _Low)
|
||||||
_Low |= (u32)((u8)PadStatus.substickX << 24); // All 8 bits
|
_Low |= (u32)((u8)PadStatus.substickX << 24); // All 8 bits
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HandleButtonCombos(PadStatus);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 CSIDevice_GCController::MapPadStatus(const GCPadStatus& pad_status)
|
||||||
|
{
|
||||||
|
// Thankfully changing mode does not change the high bits ;)
|
||||||
|
u32 _Hi = 0;
|
||||||
|
_Hi = (u32)((u8)pad_status.stickY);
|
||||||
|
_Hi |= (u32)((u8)pad_status.stickX << 8);
|
||||||
|
_Hi |= (u32)((u16)(pad_status.button | PAD_USE_ORIGIN) << 16);
|
||||||
|
return _Hi;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSIDevice_GCController::HandleButtonCombos(const GCPadStatus& pad_status)
|
||||||
|
{
|
||||||
// Keep track of the special button combos (embedded in controller hardware... :( )
|
// Keep track of the special button combos (embedded in controller hardware... :( )
|
||||||
EButtonCombo tempCombo;
|
EButtonCombo tempCombo;
|
||||||
if ((PadStatus.button & 0xff00) == (PAD_BUTTON_Y|PAD_BUTTON_X|PAD_BUTTON_START))
|
if ((pad_status.button & 0xff00) == (PAD_BUTTON_Y|PAD_BUTTON_X|PAD_BUTTON_START))
|
||||||
tempCombo = COMBO_ORIGIN;
|
tempCombo = COMBO_ORIGIN;
|
||||||
else if ((PadStatus.button & 0xff00) == (PAD_BUTTON_B|PAD_BUTTON_X|PAD_BUTTON_START))
|
else if ((pad_status.button & 0xff00) == (PAD_BUTTON_B|PAD_BUTTON_X|PAD_BUTTON_START))
|
||||||
tempCombo = COMBO_RESET;
|
tempCombo = COMBO_RESET;
|
||||||
else
|
else
|
||||||
tempCombo = COMBO_NONE;
|
tempCombo = COMBO_NONE;
|
||||||
|
@ -204,21 +217,18 @@ bool CSIDevice_GCController::GetData(u32& _Hi, u32& _Low)
|
||||||
ProcessorInterface::ResetButton_Tap();
|
ProcessorInterface::ResetButton_Tap();
|
||||||
else if (m_LastButtonCombo == COMBO_ORIGIN)
|
else if (m_LastButtonCombo == COMBO_ORIGIN)
|
||||||
{
|
{
|
||||||
m_Origin.uOriginStickX = PadStatus.stickX;
|
m_Origin.uOriginStickX = pad_status.stickX;
|
||||||
m_Origin.uOriginStickY = PadStatus.stickY;
|
m_Origin.uOriginStickY = pad_status.stickY;
|
||||||
m_Origin.uSubStickStickX = PadStatus.substickX;
|
m_Origin.uSubStickStickX = pad_status.substickX;
|
||||||
m_Origin.uSubStickStickY = PadStatus.substickY;
|
m_Origin.uSubStickStickY = pad_status.substickY;
|
||||||
m_Origin.uTrigger_L = PadStatus.triggerLeft;
|
m_Origin.uTrigger_L = pad_status.triggerLeft;
|
||||||
m_Origin.uTrigger_R = PadStatus.triggerRight;
|
m_Origin.uTrigger_R = pad_status.triggerRight;
|
||||||
}
|
}
|
||||||
m_LastButtonCombo = COMBO_NONE;
|
m_LastButtonCombo = COMBO_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// SendCommand
|
// SendCommand
|
||||||
void CSIDevice_GCController::SendCommand(u32 _Cmd, u8 _Poll)
|
void CSIDevice_GCController::SendCommand(u32 _Cmd, u8 _Poll)
|
||||||
{
|
{
|
||||||
|
@ -239,7 +249,12 @@ void CSIDevice_GCController::SendCommand(u32 _Cmd, u8 _Poll)
|
||||||
const u8 numPAD = NetPlay_InGamePadToLocalPad(ISIDevice::m_iDeviceNumber);
|
const u8 numPAD = NetPlay_InGamePadToLocalPad(ISIDevice::m_iDeviceNumber);
|
||||||
|
|
||||||
if (numPAD < 4)
|
if (numPAD < 4)
|
||||||
Pad::Rumble(numPAD, uType, uStrength);
|
{
|
||||||
|
if (uType == 1 && uStrength > 2)
|
||||||
|
Pad::Rumble(numPAD, 1.0);
|
||||||
|
else
|
||||||
|
Pad::Rumble(numPAD, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
if (!_Poll)
|
if (!_Poll)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,11 +7,9 @@
|
||||||
#include "Core/HW/SI_Device.h"
|
#include "Core/HW/SI_Device.h"
|
||||||
#include "InputCommon/GCPadStatus.h"
|
#include "InputCommon/GCPadStatus.h"
|
||||||
|
|
||||||
|
|
||||||
// standard GameCube controller
|
|
||||||
class CSIDevice_GCController : public ISIDevice
|
class CSIDevice_GCController : public ISIDevice
|
||||||
{
|
{
|
||||||
private:
|
protected:
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
enum EBufferCommands
|
enum EBufferCommands
|
||||||
|
@ -94,6 +92,9 @@ public:
|
||||||
// Return true on new data
|
// Return true on new data
|
||||||
virtual bool GetData(u32& _Hi, u32& _Low) override;
|
virtual bool GetData(u32& _Hi, u32& _Low) override;
|
||||||
|
|
||||||
|
virtual u32 MapPadStatus(const GCPadStatus& pad_status);
|
||||||
|
virtual void HandleButtonCombos(const GCPadStatus& pad_status);
|
||||||
|
|
||||||
// Send a command directly
|
// Send a command directly
|
||||||
virtual void SendCommand(u32 _Cmd, u8 _Poll) override;
|
virtual void SendCommand(u32 _Cmd, u8 _Poll) override;
|
||||||
|
|
||||||
|
|
|
@ -2,241 +2,18 @@
|
||||||
// Licensed under GPLv2
|
// Licensed under GPLv2
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
|
||||||
#include "Core/Core.h"
|
|
||||||
#include "Core/CoreTiming.h"
|
|
||||||
#include "Core/Movie.h"
|
|
||||||
#include "Core/HW/EXI_Device.h"
|
|
||||||
#include "Core/HW/EXI_DeviceMic.h"
|
|
||||||
#include "Core/HW/GCPad.h"
|
#include "Core/HW/GCPad.h"
|
||||||
#include "Core/HW/ProcessorInterface.h"
|
|
||||||
#include "Core/HW/SI.h"
|
|
||||||
#include "Core/HW/SI_Device.h"
|
|
||||||
#include "Core/HW/SI_DeviceGCSteeringWheel.h"
|
#include "Core/HW/SI_DeviceGCSteeringWheel.h"
|
||||||
#include "Core/HW/SystemTimers.h"
|
|
||||||
|
|
||||||
// --- standard GameCube controller ---
|
|
||||||
CSIDevice_GCSteeringWheel::CSIDevice_GCSteeringWheel(SIDevices device, int _iDeviceNumber)
|
CSIDevice_GCSteeringWheel::CSIDevice_GCSteeringWheel(SIDevices device, int _iDeviceNumber)
|
||||||
: ISIDevice(device, _iDeviceNumber)
|
: CSIDevice_GCController(device, _iDeviceNumber)
|
||||||
, m_TButtonComboStart(0)
|
{}
|
||||||
, m_TButtonCombo(0)
|
|
||||||
, m_LastButtonCombo(COMBO_NONE)
|
|
||||||
{
|
|
||||||
memset(&m_Origin, 0, sizeof(SOrigin));
|
|
||||||
m_Origin.uCommand = CMD_ORIGIN;
|
|
||||||
m_Origin.uOriginStickX = 0x80; // center
|
|
||||||
m_Origin.uOriginStickY = 0x80;
|
|
||||||
m_Origin.uSubStickStickX = 0x80;
|
|
||||||
m_Origin.uSubStickStickY = 0x80;
|
|
||||||
m_Origin.uTrigger_L = 0x1F; // 0-30 is the lower deadzone
|
|
||||||
m_Origin.uTrigger_R = 0x1F;
|
|
||||||
|
|
||||||
// Dunno if we need to do this, game/lib should set it?
|
|
||||||
m_Mode = 0x03;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CSIDevice_GCSteeringWheel::RunBuffer(u8* _pBuffer, int _iLength)
|
|
||||||
{
|
|
||||||
// For debug logging only
|
|
||||||
ISIDevice::RunBuffer(_pBuffer, _iLength);
|
|
||||||
|
|
||||||
// Read the command
|
|
||||||
EBufferCommands command = static_cast<EBufferCommands>(_pBuffer[3]);
|
|
||||||
|
|
||||||
// Handle it
|
|
||||||
switch (command)
|
|
||||||
{
|
|
||||||
case CMD_RESET:
|
|
||||||
*(u32*)&_pBuffer[0] = SI_GC_STEERING;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CMD_ORIGIN:
|
|
||||||
{
|
|
||||||
INFO_LOG(SERIALINTERFACE, "PAD - Get Origin");
|
|
||||||
u8* pCalibration = reinterpret_cast<u8*>(&m_Origin);
|
|
||||||
for (int i = 0; i < (int)sizeof(SOrigin); i++)
|
|
||||||
{
|
|
||||||
_pBuffer[i ^ 3] = *pCalibration++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Recalibrate (FiRES: i am not 100 percent sure about this)
|
|
||||||
case CMD_RECALIBRATE:
|
|
||||||
{
|
|
||||||
INFO_LOG(SERIALINTERFACE, "PAD - Recalibrate");
|
|
||||||
u8* pCalibration = reinterpret_cast<u8*>(&m_Origin);
|
|
||||||
for (int i = 0; i < (int)sizeof(SOrigin); i++)
|
|
||||||
{
|
|
||||||
_pBuffer[i ^ 3] = *pCalibration++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Seen in F-Zero GX
|
|
||||||
case CMD_MOTOR_OFF:
|
|
||||||
break;
|
|
||||||
|
|
||||||
// DEFAULT
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
ERROR_LOG(SERIALINTERFACE, "Unknown SI command (0x%x)", command);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _iLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// GetData
|
|
||||||
|
|
||||||
// Return true on new data (max 7 Bytes and 6 bits ;)
|
|
||||||
// [00?SYXBA] [1LRZUDRL] [x] [y] [cx] [cy] [l] [r]
|
|
||||||
// |\_ ERR_LATCH (error latched - check SISR)
|
|
||||||
// |_ ERR_STATUS (error on last GetData or SendCmd?)
|
|
||||||
bool CSIDevice_GCSteeringWheel::GetData(u32& _Hi, u32& _Low)
|
|
||||||
{
|
|
||||||
GCPadStatus PadStatus;
|
|
||||||
memset(&PadStatus, 0, sizeof(PadStatus));
|
|
||||||
|
|
||||||
Pad::GetStatus(ISIDevice::m_iDeviceNumber, &PadStatus);
|
|
||||||
Movie::CallGCInputManip(&PadStatus, ISIDevice::m_iDeviceNumber);
|
|
||||||
|
|
||||||
Movie::SetPolledDevice();
|
|
||||||
if (NetPlay_GetInput(ISIDevice::m_iDeviceNumber, &PadStatus))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else if (Movie::IsPlayingInput())
|
|
||||||
{
|
|
||||||
Movie::PlayController(&PadStatus, ISIDevice::m_iDeviceNumber);
|
|
||||||
Movie::InputUpdate();
|
|
||||||
}
|
|
||||||
else if (Movie::IsRecordingInput())
|
|
||||||
{
|
|
||||||
Movie::RecordInput(&PadStatus, ISIDevice::m_iDeviceNumber);
|
|
||||||
Movie::InputUpdate();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Movie::CheckPadStatus(&PadStatus, ISIDevice::m_iDeviceNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Thankfully changing mode does not change the high bits ;)
|
|
||||||
_Hi = (u32)((u8)PadStatus.stickX); // Steering
|
|
||||||
_Hi |= 0x800; // Pedal connected flag
|
|
||||||
_Hi |= (u32)((u16)(PadStatus.button | PAD_USE_ORIGIN) << 16);
|
|
||||||
|
|
||||||
// Low bits are packed differently per mode
|
|
||||||
if (m_Mode == 0 || m_Mode == 5 || m_Mode == 7)
|
|
||||||
{
|
|
||||||
_Low = (u8)(PadStatus.analogB >> 4); // Top 4 bits
|
|
||||||
_Low |= (u32)((u8)(PadStatus.analogA >> 4) << 4); // Top 4 bits
|
|
||||||
_Low |= (u32)((u8)(PadStatus.triggerRight >> 4) << 8); // Top 4 bits
|
|
||||||
_Low |= (u32)((u8)(PadStatus.triggerLeft >> 4) << 12); // Top 4 bits
|
|
||||||
_Low |= (u32)((u8)(PadStatus.substickY) << 16); // All 8 bits
|
|
||||||
_Low |= (u32)((u8)(PadStatus.substickX) << 24); // All 8 bits
|
|
||||||
}
|
|
||||||
else if (m_Mode == 1)
|
|
||||||
{
|
|
||||||
_Low = (u8)(PadStatus.analogB >> 4); // Top 4 bits
|
|
||||||
_Low |= (u32)((u8)(PadStatus.analogA >> 4) << 4); // Top 4 bits
|
|
||||||
_Low |= (u32)((u8)PadStatus.triggerRight << 8); // All 8 bits
|
|
||||||
_Low |= (u32)((u8)PadStatus.triggerLeft << 16); // All 8 bits
|
|
||||||
_Low |= (u32)((u8)PadStatus.substickY << 24); // Top 4 bits
|
|
||||||
_Low |= (u32)((u8)PadStatus.substickX << 28); // Top 4 bits
|
|
||||||
}
|
|
||||||
else if (m_Mode == 2)
|
|
||||||
{
|
|
||||||
_Low = (u8)(PadStatus.analogB); // All 8 bits
|
|
||||||
_Low |= (u32)((u8)(PadStatus.analogA) << 8); // All 8 bits
|
|
||||||
_Low |= (u32)((u8)(PadStatus.triggerRight >> 4) << 16); // Top 4 bits
|
|
||||||
_Low |= (u32)((u8)(PadStatus.triggerLeft >> 4) << 20); // Top 4 bits
|
|
||||||
_Low |= (u32)((u8)PadStatus.substickY << 24); // Top 4 bits
|
|
||||||
_Low |= (u32)((u8)PadStatus.substickX << 28); // Top 4 bits
|
|
||||||
}
|
|
||||||
else if (m_Mode == 3)
|
|
||||||
{
|
|
||||||
// Analog A/B are always 0
|
|
||||||
_Low = (u8)PadStatus.triggerRight; // All 8 bits
|
|
||||||
_Low |= (u32)((u8)PadStatus.triggerLeft << 8); // All 8 bits
|
|
||||||
_Low |= (u32)((u8)PadStatus.substickY << 16); // All 8 bits
|
|
||||||
_Low |= (u32)((u8)PadStatus.substickX << 24); // All 8 bits
|
|
||||||
}
|
|
||||||
else if (m_Mode == 4)
|
|
||||||
{
|
|
||||||
_Low = (u8)(PadStatus.analogB); // All 8 bits
|
|
||||||
_Low |= (u32)((u8)(PadStatus.analogA) << 8); // All 8 bits
|
|
||||||
// triggerLeft/Right are always 0
|
|
||||||
_Low |= (u32)((u8)PadStatus.substickY << 16); // All 8 bits
|
|
||||||
_Low |= (u32)((u8)PadStatus.substickX << 24); // All 8 bits
|
|
||||||
}
|
|
||||||
else if (m_Mode == 6)
|
|
||||||
{
|
|
||||||
_Low = (u8)PadStatus.triggerRight; // All 8 bits
|
|
||||||
_Low |= (u32)((u8)PadStatus.triggerLeft << 8); // All 8 bits
|
|
||||||
|
|
||||||
// The GC Steering Wheel appears to have combined pedals
|
|
||||||
// (both the Accelerate and Brake pedals are mapped to a single axis)
|
|
||||||
// We use the stickY axis for the pedals.
|
|
||||||
if (PadStatus.stickY < 128)
|
|
||||||
_Low |= (u32)((u8)(255 - ((PadStatus.stickY & 0x7f) * 2)) << 16); // All 8 bits (Brake)
|
|
||||||
if (PadStatus.stickY >= 128)
|
|
||||||
_Low |= (u32)((u8)((PadStatus.stickY & 0x7f) * 2) << 24); // All 8 bits (Accelerate)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep track of the special button combos (embedded in controller hardware... :( )
|
|
||||||
EButtonCombo tempCombo;
|
|
||||||
if ((PadStatus.button & 0xff00) == (PAD_BUTTON_Y|PAD_BUTTON_X|PAD_BUTTON_START))
|
|
||||||
tempCombo = COMBO_ORIGIN;
|
|
||||||
else if ((PadStatus.button & 0xff00) == (PAD_BUTTON_B|PAD_BUTTON_X|PAD_BUTTON_START))
|
|
||||||
tempCombo = COMBO_RESET;
|
|
||||||
else
|
|
||||||
tempCombo = COMBO_NONE;
|
|
||||||
if (tempCombo != m_LastButtonCombo)
|
|
||||||
{
|
|
||||||
m_LastButtonCombo = tempCombo;
|
|
||||||
if (m_LastButtonCombo != COMBO_NONE)
|
|
||||||
m_TButtonComboStart = CoreTiming::GetTicks();
|
|
||||||
}
|
|
||||||
if (m_LastButtonCombo != COMBO_NONE)
|
|
||||||
{
|
|
||||||
m_TButtonCombo = CoreTiming::GetTicks();
|
|
||||||
if ((m_TButtonCombo - m_TButtonComboStart) > SystemTimers::GetTicksPerSecond() * 3)
|
|
||||||
{
|
|
||||||
if (m_LastButtonCombo == COMBO_RESET)
|
|
||||||
{
|
|
||||||
ProcessorInterface::ResetButton_Tap();
|
|
||||||
}
|
|
||||||
else if (m_LastButtonCombo == COMBO_ORIGIN)
|
|
||||||
{
|
|
||||||
m_Origin.uOriginStickX = PadStatus.stickX;
|
|
||||||
m_Origin.uOriginStickY = PadStatus.stickY;
|
|
||||||
m_Origin.uSubStickStickX = PadStatus.substickX;
|
|
||||||
m_Origin.uSubStickStickY = PadStatus.substickY;
|
|
||||||
m_Origin.uTrigger_L = PadStatus.triggerLeft;
|
|
||||||
m_Origin.uTrigger_R = PadStatus.triggerRight;
|
|
||||||
}
|
|
||||||
m_LastButtonCombo = COMBO_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// SendCommand
|
|
||||||
void CSIDevice_GCSteeringWheel::SendCommand(u32 _Cmd, u8 _Poll)
|
void CSIDevice_GCSteeringWheel::SendCommand(u32 _Cmd, u8 _Poll)
|
||||||
{
|
{
|
||||||
UCommand command(_Cmd);
|
UCommand command(_Cmd);
|
||||||
|
|
||||||
switch (command.Command)
|
if (command.Command == CMD_FORCE)
|
||||||
{
|
|
||||||
// Costis sent it in some demos :)
|
|
||||||
case 0x00:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CMD_FORCE:
|
|
||||||
{
|
{
|
||||||
unsigned int uStrength = command.Parameter1; // 0 = left strong, 127 = left weak, 128 = right weak, 255 = right strong
|
unsigned int uStrength = command.Parameter1; // 0 = left strong, 127 = left weak, 128 = right weak, 255 = right strong
|
||||||
unsigned int uType = command.Parameter2; // 06 = motor on, 04 = motor off
|
unsigned int uType = command.Parameter2; // 06 = motor on, 04 = motor off
|
||||||
|
@ -245,7 +22,18 @@ void CSIDevice_GCSteeringWheel::SendCommand(u32 _Cmd, u8 _Poll)
|
||||||
const u8 numPAD = NetPlay_InGamePadToLocalPad(ISIDevice::m_iDeviceNumber);
|
const u8 numPAD = NetPlay_InGamePadToLocalPad(ISIDevice::m_iDeviceNumber);
|
||||||
|
|
||||||
if (numPAD < 4)
|
if (numPAD < 4)
|
||||||
Pad::Motor(numPAD, uType, uStrength);
|
{
|
||||||
|
if (uType == 0x06)
|
||||||
|
{
|
||||||
|
// map 0..255 to -1.0..1.0
|
||||||
|
ControlState strength = uStrength / 127.5 - 1;
|
||||||
|
Pad::Rumble(numPAD, strength);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Pad::Rumble(numPAD, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!_Poll)
|
if (!_Poll)
|
||||||
{
|
{
|
||||||
|
@ -253,41 +41,8 @@ void CSIDevice_GCSteeringWheel::SendCommand(u32 _Cmd, u8 _Poll)
|
||||||
INFO_LOG(SERIALINTERFACE, "PAD %i set to mode %i", ISIDevice::m_iDeviceNumber, m_Mode);
|
INFO_LOG(SERIALINTERFACE, "PAD %i set to mode %i", ISIDevice::m_iDeviceNumber, m_Mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
else
|
||||||
|
|
||||||
case CMD_WRITE:
|
|
||||||
{
|
{
|
||||||
unsigned int uType = command.Parameter1; // 0 = stop, 1 = rumble, 2 = stop hard
|
return CSIDevice_GCController::SendCommand(_Cmd, _Poll);
|
||||||
unsigned int uStrength = command.Parameter2;
|
|
||||||
|
|
||||||
// get the correct pad number that should rumble locally when using netplay
|
|
||||||
const u8 numPAD = NetPlay_InGamePadToLocalPad(ISIDevice::m_iDeviceNumber);
|
|
||||||
|
|
||||||
if (numPAD < 4)
|
|
||||||
Pad::Rumble(numPAD, uType, uStrength);
|
|
||||||
|
|
||||||
if (!_Poll)
|
|
||||||
{
|
|
||||||
m_Mode = command.Parameter2;
|
|
||||||
INFO_LOG(SERIALINTERFACE, "PAD %i set to mode %i", ISIDevice::m_iDeviceNumber, m_Mode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
ERROR_LOG(SERIALINTERFACE, "Unknown direct command (0x%x)", _Cmd);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Savestate support
|
|
||||||
void CSIDevice_GCSteeringWheel::DoState(PointerWrap& p)
|
|
||||||
{
|
|
||||||
p.Do(m_Origin);
|
|
||||||
p.Do(m_Mode);
|
|
||||||
p.Do(m_TButtonComboStart);
|
|
||||||
p.Do(m_TButtonCombo);
|
|
||||||
p.Do(m_LastButtonCombo);
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,14 +4,11 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Core/HW/SI_Device.h"
|
#include "Core/HW/SI_DeviceGCController.h"
|
||||||
#include "InputCommon/GCPadStatus.h"
|
|
||||||
|
|
||||||
// standard GameCube controller
|
class CSIDevice_GCSteeringWheel : public CSIDevice_GCController
|
||||||
class CSIDevice_GCSteeringWheel : public ISIDevice
|
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
enum EBufferCommands
|
enum EBufferCommands
|
||||||
{
|
{
|
||||||
|
@ -21,82 +18,13 @@ private:
|
||||||
CMD_MOTOR_OFF = 0xff,
|
CMD_MOTOR_OFF = 0xff,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SOrigin
|
|
||||||
{
|
|
||||||
u8 uCommand;// Maybe should be button bits?
|
|
||||||
u8 unk_1; // ..and this would be the other half
|
|
||||||
u8 uOriginStickX;
|
|
||||||
u8 uOriginStickY;
|
|
||||||
u8 uSubStickStickX;
|
|
||||||
u8 uSubStickStickY;
|
|
||||||
u8 uTrigger_L;
|
|
||||||
u8 uTrigger_R;
|
|
||||||
u8 unk_4;
|
|
||||||
u8 unk_5;
|
|
||||||
u8 unk_6;
|
|
||||||
u8 unk_7;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum EDirectCommands
|
enum EDirectCommands
|
||||||
{
|
{
|
||||||
CMD_FORCE = 0x30,
|
CMD_FORCE = 0x30,
|
||||||
CMD_WRITE = 0x40
|
CMD_WRITE = 0x40
|
||||||
};
|
};
|
||||||
|
|
||||||
union UCommand
|
|
||||||
{
|
|
||||||
u32 Hex;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
u32 Parameter1 : 8;
|
|
||||||
u32 Parameter2 : 8;
|
|
||||||
u32 Command : 8;
|
|
||||||
u32 : 8;
|
|
||||||
};
|
|
||||||
UCommand() {Hex = 0;}
|
|
||||||
UCommand(u32 _iValue) {Hex = _iValue;}
|
|
||||||
};
|
|
||||||
|
|
||||||
enum EButtonCombo
|
|
||||||
{
|
|
||||||
COMBO_NONE = 0,
|
|
||||||
COMBO_ORIGIN,
|
|
||||||
COMBO_RESET
|
|
||||||
};
|
|
||||||
|
|
||||||
// struct to compare input against
|
|
||||||
// Set on connection and (standard pad only) on button combo
|
|
||||||
SOrigin m_Origin;
|
|
||||||
|
|
||||||
// PADAnalogMode
|
|
||||||
u8 m_Mode;
|
|
||||||
|
|
||||||
// Timer to track special button combos:
|
|
||||||
// y, X, start for 3 seconds updates origin with current status
|
|
||||||
// Technically, the above is only on standard pad, wavebird does not support it for example
|
|
||||||
// b, x, start for 3 seconds triggers reset (PI reset button interrupt)
|
|
||||||
u64 m_TButtonComboStart, m_TButtonCombo;
|
|
||||||
// Type of button combo from the last/current poll
|
|
||||||
EButtonCombo m_LastButtonCombo;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Constructor
|
|
||||||
CSIDevice_GCSteeringWheel(SIDevices device, int _iDeviceNumber);
|
CSIDevice_GCSteeringWheel(SIDevices device, int _iDeviceNumber);
|
||||||
|
virtual void SendCommand(u32 _Cmd, u8 _Poll);
|
||||||
// Run the SI Buffer
|
|
||||||
virtual int RunBuffer(u8* _pBuffer, int _iLength) override;
|
|
||||||
|
|
||||||
// Send and Receive pad input from network
|
|
||||||
static bool NetPlay_GetInput(u8 numPAD, GCPadStatus* status);
|
|
||||||
static u8 NetPlay_InGamePadToLocalPad(u8 numPAD);
|
|
||||||
|
|
||||||
// Return true on new data
|
|
||||||
virtual bool GetData(u32& _Hi, u32& _Low) override;
|
|
||||||
|
|
||||||
// Send a command directly
|
|
||||||
virtual void SendCommand(u32 _Cmd, u8 _Poll) override;
|
|
||||||
|
|
||||||
// Savestate support
|
|
||||||
virtual void DoState(PointerWrap& p) override;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -61,6 +61,8 @@ IPC_HLE_PERIOD: For the Wiimote this is the call schedule:
|
||||||
#include "Core/IPC_HLE/WII_IPC_HLE.h"
|
#include "Core/IPC_HLE/WII_IPC_HLE.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
|
||||||
|
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||||
|
|
||||||
#include "VideoCommon/CommandProcessor.h"
|
#include "VideoCommon/CommandProcessor.h"
|
||||||
#include "VideoCommon/VideoBackendBase.h"
|
#include "VideoCommon/VideoBackendBase.h"
|
||||||
|
|
||||||
|
@ -79,6 +81,7 @@ static int et_DSP;
|
||||||
static int et_IPC_HLE;
|
static int et_IPC_HLE;
|
||||||
static int et_PatchEngine; // PatchEngine updates every 1/60th of a second by default
|
static int et_PatchEngine; // PatchEngine updates every 1/60th of a second by default
|
||||||
static int et_Throttle;
|
static int et_Throttle;
|
||||||
|
static int et_UpdateInput;
|
||||||
|
|
||||||
// These are badly educated guesses
|
// These are badly educated guesses
|
||||||
// Feel free to experiment. Set these in Init below.
|
// Feel free to experiment. Set these in Init below.
|
||||||
|
@ -132,6 +135,14 @@ static void VICallback(u64 userdata, int cyclesLate)
|
||||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerLine() - cyclesLate, et_VI);
|
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerLine() - cyclesLate, et_VI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void UpdateInputCallback(u64 userdata, int cyclesLate)
|
||||||
|
{
|
||||||
|
g_controller_interface.UpdateInput();
|
||||||
|
|
||||||
|
// Poll system input every 1/60th of a second.
|
||||||
|
CoreTiming::ScheduleEvent(SystemTimers::GetTicksPerSecond() / 60 - cyclesLate, et_UpdateInput);
|
||||||
|
}
|
||||||
|
|
||||||
static void SICallback(u64 userdata, int cyclesLate)
|
static void SICallback(u64 userdata, int cyclesLate)
|
||||||
{
|
{
|
||||||
SerialInterface::UpdateDevices();
|
SerialInterface::UpdateDevices();
|
||||||
|
@ -258,6 +269,7 @@ void Init()
|
||||||
et_IPC_HLE = CoreTiming::RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback);
|
et_IPC_HLE = CoreTiming::RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback);
|
||||||
et_PatchEngine = CoreTiming::RegisterEvent("PatchEngine", PatchEngineCallback);
|
et_PatchEngine = CoreTiming::RegisterEvent("PatchEngine", PatchEngineCallback);
|
||||||
et_Throttle = CoreTiming::RegisterEvent("Throttle", ThrottleCallback);
|
et_Throttle = CoreTiming::RegisterEvent("Throttle", ThrottleCallback);
|
||||||
|
et_UpdateInput = CoreTiming::RegisterEvent("UpdateInput", UpdateInputCallback);
|
||||||
|
|
||||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerLine(), et_VI);
|
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerLine(), et_VI);
|
||||||
CoreTiming::ScheduleEvent(0, et_DSP);
|
CoreTiming::ScheduleEvent(0, et_DSP);
|
||||||
|
@ -271,6 +283,8 @@ void Init()
|
||||||
|
|
||||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
|
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
|
||||||
CoreTiming::ScheduleEvent(IPC_HLE_PERIOD, et_IPC_HLE);
|
CoreTiming::ScheduleEvent(IPC_HLE_PERIOD, et_IPC_HLE);
|
||||||
|
|
||||||
|
CoreTiming::ScheduleEvent(0, et_UpdateInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shutdown()
|
void Shutdown()
|
||||||
|
|
|
@ -17,7 +17,6 @@ namespace Wiimote
|
||||||
{
|
{
|
||||||
|
|
||||||
static InputConfig s_config(WIIMOTE_INI_NAME, _trans("Wiimote"), "Wiimote");
|
static InputConfig s_config(WIIMOTE_INI_NAME, _trans("Wiimote"), "Wiimote");
|
||||||
static int s_last_number = 4;
|
|
||||||
|
|
||||||
InputConfig* GetConfig()
|
InputConfig* GetConfig()
|
||||||
{
|
{
|
||||||
|
@ -115,13 +114,6 @@ void Update(int _number)
|
||||||
// TODO: change this to a try_to_lock, and make it give empty input on failure
|
// TODO: change this to a try_to_lock, and make it give empty input on failure
|
||||||
std::lock_guard<std::recursive_mutex> lk(s_config.controls_lock);
|
std::lock_guard<std::recursive_mutex> lk(s_config.controls_lock);
|
||||||
|
|
||||||
if (_number <= s_last_number)
|
|
||||||
{
|
|
||||||
g_controller_interface.UpdateOutput();
|
|
||||||
g_controller_interface.UpdateInput();
|
|
||||||
}
|
|
||||||
s_last_number = _number;
|
|
||||||
|
|
||||||
if (WIIMOTE_SRC_EMU & g_wiimote_sources[_number])
|
if (WIIMOTE_SRC_EMU & g_wiimote_sources[_number])
|
||||||
((WiimoteEmu::Wiimote*)s_config.controllers[_number])->Update();
|
((WiimoteEmu::Wiimote*)s_config.controllers[_number])->Update();
|
||||||
else
|
else
|
||||||
|
@ -154,7 +146,6 @@ void DoState(u8 **ptr, PointerWrap::Mode mode)
|
||||||
// TODO:
|
// TODO:
|
||||||
|
|
||||||
PointerWrap p(ptr, mode);
|
PointerWrap p(ptr, mode);
|
||||||
p.Do(s_last_number);
|
|
||||||
for (unsigned int i=0; i<MAX_BBMOTES; ++i)
|
for (unsigned int i=0; i<MAX_BBMOTES; ++i)
|
||||||
((WiimoteEmu::Wiimote*)s_config.controllers[i])->DoState(p);
|
((WiimoteEmu::Wiimote*)s_config.controllers[i])->DoState(p);
|
||||||
}
|
}
|
||||||
|
|
|
@ -835,16 +835,6 @@ bool WiimoteEmu::Wiimote::NetPlay_GetWiimoteData(int wiimote, u8* data, u8 size)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSIDevice_GCSteeringWheel::NetPlay_GetInput(u8 numPAD, GCPadStatus* PadStatus)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSIDevice_DanceMat::NetPlay_GetInput(u8 numPAD, GCPadStatus* PadStatus)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// called from ---CPU--- thread
|
// called from ---CPU--- thread
|
||||||
// so all players' games get the same time
|
// so all players' games get the same time
|
||||||
u32 CEXIIPL::NetPlay_GetGCTime()
|
u32 CEXIIPL::NetPlay_GetGCTime()
|
||||||
|
@ -869,16 +859,6 @@ u8 CSIDevice_GCController::NetPlay_InGamePadToLocalPad(u8 numPAD)
|
||||||
return numPAD;
|
return numPAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 CSIDevice_GCSteeringWheel::NetPlay_InGamePadToLocalPad(u8 numPAD)
|
|
||||||
{
|
|
||||||
return CSIDevice_GCController::NetPlay_InGamePadToLocalPad(numPAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CSIDevice_DanceMat::NetPlay_InGamePadToLocalPad(u8 numPAD)
|
|
||||||
{
|
|
||||||
return CSIDevice_GCController::NetPlay_InGamePadToLocalPad(numPAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NetPlay::IsNetPlayRunning()
|
bool NetPlay::IsNetPlayRunning()
|
||||||
{
|
{
|
||||||
return netplay_client != nullptr;
|
return netplay_client != nullptr;
|
||||||
|
|
|
@ -39,9 +39,6 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool UpdateInput() { return true; }
|
|
||||||
bool UpdateOutput() { return true; }
|
|
||||||
|
|
||||||
Touchscreen(int padID);
|
Touchscreen(int padID);
|
||||||
~Touchscreen() {}
|
~Touchscreen() {}
|
||||||
|
|
||||||
|
|
|
@ -98,9 +98,6 @@ void ControllerInterface::Shutdown()
|
||||||
for (ciface::Core::Device::Output* o : d->Outputs())
|
for (ciface::Core::Device::Output* o : d->Outputs())
|
||||||
o->SetState(0);
|
o->SetState(0);
|
||||||
|
|
||||||
// Update output
|
|
||||||
d->UpdateOutput();
|
|
||||||
|
|
||||||
// Delete device
|
// Delete device
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
@ -135,52 +132,15 @@ void ControllerInterface::Shutdown()
|
||||||
//
|
//
|
||||||
// Update input for all devices, return true if all devices returned successful
|
// Update input for all devices, return true if all devices returned successful
|
||||||
//
|
//
|
||||||
bool ControllerInterface::UpdateInput(const bool force)
|
void ControllerInterface::UpdateInput()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::recursive_mutex> lk(update_lock, std::defer_lock);
|
std::unique_lock<std::recursive_mutex> lk(update_lock, std::defer_lock);
|
||||||
|
|
||||||
if (force)
|
if (!lk.try_lock())
|
||||||
lk.lock();
|
return;
|
||||||
else if (!lk.try_lock())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
size_t ok_count = 0;
|
|
||||||
|
|
||||||
for (ciface::Core::Device* d : m_devices)
|
for (ciface::Core::Device* d : m_devices)
|
||||||
{
|
d->UpdateInput();
|
||||||
if (d->UpdateInput())
|
|
||||||
++ok_count;
|
|
||||||
//else
|
|
||||||
// disabled. it might be causing problems
|
|
||||||
//(*d)->ClearInputState();
|
|
||||||
}
|
|
||||||
|
|
||||||
return (m_devices.size() == ok_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// UpdateOutput
|
|
||||||
//
|
|
||||||
// Update output for all devices, return true if all devices returned successful
|
|
||||||
//
|
|
||||||
bool ControllerInterface::UpdateOutput(const bool force)
|
|
||||||
{
|
|
||||||
std::unique_lock<std::recursive_mutex> lk(update_lock, std::defer_lock);
|
|
||||||
|
|
||||||
if (force)
|
|
||||||
lk.lock();
|
|
||||||
else if (!lk.try_lock())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
size_t ok_count = 0;
|
|
||||||
|
|
||||||
for (ciface::Core::Device* d : m_devices)
|
|
||||||
{
|
|
||||||
if (d->UpdateOutput())
|
|
||||||
++ok_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (m_devices.size() == ok_count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -299,14 +259,9 @@ ciface::Core::Device::Control* ControllerInterface::OutputReference::Detect(cons
|
||||||
|
|
||||||
// this loop is to make stuff like flashing keyboard LEDs work
|
// this loop is to make stuff like flashing keyboard LEDs work
|
||||||
while (ms > (slept += 10))
|
while (ms > (slept += 10))
|
||||||
{
|
|
||||||
// TODO: improve this to update more than just the default device's output
|
|
||||||
device->UpdateOutput();
|
|
||||||
Common::SleepCurrentThread(10);
|
Common::SleepCurrentThread(10);
|
||||||
}
|
|
||||||
|
|
||||||
State(0);
|
State(0);
|
||||||
device->UpdateOutput();
|
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,8 +120,7 @@ public:
|
||||||
bool IsInit() const { return m_is_init; }
|
bool IsInit() const { return m_is_init; }
|
||||||
|
|
||||||
void UpdateReference(ControlReference* control, const ciface::Core::DeviceQualifier& default_device) const;
|
void UpdateReference(ControlReference* control, const ciface::Core::DeviceQualifier& default_device) const;
|
||||||
bool UpdateInput(const bool force = false);
|
void UpdateInput();
|
||||||
bool UpdateOutput(const bool force = false);
|
|
||||||
|
|
||||||
std::recursive_mutex update_lock;
|
std::recursive_mutex update_lock;
|
||||||
|
|
||||||
|
|
|
@ -149,7 +149,9 @@ Joystick::Joystick( /*const LPCDIDEVICEINSTANCE lpddi, */const LPDIRECTINPUTDEVI
|
||||||
InitForceFeedback(m_device, (int)objects.size());
|
InitForceFeedback(m_device, (int)objects.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
ClearInputState();
|
ZeroMemory(&m_state_in, sizeof(m_state_in));
|
||||||
|
// set hats to center
|
||||||
|
memset(m_state_in.rgdwPOV, 0xFF, sizeof(m_state_in.rgdwPOV));
|
||||||
}
|
}
|
||||||
|
|
||||||
Joystick::~Joystick()
|
Joystick::~Joystick()
|
||||||
|
@ -158,13 +160,6 @@ Joystick::~Joystick()
|
||||||
m_device->Release();
|
m_device->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Joystick::ClearInputState()
|
|
||||||
{
|
|
||||||
ZeroMemory(&m_state_in, sizeof(m_state_in));
|
|
||||||
// set hats to center
|
|
||||||
memset(m_state_in.rgdwPOV, 0xFF, sizeof(m_state_in.rgdwPOV));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Joystick::GetName() const
|
std::string Joystick::GetName() const
|
||||||
{
|
{
|
||||||
return GetDeviceName(m_device);
|
return GetDeviceName(m_device);
|
||||||
|
@ -182,7 +177,7 @@ std::string Joystick::GetSource() const
|
||||||
|
|
||||||
// update IO
|
// update IO
|
||||||
|
|
||||||
bool Joystick::UpdateInput()
|
void Joystick::UpdateInput()
|
||||||
{
|
{
|
||||||
HRESULT hr = 0;
|
HRESULT hr = 0;
|
||||||
|
|
||||||
|
@ -220,9 +215,7 @@ bool Joystick::UpdateInput()
|
||||||
|
|
||||||
// try reacquire if input lost
|
// try reacquire if input lost
|
||||||
if (DIERR_INPUTLOST == hr || DIERR_NOTACQUIRED == hr)
|
if (DIERR_INPUTLOST == hr || DIERR_NOTACQUIRED == hr)
|
||||||
hr = m_device->Acquire();
|
m_device->Acquire();
|
||||||
|
|
||||||
return SUCCEEDED(hr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// get name
|
// get name
|
||||||
|
|
|
@ -52,9 +52,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool UpdateInput();
|
void UpdateInput() override;
|
||||||
|
|
||||||
void ClearInputState();
|
|
||||||
|
|
||||||
Joystick(const LPDIRECTINPUTDEVICE8 device, const unsigned int index);
|
Joystick(const LPDIRECTINPUTDEVICE8 device, const unsigned int index);
|
||||||
~Joystick();
|
~Joystick();
|
||||||
|
|
|
@ -30,17 +30,6 @@ static const struct
|
||||||
#include "InputCommon/ControllerInterface/DInput/NamedKeys.h" // NOLINT
|
#include "InputCommon/ControllerInterface/DInput/NamedKeys.h" // NOLINT
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct
|
|
||||||
{
|
|
||||||
const BYTE code;
|
|
||||||
const char* const name;
|
|
||||||
} named_lights[] =
|
|
||||||
{
|
|
||||||
{ VK_NUMLOCK, "NUM LOCK" },
|
|
||||||
{ VK_CAPITAL, "CAPS LOCK" },
|
|
||||||
{ VK_SCROLL, "SCROLL LOCK" }
|
|
||||||
};
|
|
||||||
|
|
||||||
// lil silly
|
// lil silly
|
||||||
static HWND hwnd;
|
static HWND hwnd;
|
||||||
|
|
||||||
|
@ -102,16 +91,11 @@ KeyboardMouse::KeyboardMouse(const LPDIRECTINPUTDEVICE8 kb_device, const LPDIREC
|
||||||
m_last_update = GetTickCount();
|
m_last_update = GetTickCount();
|
||||||
|
|
||||||
ZeroMemory(&m_state_in, sizeof(m_state_in));
|
ZeroMemory(&m_state_in, sizeof(m_state_in));
|
||||||
ZeroMemory(m_state_out, sizeof(m_state_out));
|
|
||||||
ZeroMemory(&m_current_state_out, sizeof(m_current_state_out));
|
|
||||||
|
|
||||||
// KEYBOARD
|
// KEYBOARD
|
||||||
// add keys
|
// add keys
|
||||||
for (u8 i = 0; i < sizeof(named_keys)/sizeof(*named_keys); ++i)
|
for (u8 i = 0; i < sizeof(named_keys)/sizeof(*named_keys); ++i)
|
||||||
AddInput(new Key(i, m_state_in.keyboard[named_keys[i].code]));
|
AddInput(new Key(i, m_state_in.keyboard[named_keys[i].code]));
|
||||||
// add lights
|
|
||||||
for (u8 i = 0; i < sizeof(named_lights)/sizeof(*named_lights); ++i)
|
|
||||||
AddOutput(new Light(i));
|
|
||||||
|
|
||||||
// MOUSE
|
// MOUSE
|
||||||
// get caps
|
// get caps
|
||||||
|
@ -155,7 +139,7 @@ void GetMousePos(ControlState* const x, ControlState* const y)
|
||||||
*y = (ControlState)point.y / (ControlState)win_height * 2 - 1;
|
*y = (ControlState)point.y / (ControlState)win_height * 2 - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KeyboardMouse::UpdateInput()
|
void KeyboardMouse::UpdateInput()
|
||||||
{
|
{
|
||||||
DIMOUSESTATE2 tmp_mouse;
|
DIMOUSESTATE2 tmp_mouse;
|
||||||
|
|
||||||
|
@ -191,50 +175,7 @@ bool KeyboardMouse::UpdateInput()
|
||||||
|
|
||||||
// update mouse cursor
|
// update mouse cursor
|
||||||
GetMousePos(&m_state_in.cursor.x, &m_state_in.cursor.y);
|
GetMousePos(&m_state_in.cursor.x, &m_state_in.cursor.y);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KeyboardMouse::UpdateOutput()
|
|
||||||
{
|
|
||||||
class KInput : public INPUT
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
KInput( const unsigned char key, const bool up = false )
|
|
||||||
{
|
|
||||||
memset( this, 0, sizeof(*this) );
|
|
||||||
type = INPUT_KEYBOARD;
|
|
||||||
ki.wVk = key;
|
|
||||||
|
|
||||||
if (up)
|
|
||||||
ki.dwFlags = KEYEVENTF_KEYUP;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector< KInput > kbinputs;
|
|
||||||
for (unsigned int i = 0; i < sizeof(m_state_out)/sizeof(*m_state_out); ++i)
|
|
||||||
{
|
|
||||||
bool want_on = false;
|
|
||||||
if (m_state_out[i])
|
|
||||||
want_on = m_state_out[i] > GetTickCount() % 255 ; // light should flash when output is 0.5
|
|
||||||
|
|
||||||
// lights are set to their original state when output is zero
|
|
||||||
if (want_on ^ m_current_state_out[i])
|
|
||||||
{
|
|
||||||
kbinputs.push_back(KInput(named_lights[i].code)); // press
|
|
||||||
kbinputs.push_back(KInput(named_lights[i].code, true)); // release
|
|
||||||
|
|
||||||
m_current_state_out[i] ^= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kbinputs.size())
|
|
||||||
return ( kbinputs.size() == SendInput( (UINT)kbinputs.size(), &kbinputs[0], sizeof( kbinputs[0] ) ) );
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KeyboardMouse::GetName() const
|
std::string KeyboardMouse::GetName() const
|
||||||
|
@ -280,11 +221,6 @@ std::string KeyboardMouse::Cursor::GetName() const
|
||||||
return tmpstr;
|
return tmpstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KeyboardMouse::Light::GetName() const
|
|
||||||
{
|
|
||||||
return named_lights[m_index].name;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get/set state
|
// get/set state
|
||||||
ControlState KeyboardMouse::Key::GetState() const
|
ControlState KeyboardMouse::Key::GetState() const
|
||||||
{
|
{
|
||||||
|
@ -306,10 +242,5 @@ ControlState KeyboardMouse::Cursor::GetState() const
|
||||||
return std::max(0.0, ControlState(m_axis) / (m_positive ? 1.0 : -1.0));
|
return std::max(0.0, ControlState(m_axis) / (m_positive ? 1.0 : -1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyboardMouse::Light::SetState(const ControlState state)
|
|
||||||
{
|
|
||||||
//state_out[m_index] = (unsigned char)(state * 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,19 +76,8 @@ private:
|
||||||
const bool m_positive;
|
const bool m_positive;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Light : public Output
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
std::string GetName() const;
|
void UpdateInput() override;
|
||||||
Light(u8 index) : m_index(index) {}
|
|
||||||
void SetState(ControlState state);
|
|
||||||
private:
|
|
||||||
const u8 m_index;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool UpdateInput();
|
|
||||||
bool UpdateOutput();
|
|
||||||
|
|
||||||
KeyboardMouse(const LPDIRECTINPUTDEVICE8 kb_device, const LPDIRECTINPUTDEVICE8 mo_device);
|
KeyboardMouse(const LPDIRECTINPUTDEVICE8 kb_device, const LPDIRECTINPUTDEVICE8 mo_device);
|
||||||
~KeyboardMouse();
|
~KeyboardMouse();
|
||||||
|
@ -103,8 +92,6 @@ private:
|
||||||
|
|
||||||
DWORD m_last_update;
|
DWORD m_last_update;
|
||||||
State m_state_in;
|
State m_state_in;
|
||||||
unsigned char m_state_out[3]; // NUM CAPS SCROLL
|
|
||||||
bool m_current_state_out[3]; // NUM CAPS SCROLL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,20 +66,6 @@ Device::Output* Device::FindOutput(const std::string &name) const
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Device :: ClearInputState
|
|
||||||
//
|
|
||||||
// Device classes should override this function
|
|
||||||
// ControllerInterface will call this when the device returns failure during UpdateInput
|
|
||||||
// used to try to set all buttons and axes to their default state when user unplugs a gamepad during play
|
|
||||||
// buttons/axes that were held down at the time of unplugging should be seen as not pressed after unplugging
|
|
||||||
//
|
|
||||||
void Device::ClearInputState()
|
|
||||||
{
|
|
||||||
// this is going to be called for every UpdateInput call that fails
|
|
||||||
// kinda slow but, w/e, should only happen when user unplugs a device while playing
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Device::Control::InputGateOn()
|
bool Device::Control::InputGateOn()
|
||||||
{
|
{
|
||||||
if (SConfig::GetInstance().m_BackgroundInput)
|
if (SConfig::GetInstance().m_BackgroundInput)
|
||||||
|
|
|
@ -100,10 +100,7 @@ public:
|
||||||
virtual std::string GetName() const = 0;
|
virtual std::string GetName() const = 0;
|
||||||
virtual int GetId() const = 0;
|
virtual int GetId() const = 0;
|
||||||
virtual std::string GetSource() const = 0;
|
virtual std::string GetSource() const = 0;
|
||||||
virtual bool UpdateInput() = 0;
|
virtual void UpdateInput() {}
|
||||||
virtual bool UpdateOutput() = 0;
|
|
||||||
|
|
||||||
virtual void ClearInputState();
|
|
||||||
|
|
||||||
const std::vector<Input*>& Inputs() const { return m_inputs; }
|
const std::vector<Input*>& Inputs() const { return m_inputs; }
|
||||||
const std::vector<Output*>& Outputs() const { return m_outputs; }
|
const std::vector<Output*>& Outputs() const { return m_outputs; }
|
||||||
|
|
|
@ -38,17 +38,6 @@ static const ForceType force_type_names[] =
|
||||||
//{GUID_Friction, "Friction"},
|
//{GUID_Friction, "Friction"},
|
||||||
};
|
};
|
||||||
|
|
||||||
ForceFeedbackDevice::~ForceFeedbackDevice()
|
|
||||||
{
|
|
||||||
// release the ff effect iface's
|
|
||||||
for (EffectState& state : m_state_out)
|
|
||||||
{
|
|
||||||
state.iface->Stop();
|
|
||||||
state.iface->Unload();
|
|
||||||
state.iface->Release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ForceFeedbackDevice::InitForceFeedback(const LPDIRECTINPUTDEVICE8 device, int cAxes)
|
bool ForceFeedbackDevice::InitForceFeedback(const LPDIRECTINPUTDEVICE8 device, int cAxes)
|
||||||
{
|
{
|
||||||
if (cAxes == 0)
|
if (cAxes == 0)
|
||||||
|
@ -107,14 +96,12 @@ bool ForceFeedbackDevice::InitForceFeedback(const LPDIRECTINPUTDEVICE8 device, i
|
||||||
LPDIRECTINPUTEFFECT pEffect;
|
LPDIRECTINPUTEFFECT pEffect;
|
||||||
if (SUCCEEDED(device->CreateEffect(f.guid, &eff, &pEffect, nullptr)))
|
if (SUCCEEDED(device->CreateEffect(f.guid, &eff, &pEffect, nullptr)))
|
||||||
{
|
{
|
||||||
m_state_out.push_back(EffectState(pEffect));
|
|
||||||
|
|
||||||
if (f.guid == GUID_ConstantForce)
|
if (f.guid == GUID_ConstantForce)
|
||||||
AddOutput(new ForceConstant(f.name, m_state_out.back()));
|
AddOutput(new ForceConstant(f.name, pEffect));
|
||||||
else if (f.guid == GUID_RampForce)
|
else if (f.guid == GUID_RampForce)
|
||||||
AddOutput(new ForceRamp(f.name, m_state_out.back()));
|
AddOutput(new ForceRamp(f.name, pEffect));
|
||||||
else
|
else
|
||||||
AddOutput(new ForcePeriodic(f.name, m_state_out.back()));
|
AddOutput(new ForcePeriodic(f.name, pEffect));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,40 +120,32 @@ bool ForceFeedbackDevice::InitForceFeedback(const LPDIRECTINPUTDEVICE8 device, i
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ForceFeedbackDevice::UpdateOutput()
|
template<typename P>
|
||||||
|
ForceFeedbackDevice::Force<P>::~Force()
|
||||||
{
|
{
|
||||||
size_t ok_count = 0;
|
m_iface->Stop();
|
||||||
|
m_iface->Unload();
|
||||||
|
m_iface->Release();
|
||||||
|
}
|
||||||
|
|
||||||
DIEFFECT eff;
|
template<typename P>
|
||||||
memset(&eff, 0, sizeof(eff));
|
void ForceFeedbackDevice::Force<P>::Update()
|
||||||
|
{
|
||||||
|
DIEFFECT eff = {};
|
||||||
eff.dwSize = sizeof(DIEFFECT);
|
eff.dwSize = sizeof(DIEFFECT);
|
||||||
eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
|
eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
|
||||||
|
|
||||||
for (EffectState& state : m_state_out)
|
eff.cbTypeSpecificParams = sizeof(P);
|
||||||
{
|
eff.lpvTypeSpecificParams = ¶ms;
|
||||||
if (state.params)
|
|
||||||
{
|
|
||||||
if (state.size)
|
|
||||||
{
|
|
||||||
eff.cbTypeSpecificParams = state.size;
|
|
||||||
eff.lpvTypeSpecificParams = state.params;
|
|
||||||
// set params and start effect
|
// set params and start effect
|
||||||
ok_count += SUCCEEDED(state.iface->SetParameters(&eff, DIEP_TYPESPECIFICPARAMS | DIEP_START));
|
m_iface->SetParameters(&eff, DIEP_TYPESPECIFICPARAMS | DIEP_START);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ok_count += SUCCEEDED(state.iface->Stop());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state.params = nullptr;
|
template<typename P>
|
||||||
}
|
void ForceFeedbackDevice::Force<P>::Stop()
|
||||||
else
|
|
||||||
{
|
{
|
||||||
++ok_count;
|
m_iface->Stop();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (m_state_out.size() == ok_count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
@ -174,15 +153,14 @@ void ForceFeedbackDevice::ForceConstant::SetState(const ControlState state)
|
||||||
{
|
{
|
||||||
const LONG new_val = LONG(10000 * state);
|
const LONG new_val = LONG(10000 * state);
|
||||||
|
|
||||||
LONG &val = params.lMagnitude;
|
if (params.lMagnitude == new_val)
|
||||||
if (val != new_val)
|
return;
|
||||||
{
|
|
||||||
val = new_val;
|
|
||||||
m_state.params = ¶ms; // tells UpdateOutput the state has changed
|
|
||||||
|
|
||||||
// tells UpdateOutput to either start or stop the force
|
params.lMagnitude = new_val;
|
||||||
m_state.size = new_val ? sizeof(params) : 0;
|
if (new_val)
|
||||||
}
|
Update();
|
||||||
|
else
|
||||||
|
Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
@ -190,14 +168,14 @@ void ForceFeedbackDevice::ForceRamp::SetState(const ControlState state)
|
||||||
{
|
{
|
||||||
const LONG new_val = LONG(10000 * state);
|
const LONG new_val = LONG(10000 * state);
|
||||||
|
|
||||||
if (params.lStart != new_val)
|
if (params.lStart == new_val)
|
||||||
{
|
return;
|
||||||
params.lStart = params.lEnd = new_val;
|
|
||||||
m_state.params = ¶ms; // tells UpdateOutput the state has changed
|
|
||||||
|
|
||||||
// tells UpdateOutput to either start or stop the force
|
params.lStart = params.lEnd = new_val;
|
||||||
m_state.size = new_val ? sizeof(params) : 0;
|
if (new_val)
|
||||||
}
|
Update();
|
||||||
|
else
|
||||||
|
Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
@ -205,22 +183,19 @@ void ForceFeedbackDevice::ForcePeriodic::SetState(const ControlState state)
|
||||||
{
|
{
|
||||||
const DWORD new_val = DWORD(10000 * state);
|
const DWORD new_val = DWORD(10000 * state);
|
||||||
|
|
||||||
DWORD &val = params.dwMagnitude;
|
if (params.dwMagnitude == new_val)
|
||||||
if (val != new_val)
|
return;
|
||||||
{
|
|
||||||
val = new_val;
|
|
||||||
//params.dwPeriod = 0;//DWORD(0.05 * DI_SECONDS); // zero is working fine for me
|
|
||||||
|
|
||||||
m_state.params = ¶ms; // tells UpdateOutput the state has changed
|
params.dwMagnitude = new_val;
|
||||||
|
if (new_val)
|
||||||
// tells UpdateOutput to either start or stop the force
|
Update();
|
||||||
m_state.size = new_val ? sizeof(params) : 0;
|
else
|
||||||
}
|
Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename P>
|
template <typename P>
|
||||||
ForceFeedbackDevice::Force<P>::Force(const std::string& name, EffectState& state)
|
ForceFeedbackDevice::Force<P>::Force(const std::string& name, LPDIRECTINPUTEFFECT iface)
|
||||||
: m_name(name), m_state(state)
|
: m_name(name), m_iface(iface)
|
||||||
{
|
{
|
||||||
memset(¶ms, 0, sizeof(params));
|
memset(¶ms, 0, sizeof(params));
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,25 +25,19 @@ namespace ForceFeedback
|
||||||
class ForceFeedbackDevice : public Core::Device
|
class ForceFeedbackDevice : public Core::Device
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
struct EffectState
|
|
||||||
{
|
|
||||||
EffectState(LPDIRECTINPUTEFFECT eff) : iface(eff), params(nullptr), size(0) {}
|
|
||||||
|
|
||||||
LPDIRECTINPUTEFFECT iface;
|
|
||||||
void* params; // null when force hasn't changed
|
|
||||||
u8 size; // zero when force should stop
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename P>
|
template <typename P>
|
||||||
class Force : public Output
|
class Force : public Output
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::string GetName() const;
|
std::string GetName() const;
|
||||||
Force(const std::string& name, EffectState& state);
|
Force(const std::string& name, LPDIRECTINPUTEFFECT iface);
|
||||||
|
~Force();
|
||||||
void SetState(ControlState state);
|
void SetState(ControlState state);
|
||||||
|
void Update();
|
||||||
|
void Stop();
|
||||||
private:
|
private:
|
||||||
const std::string m_name;
|
const std::string m_name;
|
||||||
EffectState& m_state;
|
LPDIRECTINPUTEFFECT m_iface;
|
||||||
P params;
|
P params;
|
||||||
};
|
};
|
||||||
typedef Force<DICONSTANTFORCE> ForceConstant;
|
typedef Force<DICONSTANTFORCE> ForceConstant;
|
||||||
|
@ -52,11 +46,6 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool InitForceFeedback(const LPDIRECTINPUTDEVICE8, int cAxes);
|
bool InitForceFeedback(const LPDIRECTINPUTDEVICE8, int cAxes);
|
||||||
bool UpdateOutput();
|
|
||||||
|
|
||||||
virtual ~ForceFeedbackDevice();
|
|
||||||
private:
|
|
||||||
std::list<EffectState> m_state_out;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -72,8 +72,6 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool UpdateInput();
|
|
||||||
|
|
||||||
Joystick(IOHIDDeviceRef device, std::string name, int index);
|
Joystick(IOHIDDeviceRef device, std::string name, int index);
|
||||||
~Joystick();
|
~Joystick();
|
||||||
|
|
||||||
|
|
|
@ -90,11 +90,6 @@ Joystick::~Joystick()
|
||||||
m_ff_device->Release();
|
m_ff_device->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Joystick::UpdateInput()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Joystick::GetName() const
|
std::string Joystick::GetName() const
|
||||||
{
|
{
|
||||||
return m_device_name;
|
return m_device_name;
|
||||||
|
|
|
@ -53,8 +53,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool UpdateInput();
|
void UpdateInput() override;
|
||||||
bool UpdateOutput();
|
|
||||||
|
|
||||||
Keyboard(IOHIDDeviceRef device, std::string name, int index, void *window);
|
Keyboard(IOHIDDeviceRef device, std::string name, int index, void *window);
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ Keyboard::Keyboard(IOHIDDeviceRef device, std::string name, int index, void *win
|
||||||
AddInput(new Button(i, m_mousebuttons[i]));
|
AddInput(new Button(i, m_mousebuttons[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Keyboard::UpdateInput()
|
void Keyboard::UpdateInput()
|
||||||
{
|
{
|
||||||
CGRect bounds = CGRectZero;
|
CGRect bounds = CGRectZero;
|
||||||
uint32_t windowid[1] = { m_windowid };
|
uint32_t windowid[1] = { m_windowid };
|
||||||
|
@ -85,13 +85,6 @@ bool Keyboard::UpdateInput()
|
||||||
m_mousebuttons[0] = CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, kCGMouseButtonLeft);
|
m_mousebuttons[0] = CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, kCGMouseButtonLeft);
|
||||||
m_mousebuttons[1] = CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, kCGMouseButtonRight);
|
m_mousebuttons[1] = CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, kCGMouseButtonRight);
|
||||||
m_mousebuttons[2] = CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, kCGMouseButtonCenter);
|
m_mousebuttons[2] = CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, kCGMouseButtonCenter);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Keyboard::UpdateOutput()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Keyboard::GetName() const
|
std::string Keyboard::GetName() const
|
||||||
|
|
|
@ -121,40 +121,26 @@ Joystick::Joystick(SDL_Joystick* const joystick, const int sdl_index, const unsi
|
||||||
|
|
||||||
// constant effect
|
// constant effect
|
||||||
if (supported_effects & SDL_HAPTIC_CONSTANT)
|
if (supported_effects & SDL_HAPTIC_CONSTANT)
|
||||||
{
|
AddOutput(new ConstantEffect(m_haptic));
|
||||||
m_state_out.push_back(EffectIDState());
|
|
||||||
AddOutput(new ConstantEffect(m_state_out.back()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ramp effect
|
// ramp effect
|
||||||
if (supported_effects & SDL_HAPTIC_RAMP)
|
if (supported_effects & SDL_HAPTIC_RAMP)
|
||||||
{
|
AddOutput(new RampEffect(m_haptic));
|
||||||
m_state_out.push_back(EffectIDState());
|
|
||||||
AddOutput(new RampEffect(m_state_out.back()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// sine effect
|
// sine effect
|
||||||
if (supported_effects & SDL_HAPTIC_SINE)
|
if (supported_effects & SDL_HAPTIC_SINE)
|
||||||
{
|
AddOutput(new SineEffect(m_haptic));
|
||||||
m_state_out.push_back(EffectIDState());
|
|
||||||
AddOutput(new SineEffect(m_state_out.back()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SDL_HAPTIC_SQUARE
|
#ifdef SDL_HAPTIC_SQUARE
|
||||||
// square effect
|
// square effect
|
||||||
if (supported_effects & SDL_HAPTIC_SQUARE)
|
if (supported_effects & SDL_HAPTIC_SQUARE)
|
||||||
{
|
AddOutput(new SquareEffect(m_haptic));
|
||||||
m_state_out.push_back(EffectIDState());
|
|
||||||
AddOutput(new SquareEffect(m_state_out.back()));
|
|
||||||
}
|
|
||||||
#endif // defined(SDL_HAPTIC_SQUARE)
|
#endif // defined(SDL_HAPTIC_SQUARE)
|
||||||
|
|
||||||
// triangle effect
|
// triangle effect
|
||||||
if (supported_effects & SDL_HAPTIC_TRIANGLE)
|
if (supported_effects & SDL_HAPTIC_TRIANGLE)
|
||||||
{
|
AddOutput(new TriangleEffect(m_haptic));
|
||||||
m_state_out.push_back(EffectIDState());
|
|
||||||
AddOutput(new TriangleEffect(m_state_out.back()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -167,13 +153,6 @@ Joystick::~Joystick()
|
||||||
{
|
{
|
||||||
// stop/destroy all effects
|
// stop/destroy all effects
|
||||||
SDL_HapticStopAll(m_haptic);
|
SDL_HapticStopAll(m_haptic);
|
||||||
for (auto &i : m_state_out)
|
|
||||||
{
|
|
||||||
if (i.id != -1)
|
|
||||||
{
|
|
||||||
SDL_HapticDestroyEffect(m_haptic, i.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// close haptic first
|
// close haptic first
|
||||||
SDL_HapticClose(m_haptic);
|
SDL_HapticClose(m_haptic);
|
||||||
}
|
}
|
||||||
|
@ -184,6 +163,26 @@ Joystick::~Joystick()
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_SDL_HAPTIC
|
#ifdef USE_SDL_HAPTIC
|
||||||
|
void Joystick::HapticEffect::Update()
|
||||||
|
{
|
||||||
|
if (m_id == -1 && m_effect.type > 0)
|
||||||
|
{
|
||||||
|
m_id = SDL_HapticNewEffect(m_haptic, &m_effect);
|
||||||
|
if (m_id > -1)
|
||||||
|
SDL_HapticRunEffect(m_haptic, m_id, 1);
|
||||||
|
}
|
||||||
|
else if (m_id > -1 && m_effect.type == 0)
|
||||||
|
{
|
||||||
|
SDL_HapticStopEffect(m_haptic, m_id);
|
||||||
|
SDL_HapticDestroyEffect(m_haptic, m_id);
|
||||||
|
m_id = -1;
|
||||||
|
}
|
||||||
|
else if (m_id > -1)
|
||||||
|
{
|
||||||
|
SDL_HapticUpdateEffect(m_haptic, m_id, &m_effect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string Joystick::ConstantEffect::GetName() const
|
std::string Joystick::ConstantEffect::GetName() const
|
||||||
{
|
{
|
||||||
return "Constant";
|
return "Constant";
|
||||||
|
@ -215,58 +214,51 @@ void Joystick::ConstantEffect::SetState(ControlState state)
|
||||||
{
|
{
|
||||||
if (state)
|
if (state)
|
||||||
{
|
{
|
||||||
m_effect.effect.type = SDL_HAPTIC_CONSTANT;
|
m_effect.type = SDL_HAPTIC_CONSTANT;
|
||||||
m_effect.effect.constant.length = SDL_HAPTIC_INFINITY;
|
m_effect.constant.length = SDL_HAPTIC_INFINITY;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_effect.effect.type = 0;
|
m_effect.type = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Sint16 old = m_effect.effect.constant.level;
|
m_effect.constant.level = (Sint16)(state * 0x7FFF);
|
||||||
m_effect.effect.constant.level = (Sint16)(state * 0x7FFF);
|
Update();
|
||||||
if (old != m_effect.effect.constant.level)
|
|
||||||
m_effect.changed = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Joystick::RampEffect::SetState(ControlState state)
|
void Joystick::RampEffect::SetState(ControlState state)
|
||||||
{
|
{
|
||||||
if (state)
|
if (state)
|
||||||
{
|
{
|
||||||
m_effect.effect.type = SDL_HAPTIC_RAMP;
|
m_effect.type = SDL_HAPTIC_RAMP;
|
||||||
m_effect.effect.ramp.length = SDL_HAPTIC_INFINITY;
|
m_effect.ramp.length = SDL_HAPTIC_INFINITY;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_effect.effect.type = 0;
|
m_effect.type = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Sint16 old = m_effect.effect.ramp.start;
|
m_effect.ramp.start = (Sint16)(state * 0x7FFF);
|
||||||
m_effect.effect.ramp.start = (Sint16)(state * 0x7FFF);
|
Update();
|
||||||
if (old != m_effect.effect.ramp.start)
|
|
||||||
m_effect.changed = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Joystick::SineEffect::SetState(ControlState state)
|
void Joystick::SineEffect::SetState(ControlState state)
|
||||||
{
|
{
|
||||||
if (state)
|
if (state)
|
||||||
{
|
{
|
||||||
m_effect.effect.type = SDL_HAPTIC_SINE;
|
m_effect.type = SDL_HAPTIC_SINE;
|
||||||
m_effect.effect.periodic.length = 250;
|
m_effect.periodic.length = 250;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_effect.effect.type = 0;
|
m_effect.type = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Sint16 old = m_effect.effect.periodic.magnitude;
|
m_effect.periodic.period = 5;
|
||||||
m_effect.effect.periodic.period = 5;
|
m_effect.periodic.magnitude = (Sint16)(state * 0x5000);
|
||||||
m_effect.effect.periodic.magnitude = (Sint16)(state * 0x5000);
|
m_effect.periodic.attack_length = 0;
|
||||||
m_effect.effect.periodic.attack_length = 0;
|
m_effect.periodic.fade_length = 500;
|
||||||
m_effect.effect.periodic.fade_length = 500;
|
Update();
|
||||||
|
|
||||||
if (old != m_effect.effect.periodic.magnitude)
|
|
||||||
m_effect.changed = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SDL_HAPTIC_SQUARE
|
#ifdef SDL_HAPTIC_SQUARE
|
||||||
|
@ -274,22 +266,19 @@ void Joystick::SquareEffect::SetState(ControlState state)
|
||||||
{
|
{
|
||||||
if (state)
|
if (state)
|
||||||
{
|
{
|
||||||
m_effect.effect.type = SDL_HAPTIC_SQUARE;
|
m_effect.type = SDL_HAPTIC_SQUARE;
|
||||||
m_effect.effect.periodic.length = 250;
|
m_effect.periodic.length = 250;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_effect.effect.type = 0;
|
m_effect.type = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Sint16 old = m_effect.effect.periodic.magnitude;
|
m_effect.periodic.period = 5;
|
||||||
m_effect.effect.periodic.period = 5;
|
m_effect.periodic.magnitude = state * 0x5000;
|
||||||
m_effect.effect.periodic.magnitude = state * 0x5000;
|
m_effect.periodic.attack_length = 0;
|
||||||
m_effect.effect.periodic.attack_length = 0;
|
m_effect.periodic.fade_length = 100;
|
||||||
m_effect.effect.periodic.fade_length = 100;
|
Update();
|
||||||
|
|
||||||
if (old != m_effect.effect.periodic.magnitude)
|
|
||||||
m_effect.changed = true;
|
|
||||||
}
|
}
|
||||||
#endif // defined(SDL_HAPTIC_SQUARE)
|
#endif // defined(SDL_HAPTIC_SQUARE)
|
||||||
|
|
||||||
|
@ -297,69 +286,26 @@ void Joystick::TriangleEffect::SetState(ControlState state)
|
||||||
{
|
{
|
||||||
if (state)
|
if (state)
|
||||||
{
|
{
|
||||||
m_effect.effect.type = SDL_HAPTIC_TRIANGLE;
|
m_effect.type = SDL_HAPTIC_TRIANGLE;
|
||||||
m_effect.effect.periodic.length = 250;
|
m_effect.periodic.length = 250;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_effect.effect.type = 0;
|
m_effect.type = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Sint16 old = m_effect.effect.periodic.magnitude;
|
m_effect.periodic.period = 5;
|
||||||
m_effect.effect.periodic.period = 5;
|
m_effect.periodic.magnitude = (Sint16)(state * 0x5000);
|
||||||
m_effect.effect.periodic.magnitude = (Sint16)(state * 0x5000);
|
m_effect.periodic.attack_length = 0;
|
||||||
m_effect.effect.periodic.attack_length = 0;
|
m_effect.periodic.fade_length = 100;
|
||||||
m_effect.effect.periodic.fade_length = 100;
|
Update();
|
||||||
|
|
||||||
if (old != m_effect.effect.periodic.magnitude)
|
|
||||||
m_effect.changed = true;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool Joystick::UpdateInput()
|
void Joystick::UpdateInput()
|
||||||
{
|
{
|
||||||
// each joystick is doin this, o well
|
// each joystick is doin this, o well
|
||||||
SDL_JoystickUpdate();
|
SDL_JoystickUpdate();
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Joystick::UpdateOutput()
|
|
||||||
{
|
|
||||||
#ifdef USE_SDL_HAPTIC
|
|
||||||
for (auto &i : m_state_out)
|
|
||||||
{
|
|
||||||
if (i.changed) // if SetState was called on this output
|
|
||||||
{
|
|
||||||
if (-1 == i.id) // effect isn't currently uploaded
|
|
||||||
{
|
|
||||||
if (i.effect.type) // if outputstate is >0 this would be true
|
|
||||||
{
|
|
||||||
if ((i.id = SDL_HapticNewEffect(m_haptic, &i.effect)) > -1) // upload the effect
|
|
||||||
{
|
|
||||||
SDL_HapticRunEffect(m_haptic, i.id, 1); // run the effect
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // effect is already uploaded
|
|
||||||
{
|
|
||||||
if (i.effect.type) // if ouputstate >0
|
|
||||||
{
|
|
||||||
SDL_HapticUpdateEffect(m_haptic, i.id, &i.effect); // update the effect
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SDL_HapticStopEffect(m_haptic, i.id); // else, stop and remove the effect
|
|
||||||
SDL_HapticDestroyEffect(m_haptic, i.id);
|
|
||||||
i.id = -1; // mark it as not uploaded
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
i.changed = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Joystick::GetName() const
|
std::string Joystick::GetName() const
|
||||||
|
|
|
@ -33,17 +33,6 @@ class Joystick : public Core::Device
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
#ifdef USE_SDL_HAPTIC
|
|
||||||
struct EffectIDState
|
|
||||||
{
|
|
||||||
EffectIDState() : effect(SDL_HapticEffect()), id(-1), changed(false) {}
|
|
||||||
|
|
||||||
SDL_HapticEffect effect;
|
|
||||||
int id;
|
|
||||||
bool changed;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class Button : public Core::Device::Input
|
class Button : public Core::Device::Input
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -80,62 +69,65 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef USE_SDL_HAPTIC
|
#ifdef USE_SDL_HAPTIC
|
||||||
class ConstantEffect : public Output
|
class HapticEffect : public Output
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::string GetName() const override;
|
HapticEffect(SDL_Haptic* haptic) : m_haptic(haptic), m_id(-1) {}
|
||||||
ConstantEffect(EffectIDState& effect) : m_effect(effect) {}
|
~HapticEffect() { m_effect.type = 0; Update(); }
|
||||||
void SetState(ControlState state) override;
|
|
||||||
private:
|
protected:
|
||||||
EffectIDState& m_effect;
|
void Update();
|
||||||
|
|
||||||
|
SDL_HapticEffect m_effect;
|
||||||
|
SDL_Haptic* m_haptic;
|
||||||
|
int m_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RampEffect : public Output
|
class ConstantEffect : public HapticEffect
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
ConstantEffect(SDL_Haptic* haptic) : HapticEffect(haptic) {}
|
||||||
std::string GetName() const override;
|
std::string GetName() const override;
|
||||||
RampEffect(EffectIDState& effect) : m_effect(effect) {}
|
|
||||||
void SetState(ControlState state) override;
|
void SetState(ControlState state) override;
|
||||||
private:
|
|
||||||
EffectIDState& m_effect;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SineEffect : public Output
|
class RampEffect : public HapticEffect
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
RampEffect(SDL_Haptic* haptic) : HapticEffect(haptic) {}
|
||||||
|
std::string GetName() const override;
|
||||||
|
void SetState(ControlState state) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SineEffect : public HapticEffect
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SineEffect(SDL_Haptic* haptic) : HapticEffect(haptic) {}
|
||||||
std::string GetName() const override;
|
std::string GetName() const override;
|
||||||
SineEffect(EffectIDState& effect) : m_effect(effect) {}
|
|
||||||
void SetState(ControlState state) override;
|
void SetState(ControlState state) override;
|
||||||
private:
|
|
||||||
EffectIDState& m_effect;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef SDL_HAPTIC_SQUARE
|
#ifdef SDL_HAPTIC_SQUARE
|
||||||
class SquareEffect : public Output
|
class SquareEffect : public HapticEffect
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
SquareEffect(SDL_Haptic* haptic) : HapticEffect(haptic) {}
|
||||||
std::string GetName() const;
|
std::string GetName() const;
|
||||||
SquareEffect(EffectIDState& effect) : m_effect(effect) {}
|
|
||||||
void SetState(ControlState state);
|
void SetState(ControlState state);
|
||||||
private:
|
|
||||||
EffectIDState& m_effect;
|
|
||||||
};
|
};
|
||||||
#endif // defined(SDL_HAPTIC_SQUARE)
|
#endif // defined(SDL_HAPTIC_SQUARE)
|
||||||
|
|
||||||
class TriangleEffect : public Output
|
class TriangleEffect : public HapticEffect
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
TriangleEffect(SDL_Haptic* haptic) : HapticEffect(haptic) {}
|
||||||
std::string GetName() const override;
|
std::string GetName() const override;
|
||||||
TriangleEffect(EffectIDState& effect) : m_effect(effect) {}
|
|
||||||
void SetState(ControlState state) override;
|
void SetState(ControlState state) override;
|
||||||
private:
|
|
||||||
EffectIDState& m_effect;
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool UpdateInput() override;
|
void UpdateInput() override;
|
||||||
bool UpdateOutput() override;
|
|
||||||
|
|
||||||
Joystick(SDL_Joystick* const joystick, const int sdl_index, const unsigned int index);
|
Joystick(SDL_Joystick* const joystick, const int sdl_index, const unsigned int index);
|
||||||
~Joystick();
|
~Joystick();
|
||||||
|
@ -150,7 +142,6 @@ private:
|
||||||
const unsigned int m_index;
|
const unsigned int m_index;
|
||||||
|
|
||||||
#ifdef USE_SDL_HAPTIC
|
#ifdef USE_SDL_HAPTIC
|
||||||
std::list<EffectIDState> m_state_out;
|
|
||||||
SDL_Haptic* m_haptic;
|
SDL_Haptic* m_haptic;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
@ -121,7 +121,6 @@ Device::Device(const XINPUT_CAPABILITIES& caps, u8 index)
|
||||||
: m_index(index), m_subtype(caps.SubType)
|
: m_index(index), m_subtype(caps.SubType)
|
||||||
{
|
{
|
||||||
ZeroMemory(&m_state_out, sizeof(m_state_out));
|
ZeroMemory(&m_state_out, sizeof(m_state_out));
|
||||||
ZeroMemory(&m_current_state_out, sizeof(m_current_state_out));
|
|
||||||
|
|
||||||
// XInputGetCaps seems to always claim all capabilities are supported
|
// XInputGetCaps seems to always claim all capabilities are supported
|
||||||
// but I will leave all this stuff in, incase m$ fixes xinput up a bit
|
// but I will leave all this stuff in, incase m$ fixes xinput up a bit
|
||||||
|
@ -162,14 +161,9 @@ Device::Device(const XINPUT_CAPABILITIES& caps, u8 index)
|
||||||
{
|
{
|
||||||
//WORD val = (&caps.Vibration.wLeftMotorSpeed)[i]; // should be max value / nope, more lies
|
//WORD val = (&caps.Vibration.wLeftMotorSpeed)[i]; // should be max value / nope, more lies
|
||||||
if ((&caps.Vibration.wLeftMotorSpeed)[i])
|
if ((&caps.Vibration.wLeftMotorSpeed)[i])
|
||||||
AddOutput(new Motor(i, (&m_state_out.wLeftMotorSpeed)[i], 65535));
|
AddOutput(new Motor(i, this, (&m_state_out.wLeftMotorSpeed)[i], 65535));
|
||||||
}
|
}
|
||||||
|
|
||||||
ClearInputState();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Device::ClearInputState()
|
|
||||||
{
|
|
||||||
ZeroMemory(&m_state_in, sizeof(m_state_in));
|
ZeroMemory(&m_state_in, sizeof(m_state_in));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,24 +202,14 @@ std::string Device::GetSource() const
|
||||||
|
|
||||||
// Update I/O
|
// Update I/O
|
||||||
|
|
||||||
bool Device::UpdateInput()
|
void Device::UpdateInput()
|
||||||
{
|
{
|
||||||
return (ERROR_SUCCESS == PXInputGetState(m_index, &m_state_in));
|
PXInputGetState(m_index, &m_state_in);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device::UpdateOutput()
|
void Device::UpdateMotors()
|
||||||
{
|
{
|
||||||
// this if statement is to make rumble work better when multiple ControllerInterfaces are using the device
|
PXInputSetState(m_index, &m_state_out);
|
||||||
// only calls XInputSetState if the state changed
|
|
||||||
if (memcmp(&m_state_out, &m_current_state_out, sizeof(m_state_out)))
|
|
||||||
{
|
|
||||||
m_current_state_out = m_state_out;
|
|
||||||
return (ERROR_SUCCESS == PXInputSetState(m_index, &m_state_out));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET name/source/id
|
// GET name/source/id
|
||||||
|
@ -270,6 +254,7 @@ ControlState Device::Axis::GetState() const
|
||||||
void Device::Motor::SetState(ControlState state)
|
void Device::Motor::SetState(ControlState state)
|
||||||
{
|
{
|
||||||
m_motor = (WORD)(state * m_range);
|
m_motor = (WORD)(state * m_range);
|
||||||
|
m_parent->UpdateMotors();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,19 +64,17 @@ private:
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::string GetName() const;
|
std::string GetName() const;
|
||||||
Motor(u8 index, WORD& motor, WORD range) : m_index(index), m_motor(motor), m_range(range) {}
|
Motor(u8 index, Device* parent, WORD &motor, WORD range) : m_index(index), m_parent(parent), m_motor(motor), m_range(range) {}
|
||||||
void SetState(ControlState state);
|
void SetState(ControlState state);
|
||||||
private:
|
private:
|
||||||
WORD& m_motor;
|
WORD& m_motor;
|
||||||
const WORD m_range;
|
const WORD m_range;
|
||||||
const u8 m_index;
|
const u8 m_index;
|
||||||
|
Device* m_parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool UpdateInput();
|
void UpdateInput() override;
|
||||||
bool UpdateOutput();
|
|
||||||
|
|
||||||
void ClearInputState();
|
|
||||||
|
|
||||||
Device(const XINPUT_CAPABILITIES& capabilities, u8 index);
|
Device(const XINPUT_CAPABILITIES& capabilities, u8 index);
|
||||||
|
|
||||||
|
@ -84,9 +82,11 @@ public:
|
||||||
int GetId() const;
|
int GetId() const;
|
||||||
std::string GetSource() const;
|
std::string GetSource() const;
|
||||||
|
|
||||||
|
void UpdateMotors();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
XINPUT_STATE m_state_in;
|
XINPUT_STATE m_state_in;
|
||||||
XINPUT_VIBRATION m_state_out, m_current_state_out;
|
XINPUT_VIBRATION m_state_out;
|
||||||
const BYTE m_subtype;
|
const BYTE m_subtype;
|
||||||
const u8 m_index;
|
const u8 m_index;
|
||||||
};
|
};
|
||||||
|
|
|
@ -208,7 +208,7 @@ void KeyboardMouse::UpdateCursor()
|
||||||
m_state.cursor.y = win_y / (float)win_attribs.height * 2 - 1;
|
m_state.cursor.y = win_y / (float)win_attribs.height * 2 - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KeyboardMouse::UpdateInput()
|
void KeyboardMouse::UpdateInput()
|
||||||
{
|
{
|
||||||
XFlush(m_display);
|
XFlush(m_display);
|
||||||
|
|
||||||
|
@ -282,13 +282,6 @@ bool KeyboardMouse::UpdateInput()
|
||||||
m_state.axis.y *= MOUSE_AXIS_SMOOTHING;
|
m_state.axis.y *= MOUSE_AXIS_SMOOTHING;
|
||||||
m_state.axis.y += delta_y;
|
m_state.axis.y += delta_y;
|
||||||
m_state.axis.y /= MOUSE_AXIS_SMOOTHING+1.0f;
|
m_state.axis.y /= MOUSE_AXIS_SMOOTHING+1.0f;
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KeyboardMouse::UpdateOutput()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KeyboardMouse::GetName() const
|
std::string KeyboardMouse::GetName() const
|
||||||
|
|
|
@ -98,8 +98,7 @@ private:
|
||||||
void UpdateCursor();
|
void UpdateCursor();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool UpdateInput() override;
|
void UpdateInput() override;
|
||||||
bool UpdateOutput() override;
|
|
||||||
|
|
||||||
KeyboardMouse(Window window, int opcode, int pointer_deviceid, int keyboard_deviceid);
|
KeyboardMouse(Window window, int opcode, int pointer_deviceid, int keyboard_deviceid);
|
||||||
~KeyboardMouse();
|
~KeyboardMouse();
|
||||||
|
|
|
@ -49,7 +49,7 @@ KeyboardMouse::~KeyboardMouse()
|
||||||
XCloseDisplay(m_display);
|
XCloseDisplay(m_display);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KeyboardMouse::UpdateInput()
|
void KeyboardMouse::UpdateInput()
|
||||||
{
|
{
|
||||||
XQueryKeymap(m_display, m_state.keyboard);
|
XQueryKeymap(m_display, m_state.keyboard);
|
||||||
|
|
||||||
|
@ -64,16 +64,8 @@ bool KeyboardMouse::UpdateInput()
|
||||||
// the mouse position as a range from -1 to 1
|
// the mouse position as a range from -1 to 1
|
||||||
m_state.cursor.x = (float)win_x / (float)win_attribs.width * 2 - 1;
|
m_state.cursor.x = (float)win_x / (float)win_attribs.width * 2 - 1;
|
||||||
m_state.cursor.y = (float)win_y / (float)win_attribs.height * 2 - 1;
|
m_state.cursor.y = (float)win_y / (float)win_attribs.height * 2 - 1;
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KeyboardMouse::UpdateOutput()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::string KeyboardMouse::GetName() const
|
std::string KeyboardMouse::GetName() const
|
||||||
{
|
{
|
||||||
return "Keyboard Mouse";
|
return "Keyboard Mouse";
|
||||||
|
|
|
@ -70,8 +70,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool UpdateInput() override;
|
void UpdateInput() override;
|
||||||
bool UpdateOutput() override;
|
|
||||||
|
|
||||||
KeyboardMouse(Window window);
|
KeyboardMouse(Window window);
|
||||||
~KeyboardMouse();
|
~KeyboardMouse();
|
||||||
|
|
Loading…
Reference in New Issue