Skip to content

Commit 3aff536

Browse files
committed
Add touch screen, special buttons, etc.
1 parent 3bdd9f4 commit 3aff536

2 files changed

Lines changed: 168 additions & 24 deletions

File tree

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,11 @@
11
# InputRedirectionClient-Qt
22
Input redirection client for the 3DS using QtGamepad
3+
4+
Supported platforms:
5+
6+
* Windows (via xinput, if you don't have a Xbox controller you should use x360ce)
7+
* Linux (via evdev)
8+
* OSX
9+
* maybe others?
10+
11+
If you have multiple controllers connected at the same time, this software will combine their inputs.

main.cpp

Lines changed: 159 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,20 @@
77
#include <QUdpSocket>
88
#include <QTimer>
99
#include <QFormLayout>
10+
#include <QVBoxLayout>
1011
#include <QLineEdit>
12+
#include <QPushButton>
1113
#include <QCheckBox>
1214
#include <QDialog>
15+
#include <QMouseEvent>
16+
#include <QCloseEvent>
17+
18+
#include <algorithm>
19+
20+
#define CPAD_BOUND 0x5d0
21+
22+
#define TOUCH_SCREEN_WIDTH 320
23+
#define TOUCH_SCREEN_HEIGHT 240
1324

1425
typedef uint32_t u32;
1526
typedef uint16_t u16;
@@ -18,8 +29,12 @@ typedef uint8_t u8;
1829
double lx = 0.0, ly = 0.0;
1930
double rx = 0.0, ry = 0.0;
2031
QGamepadManager::GamepadButtons buttons = 0;
32+
u32 specialButtons = 0;
2133
QString ipAddress;
22-
int yAxisMultiplicator = 1;
34+
int yAxisMultiplier = 1;
35+
36+
bool touchScreenPressed;
37+
QPoint touchScreenPosition;
2338

2439
void sendFrame(void)
2540
{
@@ -45,25 +60,44 @@ void sendFrame(void)
4560
hidPad &= ~(1 << i);
4661
}
4762

48-
u32 touchState = 0x2000000;
49-
u32 circleState = 0x7ff7ff;
50-
u16 x = (u16)(lx * 0x5d0 + 0x800);
51-
u16 y = (u16)(ly * 0x5d0 + 0x800);
63+
specialButtons |= (buttons & (1 << QGamepadManager::ButtonGuide)) ? 1 : 0;
64+
65+
u32 touchScreenState = 0x2000000;
66+
u32 circlePadState = 0x7ff7ff;
5267

5368
if(lx != 0.0 || ly != 0.0)
54-
circleState = ((u32) y << 12) | (u32)x;
69+
{
70+
u32 x = (u32)(lx * CPAD_BOUND + 0x800);
71+
u32 y = (u32)(ly * CPAD_BOUND + 0x800);
72+
x = x >= 0xfff ? 0xfff : x;
73+
y = y >= 0xfff ? 0xfff : y;
5574

56-
QByteArray ba(12, 0);
57-
qToLittleEndian(hidPad, (uchar *)ba.data());
58-
qToLittleEndian(touchState, (uchar *)ba.data() + 4);
59-
qToLittleEndian(circleState, (uchar *)ba.data() + 8);
75+
circlePadState = (y << 12) | x;
76+
}
6077

78+
if(touchScreenPressed)
79+
{
80+
u32 x = (u32)(0xfff * std::min(std::max(0, touchScreenPosition.x()), TOUCH_SCREEN_WIDTH)) / TOUCH_SCREEN_WIDTH;
81+
u32 y = (u32)(0xfff * std::min(std::max(0, touchScreenPosition.y()), TOUCH_SCREEN_HEIGHT)) / TOUCH_SCREEN_HEIGHT;
82+
touchScreenState = (1 << 24) | (y << 12) | x;
83+
}
84+
85+
u32 extraButtons = 0; // unk
86+
u32 cpadProState = 0; // unk
87+
88+
QByteArray ba(24, 0);
89+
qToLittleEndian(hidPad, (uchar *)ba.data());
90+
qToLittleEndian(touchScreenState, (uchar *)ba.data() + 4);
91+
qToLittleEndian(circlePadState, (uchar *)ba.data() + 8);
92+
qToLittleEndian(extraButtons, (uchar *)ba.data() + 12);
93+
qToLittleEndian(cpadProState, (uchar *)ba.data() + 16);
94+
qToLittleEndian(specialButtons, (uchar *)ba.data() + 20);
6195
QUdpSocket().writeDatagram(ba, QHostAddress(ipAddress), 4950);
6296
}
6397

6498
struct GamepadMonitor : public QObject {
6599

66-
GamepadMonitor(QObject *parent = Q_NULLPTR) : QObject(parent)
100+
GamepadMonitor(QObject *parent = nullptr) : QObject(parent)
67101
{
68102
connect(QGamepadManager::instance(), &QGamepadManager::gamepadButtonPressEvent, this,
69103
[](int deviceId, QGamepadManager::GamepadButton button, double value)
@@ -92,7 +126,7 @@ struct GamepadMonitor : public QObject {
92126
lx = value;
93127
break;
94128
case QGamepadManager::AxisLeftY:
95-
ly = yAxisMultiplicator * -value; // for some reason qt inverts this
129+
ly = yAxisMultiplier * -value; // for some reason qt inverts this
96130
break;
97131
default: break;
98132
}
@@ -102,14 +136,44 @@ struct GamepadMonitor : public QObject {
102136
};
103137

104138
struct TouchScreen : public QDialog {
105-
TouchScreen(QWidget *parent = Q_NULLPTR) : QDialog(parent)
139+
TouchScreen(QWidget *parent = nullptr) : QDialog(parent)
140+
{
141+
this->setFixedSize(TOUCH_SCREEN_WIDTH, TOUCH_SCREEN_HEIGHT);
142+
this->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint);
143+
this->setWindowTitle(tr("InputRedirectionClient-Qt - Touch screen"));
144+
}
145+
146+
void mousePressEvent(QMouseEvent *ev)
106147
{
107-
this->setFixedSize(320, 240);
148+
if(ev->button() == Qt::LeftButton)
149+
{
150+
touchScreenPressed = true;
151+
touchScreenPosition = ev->pos();
152+
sendFrame();
153+
}
154+
}
155+
156+
void mouseMoveEvent(QMouseEvent *ev)
157+
{
158+
if(touchScreenPressed && (ev->buttons() & Qt::LeftButton))
159+
{
160+
touchScreenPosition = ev->pos();
161+
sendFrame();
162+
}
163+
}
164+
165+
void mouseReleaseEvent(QMouseEvent *ev)
166+
{
167+
if(ev->button() == Qt::LeftButton)
168+
{
169+
touchScreenPressed = false;
170+
sendFrame();
171+
}
108172
}
109173
};
110174

111175
struct FrameTimer : public QTimer {
112-
FrameTimer(QObject *parent = Q_NULLPTR) : QTimer(parent)
176+
FrameTimer(QObject *parent = nullptr) : QTimer(parent)
113177
{
114178
connect(this, &QTimer::timeout, this,
115179
[](void)
@@ -123,21 +187,32 @@ struct FrameTimer : public QTimer {
123187
class Widget : public QWidget
124188
{
125189
private:
126-
QFormLayout *layout;
190+
QVBoxLayout *layout;
191+
QFormLayout *formLayout;
127192
QLineEdit *addrLineEdit;
128193
QCheckBox *invertYCheckbox;
194+
QPushButton *homeButton, *powerButton, *longPowerButton;
129195
TouchScreen *touchScreen;
130196
public:
131-
Widget(QWidget *parent = Q_NULLPTR) : QWidget(parent)
197+
Widget(QWidget *parent = nullptr) : QWidget(parent)
132198
{
199+
layout = new QVBoxLayout(this);
200+
133201
addrLineEdit = new QLineEdit(this);
134202
invertYCheckbox = new QCheckBox(this);
135-
layout = new QFormLayout(this);
203+
formLayout = new QFormLayout;
204+
205+
formLayout->addRow(tr("IP &address"), addrLineEdit);
206+
formLayout->addRow(tr("&Invert Y axis"), invertYCheckbox);
136207

137-
layout->addRow(tr("IP &address"), addrLineEdit);
138-
layout->addRow(tr("&Invert Y axis"), invertYCheckbox);
208+
homeButton = new QPushButton(tr("&HOME"), this);
209+
powerButton = new QPushButton(tr("&POWER"), this);
210+
longPowerButton = new QPushButton(tr("POWER (&long)"), this);
139211

140-
this->setLayout(layout);
212+
layout->addLayout(formLayout);
213+
layout->addWidget(homeButton);
214+
layout->addWidget(powerButton);
215+
layout->addWidget(longPowerButton);
141216

142217
connect(addrLineEdit, &QLineEdit::textChanged, this,
143218
[](const QString &text)
@@ -151,16 +226,76 @@ class Widget : public QWidget
151226
switch(state)
152227
{
153228
case Qt::Unchecked:
154-
yAxisMultiplicator = 1;
229+
yAxisMultiplier = 1;
155230
break;
156231
case Qt::Checked:
157-
yAxisMultiplicator = -1;
232+
yAxisMultiplier = -1;
158233
break;
159234
default: break;
160235
}
161236
});
162237

163-
touchScreen = new TouchScreen(this); // TODO: fix this
238+
connect(homeButton, &QPushButton::pressed, this,
239+
[](void)
240+
{
241+
specialButtons |= 1;
242+
sendFrame();
243+
});
244+
245+
connect(homeButton, &QPushButton::released, this,
246+
[](void)
247+
{
248+
specialButtons &= ~1;
249+
sendFrame();
250+
});
251+
252+
connect(powerButton, &QPushButton::pressed, this,
253+
[](void)
254+
{
255+
specialButtons |= 2;
256+
sendFrame();
257+
});
258+
259+
connect(powerButton, &QPushButton::released, this,
260+
[](void)
261+
{
262+
specialButtons &= ~2;
263+
sendFrame();
264+
});
265+
266+
connect(longPowerButton, &QPushButton::pressed, this,
267+
[](void)
268+
{
269+
specialButtons |= 4;
270+
sendFrame();
271+
});
272+
273+
connect(longPowerButton, &QPushButton::released, this,
274+
[](void)
275+
{
276+
specialButtons &= ~4;
277+
sendFrame();
278+
});
279+
280+
touchScreen = new TouchScreen(nullptr);
281+
this->setWindowTitle(tr("InputRedirectionClient-Qt"));
282+
}
283+
284+
void show(void)
285+
{
286+
QWidget::show();
287+
touchScreen->show();
288+
}
289+
290+
void closeEvent(QCloseEvent *ev)
291+
{
292+
touchScreen->close();
293+
ev->accept();
294+
}
295+
296+
virtual ~Widget(void)
297+
{
298+
delete touchScreen;
164299
}
165300

166301
};

0 commit comments

Comments
 (0)