diff --git a/Source/Core/Core/HW/SI_DeviceDanceMat.cpp b/Source/Core/Core/HW/SI_DeviceDanceMat.cpp index 8f64fc962c..ca12a9e343 100644 --- a/Source/Core/Core/HW/SI_DeviceDanceMat.cpp +++ b/Source/Core/Core/HW/SI_DeviceDanceMat.cpp @@ -2,250 +2,40 @@ // Licensed under GPLv2 // 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/SystemTimers.h" -// --- Dance mat GameCube controller --- CSIDevice_DanceMat::CSIDevice_DanceMat(SIDevices device, int _iDeviceNumber) - : ISIDevice(device, _iDeviceNumber) - , m_TButtonComboStart(0) - , m_TButtonCombo(0) - , m_LastButtonCombo(COMBO_NONE) + : CSIDevice_GCController(device, _iDeviceNumber) {} + +u32 CSIDevice_DanceMat::MapPadStatus(const GCPadStatus& pad_status) { - 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? - 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(_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(&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(&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 // Z = + button, Start = - button u16 map = 0; - if (PadStatus.button & PAD_BUTTON_UP) + if (pad_status.button & PAD_BUTTON_UP) map |= 0x1000; - if (PadStatus.button & PAD_BUTTON_DOWN) + if (pad_status.button & PAD_BUTTON_DOWN) map |= 0x2; - if (PadStatus.button & PAD_BUTTON_LEFT) + if (pad_status.button & PAD_BUTTON_LEFT) map |= 0x8; - if (PadStatus.button & PAD_BUTTON_RIGHT) + if (pad_status.button & PAD_BUTTON_RIGHT) map |= 0x4; - if (PadStatus.button & PAD_BUTTON_Y) + if (pad_status.button & PAD_BUTTON_Y) map |= 0x200; - if (PadStatus.button & PAD_BUTTON_A) + if (pad_status.button & PAD_BUTTON_A) map |= 0x10; - if (PadStatus.button & PAD_BUTTON_B) + if (pad_status.button & PAD_BUTTON_B) map |= 0x100; - if (PadStatus.button & PAD_BUTTON_X) + if (pad_status.button & PAD_BUTTON_X) map |= 0x800; - if (PadStatus.button & PAD_TRIGGER_Z) + if (pad_status.button & PAD_TRIGGER_Z) map |= 0x400; - if (PadStatus.button & PAD_BUTTON_START) + if (pad_status.button & PAD_BUTTON_START) map |= 0x1; - _Hi = (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; + return (u32)(map << 16) | 0x8080; } - -// SendCommand -void CSIDevice_DanceMat::SendCommand(u32 _Cmd, u8 _Poll) +void CSIDevice_DanceMat::HandleButtonCombos(const GCPadStatus& pad_status) { - 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); } diff --git a/Source/Core/Core/HW/SI_DeviceDanceMat.h b/Source/Core/Core/HW/SI_DeviceDanceMat.h index 3eaf5c4be8..16711d254f 100644 --- a/Source/Core/Core/HW/SI_DeviceDanceMat.h +++ b/Source/Core/Core/HW/SI_DeviceDanceMat.h @@ -4,98 +4,12 @@ #pragma once -#include "Core/HW/SI_Device.h" -#include "InputCommon/GCPadStatus.h" +#include "Core/HW/SI_DeviceGCController.h" -// standard GameCube controller -class CSIDevice_DanceMat : public ISIDevice +class CSIDevice_DanceMat : public CSIDevice_GCController { -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: - - // Constructor CSIDevice_DanceMat(SIDevices device, int _iDeviceNumber); - - // 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; + virtual u32 MapPadStatus(const GCPadStatus& pad_status) override; + virtual void HandleButtonCombos(const GCPadStatus& pad_status) override; }; diff --git a/Source/Core/Core/HW/SI_DeviceGCController.cpp b/Source/Core/Core/HW/SI_DeviceGCController.cpp index f3c6efcbb0..fa01873adf 100644 --- a/Source/Core/Core/HW/SI_DeviceGCController.cpp +++ b/Source/Core/Core/HW/SI_DeviceGCController.cpp @@ -131,10 +131,7 @@ bool CSIDevice_GCController::GetData(u32& _Hi, u32& _Low) Movie::CheckPadStatus(&PadStatus, ISIDevice::m_iDeviceNumber); } - // Thankfully changing mode does not change the high bits ;) - _Hi = (u32)((u8)PadStatus.stickY); - _Hi |= (u32)((u8)PadStatus.stickX << 8); - _Hi |= (u32)((u16)(PadStatus.button | PAD_USE_ORIGIN) << 16); + _Hi = MapPadStatus(PadStatus); // Low bits are packed differently per mode 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 } + 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... :( ) 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; - 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; else tempCombo = COMBO_NONE; @@ -204,21 +217,18 @@ bool CSIDevice_GCController::GetData(u32& _Hi, u32& _Low) 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_Origin.uOriginStickX = pad_status.stickX; + m_Origin.uOriginStickY = pad_status.stickY; + m_Origin.uSubStickStickX = pad_status.substickX; + m_Origin.uSubStickStickY = pad_status.substickY; + m_Origin.uTrigger_L = pad_status.triggerLeft; + m_Origin.uTrigger_R = pad_status.triggerRight; } m_LastButtonCombo = COMBO_NONE; } } - - return true; } - // SendCommand void CSIDevice_GCController::SendCommand(u32 _Cmd, u8 _Poll) { diff --git a/Source/Core/Core/HW/SI_DeviceGCController.h b/Source/Core/Core/HW/SI_DeviceGCController.h index 254df8d233..403b5a6dad 100644 --- a/Source/Core/Core/HW/SI_DeviceGCController.h +++ b/Source/Core/Core/HW/SI_DeviceGCController.h @@ -7,11 +7,9 @@ #include "Core/HW/SI_Device.h" #include "InputCommon/GCPadStatus.h" - -// standard GameCube controller class CSIDevice_GCController : public ISIDevice { -private: +protected: // Commands enum EBufferCommands @@ -24,8 +22,8 @@ private: struct SOrigin { - u8 uCommand;// Maybe should be button bits? - u8 unk_1; // ..and this would be the other half + u8 uCommand; // Maybe should be button bits? + u8 unk_1; // ..and this would be the other half u8 uOriginStickX; u8 uOriginStickY; u8 uSubStickStickX; @@ -94,6 +92,9 @@ public: // Return true on new data 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 virtual void SendCommand(u32 _Cmd, u8 _Poll) override; diff --git a/Source/Core/Core/HW/SI_DeviceGCSteeringWheel.cpp b/Source/Core/Core/HW/SI_DeviceGCSteeringWheel.cpp index bf803c5ce0..61f8150de4 100644 --- a/Source/Core/Core/HW/SI_DeviceGCSteeringWheel.cpp +++ b/Source/Core/Core/HW/SI_DeviceGCSteeringWheel.cpp @@ -2,292 +2,36 @@ // Licensed under GPLv2 // 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_DeviceGCSteeringWheel.h" -#include "Core/HW/SystemTimers.h" -// --- standard GameCube controller --- CSIDevice_GCSteeringWheel::CSIDevice_GCSteeringWheel(SIDevices device, int _iDeviceNumber) - : ISIDevice(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; + : CSIDevice_GCController(device, _iDeviceNumber) +{} - // 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(_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(&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(&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) { UCommand command(_Cmd); - switch (command.Command) + if (command.Command == CMD_FORCE) { - // Costis sent it in some demos :) - case 0x00: - break; + 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 - case CMD_FORCE: + // get the correct pad number that should rumble locally when using netplay + const u8 numPAD = NetPlay_InGamePadToLocalPad(ISIDevice::m_iDeviceNumber); + + if (numPAD < 4) + Pad::Motor(numPAD, uType, uStrength); + + if (!_Poll) { - 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 - - // get the correct pad number that should rumble locally when using netplay - const u8 numPAD = NetPlay_InGamePadToLocalPad(ISIDevice::m_iDeviceNumber); - - if (numPAD < 4) - Pad::Motor(numPAD, uType, uStrength); - - if (!_Poll) - { - m_Mode = command.Parameter2; - INFO_LOG(SERIALINTERFACE, "PAD %i set to mode %i", ISIDevice::m_iDeviceNumber, m_Mode); - } + m_Mode = command.Parameter2; + INFO_LOG(SERIALINTERFACE, "PAD %i set to mode %i", ISIDevice::m_iDeviceNumber, m_Mode); } - 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); - } - break; + } + else + { + return CSIDevice_GCController::SendCommand(_Cmd, _Poll); } } - -// 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); -} diff --git a/Source/Core/Core/HW/SI_DeviceGCSteeringWheel.h b/Source/Core/Core/HW/SI_DeviceGCSteeringWheel.h index 6e231436f8..b5853713fa 100644 --- a/Source/Core/Core/HW/SI_DeviceGCSteeringWheel.h +++ b/Source/Core/Core/HW/SI_DeviceGCSteeringWheel.h @@ -4,14 +4,11 @@ #pragma once -#include "Core/HW/SI_Device.h" -#include "InputCommon/GCPadStatus.h" +#include "Core/HW/SI_DeviceGCController.h" -// standard GameCube controller -class CSIDevice_GCSteeringWheel : public ISIDevice +class CSIDevice_GCSteeringWheel : public CSIDevice_GCController { private: - // Commands enum EBufferCommands { @@ -21,82 +18,13 @@ private: 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 { CMD_FORCE = 0x30, 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: - - // Constructor CSIDevice_GCSteeringWheel(SIDevices device, int _iDeviceNumber); - - // 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; + virtual void SendCommand(u32 _Cmd, u8 _Poll); }; diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp index 1f664f0ccd..bcabce5742 100644 --- a/Source/Core/Core/NetPlayClient.cpp +++ b/Source/Core/Core/NetPlayClient.cpp @@ -835,16 +835,6 @@ bool WiimoteEmu::Wiimote::NetPlay_GetWiimoteData(int wiimote, u8* data, u8 size) 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 // so all players' games get the same time u32 CEXIIPL::NetPlay_GetGCTime() @@ -869,16 +859,6 @@ u8 CSIDevice_GCController::NetPlay_InGamePadToLocalPad(u8 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() { return netplay_client != nullptr;