Merge pull request #36 from lioncash/array

DolphinSmashAdapter: Make use of std::array where applicable
This commit is contained in:
Phillip Stephens 2019-09-06 23:23:08 -07:00 committed by GitHub
commit 85bdc694bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 87 additions and 84 deletions

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <array>
#include <cstddef>
#include <cstdint> #include <cstdint>
#include "boo/System.hpp" #include "boo/System.hpp"
@ -31,42 +33,33 @@ enum class EDolphinControllerButtons {
ENABLE_BITWISE_ENUM(EDolphinControllerButtons) ENABLE_BITWISE_ENUM(EDolphinControllerButtons)
struct DolphinControllerState { struct DolphinControllerState {
int16_t m_leftStick[2] = {0}; std::array<int16_t, 2> m_leftStick{};
int16_t m_rightStick[2] = {0}; std::array<int16_t, 2> m_rightStick{};
int16_t m_analogTriggers[2] = {0}; std::array<int16_t, 2> m_analogTriggers{};
uint16_t m_btns = 0; uint16_t m_btns = 0;
void reset() { void reset() {
m_leftStick[0] = 0; m_leftStick = {};
m_leftStick[1] = 0; m_rightStick = {};
m_rightStick[0] = 0; m_analogTriggers = {};
m_rightStick[1] = 0;
m_analogTriggers[0] = 0;
m_analogTriggers[1] = 0;
m_btns = 0; m_btns = 0;
} }
void clamp(); void clamp();
}; };
struct IDolphinSmashAdapterCallback { struct IDolphinSmashAdapterCallback {
virtual void controllerConnected(unsigned idx, EDolphinControllerType type) { virtual void controllerConnected([[maybe_unused]] unsigned idx, [[maybe_unused]] EDolphinControllerType type) {}
(void)idx; virtual void controllerDisconnected([[maybe_unused]] unsigned idx) {}
(void)type; virtual void controllerUpdate([[maybe_unused]] unsigned idx, [[maybe_unused]] EDolphinControllerType type,
} [[maybe_unused]] const DolphinControllerState& state) {}
virtual void controllerDisconnected(unsigned idx) { (void)idx; }
virtual void controllerUpdate(unsigned idx, EDolphinControllerType type, const DolphinControllerState& state) {
(void)idx;
(void)type;
(void)state;
}
}; };
class DolphinSmashAdapter final : public TDeviceBase<IDolphinSmashAdapterCallback> { class DolphinSmashAdapter final : public TDeviceBase<IDolphinSmashAdapterCallback> {
int16_t m_leftStickCal[2] = {0x7f}; std::array<int16_t, 2> m_leftStickCal{0x7f, 0};
int16_t m_rightStickCal[2] = {0x7f}; std::array<int16_t, 2> m_rightStickCal{0x7f, 0};
int16_t m_triggersCal[2] = {0x0}; std::array<int16_t, 2> m_triggersCal{};
uint8_t m_knownControllers = 0; uint8_t m_knownControllers = 0;
uint8_t m_rumbleRequest = 0; uint8_t m_rumbleRequest = 0;
bool m_hardStop[4] = {false}; std::array<bool, 4> m_hardStop{};
uint8_t m_rumbleState = 0xf; /* Force initial send of stop-rumble command */ uint8_t m_rumbleState = 0xf; /* Force initial send of stop-rumble command */
void deviceDisconnected() override; void deviceDisconnected() override;
void initialCycle() override; void initialCycle() override;
@ -81,15 +74,21 @@ public:
TDeviceBase<IDolphinSmashAdapterCallback>::setCallback(cb); TDeviceBase<IDolphinSmashAdapterCallback>::setCallback(cb);
m_knownControllers = 0; m_knownControllers = 0;
} }
void startRumble(unsigned idx) {
if (idx >= 4) void startRumble(size_t idx) {
if (idx >= m_hardStop.size()) {
return; return;
m_rumbleRequest |= 1 << idx;
} }
void stopRumble(unsigned idx, bool hard = false) {
if (idx >= 4) m_rumbleRequest |= 1U << idx;
}
void stopRumble(size_t idx, bool hard = false) {
if (idx >= m_hardStop.size()) {
return; return;
m_rumbleRequest &= ~(1 << idx); }
m_rumbleRequest &= ~(1U << idx);
m_hardStop[idx] = hard; m_hardStop[idx] = hard;
} }
}; };

View File

@ -1,9 +1,6 @@
#include "boo/inputdev/DolphinSmashAdapter.hpp" #include "boo/inputdev/DolphinSmashAdapter.hpp"
#include "boo/inputdev/DeviceSignature.hpp" #include "boo/inputdev/DeviceSignature.hpp"
#include <cstdio>
#include <cstring>
namespace boo { namespace boo {
/* /*
* Reference: https://github.com/ToadKing/wii-u-gc-adapter/blob/master/wii-u-gc-adapter.c * Reference: https://github.com/ToadKing/wii-u-gc-adapter/blob/master/wii-u-gc-adapter.c
@ -14,9 +11,10 @@ DolphinSmashAdapter::DolphinSmashAdapter(DeviceToken* token)
DolphinSmashAdapter::~DolphinSmashAdapter() {} DolphinSmashAdapter::~DolphinSmashAdapter() {}
constexpr EDolphinControllerType parseType(unsigned char status) { static constexpr EDolphinControllerType parseType(unsigned char status) {
EDolphinControllerType type = const auto type =
EDolphinControllerType(status) & (EDolphinControllerType::Normal | EDolphinControllerType::Wavebird); EDolphinControllerType(status) & (EDolphinControllerType::Normal | EDolphinControllerType::Wavebird);
switch (type) { switch (type) {
case EDolphinControllerType::Normal: case EDolphinControllerType::Normal:
case EDolphinControllerType::Wavebird: case EDolphinControllerType::Wavebird:
@ -26,13 +24,13 @@ constexpr EDolphinControllerType parseType(unsigned char status) {
} }
} }
static EDolphinControllerType parseState(DolphinControllerState* stateOut, uint8_t* payload, bool& rumble) { static EDolphinControllerType parseState(DolphinControllerState* stateOut, const uint8_t* payload, bool& rumble) {
unsigned char status = payload[0]; const unsigned char status = payload[0];
EDolphinControllerType type = parseType(status); const EDolphinControllerType type = parseType(status);
rumble = ((status & 0x04) != 0) ? true : false; rumble = ((status & 0x04) != 0) ? true : false;
stateOut->m_btns = (uint16_t)payload[1] << 8 | (uint16_t)payload[2]; stateOut->m_btns = static_cast<uint16_t>(payload[1]) << 8 | static_cast<uint16_t>(payload[2]);
stateOut->m_leftStick[0] = payload[3]; stateOut->m_leftStick[0] = payload[3];
stateOut->m_leftStick[1] = payload[4]; stateOut->m_leftStick[1] = payload[4];
@ -45,43 +43,44 @@ static EDolphinControllerType parseState(DolphinControllerState* stateOut, uint8
} }
void DolphinSmashAdapter::initialCycle() { void DolphinSmashAdapter::initialCycle() {
uint8_t handshakePayload[] = {0x13}; constexpr std::array<uint8_t, 1> handshakePayload{0x13};
sendUSBInterruptTransfer(handshakePayload, sizeof(handshakePayload)); sendUSBInterruptTransfer(handshakePayload.data(), handshakePayload.size());
} }
void DolphinSmashAdapter::transferCycle() { void DolphinSmashAdapter::transferCycle() {
uint8_t payload[37]; std::array<uint8_t, 37> payload;
size_t recvSz = receiveUSBInterruptTransfer(payload, sizeof(payload)); const size_t recvSz = receiveUSBInterruptTransfer(payload.data(), payload.size());
if (recvSz != 37 || payload[0] != 0x21) if (recvSz != payload.size() || payload[0] != 0x21) {
return; return;
}
// fmt::print("RECEIVED DATA {} {:02X}\n", recvSz, payload[0]); // fmt::print("RECEIVED DATA {} {:02X}\n", recvSz, payload[0]);
std::lock_guard<std::mutex> lk(m_callbackLock); std::lock_guard<std::mutex> lk(m_callbackLock);
if (!m_callback) if (!m_callback) {
return; return;
}
/* Parse controller states */ /* Parse controller states */
uint8_t* controller = &payload[1]; const uint8_t* controller = &payload[1];
uint8_t rumbleMask = 0; uint8_t rumbleMask = 0;
for (uint32_t i = 0; i < 4; i++, controller += 9) { for (uint32_t i = 0; i < 4; i++, controller += 9) {
DolphinControllerState state; DolphinControllerState state;
bool rumble = false; bool rumble = false;
EDolphinControllerType type = parseState(&state, controller, rumble); const EDolphinControllerType type = parseState(&state, controller, rumble);
if (True(type) && !(m_knownControllers & 1 << i)) {
m_leftStickCal[0] = state.m_leftStick[0]; if (True(type) && (m_knownControllers & (1U << i)) == 0) {
m_leftStickCal[1] = state.m_leftStick[1]; m_leftStickCal = state.m_leftStick;
m_rightStickCal[0] = state.m_rightStick[0]; m_rightStickCal = state.m_rightStick;
m_rightStickCal[1] = state.m_rightStick[1]; m_triggersCal = state.m_analogTriggers;
m_triggersCal[0] = state.m_analogTriggers[0]; m_knownControllers |= 1U << i;
m_triggersCal[1] = state.m_analogTriggers[1];
m_knownControllers |= 1 << i;
m_callback->controllerConnected(i, type); m_callback->controllerConnected(i, type);
} else if (False(type) && (m_knownControllers & 1 << i)) { } else if (False(type) && (m_knownControllers & (1U << i)) != 0) {
m_knownControllers &= ~(1 << i); m_knownControllers &= ~(1U << i);
m_callback->controllerDisconnected(i); m_callback->controllerDisconnected(i);
} }
if (m_knownControllers & 1 << i) {
if ((m_knownControllers & (1U << i)) != 0) {
state.m_leftStick[0] = state.m_leftStick[0] - m_leftStickCal[0]; state.m_leftStick[0] = state.m_leftStick[0] - m_leftStickCal[0];
state.m_leftStick[1] = state.m_leftStick[1] - m_leftStickCal[1]; state.m_leftStick[1] = state.m_leftStick[1] - m_leftStickCal[1];
state.m_rightStick[0] = state.m_rightStick[0] - m_rightStickCal[0]; state.m_rightStick[0] = state.m_rightStick[0] - m_rightStickCal[0];
@ -90,41 +89,44 @@ void DolphinSmashAdapter::transferCycle() {
state.m_analogTriggers[1] = state.m_analogTriggers[1] - m_triggersCal[1]; state.m_analogTriggers[1] = state.m_analogTriggers[1] - m_triggersCal[1];
m_callback->controllerUpdate(i, type, state); m_callback->controllerUpdate(i, type, state);
} }
rumbleMask |= rumble ? 1 << i : 0;
rumbleMask |= rumble ? 1U << i : 0;
} }
/* Send rumble message (if needed) */ /* Send rumble message (if needed) */
uint8_t rumbleReq = m_rumbleRequest & rumbleMask; const uint8_t rumbleReq = m_rumbleRequest & rumbleMask;
if (rumbleReq != m_rumbleState) { if (rumbleReq != m_rumbleState) {
uint8_t rumbleMessage[5] = {0x11}; std::array<uint8_t, 5> rumbleMessage{0x11, 0, 0, 0, 0};
for (int i = 0; i < 4; ++i) { for (size_t i = 0; i < 4; ++i) {
if (rumbleReq & 1 << i) if ((rumbleReq & (1U << i)) != 0) {
rumbleMessage[i + 1] = 1; rumbleMessage[i + 1] = 1;
else if (m_hardStop[i]) } else if (m_hardStop[i]) {
rumbleMessage[i + 1] = 2; rumbleMessage[i + 1] = 2;
else } else {
rumbleMessage[i + 1] = 0; rumbleMessage[i + 1] = 0;
} }
}
sendUSBInterruptTransfer(rumbleMessage, sizeof(rumbleMessage)); sendUSBInterruptTransfer(rumbleMessage.data(), rumbleMessage.size());
m_rumbleState = rumbleReq; m_rumbleState = rumbleReq;
} }
} }
void DolphinSmashAdapter::finalCycle() { void DolphinSmashAdapter::finalCycle() {
uint8_t rumbleMessage[5] = {0x11, 0, 0, 0, 0}; constexpr std::array<uint8_t, 5> rumbleMessage{0x11, 0, 0, 0, 0};
sendUSBInterruptTransfer(rumbleMessage, sizeof(rumbleMessage)); sendUSBInterruptTransfer(rumbleMessage.data(), sizeof(rumbleMessage));
} }
void DolphinSmashAdapter::deviceDisconnected() { void DolphinSmashAdapter::deviceDisconnected() {
for (uint32_t i = 0; i < 4; i++) { for (uint32_t i = 0; i < 4; i++) {
if (m_knownControllers & 1 << i) { if ((m_knownControllers & (1U << i)) != 0) {
m_knownControllers &= ~(1 << i); m_knownControllers &= ~(1U << i);
std::lock_guard<std::mutex> lk(m_callbackLock); std::lock_guard<std::mutex> lk(m_callbackLock);
if (m_callback) if (m_callback) {
m_callback->controllerDisconnected(i); m_callback->controllerDisconnected(i);
} }
} }
}
} }
/* The following code is derived from pad.c in libogc /* The following code is derived from pad.c in libogc
@ -151,15 +153,15 @@ void DolphinSmashAdapter::deviceDisconnected() {
* distribution. * distribution.
*/ */
static int16_t pad_clampregion[8] = {30, 180, 15, 72, 40, 15, 59, 31}; constexpr std::array<int16_t, 8> pad_clampregion{
30, 180, 15, 72, 40, 15, 59, 31,
};
static void pad_clampstick(int16_t& px, int16_t& py, int16_t max, int16_t xy, int16_t min) { static void pad_clampstick(int16_t& px, int16_t& py, int16_t max, int16_t xy, int16_t min) {
int x = px; int x = px;
int y = py; int y = py;
int signX;
int signY;
int d;
int signX;
if (x > 0) { if (x > 0) {
signX = 1; signX = 1;
} else { } else {
@ -167,6 +169,7 @@ static void pad_clampstick(int16_t& px, int16_t& py, int16_t max, int16_t xy, in
x = -x; x = -x;
} }
int signY;
if (y > 0) { if (y > 0) {
signY = 1; signY = 1;
} else { } else {
@ -174,10 +177,11 @@ static void pad_clampstick(int16_t& px, int16_t& py, int16_t max, int16_t xy, in
y = -y; y = -y;
} }
if (x <= min) if (x <= min) {
x = 0; x = 0;
else } else {
x -= min; x -= min;
}
if (y <= min) { if (y <= min) {
y = 0; y = 0;
@ -191,13 +195,13 @@ static void pad_clampstick(int16_t& px, int16_t& py, int16_t max, int16_t xy, in
} }
if (xy * y <= xy * x) { if (xy * y <= xy * x) {
d = xy * x + (max - xy) * y; const int d = xy * x + (max - xy) * y;
if (xy * max < d) { if (xy * max < d) {
x = int16_t(xy * max * x / d); x = int16_t(xy * max * x / d);
y = int16_t(xy * max * y / d); y = int16_t(xy * max * y / d);
} }
} else { } else {
d = xy * y + (max - xy) * x; const int d = xy * y + (max - xy) * x;
if (xy * max < d) { if (xy * max < d) {
x = int16_t(xy * max * x / d); x = int16_t(xy * max * x / d);
y = int16_t(xy * max * y / d); y = int16_t(xy * max * y / d);
@ -209,15 +213,15 @@ static void pad_clampstick(int16_t& px, int16_t& py, int16_t max, int16_t xy, in
} }
static void pad_clamptrigger(int16_t& trigger) { static void pad_clamptrigger(int16_t& trigger) {
int16_t min, max; const int16_t min = pad_clampregion[0];
const int16_t max = pad_clampregion[1];
min = pad_clampregion[0]; if (min > trigger) {
max = pad_clampregion[1];
if (min > trigger)
trigger = 0; trigger = 0;
else { } else {
if (max < trigger) if (max < trigger) {
trigger = max; trigger = max;
}
trigger -= min; trigger -= min;
} }
} }