Initial CDolphinController RE

This commit is contained in:
Phillip Stephens 2022-03-19 21:19:43 -07:00
parent ec430567c3
commit a96fe24260
Signed by: Antidote
GPG Key ID: F8BEE4C83DACA60D
16 changed files with 293 additions and 13 deletions

View File

@ -0,0 +1,22 @@
#pragma once
namespace metaforce {
enum class EJoyAxis {
LeftX,
LeftY,
RightX,
RightY,
MAX
};
class CControllerAxis {
float x0_absolute = 0.f;
float x4_relative = 0.f;
public:
void SetRelativeValue(float val) { x0_absolute = val; }
float GetRelativeValue() const { return x0_absolute; }
void SetAbsoluteValue(float val) { x4_relative = val; }
float GetAbsoluteValue() const { return x4_relative; }
};
} // namespace metaforce

View File

@ -0,0 +1,39 @@
#pragma once
#include "Runtime/GCNTypes.hpp"
namespace metaforce {
enum class EButton {
A,
B,
X,
Y,
Start,
Z,
Up,
Right,
Down,
Left,
L,
R,
MAX,
};
enum class EAnalogButton {
Left,
Right
};
class CControllerButton {
bool x0_;
bool x1_pressed;
bool x2_;
public:
void SetIsPressed(bool pressed) { x1_pressed = pressed; }
[[nodiscard]] bool GetIsPressed() const { return x1_pressed; }
void SetPressEvent(bool press);
[[nodiscard]] bool GetPressEvent() const;
void SetReleaseEvent(bool release);
};
} // namespace metaforce

View File

@ -0,0 +1,4 @@
#include "Runtime/Input/CControllerGamepadData.hpp"
namespace metaforce {
}

View File

@ -0,0 +1,28 @@
#pragma once
#include "Runtime/Input/CControllerAxis.hpp"
#include "Runtime/Input/CControllerButton.hpp"
#include <array>
namespace metaforce {
class CControllerGamepadData {
bool x0_present;
std::array<CControllerAxis, 4> x4_axes;
std::array<CControllerAxis, 2> x24_triggers;
std::array<CControllerButton, 12> x34_buttons;
public:
void SetDeviceIsPresent(bool present) { x0_present = present; }
[[nodiscard]] bool DeviceIsPresent() const { return x0_present; }
[[nodiscard]] const CControllerAxis& GetAxis(EJoyAxis axis) const { return x4_axes[u32(axis)]; }
[[nodiscard]] CControllerAxis& GetAxis(EJoyAxis axis) { return x4_axes[u32(axis)]; }
[[nodiscard]] const CControllerButton& GetButton(EButton button) const { return x34_buttons[u32(button)]; }
[[nodiscard]] CControllerButton& GetButton(EButton button) { return x34_buttons[u32(button)]; }
[[nodiscard]] const CControllerAxis& GetAnalogButton(EAnalogButton button) const { return x24_triggers[u32(button)]; }
[[nodiscard]] CControllerAxis& GetAnalogButton(EAnalogButton button) { return x24_triggers[u32(button)]; }
};
} // namespace metaforce

View File

@ -0,0 +1,98 @@
#include "Runtime/Input/CDolphinController.hpp"
namespace PAD {
// clang-format off
enum BUTTON : u16 {
LEFT = 0x0001,
RIGHT = 0x0002,
DOWN = 0x0004,
UP = 0x0008,
TRIGGER_Z = 0x0010,
TRIGGER_R = 0x0020,
TRIGGER_L = 0x0040,
BUTTON_A = 0x0100,
BUTTON_B = 0x0200,
BUTTON_X = 0x0400,
BUTTON_Y = 0x0800,
BUTTON_START = 0x1000,
};
// clang-format on
} // namespace PAD
namespace metaforce {
CDolphinController::CDolphinController() {
static bool sIsInitialized = false;
if (!sIsInitialized) {
// PADSetSpec(5);
// PADInit();
sIsInitialized = true;
}
}
void CDolphinController::SetMotorState(EIOPort port, EMotorState state) { x194_motorStates[u32(port)] = state; }
float CDolphinController::GetAnalogStickMaxValue(EJoyAxis axis) {
if (axis >= EJoyAxis::LeftX && axis <= EJoyAxis::LeftY) {
return 72.f;
}
if (axis >= EJoyAxis::RightX && axis <= EJoyAxis::RightY) {
return 59.f;
}
return 0.f;
}
void CDolphinController::ProcessAxis(u32 controller, EJoyAxis axis) {
const auto maxAxisValue = GetAnalogStickMaxValue(axis);
auto& data = x34_gamepadStates[controller].GetAxis(axis);
float axisValue = 0.f;
if (axis == EJoyAxis::LeftX) {
axisValue = x4_status[controller].x2_stickX;
} else if (axis == EJoyAxis::LeftY) {
axisValue = x4_status[controller].x3_stickY;
} else if (axis == EJoyAxis::RightX) {
axisValue = x4_status[controller].x4_substickX;
} else if (axis == EJoyAxis::RightY) {
axisValue = x4_status[controller].x5_substickY;
}
axisValue *= 1.f / maxAxisValue;
float absolute = kAbsoluteMinimum;
if (axisValue < kAbsoluteMinimum) {
absolute = kAbsoluteMinimum;
} else if (axisValue > kAbsoluteMaximum) {
absolute = kAbsoluteMaximum;
}
axisValue = absolute - data.GetAbsoluteValue();
float relativeValue = kRelativeMinimum;
if (axisValue < kRelativeMinimum) {
relativeValue = kRelativeMinimum;
} else if (axisValue > kRelativeMaximum) {
relativeValue = kRelativeMaximum;
}
data.SetAbsoluteValue(absolute);
data.SetRelativeValue(relativeValue);
}
static constexpr std::array<u16, size_t(EButton::MAX)> mButtonMapping{
PAD::BUTTON_A, PAD::BUTTON_B, PAD::BUTTON_X, PAD::BUTTON_Y, PAD::BUTTON_START, PAD::TRIGGER_Z,
PAD::UP, PAD::RIGHT, PAD::DOWN, PAD::LEFT, PAD::TRIGGER_L, PAD::TRIGGER_R,
};
void CDolphinController::ProcessButtons(u32 controller) {
for (u32 i = 0; i < u32(EButton::MAX); ++i) {
ProcessDigitalButton(controller, x34_gamepadStates[controller].GetButton(EButton(i)), mButtonMapping[i]);
}
ProcessAnalogButton(x4_status[controller].x6_triggerL,
x34_gamepadStates[controller].GetAnalogButton(EAnalogButton::Left));
ProcessAnalogButton(x4_status[controller].x7_triggerR,
x34_gamepadStates[controller].GetAnalogButton(EAnalogButton::Right));
}
void CDolphinController::ProcessDigitalButton(u32 controller, CControllerButton& button, u16 mapping) {}
void CDolphinController::ProcessAnalogButton(float value, CControllerAxis& axis) {}
void CDolphinController::Initialize() {}
} // namespace metaforce

View File

@ -0,0 +1,48 @@
#pragma once
#include "Runtime/Input/IController.hpp"
namespace metaforce {
struct PADStatus {
u16 x0_buttons;
s8 x2_stickX;
s8 x3_stickY;
s8 x4_substickX;
s8 x5_substickY;
u8 x6_triggerL;
u8 x7_triggerR;
u8 x8_analogA;
u8 x9_analogB;
s8 xa_err;
};
class CDolphinController : public IController {
std::array<PADStatus, 4> x4_status;
std::array<CControllerGamepadData, 4> x34_gamepadStates{};
std::array<EMotorState, 4> x194_motorStates;
std::array<u32, 4> x1a4_controllerTypes{};
std::array<u32, 4> x1b4_{};
u32 x1c4_ = 0xf0000000;
u32 x1c8_ = 0;
u32 x1cc_ = 0;
public:
CDolphinController();
void Poll() override{};
[[nodiscard]] u32 GetDeviceCount() const override { return 4; };
[[nodiscard]] CControllerGamepadData& GetGamepadData(u32 controller) override {
return x34_gamepadStates[controller];
};
[[nodiscard]] u32 GetControllerType(u32 controller) const override { return x1a4_controllerTypes[controller]; }
void SetMotorState(EIOPort port, EMotorState state) override;
float GetAnalogStickMaxValue(EJoyAxis axis);
void ProcessAxis(u32 controller, EJoyAxis axis);
void ProcessButtons(u32 controller);
void ProcessDigitalButton(u32 controller, CControllerButton& button, u16 mapping);
void ProcessAnalogButton(float value, CControllerAxis& axis);
void Initialize();
};
} // namespace metaforce

View File

@ -4,16 +4,13 @@
#include <atomic>
#include <mutex>
#include "Runtime/Input/InputTypes.hpp"
#include "Runtime/Input/CFinalInput.hpp"
#include "Runtime/Input/CKeyboardMouseController.hpp"
namespace metaforce {
class CArchitectureQueue;
enum class EIOPort { Zero, One, Two, Three };
enum class EMotorState { Stop, Rumble, StopHard };
class CInputGenerator /*: public boo::DeviceFinder*/ {
enum class EStatusChange { NoChange = 0, Connected = 1, Disconnected = 2 };
@ -152,7 +149,7 @@ public:
// }
void SetMotorState(EIOPort port, EMotorState state);
void ControlAllMotors(const std::array<EMotorState, 4>& states) {
for (u32 i = 0; i <= size_t(EIOPort::Three); ++i ) {
for (u32 i = 0; i <= size_t(EIOPort::Player4); ++i ) {
SetMotorState(EIOPort(i), states[i]);
}
}

View File

@ -1,5 +1,9 @@
set(INPUT_SOURCES
IController.hpp
IController.hpp DolphinIController.cpp
CControllerAxis.hpp
CControllerButton.hpp
CControllerGamepadData.hpp CControllerGamepadData.cpp
CDolphinController.hpp CDolphinController.cpp
CKeyboardMouseController.hpp
ControlMapper.hpp ControlMapper.cpp
CInputGenerator.hpp CInputGenerator.cpp

View File

@ -20,7 +20,7 @@ s16 CRumbleManager::Rumble(CStateManager& mgr, const zeus::CVector3f& pos, ERumb
s16 CRumbleManager::Rumble(CStateManager& mgr, ERumbleFxId fx, float gain, ERumblePriority priority) {
if (g_GameState->GameOptions().GetIsRumbleEnabled())
return x0_rumbleGenerator.Rumble(RumbleFxTable[size_t(fx)], gain, priority, EIOPort::Zero);
return x0_rumbleGenerator.Rumble(RumbleFxTable[size_t(fx)], gain, priority, EIOPort::Player1);
return -1;
}

View File

@ -17,7 +17,7 @@ public:
void StopRumble(s16 id) {
if (id == -1)
return;
x0_rumbleGenerator.Stop(id, EIOPort::Zero);
x0_rumbleGenerator.Stop(id, EIOPort::Player1);
}
void HardStopAll() { x0_rumbleGenerator.HardStopAll(); }
s16 Rumble(CStateManager& mgr, const zeus::CVector3f& pos, ERumbleFxId fx, float dist, ERumblePriority priority);

View File

@ -0,0 +1,10 @@
#include "Runtime/Input/IController.hpp"
#include "Runtime/Input/CDolphinController.hpp"
namespace metaforce {
IController* IController::Create() {
CDolphinController* cont = new CDolphinController();
cont->Initialize();
return cont;
}
}

View File

@ -1,12 +1,26 @@
#pragma once
#include "Runtime/Input/InputTypes.hpp"
#include "Runtime/Input/CControllerGamepadData.hpp"
#include "Runtime/GCNTypes.hpp"
namespace metaforce {
class IController {
protected:
static constexpr float kAbsoluteMinimum = -1.f;
static constexpr float kAbsoluteMaximum = 1.f;
static constexpr float kRelativeMinimum = -1.f;
static constexpr float kRelativeMaximum = 1.f;
public:
enum class EMotorState { Stop = 0, Rumble = 1, StopHard = 2 };
virtual void Poll() = 0;
virtual void SetMotorState(EMotorState state) = 0;
virtual u32 GetDeviceCount() const = 0;
virtual CControllerGamepadData& GetGamepadData(u32 controller) = 0;
virtual u32 GetControllerType(u32 controller) const = 0;
virtual void SetMotorState(EIOPort port, EMotorState state) = 0;
static IController* Create();
};
} // namespace metaforce

View File

@ -0,0 +1,16 @@
#pragma once
namespace metaforce {
enum class EIOPort {
Player1,
Player2,
Player3,
Player4,
};
enum class EMotorState {
Stop = 0,
Rumble = 1,
StopHard = 2,
};
} // namespace metaforce

View File

@ -1395,7 +1395,7 @@ void CFrontEndUI::SOptionsFrontEndFrame::DoMenuSelectionChange(CGuiTableGroup* c
if (option.option == EGameOption::Rumble && caller->GetUserSelection() > 0) {
x40_rumbleGen.HardStopAll();
x40_rumbleGen.Rumble(RumbleFxTable[size_t(ERumbleFxId::PlayerBump)], 1.f, ERumblePriority::One, EIOPort::Zero);
x40_rumbleGen.Rumble(RumbleFxTable[size_t(ERumbleFxId::PlayerBump)], 1.f, ERumblePriority::One, EIOPort::Player1);
}
}
}

View File

@ -629,7 +629,7 @@ void CInGameGuiManager::ShowPauseGameHudMessage(CStateManager& stateMgr, CAssetI
}
void CInGameGuiManager::PauseGame(CStateManager& stateMgr, EInGameGuiState state) {
g_InputGenerator->SetMotorState(EIOPort::Zero, EMotorState::Stop);
g_InputGenerator->SetMotorState(EIOPort::Player1, EMotorState::Stop);
CSfxManager::SetChannel(CSfxManager::ESfxChannels::PauseScreen);
BeginStateTransition(state, stateMgr);
}

View File

@ -85,7 +85,7 @@ void COptionsScreen::OnEnumChanged(CGuiTableGroup* caller, int oldSel) {
if (opt == EGameOption::Rumble && caller->GetUserSelection() > 0) {
x1a8_rumble.HardStopAll();
x1a8_rumble.Rumble(RumbleFxTable[size_t(ERumbleFxId::PlayerBump)], 1.f, ERumblePriority::One, EIOPort::Zero);
x1a8_rumble.Rumble(RumbleFxTable[size_t(ERumbleFxId::PlayerBump)], 1.f, ERumblePriority::One, EIOPort::Player1);
}
CPauseScreenBase::UpdateSideTable(caller);