Skip to content

Commit be5274a

Browse files
authored
Merge pull request #1815 from johnbaumann/psyqo_multitap_additions
psyqo Multi-tap driver and example update
2 parents eba3c7a + 588f68d commit be5274a

File tree

4 files changed

+324
-139
lines changed

4 files changed

+324
-139
lines changed

src/mips/psyqo/advancedpad.hh

Lines changed: 95 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
MIT License
44
5-
Copyright (c) 2024 PCSX-Redux authors
5+
Copyright (c) 2025 PCSX-Redux authors
66
77
Permission is hereby granted, free of charge, to any person obtaining a copy
88
of this software and associated documentation files (the "Software"), to deal
@@ -29,6 +29,8 @@ SOFTWARE.
2929
#include <EASTL/functional.h>
3030
#include <stdint.h>
3131

32+
#include "psyqo/utility-polyfill.h"
33+
3234
namespace psyqo {
3335

3436
/**
@@ -42,7 +44,7 @@ namespace psyqo {
4244

4345
class AdvancedPad {
4446
public:
45-
enum Pad { Pad1a, Pad1b, Pad1c, Pad1d, Pad2a, Pad2b, Pad2c, Pad2d };
47+
enum class Pad : unsigned { Pad1a, Pad1b, Pad1c, Pad1d, Pad2a, Pad2b, Pad2c, Pad2d };
4648

4749
enum Button {
4850
Select = 0,
@@ -63,31 +65,17 @@ class AdvancedPad {
6365
Square = 15,
6466
};
6567

66-
enum Command : uint8_t {
67-
PadSelect = 0x01,
68-
ReadPad = 0x42, // 'B' Read Buttons AND analog inputs
69-
// Config mode commands
70-
ToggleConfigMode = 0x43, // 'C' Enter/Exit Configuration Mode
71-
SetLED = 0x44, // 'D' Set LED State (analog mode on/off)
72-
GetLED = 0x45, // 'E' Get LED State (and whatever values)
73-
GetMotorInfo = 0x46, // 'F' Allegedly get info about a motor
74-
GetMotorList = 0x47, // 'G' Allegedly get list of motors
75-
GetMotorState = 0x48, // 'H' Allegedly get motor state
76-
GetSupportedModes = 0x4c, // 'L' Allegedly get supported modes
77-
ConfigRequestFormat = 0x4d, // 'M' Allegedly configure poll request format
78-
ConfigResponseFormat = 0x4f, // 'O' Allegedly configure poll response format
79-
};
80-
8168
enum PadType : uint8_t {
8269
Mouse = 0x12, // (two button mouse)
8370
NegCon = 0x23, // (steering twist/wheel/paddle)
8471
KonamiLightgun = 0x31, // (IRQ10-type)
8572
DigitalPad = 0x41, // (or analog pad/stick in digital mode; LED=Off)
8673
AnalogStick = 0x53, // (or analog pad in "flight mode"; LED=Green)
87-
NamcoLightgun = 0x63, // (Cinch-type)
74+
NamcoLightGun = 0x63, // (Cinch-type)
8875
AnalogPad = 0x73, // (in normal analog mode; LED=Red)
8976
Multitap = 0x80, // (multiplayer adaptor) (when activated)
90-
Jogcon = 0xe3, // (steering dial)
77+
JogCon = 0xe3, // (steering dial)
78+
FishingCon = 0xe5, // (fishing rod)
9179
ConfigMode = 0xf3, // (when in config mode; see rumble command 43h)
9280
None = 0xff // (no controller connected, pins floating High-Z)
9381
};
@@ -143,7 +131,7 @@ class AdvancedPad {
143131
* @param pad The pad to query.
144132
* @return A boolean value indicating whether the pad is connected.
145133
*/
146-
bool isPadConnected(Pad pad) const { return (m_padData[pad][0] & 0xff) == 0; }
134+
bool isPadConnected(Pad pad) const { return m_padData[toUnderlying(pad)].connected == 0; }
147135

148136
/**
149137
* @brief Returns the state of a button.
@@ -155,23 +143,103 @@ class AdvancedPad {
155143
* @param button The button to query.
156144
* @return A boolean value indicating whether the button is pressed.
157145
*/
158-
bool isButtonPressed(Pad pad, Button button) const { return (m_padData[pad][1] & (1 << button)) == 0; }
146+
bool isButtonPressed(Pad pad, Button button) const {
147+
return (m_padData[toUnderlying(pad)].buttons & (1 << button)) == 0;
148+
}
149+
150+
/**
151+
* @brief Returns the state of an Analog Input.
152+
*
153+
* @details See the specific Analog Input functions for details.
154+
* Indices greater than 3 will return 0.
155+
* index 0: For analog pads: RightJoyX (00h=Left, 80h=Center, FFh=Right), mouse: X-axis
156+
* index 1: For analog pads: RightJoyY (00h=Up, 80h=Center, FFh=Down), mouse: Y-axis
157+
* index 2: For analog pads: LeftJoyX (00h=Left, 80h=Center, FFh=Right)
158+
* index 3: For analog pads: LeftJoyY (00h=Up, 80h=Center, FFh=Down)
159+
*
160+
* @param pad The pad to query.
161+
* @param index The index of the Analog Input(adc#).
162+
* @return The state of the Analog Input as an unsigned 8-bit value(0-255).
163+
*/
164+
uint8_t getAdc(Pad pad, unsigned int index) const {
165+
const unsigned padIndex = toUnderlying(pad);
166+
167+
return index <= 7 ? m_padData[padIndex].adc[index] : 0;
168+
}
169+
170+
/**
171+
* @brief Returns raw pad data as an unsigned 16-bit value.
172+
*
173+
* @details A low level call which returns the halfword value for the requested index of the given pad index.
174+
* It is recommended to use the higher level functions instead.
175+
* index 0: pad type << 8 | connected(0 = connected, ffh = disconnected)
176+
* index 1: button state
177+
* index 2: analog input 1 << 8 | analog input 0
178+
* index 3: analog input 3 << 8 | analog input 2
179+
* The index is modulo 4, so it will wrap around if it is greater than 3.
180+
*
181+
*
182+
* @param pad The pad to query.
183+
* @param index The index of the halfword.
184+
* @return The value of the halfword.
185+
*/
186+
187+
uint16_t getHalfword(Pad pad, unsigned int index) const { return m_padData[toUnderlying(pad)].packed[index % 4]; }
188+
189+
/**
190+
* @brief Returns the type of the pad.
191+
*
192+
* @details Known pad types are defined in the PadType enum, returns 0xff if no pad is connected.
193+
* PadType::Multitap is for internal use only, and should not be returned.
194+
* Pad connection status should be checked with isPadConnected.
195+
*
196+
* @param pad The pad to query.
197+
* @return The type of the pad.
198+
*/
199+
uint8_t getPadType(Pad pad) const { return m_padData[toUnderlying(pad)].padType; }
159200

160201
private:
202+
enum Command : uint8_t {
203+
PadSelect = 0x01,
204+
ReadPad = 0x42, // 'B' Read Buttons AND analog inputs
205+
// Config mode commands
206+
ToggleConfigMode = 0x43, // 'C' Enter/Exit Configuration Mode
207+
SetLED = 0x44, // 'D' Set LED State (analog mode on/off)
208+
GetLED = 0x45, // 'E' Get LED State (and whatever values)
209+
GetMotorInfo = 0x46, // 'F' Allegedly get info about a motor
210+
GetMotorList = 0x47, // 'G' Allegedly get list of motors
211+
GetMotorState = 0x48, // 'H' Allegedly get motor state
212+
GetSupportedModes = 0x4c, // 'L' Allegedly get supported modes
213+
ConfigRequestFormat = 0x4d, // 'M' Allegedly configure poll request format
214+
ConfigResponseFormat = 0x4f, // 'O' Allegedly configure poll response format
215+
};
216+
161217
void busyLoop(unsigned delay) {
162218
unsigned cycles = 0;
163219
while (++cycles < delay) asm("");
164220
};
165221

222+
void configurePort(uint8_t port);
223+
166224
void flushRxBuffer();
167225
uint8_t outputDefault(unsigned ticks);
168226
uint8_t outputMultitap(unsigned ticks);
169227
void processChanges(Pad pad);
170228
void readPad();
171-
uint8_t transceive(uint8_t data_out);
229+
uint8_t transceive(uint8_t dataOut);
172230
bool waitForAck(); // true if ack received, false if timeout
173231

174-
uint16_t m_padData[8][4];
232+
union PadData {
233+
struct {
234+
uint8_t connected;
235+
uint8_t padType;
236+
uint16_t buttons;
237+
uint8_t adc[8];
238+
};
239+
uint16_t packed[6];
240+
};
241+
242+
PadData m_padData[8];
175243
eastl::function<void(Event)> m_callback;
176244
bool m_connected[8] = {false, false, false, false, false, false, false, false};
177245
uint16_t m_buttons[8] = {
@@ -183,25 +251,25 @@ class AdvancedPad {
183251

184252
// prefix increment operator
185253
inline psyqo::AdvancedPad::Pad& operator++(psyqo::AdvancedPad::Pad& pad) {
186-
return pad = static_cast<psyqo::AdvancedPad::Pad>((static_cast<unsigned>(pad) + 1) & 7);
254+
return pad = static_cast<psyqo::AdvancedPad::Pad>((toUnderlying(pad) + 1) & 7);
187255
}
188256

189257
// postfix increment operator
190258
inline psyqo::AdvancedPad::Pad operator++(psyqo::AdvancedPad::Pad& pad, int) {
191259
psyqo::AdvancedPad::Pad copy(pad);
192-
pad = static_cast<psyqo::AdvancedPad::Pad>((static_cast<unsigned>(pad) + 1) & 7);
260+
pad = static_cast<psyqo::AdvancedPad::Pad>((toUnderlying(pad) + 1) & 7);
193261
return copy;
194262
}
195263

196264
// prefix decrement operator
197265
inline psyqo::AdvancedPad::Pad& operator--(psyqo::AdvancedPad::Pad& pad) {
198-
return pad = static_cast<psyqo::AdvancedPad::Pad>((static_cast<unsigned>(pad) - 1) & 7);
266+
return pad = static_cast<psyqo::AdvancedPad::Pad>((toUnderlying(pad) - 1) & 7);
199267
}
200268

201269
// postfix decrement operator
202270
inline psyqo::AdvancedPad::Pad operator--(psyqo::AdvancedPad::Pad& pad, int) {
203271
psyqo::AdvancedPad::Pad copy(pad);
204-
pad = static_cast<psyqo::AdvancedPad::Pad>((static_cast<unsigned>(pad) - 1) & 7);
272+
pad = static_cast<psyqo::AdvancedPad::Pad>((toUnderlying(pad) - 1) & 7);
205273
return copy;
206274
}
207275

0 commit comments

Comments
 (0)