Skip to content

Commit 5f9d04c

Browse files
committed
input: Rework input subsystem
Now we can route keyboard and controller input to either of the two controller stots, with full remap support
1 parent 45d355b commit 5f9d04c

File tree

10 files changed

+968
-270
lines changed

10 files changed

+968
-270
lines changed

CMakeLists.txt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
cmake_minimum_required(VERSION 3.21)
22
project(iris LANGUAGES C CXX)
33

4-
# We need to build release always, unoptimized builds
5-
# won't cut it.
6-
set(CMAKE_BUILD_TYPE "RelWithDebInfo")
7-
84
set(WIN_ICON ${CMAKE_CURRENT_SOURCE_DIR}/res/iris.rc)
95
set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64")
106
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15")
@@ -133,6 +129,7 @@ target_sources(iris PRIVATE
133129
src/list.c
134130
src/scheduler.c
135131
src/dev/ds.c
132+
src/dev/guncon.c
136133
src/dev/mcd.c
137134
src/dev/mtap.c
138135
src/dev/ps1_mcd.c

frontend/input.cpp

Lines changed: 95 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -8,185 +8,117 @@
88

99
namespace iris {
1010

11-
uint32_t map_keyboard_button(iris::instance* iris, SDL_Keycode k) {
12-
if (k == SDLK_X ) return DS_BT_CROSS;
13-
if (k == SDLK_A ) return DS_BT_SQUARE;
14-
if (k == SDLK_W ) return DS_BT_TRIANGLE;
15-
if (k == SDLK_D ) return DS_BT_CIRCLE;
16-
if (k == SDLK_RETURN) return DS_BT_START;
17-
if (k == SDLK_S ) return DS_BT_SELECT;
18-
if (k == SDLK_UP ) return DS_BT_UP;
19-
if (k == SDLK_DOWN ) return DS_BT_DOWN;
20-
if (k == SDLK_LEFT ) return DS_BT_LEFT;
21-
if (k == SDLK_RIGHT ) return DS_BT_RIGHT;
22-
if (k == SDLK_Q ) return DS_BT_L1;
23-
if (k == SDLK_E ) return DS_BT_R1;
24-
if (k == SDLK_1 ) return DS_BT_L2;
25-
if (k == SDLK_3 ) return DS_BT_R2;
26-
if (k == SDLK_Z ) return DS_BT_L3;
27-
if (k == SDLK_C ) return DS_BT_R3;
28-
if (k == SDLK_V ) return DS_BT_ANALOG;
29-
30-
return 0;
31-
}
11+
void keyboard_device::handle_event(iris::instance* iris, SDL_Event* event) {
12+
auto ievent = input::sdl_event_to_input_event(event);
13+
auto action = input::get_input_action(iris, m_slot, ievent.u64);
3214

33-
static inline input_event sdl_event_to_input_event(SDL_Event* event) {
34-
input_event ievent = {};
15+
if (!action)
16+
return;
3517

36-
ievent.type = event->type;
18+
input::execute_action(iris, *action, m_slot, event->type == SDL_EVENT_KEY_DOWN ? 1.0f : 0.0f);
19+
}
3720

38-
switch (event->type) {
39-
case SDL_EVENT_KEY_DOWN:
40-
case SDL_EVENT_KEY_UP: {
41-
ievent.id = event->key.key;
42-
} break;
21+
void gamepad_device::handle_event(iris::instance* iris, SDL_Event* event) {
22+
auto ievent = input::sdl_event_to_input_event(event);
23+
auto action = input::get_input_action(iris, m_slot, ievent.u64);
4324

44-
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
45-
case SDL_EVENT_GAMEPAD_BUTTON_UP: {
46-
ievent.id = event->gbutton.button;
47-
} break;
25+
if (!action)
26+
return;
4827

49-
case SDL_EVENT_GAMEPAD_AXIS_MOTION: {
50-
ievent.id = event->gaxis.axis;
51-
} break;
28+
if (event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN) {
29+
input::execute_action(iris, *action, m_slot, 1.0f);
30+
} else if (event->type == SDL_EVENT_GAMEPAD_BUTTON_UP) {
31+
input::execute_action(iris, *action, m_slot, 0.0f);
32+
} else if (event->type == SDL_EVENT_GAMEPAD_AXIS_MOTION) {
33+
// Convert from -32768->32767 to -1.0->1.0 and take absolute value
34+
float value = fabs(event->gaxis.value / 32767.0f);
35+
36+
input::execute_action(iris, *action, m_slot, value);
5237
}
38+
}
5339

54-
return ievent;
5540
}
5641

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;
42+
namespace iris::input {
6443

65-
case INPUT_ACTION_RELEASE_BUTTON: {
66-
if (iris->ds[slot]) {
67-
ds_button_release(iris->ds[slot], act.destination);
68-
}
69-
} break;
44+
input_action* get_input_action(iris::instance* iris, int slot, uint64_t input) {
45+
if (iris->input_map[slot] == -1)
46+
return nullptr;
7047

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-
}
48+
return iris->input_maps[iris->input_map[slot]].map.get_value(input);
7749
}
7850

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-
}
51+
static inline void change_button(iris::instance* iris, int slot, float value, uint32_t button) {
52+
if (!iris->ds[slot]) return;
9553

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-
}
54+
if (value > 0.5f) {
55+
ds_button_press(iris->ds[slot], button);
56+
} else {
57+
ds_button_release(iris->ds[slot], button);
58+
}
59+
}
11060

111-
if (iris->ds[m_slot]) {
112-
ds_button_release(iris->ds[m_slot], mask);
113-
}
61+
void execute_action(iris::instance* iris, input_action action, int slot, float value) {
62+
if (!iris->ds[slot])
63+
return;
64+
65+
switch (action) {
66+
case IRIS_DS_BT_SELECT: change_button(iris, slot, value, DS_BT_SELECT); break;
67+
case IRIS_DS_BT_L3: change_button(iris, slot, value, DS_BT_L3); break;
68+
case IRIS_DS_BT_R3: change_button(iris, slot, value, DS_BT_R3); break;
69+
case IRIS_DS_BT_START: change_button(iris, slot, value, DS_BT_START); break;
70+
case IRIS_DS_BT_UP: change_button(iris, slot, value, DS_BT_UP); break;
71+
case IRIS_DS_BT_RIGHT: change_button(iris, slot, value, DS_BT_RIGHT); break;
72+
case IRIS_DS_BT_DOWN: change_button(iris, slot, value, DS_BT_DOWN); break;
73+
case IRIS_DS_BT_LEFT: change_button(iris, slot, value, DS_BT_LEFT); break;
74+
case IRIS_DS_BT_L2: change_button(iris, slot, value, DS_BT_L2); break;
75+
case IRIS_DS_BT_R2: change_button(iris, slot, value, DS_BT_R2); break;
76+
case IRIS_DS_BT_L1: change_button(iris, slot, value, DS_BT_L1); break;
77+
case IRIS_DS_BT_R1: change_button(iris, slot, value, DS_BT_R1); break;
78+
case IRIS_DS_BT_TRIANGLE: change_button(iris, slot, value, DS_BT_TRIANGLE); break;
79+
case IRIS_DS_BT_CIRCLE: change_button(iris, slot, value, DS_BT_CIRCLE); break;
80+
case IRIS_DS_BT_CROSS: change_button(iris, slot, value, DS_BT_CROSS); break;
81+
case IRIS_DS_BT_SQUARE: change_button(iris, slot, value, DS_BT_SQUARE); break;
82+
case IRIS_DS_BT_ANALOG: change_button(iris, slot, value, DS_BT_ANALOG); break;
83+
case IRIS_DS_AX_RIGHTV_POS: ds_analog_change(iris->ds[slot], DS_AX_RIGHT_V, 0x7f + (value * 0x80)); break;
84+
case IRIS_DS_AX_RIGHTV_NEG: ds_analog_change(iris->ds[slot], DS_AX_RIGHT_V, 0x7f - (value * 0x7f)); break;
85+
case IRIS_DS_AX_RIGHTH_POS: ds_analog_change(iris->ds[slot], DS_AX_RIGHT_H, 0x7f + (value * 0x80)); break;
86+
case IRIS_DS_AX_RIGHTH_NEG: ds_analog_change(iris->ds[slot], DS_AX_RIGHT_H, 0x7f - (value * 0x7f)); break;
87+
case IRIS_DS_AX_LEFTV_POS: ds_analog_change(iris->ds[slot], DS_AX_LEFT_V, 0x7f + (value * 0x80)); break;
88+
case IRIS_DS_AX_LEFTV_NEG: ds_analog_change(iris->ds[slot], DS_AX_LEFT_V, 0x7f - (value * 0x7f)); break;
89+
case IRIS_DS_AX_LEFTH_POS: ds_analog_change(iris->ds[slot], DS_AX_LEFT_H, 0x7f + (value * 0x80)); break;
90+
case IRIS_DS_AX_LEFTH_NEG: ds_analog_change(iris->ds[slot], DS_AX_LEFT_H, 0x7f - (value * 0x7f)); break;
11491
}
11592
}
11693

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-
}
94+
input_event sdl_event_to_input_event(SDL_Event* event) {
95+
input_event ievent = {};
14096

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;
97+
switch (event->type) {
98+
case SDL_EVENT_KEY_DOWN:
99+
case SDL_EVENT_KEY_UP: {
100+
ievent.type = IRIS_EVENT_KEYBOARD;
101+
ievent.id = event->key.key;
102+
} break;
103+
104+
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
105+
case SDL_EVENT_GAMEPAD_BUTTON_UP: {
106+
ievent.type = IRIS_EVENT_GAMEPAD_BUTTON;
107+
ievent.id = event->gbutton.button;
108+
} break;
109+
110+
case SDL_EVENT_GAMEPAD_AXIS_MOTION: {
111+
if (event->gaxis.value > 0) {
112+
ievent.type = IRIS_EVENT_GAMEPAD_AXIS_POS;
113+
} else {
114+
ievent.type = IRIS_EVENT_GAMEPAD_AXIS_NEG;
187115
}
188-
}
116+
117+
ievent.id = event->gaxis.axis;
118+
} break;
189119
}
120+
121+
return ievent;
190122
}
191123

192124
std::string get_default_screenshot_filename(iris::instance* iris) {
@@ -229,7 +161,7 @@ int get_screenshot_jpg_quality(iris::instance* iris) {
229161
return 90;
230162
}
231163

232-
bool save_screenshot(iris::instance* iris, std::string path = "") {
164+
bool save_screenshot(iris::instance* iris, std::string path) {
233165
std::filesystem::path fn(path);
234166

235167
std::string directory = iris->snap_path;
@@ -367,6 +299,10 @@ void handle_keydown_event(iris::instance* iris, SDL_Event* event) {
367299
} break;
368300
}
369301

302+
iris->last_input_event_read = false;
303+
iris->last_input_event_value = 1.0f;
304+
iris->last_input_event = sdl_event_to_input_event(event);
305+
370306
if (iris->input_devices[0]) iris->input_devices[0]->handle_event(iris, event);
371307
if (iris->input_devices[1]) iris->input_devices[1]->handle_event(iris, event);
372308
}

0 commit comments

Comments
 (0)