Skip to content

Commit 5dc9acb

Browse files
committed
input: Implement controller input
ds2: Implement analog button
1 parent 640946b commit 5dc9acb

File tree

6 files changed

+370
-48
lines changed

6 files changed

+370
-48
lines changed

frontend/input.cpp

Lines changed: 172 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
namespace iris {
1010

11-
uint32_t map_button(SDL_Keycode k) {
11+
uint32_t map_keyboard_button(iris::instance* iris, SDL_Keycode k) {
1212
if (k == SDLK_X ) return DS_BT_CROSS;
1313
if (k == SDLK_A ) return DS_BT_SQUARE;
1414
if (k == SDLK_W ) return DS_BT_TRIANGLE;
@@ -25,10 +25,170 @@ uint32_t map_button(SDL_Keycode k) {
2525
if (k == SDLK_3 ) return DS_BT_R2;
2626
if (k == SDLK_Z ) return DS_BT_L3;
2727
if (k == SDLK_C ) return DS_BT_R3;
28+
if (k == SDLK_V ) return DS_BT_ANALOG;
2829

2930
return 0;
3031
}
3132

33+
static inline input_event sdl_event_to_input_event(SDL_Event* event) {
34+
input_event ievent = {};
35+
36+
ievent.type = event->type;
37+
38+
switch (event->type) {
39+
case SDL_EVENT_KEY_DOWN:
40+
case SDL_EVENT_KEY_UP: {
41+
ievent.id = event->key.key;
42+
} break;
43+
44+
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
45+
case SDL_EVENT_GAMEPAD_BUTTON_UP: {
46+
ievent.id = event->gbutton.button;
47+
} break;
48+
49+
case SDL_EVENT_GAMEPAD_AXIS_MOTION: {
50+
ievent.id = event->gaxis.axis;
51+
} break;
52+
}
53+
54+
return ievent;
55+
}
56+
57+
void handle_input_action(iris::instance* iris, input_action act, int slot, uint32_t value) {
58+
switch (act.action) {
59+
case INPUT_ACTION_PRESS_BUTTON: {
60+
if (iris->ds[slot]) {
61+
ds_button_press(iris->ds[slot], act.destination);
62+
}
63+
} break;
64+
65+
case INPUT_ACTION_RELEASE_BUTTON: {
66+
if (iris->ds[slot]) {
67+
ds_button_release(iris->ds[slot], act.destination);
68+
}
69+
} break;
70+
71+
case INPUT_ACTION_MOVE_AXIS: {
72+
if (iris->ds[slot]) {
73+
ds_analog_change(iris->ds[slot], act.destination, static_cast<uint8_t>(value));
74+
}
75+
} break;
76+
}
77+
}
78+
79+
void keyboard_device::handle_event(iris::instance* iris, SDL_Event* event) {
80+
SDL_Keycode key = event->key.key;
81+
82+
uint32_t mask = map_keyboard_button(iris, key);
83+
84+
if (event->type == SDL_EVENT_KEY_DOWN) {
85+
switch (key) {
86+
case SDLK_I: { if (iris->ds[m_slot]) ds_analog_change(iris->ds[m_slot], DS_AX_LEFT_V, 0x00); } break;
87+
case SDLK_J: { if (iris->ds[m_slot]) ds_analog_change(iris->ds[m_slot], DS_AX_LEFT_H, 0x00); } break;
88+
case SDLK_K: { if (iris->ds[m_slot]) ds_analog_change(iris->ds[m_slot], DS_AX_LEFT_V, 0xff); } break;
89+
case SDLK_L: { if (iris->ds[m_slot]) ds_analog_change(iris->ds[m_slot], DS_AX_LEFT_H, 0xff); } break;
90+
case SDLK_T: { if (iris->ds[m_slot]) ds_analog_change(iris->ds[m_slot], DS_AX_RIGHT_V, 0x00); } break;
91+
case SDLK_F: { if (iris->ds[m_slot]) ds_analog_change(iris->ds[m_slot], DS_AX_RIGHT_H, 0x00); } break;
92+
case SDLK_G: { if (iris->ds[m_slot]) ds_analog_change(iris->ds[m_slot], DS_AX_RIGHT_V, 0xff); } break;
93+
case SDLK_H: { if (iris->ds[m_slot]) ds_analog_change(iris->ds[m_slot], DS_AX_RIGHT_H, 0xff); } break;
94+
}
95+
96+
if (iris->ds[m_slot]) {
97+
ds_button_press(iris->ds[m_slot], mask);
98+
}
99+
} else if (event->type == SDL_EVENT_KEY_UP) {
100+
switch (key) {
101+
case SDLK_I: { if (iris->ds[m_slot]) ds_analog_change(iris->ds[m_slot], DS_AX_LEFT_V, 0x7f); } break;
102+
case SDLK_J: { if (iris->ds[m_slot]) ds_analog_change(iris->ds[m_slot], DS_AX_LEFT_H, 0x7f); } break;
103+
case SDLK_K: { if (iris->ds[m_slot]) ds_analog_change(iris->ds[m_slot], DS_AX_LEFT_V, 0x7f); } break;
104+
case SDLK_L: { if (iris->ds[m_slot]) ds_analog_change(iris->ds[m_slot], DS_AX_LEFT_H, 0x7f); } break;
105+
case SDLK_T: { if (iris->ds[m_slot]) ds_analog_change(iris->ds[m_slot], DS_AX_RIGHT_V, 0x7f); } break;
106+
case SDLK_F: { if (iris->ds[m_slot]) ds_analog_change(iris->ds[m_slot], DS_AX_RIGHT_H, 0x7f); } break;
107+
case SDLK_G: { if (iris->ds[m_slot]) ds_analog_change(iris->ds[m_slot], DS_AX_RIGHT_V, 0x7f); } break;
108+
case SDLK_H: { if (iris->ds[m_slot]) ds_analog_change(iris->ds[m_slot], DS_AX_RIGHT_H, 0x7f); } break;
109+
}
110+
111+
if (iris->ds[m_slot]) {
112+
ds_button_release(iris->ds[m_slot], mask);
113+
}
114+
}
115+
}
116+
117+
void gamepad_device::handle_event(iris::instance* iris, SDL_Event* event) {
118+
if (event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN || event->type == SDL_EVENT_GAMEPAD_BUTTON_UP) {
119+
if (event->gbutton.which != id)
120+
return;
121+
122+
uint32_t mask = 0;
123+
124+
switch (event->gbutton.button) {
125+
case SDL_GAMEPAD_BUTTON_SOUTH: mask = DS_BT_CROSS; break;
126+
case SDL_GAMEPAD_BUTTON_EAST: mask = DS_BT_CIRCLE; break;
127+
case SDL_GAMEPAD_BUTTON_WEST: mask = DS_BT_SQUARE; break;
128+
case SDL_GAMEPAD_BUTTON_NORTH: mask = DS_BT_TRIANGLE; break;
129+
case SDL_GAMEPAD_BUTTON_BACK: mask = DS_BT_SELECT; break;
130+
case SDL_GAMEPAD_BUTTON_START: mask = DS_BT_START; break;
131+
case SDL_GAMEPAD_BUTTON_DPAD_UP: mask = DS_BT_UP; break;
132+
case SDL_GAMEPAD_BUTTON_DPAD_DOWN: mask = DS_BT_DOWN; break;
133+
case SDL_GAMEPAD_BUTTON_DPAD_LEFT: mask = DS_BT_LEFT; break;
134+
case SDL_GAMEPAD_BUTTON_DPAD_RIGHT: mask = DS_BT_RIGHT; break;
135+
case SDL_GAMEPAD_BUTTON_LEFT_SHOULDER: mask = DS_BT_L1; break;
136+
case SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER: mask = DS_BT_R1; break;
137+
case SDL_GAMEPAD_BUTTON_LEFT_STICK: mask = DS_BT_L3; break;
138+
case SDL_GAMEPAD_BUTTON_RIGHT_STICK: mask = DS_BT_R3; break;
139+
}
140+
141+
if (event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN) {
142+
if (iris->ds[m_slot]) {
143+
ds_button_press(iris->ds[m_slot], mask);
144+
}
145+
} else if (event->type == SDL_EVENT_GAMEPAD_BUTTON_UP) {
146+
if (iris->ds[m_slot]) {
147+
ds_button_release(iris->ds[m_slot], mask);
148+
}
149+
}
150+
} else if (event->type == SDL_EVENT_GAMEPAD_AXIS_MOTION) {
151+
if (event->gaxis.which != id)
152+
return;
153+
154+
// Convert from -32768->32767 to 0.0->1.0
155+
float value = event->gaxis.value / 32767.0f;
156+
157+
value = (value + 1.0f) / 2.0f;
158+
159+
if (iris->ds[m_slot]) {
160+
switch (event->gaxis.axis) {
161+
case SDL_GAMEPAD_AXIS_LEFT_TRIGGER: {
162+
if (value > 0.5f) {
163+
ds_button_press(iris->ds[m_slot], DS_BT_L2);
164+
} else {
165+
ds_button_release(iris->ds[m_slot], DS_BT_L2);
166+
}
167+
} break;
168+
case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER: {
169+
if (value > 0.5f) {
170+
ds_button_press(iris->ds[m_slot], DS_BT_R2);
171+
} else {
172+
ds_button_release(iris->ds[m_slot], DS_BT_R2);
173+
}
174+
} break;
175+
case SDL_GAMEPAD_AXIS_LEFTX: {
176+
ds_analog_change(iris->ds[m_slot], DS_AX_LEFT_H, (uint8_t)(value * 0xff));
177+
} break;
178+
case SDL_GAMEPAD_AXIS_LEFTY: {
179+
ds_analog_change(iris->ds[m_slot], DS_AX_LEFT_V, (uint8_t)(value * 0xff));
180+
} break;
181+
case SDL_GAMEPAD_AXIS_RIGHTX: {
182+
ds_analog_change(iris->ds[m_slot], DS_AX_RIGHT_H, (uint8_t)(value * 0xff));
183+
} break;
184+
case SDL_GAMEPAD_AXIS_RIGHTY: {
185+
ds_analog_change(iris->ds[m_slot], DS_AX_RIGHT_V, (uint8_t)(value * 0xff));
186+
} break;
187+
}
188+
}
189+
}
190+
}
191+
32192
std::string get_default_screenshot_filename(iris::instance* iris) {
33193
SDL_Time t;
34194
SDL_DateTime dt;
@@ -185,8 +345,10 @@ bool save_screenshot(iris::instance* iris, std::string path = "") {
185345
return true;
186346
}
187347

188-
void handle_keydown_event(iris::instance* iris, SDL_KeyboardEvent& key) {
189-
switch (key.key) {
348+
void handle_keydown_event(iris::instance* iris, SDL_Event* event) {
349+
SDL_Keycode key = event->key.key;
350+
351+
switch (key) {
190352
case SDLK_SPACE: iris->pause = !iris->pause; break;
191353
case SDLK_F9: {
192354
bool saved = save_screenshot(iris);
@@ -203,28 +365,19 @@ void handle_keydown_event(iris::instance* iris, SDL_KeyboardEvent& key) {
203365
case SDLK_0: {
204366
ps2_iop_intc_irq(iris->ps2->iop_intc, IOP_INTC_USB);
205367
} break;
206-
case SDLK_I: if (iris->ds[0]) ds_analog_change(iris->ds[0], DS_AX_LEFT_V, 0); break;
207-
case SDLK_J: if (iris->ds[0]) ds_analog_change(iris->ds[0], DS_AX_LEFT_H, 0); break;
208-
case SDLK_K: if (iris->ds[0]) ds_analog_change(iris->ds[0], DS_AX_LEFT_V, 255); break;
209-
case SDLK_L: if (iris->ds[0]) ds_analog_change(iris->ds[0], DS_AX_LEFT_H, 255); break;
210368
}
211369

212-
uint16_t mask = map_button(key.key);
213-
214-
if (iris->ds[0]) ds_button_press(iris->ds[0], mask);
370+
if (iris->input_devices[0]) iris->input_devices[0]->handle_event(iris, event);
371+
if (iris->input_devices[1]) iris->input_devices[1]->handle_event(iris, event);
215372
}
216373

217-
void handle_keyup_event(iris::instance* iris, SDL_KeyboardEvent& key) {
218-
switch (key.key) {
219-
case SDLK_I: if (iris->ds[0]) ds_analog_change(iris->ds[0], DS_AX_LEFT_V, 0x7f); break;
220-
case SDLK_J: if (iris->ds[0]) ds_analog_change(iris->ds[0], DS_AX_LEFT_H, 0x7f); break;
221-
case SDLK_K: if (iris->ds[0]) ds_analog_change(iris->ds[0], DS_AX_LEFT_V, 0x7f); break;
222-
case SDLK_L: if (iris->ds[0]) ds_analog_change(iris->ds[0], DS_AX_LEFT_H, 0x7f); break;
223-
}
374+
void handle_keyup_event(iris::instance* iris, SDL_Event* event) {
375+
SDL_Keycode key = event->key.key;
224376

225-
uint16_t mask = map_button(key.key);
377+
// Add special keyup handling here if needed
226378

227-
if (iris->ds[0]) ds_button_release(iris->ds[0], mask);
379+
if (iris->input_devices[0]) iris->input_devices[0]->handle_event(iris, event);
380+
if (iris->input_devices[1]) iris->input_devices[1]->handle_event(iris, event);
228381
}
229382

230383
}

frontend/iris.cpp

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,8 @@ bool init(iris::instance* iris, int argc, const char* argv[]) {
437437
SDL_SetWindowSize(iris->window, iris->window_width, iris->window_height + get_menubar_height(iris));
438438
SDL_ShowWindow(iris->window);
439439

440+
iris->input_devices[0] = new iris::keyboard_device();
441+
440442
return true;
441443
}
442444

@@ -500,18 +502,75 @@ SDL_AppResult handle_events(iris::instance* iris, SDL_Event* event) {
500502
return SDL_APP_SUCCESS;
501503
} break;
502504

505+
case SDL_EVENT_GAMEPAD_ADDED: {
506+
SDL_Gamepad* gamepad = SDL_OpenGamepad(event->gdevice.which);
507+
508+
if (!gamepad) {
509+
SDL_Log("Failed to open gamepad ID %u: %s", (unsigned int) event->gdevice.which, SDL_GetError());
510+
}
511+
512+
if ((iris->input_devices[0] == nullptr) || (iris->input_devices[0]->get_type() == 0)) {
513+
if (iris->input_devices[0]) delete iris->input_devices[0];
514+
515+
iris->input_devices[0] = new iris::gamepad_device(event->gdevice.which);
516+
iris->input_devices[0]->set_slot(0);
517+
518+
push_info(iris, "\'" + std::string(SDL_GetGamepadName(gamepad)) + "\' connected to slot 1");
519+
} else if ((iris->input_devices[1] == nullptr) || (iris->input_devices[1]->get_type() == 0)) {
520+
if (iris->input_devices[1]) delete iris->input_devices[1];
521+
522+
iris->input_devices[1] = new iris::gamepad_device(event->gdevice.which);
523+
iris->input_devices[1]->set_slot(1);
524+
525+
push_info(iris, "\'" + std::string(SDL_GetGamepadName(gamepad)) + "\' connected to slot 2");
526+
} else {
527+
push_info(iris, "\'" + std::string(SDL_GetGamepadName(gamepad)) + "\' connected");
528+
}
529+
530+
iris->gamepads[event->gdevice.which] = gamepad;
531+
532+
533+
} break;
534+
535+
case SDL_EVENT_GAMEPAD_REMOVED: {
536+
SDL_Gamepad* gamepad = iris->gamepads[event->gdevice.which];
537+
538+
for (int i = 0; i < 2; i++) {
539+
if (iris->input_devices[i] && iris->input_devices[i]->get_type() == 1) {
540+
iris::gamepad_device* gp = static_cast<iris::gamepad_device*>(iris->input_devices[i]);
541+
542+
if (gp->get_id() == event->gdevice.which) {
543+
delete iris->input_devices[i];
544+
iris->input_devices[i] = new iris::keyboard_device();
545+
546+
push_info(iris, "\'" + std::string(SDL_GetGamepadName(gamepad)) + "\' in slot " + std::to_string(i + 1) + " disconnected");
547+
}
548+
}
549+
}
550+
551+
if (gamepad) {
552+
SDL_CloseGamepad(gamepad);
553+
554+
iris->gamepads.erase(event->gdevice.which);
555+
}
556+
} break;
557+
503558
case SDL_EVENT_WINDOW_CLOSE_REQUESTED: {
504559
if (event->window.windowID == SDL_GetWindowID(iris->window)) {
505560
return SDL_APP_SUCCESS;
506561
}
507562
} break;
508563

509-
case SDL_EVENT_KEY_DOWN: {
510-
handle_keydown_event(iris, event->key);
564+
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
565+
case SDL_EVENT_GAMEPAD_BUTTON_UP:
566+
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
567+
case SDL_EVENT_KEY_UP: {
568+
if (iris->input_devices[0]) iris->input_devices[0]->handle_event(iris, event);
569+
if (iris->input_devices[1]) iris->input_devices[1]->handle_event(iris, event);
511570
} break;
512571

513-
case SDL_EVENT_KEY_UP: {
514-
handle_keyup_event(iris, event->key);
572+
case SDL_EVENT_KEY_DOWN: {
573+
handle_keydown_event(iris, event);
515574
} break;
516575

517576
case SDL_EVENT_DROP_BEGIN: {
@@ -557,6 +616,13 @@ int get_menubar_height(iris::instance* iris) {
557616
}
558617

559618
void destroy(iris::instance* iris) {
619+
for (int i = 0; i < 2; i++) {
620+
if (iris->input_devices[i]) {
621+
delete iris->input_devices[i];
622+
iris->input_devices[i] = nullptr;
623+
}
624+
}
625+
560626
if (iris->imgui_enable_viewports) {
561627
iris->show_ee_control = false;
562628
iris->show_ee_state = false;

0 commit comments

Comments
 (0)