Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

psyqo Multi-tap driver and example update #1815

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 103 additions & 15 deletions src/mips/psyqo/advancedpad.hh
Original file line number Diff line number Diff line change
Expand Up @@ -63,21 +63,6 @@ class AdvancedPad {
Square = 15,
};

enum Command : uint8_t {
PadSelect = 0x01,
ReadPad = 0x42, // 'B' Read Buttons AND analog inputs
// Config mode commands
ToggleConfigMode = 0x43, // 'C' Enter/Exit Configuration Mode
SetLED = 0x44, // 'D' Set LED State (analog mode on/off)
GetLED = 0x45, // 'E' Get LED State (and whatever values)
GetMotorInfo = 0x46, // 'F' Allegedly get info about a motor
GetMotorList = 0x47, // 'G' Allegedly get list of motors
GetMotorState = 0x48, // 'H' Allegedly get motor state
GetSupportedModes = 0x4c, // 'L' Allegedly get supported modes
ConfigRequestFormat = 0x4d, // 'M' Allegedly configure poll request format
ConfigResponseFormat = 0x4f, // 'O' Allegedly configure poll response format
};

enum PadType : uint8_t {
Mouse = 0x12, // (two button mouse)
NegCon = 0x23, // (steering twist/wheel/paddle)
Expand Down Expand Up @@ -157,7 +142,110 @@ class AdvancedPad {
*/
bool isButtonPressed(Pad pad, Button button) const { return (m_padData[pad][1] & (1 << button)) == 0; }

/**
* @brief Returns the state of Analog Input 0 (if any).
*
* @details Returns the state of Analog Input 0 (if any).
*
* @param pad The pad to query.
* @return The state of the Analog Input.
*/
uint8_t getAdc0(Pad pad) const { return m_padData[pad][2] & 0xff; }

/**
* @brief Returns the state of Analog Input 1 (if any).
*
* @details Returns the state of Analog Input 1 (if any).
*
* @param pad The pad to query.
* @return The state of the Analog Input.
*/
uint8_t getAdc1(Pad pad) const { return m_padData[pad][2] >> 8; }

/**
* @brief Returns the state of Analog Input 2 (if any).
*
* @details Returns the state of Analog Input 2 (if any).
*
* @param pad The pad to query.
* @return The state of the Analog Input.
*/
uint8_t getAdc2(Pad pad) const { return m_padData[pad][3] & 0xff; }

/**
* @brief Returns the state of Analog Input 3 (if any).
*
* @details Returns the state of Analog Input 3 (if any).
*
* @param pad The pad to query.
* @return The state of the Analog Input.
*/
uint8_t getAdc3(Pad pad) const { return m_padData[pad][3] >> 8; }

/**
* @brief Returns the state of an Analog Input.
*
* @details Returns the state of an Analog Input.
*
* @param pad The pad to query.
* @param index The index of the Analog Input.
* @return The state of the Analog Input.
*/
uint8_t getAdc(Pad pad, unsigned int index) const {
switch (index) {
case 0:
return getAdc0(pad);
case 1:
return getAdc1(pad);
case 2:
return getAdc2(pad);
case 3:
return getAdc3(pad);
default:
return 0;
}
}

/**
* @brief Returns raw pad data as a 16-bit value.
*
* @details Returns the halfword value for the requested index of the given pad index.
*
* @param pad The pad to query.
* @param index The index of the halfword.
* @return The value of the halfword.
*/

uint16_t getHalfword(Pad pad, unsigned int index) const {
return m_padData[pad][index % 4];
}

/**
* @brief Returns the type of the pad.
*
* @details Returns the type of the pad.
*
* @param pad The pad to query.
* @return The type of the pad.
*/
uint8_t getPadType(Pad pad) const { return m_padData[pad][0] >> 8; }

private:
enum Command : uint8_t {
PadSelect = 0x01,
ReadPad = 0x42, // 'B' Read Buttons AND analog inputs
// Config mode commands
ToggleConfigMode = 0x43, // 'C' Enter/Exit Configuration Mode
SetLED = 0x44, // 'D' Set LED State (analog mode on/off)
GetLED = 0x45, // 'E' Get LED State (and whatever values)
GetMotorInfo = 0x46, // 'F' Allegedly get info about a motor
GetMotorList = 0x47, // 'G' Allegedly get list of motors
GetMotorState = 0x48, // 'H' Allegedly get motor state
GetSupportedModes = 0x4c, // 'L' Allegedly get supported modes
ConfigRequestFormat = 0x4d, // 'M' Allegedly configure poll request format
ConfigResponseFormat = 0x4f, // 'O' Allegedly configure poll response format
};

void busyLoop(unsigned delay) {
unsigned cycles = 0;
while (++cycles < delay) asm("");
Expand Down
74 changes: 71 additions & 3 deletions src/mips/psyqo/examples/multitap/multitap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "psyqo/gpu.hh"
#include "psyqo/kernel.hh"
#include "psyqo/scene.hh"
#include "psyqo/xprintf.h"

namespace {

Expand Down Expand Up @@ -60,6 +61,7 @@
void print(int x, int y, bool enabled, const char *text);
void printPadStatus(psyqo::AdvancedPad::Pad pad, int column, const char *name);
void printPadConnectionStatus(psyqo::AdvancedPad::Pad pad, int row, const char *name);
void printPadType(psyqo::AdvancedPad::Pad pad, int column, const char *name);
};

MultitapTest multitapTest;
Expand Down Expand Up @@ -107,7 +109,7 @@

void MultitapTestScene::printPadConnectionStatus(psyqo::AdvancedPad::Pad pad, int row, const char *name) {
auto &input = multitapTest.m_input;
print(8, row, input.isPadConnected(pad), name);
print(2, row, input.isPadConnected(pad), name);
}

void MultitapTestScene::printPadStatus(psyqo::AdvancedPad::Pad pad, int column, const char *name) {
Expand All @@ -131,6 +133,71 @@
print(column + 10, 6, input.isButtonPressed(pad, psyqo::AdvancedPad::Button::Circle), "Circle");
print(column + 10, 7, input.isButtonPressed(pad, psyqo::AdvancedPad::Button::Square), "Square");
print(column + 10, 8, input.isButtonPressed(pad, psyqo::AdvancedPad::Button::Triangle), "Triangle");

char m_textBuffer[32] = {'\0'};
const auto padType = input.getPadType(pad);

// The lower 4-bits of the pad type indicate the number of half-words of pad data
// The 1st half-word is for the digital switches
const auto halfWords = padType & 0xf;
const auto adcBytes = (halfWords - 1) * 2;

if (halfWords > 1 && padType != psyqo::AdvancedPad::PadType::None) {
sprintf(m_textBuffer, "ADC[0-%d]", adcBytes - 1);
print(column + 0, 9, false, m_textBuffer);

for (int i = 0; i < adcBytes && i < 4; i++) {
sprintf(m_textBuffer, "%02X ", input.getAdc(pad, i));
print(column + 10 + (i * 3), 9, true, m_textBuffer);
}
}
}

void MultitapTestScene::printPadType(psyqo::AdvancedPad::Pad pad, int column, const char *name) {
auto &input = multitapTest.m_input;
char m_textBuffer[16] = {'\0'};
const auto padType = input.getPadType(pad);

print(column + 0, 11, true, name);
switch (padType) {
case psyqo::AdvancedPad::PadType::Mouse:
sprintf(m_textBuffer, "Mouse");
break;
case psyqo::AdvancedPad::PadType::NegCon:
sprintf(m_textBuffer, "NegCon");
break;
case psyqo::AdvancedPad::PadType::KonamiLightgun:
sprintf(m_textBuffer, "KonamiLightgun");
break;
case psyqo::AdvancedPad::PadType::DigitalPad:
sprintf(m_textBuffer, "DigitalPad");
break;
case psyqo::AdvancedPad::PadType::AnalogStick:
sprintf(m_textBuffer, "AnalogStick");
break;
case psyqo::AdvancedPad::PadType::NamcoLightgun:
sprintf(m_textBuffer, "NamcoLightgun");
break;
case psyqo::AdvancedPad::PadType::AnalogPad:
sprintf(m_textBuffer, "AnalogPad");
break;
case psyqo::AdvancedPad::PadType::Multitap:
sprintf(m_textBuffer, "Multitap");
break;
case psyqo::AdvancedPad::PadType::Jogcon:
sprintf(m_textBuffer, "Jogcon");
break;
case psyqo::AdvancedPad::PadType::ConfigMode:
sprintf(m_textBuffer, "ConfigMode");
break;
case psyqo::AdvancedPad::PadType::None:
sprintf(m_textBuffer, "None");
break;
default:
sprintf(m_textBuffer, "Unknown");
break;
}
print(column + 10, 11, true, m_textBuffer);

Check warning on line 200 in src/mips/psyqo/examples/multitap/multitap.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ New issue: Complex Method

MultitapTestScene::printPadType has a cyclomatic complexity of 13, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.
Comment on lines +156 to +200
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Refactor to reduce cyclomatic complexity in printPadType.
This method’s complexity triggers a warning. As more pad types or logic are added, it can become unwieldy. A lookup table or map-based approach could drastically simplify this switch statement.

-switch (padType) {
  // ...
-    case psyqo::AdvancedPad::PadType::NegCon:
-        sprintf(m_textBuffer, "NegCon");
-        break;
  ...
-default:
-    sprintf(m_textBuffer, "Unknown");
-    break;
+static const struct {
+    psyqo::AdvancedPad::PadType type;
+    const char* name;
+} padTypeMap[] = {
+    { psyqo::AdvancedPad::PadType::Mouse, "Mouse" },
+    { psyqo::AdvancedPad::PadType::NegCon, "NegCon" },
+    // ...
+    { psyqo::AdvancedPad::PadType::None, "None" },
+};
+
+const auto it = std::find_if(
+    std::begin(padTypeMap), std::end(padTypeMap),
+    [padType](auto &entry) { return entry.type == padType; }
+);
+sprintf(m_textBuffer, "%s", (it != std::end(padTypeMap)) ? it->name : "Unknown");

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 GitHub Check: CodeScene Cloud Delta Analysis (main)

[warning] 156-200: ❌ New issue: Complex Method
MultitapTestScene::printPadType has a cyclomatic complexity of 13, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

}

void MultitapTestScene::start(Scene::StartReason reason) {
Expand All @@ -145,7 +212,7 @@
multitapTest.gpu().clear();

if (multitapTest.m_input.isPadConnected(m_padIndex)) {
print(7, m_padIndex, true, ">");
print(1, m_padIndex, true, ">");
}

printPadConnectionStatus(psyqo::AdvancedPad::Pad1a, 0, "Pad 1a");
Expand All @@ -157,7 +224,8 @@
printPadConnectionStatus(psyqo::AdvancedPad::Pad2c, 6, "Pad 2c");
printPadConnectionStatus(psyqo::AdvancedPad::Pad2d, 7, "Pad 2d");

printPadStatus(static_cast<psyqo::AdvancedPad::Pad>(m_padIndex), 20, "Pad Status");
printPadStatus(static_cast<psyqo::AdvancedPad::Pad>(m_padIndex), 16, "Pad Status");
printPadType(static_cast<psyqo::AdvancedPad::Pad>(m_padIndex), 16, "Pad Type");
}

int main() { return multitapTest.run(); }
Loading