GCC Code Coverage Report


Directory: main/
File: adapter/wired/saturn.c
Date: 2025-10-04 14:03:00
Exec Total Coverage
Lines: 77 174 44.3%
Functions: 5 9 55.6%
Branches: 40 95 42.1%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2019-2025, Jacques Gagnon
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #include <string.h>
7 #include "zephyr/types.h"
8 #include "tools/util.h"
9 #include "adapter/config.h"
10 #include "adapter/kb_monitor.h"
11 #include "adapter/wired/wired.h"
12 #include "system/manager.h"
13 #include "tests/cmds.h"
14 #include "bluetooth/mon.h"
15 #include "saturn.h"
16
17 enum {
18 SATURN_B = 0,
19 SATURN_C,
20 SATURN_A,
21 SATURN_START,
22 SATURN_LD_UP,
23 SATURN_LD_DOWN,
24 SATURN_LD_LEFT,
25 SATURN_LD_RIGHT,
26 SATURN_L = 11,
27 SATURN_Z,
28 SATURN_Y,
29 SATURN_X,
30 SATURN_R,
31 };
32
33 static DRAM_ATTR const uint8_t saturn_axes_idx[ADAPTER_MAX_AXES] =
34 {
35 /* AXIS_LX, AXIS_LY, AXIS_RX, AXIS_RY, TRIG_L, TRIG_R */
36 0, 1, 0, 0, 3, 2
37 };
38
39 static DRAM_ATTR const uint8_t sega_mouse_axes_idx[ADAPTER_MAX_AXES] =
40 {
41 /* AXIS_LX, AXIS_LY, AXIS_RX, AXIS_RY, TRIG_L, TRIG_R */
42 0, 1, 0, 1, 0, 1
43 };
44
45 static DRAM_ATTR const struct ctrl_meta saturn_axes_meta[ADAPTER_MAX_AXES] =
46 {
47 {.size_min = -128, .size_max = 127, .neutral = 0x80, .abs_max = 0x7F, .abs_min = 0x80},
48 {.size_min = -128, .size_max = 127, .neutral = 0x80, .abs_max = 0x7F, .abs_min = 0x80, .polarity = 1},
49 {.size_min = -128, .size_max = 127, .neutral = 0x80, .abs_max = 0x7F, .abs_min = 0x80}, //NA
50 {.size_min = -128, .size_max = 127, .neutral = 0x80, .abs_max = 0x7F, .abs_min = 0x80, .polarity = 1}, //NA
51 {.size_min = 0, .size_max = 255, .neutral = 0x00, .abs_max = 0xFF, .abs_min = 0x00},
52 {.size_min = 0, .size_max = 255, .neutral = 0x00, .abs_max = 0xFF, .abs_min = 0x00},
53 };
54
55 static DRAM_ATTR const struct ctrl_meta sega_mouse_axes_meta[ADAPTER_MAX_AXES] =
56 {
57 {.size_min = -256, .size_max = 255, .neutral = 0x00, .abs_max = 255, .abs_min = 256},
58 {.size_min = -256, .size_max = 255, .neutral = 0x00, .abs_max = 255, .abs_min = 256},
59 {.size_min = -256, .size_max = 255, .neutral = 0x00, .abs_max = 255, .abs_min = 256},
60 {.size_min = -256, .size_max = 255, .neutral = 0x00, .abs_max = 255, .abs_min = 256},
61 {.size_min = -256, .size_max = 255, .neutral = 0x00, .abs_max = 255, .abs_min = 256},
62 {.size_min = -256, .size_max = 255, .neutral = 0x00, .abs_max = 255, .abs_min = 256},
63 };
64
65 struct saturn_map {
66 uint16_t buttons;
67 union {
68 uint8_t axes[4];
69 struct {
70 uint8_t flags;
71 uint8_t scancode;
72 };
73 struct {
74 uint16_t sticks;
75 uint16_t triggers;
76 };
77 };
78 } __packed;
79
80 struct sega_mouse_map {
81 union {
82 uint8_t buttons;
83 uint8_t flags;
84 };
85 uint8_t align[1];
86 uint8_t relative[2];
87 int32_t raw_axes[2];
88 } __packed;
89
90 static const uint32_t saturn_mask[4] = {0x335F0F00, 0x00000000, 0x00000000, BR_COMBO_MASK};
91 static const uint32_t saturn_desc[4] = {0x00000000, 0x00000000, 0x00000000, 0x00000000};
92 static const uint32_t saturn_3d_mask[4] = {0x335F0F0F, 0x00000000, 0x00000000, BR_COMBO_MASK};
93 static const uint32_t saturn_3d_desc[4] = {0x1100000F, 0x00000000, 0x00000000, 0x00000000};
94 static DRAM_ATTR const uint32_t saturn_btns_mask[32] = {
95 0, 0, 0, 0,
96 0, 0, 0, 0,
97 BIT(SATURN_LD_LEFT), BIT(SATURN_LD_RIGHT), BIT(SATURN_LD_DOWN), BIT(SATURN_LD_UP),
98 0, 0, 0, 0,
99 BIT(SATURN_A), BIT(SATURN_C), BIT(SATURN_B), BIT(SATURN_Y),
100 BIT(SATURN_START), 0, 0, 0,
101 BIT(SATURN_L), BIT(SATURN_X), 0, 0,
102 BIT(SATURN_R), BIT(SATURN_Z), 0, 0,
103 };
104
105 static const uint32_t sega_mouse_mask[4] = {0x190100F0, 0x00000000, 0x00000000, BR_COMBO_MASK};
106 static const uint32_t sega_mouse_desc[4] = {0x000000F0, 0x00000000, 0x00000000, 0x00000000};
107 static const uint32_t sega_mouse_btns_mask[32] = {
108 0, 0, 0, 0,
109 0, 0, 0, 0,
110 0, 0, 0, 0,
111 0, 0, 0, 0,
112 BIT(SATURN_START), 0, 0, 0,
113 0, 0, 0, 0,
114 BIT(SATURN_C), 0, 0, BIT(SATURN_A),
115 BIT(SATURN_B), 0, 0, 0,
116 };
117
118 static const uint32_t saturn_kb_mask[4] = {0xE6FF0F0F, 0xFFFFFFFF, 0xFFFFFFFF, 0x0007FFFF | BR_COMBO_MASK};
119 static const uint32_t saturn_kb_desc[4] = {0x00000000, 0x00000000, 0x00000000, 0x00000000};
120 static const uint8_t saturn_kb_scancode[KBM_MAX] = {
121 /* Source: https://plutiedev.com/saturn-keyboard */
122 /* KB_A, KB_D, KB_S, KB_W, MOUSE_X_LEFT, MOUSE_X_RIGHT, MOUSE_Y_DOWN MOUSE_Y_UP */
123 0x1C, 0x23, 0x1B, 0x1D, 0x00, 0x00, 0x00, 0x00,
124 /* KB_LEFT, KB_RIGHT, KB_DOWN, KB_UP, MOUSE_WX_LEFT, MOUSE_WX_RIGHT, MOUSE_WY_DOWN, MOUSE_WY_UP */
125 0x86, 0x8D, 0x8A, 0x89, 0x00, 0x00, 0x00, 0x00,
126 /* KB_Q, KB_R, KB_E, KB_F, KB_ESC, KB_ENTER, KB_LWIN, KB_HASH */
127 0x15, 0x2D, 0x24, 0x2B, 0x76, 0x5A, 0x1F, 0x0E,
128 /* MOUSE_RIGHT, KB_Z, KB_LCTRL, MOUSE_MIDDLE, MOUSE_LEFT, KB_X, KB_LSHIFT, KB_SPACE */
129 0x00, 0x1A, 0x14, 0x00, 0x00, 0x22, 0x12, 0x29,
130
131 /* KB_B, KB_C, KB_G, KB_H, KB_I, KB_J, KB_K, KB_L */
132 0x32, 0x21, 0x34, 0x33, 0x43, 0x3B, 0x42, 0x4B,
133 /* KB_M, KB_N, KB_O, KB_P, KB_T, KB_U, KB_V, KB_Y */
134 0x3A, 0x31, 0x44, 0x4D, 0x2C, 0x3C, 0x2A, 0x35,
135 /* KB_1, KB_2, KB_3, KB_4, KB_5, KB_6, KB_7, KB_8 */
136 0x16, 0x1E, 0x26, 0x25, 0x2E, 0x36, 0x3D, 0x3E,
137 /* KB_9, KB_0, KB_BACKSPACE, KB_TAB, KB_MINUS, KB_EQUAL, KB_LEFTBRACE, KB_RIGHTBRACE */
138 0x46, 0x45, 0x66, 0x0D, 0x4E, 0x55, 0x54, 0x5B,
139
140 /* KB_BACKSLASH, KB_SEMICOLON, KB_APOSTROPHE, KB_GRAVE, KB_COMMA, KB_DOT, KB_SLASH, KB_CAPSLOCK */
141 0x5D, 0x4C, 0x51, 0x00, 0x41, 0x49, 0x4A, 0x58,
142 /* KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6, KB_F7, KB_F8 */
143 0x05, 0x06, 0x04, 0x0C, 0x03, 0x0B, 0x83, 0x0A,
144 /* KB_F9, KB_F10, KB_F11, KB_F12, KB_PSCREEN, KB_SCROLL, KB_PAUSE, KB_INSERT */
145 0x01, 0x09, 0x78, 0x07, 0x84, 0x7E, 0x82, 0x81,
146 /* KB_HOME, KB_PAGEUP, KB_DEL, KB_END, KB_PAGEDOWN, KB_NUMLOCK, KB_KP_DIV, KB_KP_MULTI */
147 0x87, 0x8B, 0x85, 0x88, 0x8C, 0x77, 0x80, 0x7C,
148
149 /* KB_KP_MINUS, KB_KP_PLUS, KB_KP_ENTER, KB_KP_1, KB_KP_2, KB_KP_3, KB_KP_4, KB_KP_5 */
150 0x7B, 0x79, 0x19, 0x69, 0x72, 0x7A, 0x6B, 0x73,
151 /* KB_KP_6, KB_KP_7, KB_KP_8, KB_KP_9, KB_KP_0, KB_KP_DOT, KB_LALT, KB_RCTRL */
152 0x74, 0x6C, 0x75, 0x7D, 0x70, 0x71, 0x11, 0x18,
153 /* KB_RSHIFT, KB_RALT, KB_RWIN */
154 0x59, 0x17, 0x00,
155 };
156
157 14 static void saturn_ctrl_special_action(struct wired_ctrl *ctrl_data, struct wired_data *wired_data) {
158 /* Output config mode toggle GamePad/GamePadAlt */
159
1/2
✓ Branch 0 (2→3) taken 14 times.
✗ Branch 1 (2→11) not taken.
14 if (ctrl_data->map_mask[0] & generic_btns_mask[PAD_MT]) {
160
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→7) taken 14 times.
14 if (ctrl_data->btns[0].value & generic_btns_mask[PAD_MT]) {
161 if (!atomic_test_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE)) {
162 atomic_set_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE);
163 }
164 }
165 else {
166
1/2
✗ Branch 0 (8→9) not taken.
✓ Branch 1 (8→11) taken 14 times.
14 if (atomic_test_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE)) {
167 atomic_clear_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE);
168
169 config.out_cfg[ctrl_data->index].dev_mode &= 0x01;
170 config.out_cfg[ctrl_data->index].dev_mode ^= 0x01;
171 sys_mgr_cmd(SYS_MGR_CMD_WIRED_RST);
172 }
173 }
174 }
175 14 }
176
177 4 void IRAM_ATTR saturn_init_buffer(int32_t dev_mode, struct wired_data *wired_data) {
178
1/3
✗ Branch 0 (2→3) not taken.
✗ Branch 1 (2→4) not taken.
✓ Branch 2 (2→7) taken 4 times.
4 switch (dev_mode) {
179 case DEV_KB:
180 {
181 struct saturn_map *map = (struct saturn_map *)wired_data->output;
182
183 map->buttons = 0xFFFF;
184 map->flags = 0x06;
185 map->scancode = 0x00;
186 break;
187 }
188 case DEV_MOUSE:
189 {
190 struct sega_mouse_map *map = (struct sega_mouse_map *)wired_data->output;
191
192 map->buttons = 0x00;
193 for (uint32_t i = 0; i < 2; i++) {
194 map->raw_axes[i] = 0;
195 map->relative[i] = 1;
196 }
197 break;
198 }
199 4 default:
200 {
201 4 struct saturn_map *map = (struct saturn_map *)wired_data->output;
202 4 struct saturn_map *map_mask = (struct saturn_map *)wired_data->output_mask;
203
204 4 map->buttons = 0xFFFF;
205
2/2
✓ Branch 0 (12→8) taken 24 times.
✓ Branch 1 (12→13) taken 4 times.
28 for (uint32_t i = 0; i < ADAPTER_MAX_AXES; i++) {
206
2/2
✓ Branch 0 (8→9) taken 8 times.
✓ Branch 1 (8→10) taken 16 times.
24 if (i == 2 || i == 3) {
207 8 continue;
208 }
209 16 map->axes[saturn_axes_idx[i]] = saturn_axes_meta[i].neutral;
210 }
211
212 4 map_mask->buttons = 0x0000;
213 4 map_mask->sticks = 0x0000;
214 4 map_mask->triggers = 0xFFFF;
215 4 break;
216 }
217 }
218 4 }
219
220 14 void saturn_meta_init(struct wired_ctrl *ctrl_data) {
221 14 memset((void *)ctrl_data, 0, sizeof(*ctrl_data)*WIRED_MAX_DEV);
222
223
2/2
✓ Branch 0 (13→14) taken 112 times.
✓ Branch 1 (13→15) taken 14 times.
126 for (uint32_t i = 0; i < WIRED_MAX_DEV; i++) {
224
2/2
✓ Branch 0 (10→4) taken 672 times.
✓ Branch 1 (10→11) taken 112 times.
784 for (uint32_t j = 0; j < ADAPTER_MAX_AXES; j++) {
225
2/4
✗ Branch 0 (4→5) not taken.
✗ Branch 1 (4→6) not taken.
✓ Branch 2 (4→7) taken 84 times.
✓ Branch 3 (4→8) taken 588 times.
672 switch (config.out_cfg[i].dev_mode) {
226 case DEV_KB:
227 ctrl_data[i].mask = saturn_kb_mask;
228 ctrl_data[i].desc = saturn_kb_desc;
229 goto exit_axes_loop;
230 case DEV_MOUSE:
231 ctrl_data[i].mask = sega_mouse_mask;
232 ctrl_data[i].desc = sega_mouse_desc;
233 ctrl_data[i].axes[j].meta = &sega_mouse_axes_meta[j];
234 break;
235 84 case DEV_PAD_ALT:
236 84 ctrl_data[i].mask = saturn_3d_mask;
237 84 ctrl_data[i].desc = saturn_3d_desc;
238 84 ctrl_data[i].axes[j].meta = &saturn_axes_meta[j];
239 84 break;
240 588 default:
241 588 ctrl_data[i].mask = saturn_mask;
242 588 ctrl_data[i].desc = saturn_desc;
243 588 ctrl_data[i].axes[j].meta = &saturn_axes_meta[j];
244 588 break;
245 }
246 }
247 112 exit_axes_loop:
248 112 ;
249 }
250 14 }
251
252 14 void saturn_ctrl_from_generic(struct wired_ctrl *ctrl_data, struct wired_data *wired_data) {
253 14 struct saturn_map map_tmp;
254
255 14 memcpy((void *)&map_tmp, wired_data->output, sizeof(map_tmp));
256
257
2/2
✓ Branch 0 (11→4) taken 448 times.
✓ Branch 1 (11→12) taken 14 times.
462 for (uint32_t i = 0; i < ARRAY_SIZE(generic_btns_mask); i++) {
258
2/2
✓ Branch 0 (4→5) taken 252 times.
✓ Branch 1 (4→10) taken 196 times.
448 if (ctrl_data->map_mask[0] & BIT(i)) {
259
2/2
✓ Branch 0 (5→6) taken 14 times.
✓ Branch 1 (5→7) taken 238 times.
252 if (ctrl_data->btns[0].value & generic_btns_mask[i]) {
260 14 map_tmp.buttons &= ~saturn_btns_mask[i];
261 14 wired_data->cnt_mask[i] = ctrl_data->btns[0].cnt_mask[i];
262 }
263
3/4
✓ Branch 0 (7→8) taken 238 times.
✗ Branch 1 (7→9) not taken.
✓ Branch 2 (8→9) taken 210 times.
✓ Branch 3 (8→10) taken 28 times.
238 else if (!(config.out_cfg[ctrl_data->index].dev_mode == DEV_PAD_ALT && (i == PAD_LM || i == PAD_RM))) {
264 210 map_tmp.buttons |= saturn_btns_mask[i];
265 210 wired_data->cnt_mask[i] = 0;
266 }
267 }
268 }
269
270 14 saturn_ctrl_special_action(ctrl_data, wired_data);
271
272
1/2
✓ Branch 0 (13→14) taken 14 times.
✗ Branch 1 (13→36) not taken.
14 if (config.out_cfg[ctrl_data->index].dev_mode == DEV_PAD_ALT) {
273
2/2
✓ Branch 0 (27→15) taken 84 times.
✓ Branch 1 (27→28) taken 14 times.
98 for (uint32_t i = 0; i < ADAPTER_MAX_AXES; i++) {
274
2/2
✓ Branch 0 (15→16) taken 28 times.
✓ Branch 1 (15→17) taken 56 times.
84 if (i == 2 || i == 3) {
275 28 continue;
276 }
277
1/2
✓ Branch 0 (18→19) taken 56 times.
✗ Branch 1 (18→24) not taken.
56 if (ctrl_data->map_mask[0] & (axis_to_btn_mask(i) & saturn_3d_desc[0])) {
278
1/2
✗ Branch 0 (19→20) not taken.
✓ Branch 1 (19→21) taken 56 times.
56 if (ctrl_data->axes[i].value > ctrl_data->axes[i].meta->size_max) {
279 map_tmp.axes[saturn_axes_idx[i]] = 255;
280 }
281
1/2
✗ Branch 0 (21→22) not taken.
✓ Branch 1 (21→23) taken 56 times.
56 else if (ctrl_data->axes[i].value < ctrl_data->axes[i].meta->size_min) {
282 map_tmp.axes[saturn_axes_idx[i]] = 0;
283 }
284 else {
285 56 map_tmp.axes[saturn_axes_idx[i]] = (uint8_t)(ctrl_data->axes[i].value + ctrl_data->axes[i].meta->neutral);
286 }
287 }
288 56 wired_data->cnt_mask[axis_to_btn_id(i)] = ctrl_data->axes[i].cnt_mask;
289 }
290
291
2/2
✓ Branch 0 (28→29) taken 11 times.
✓ Branch 1 (28→30) taken 3 times.
14 if (map_tmp.axes[saturn_axes_idx[TRIG_L]] < 0x56) {
292 11 map_tmp.buttons |= BIT(SATURN_L);
293 }
294
2/2
✓ Branch 0 (30→31) taken 2 times.
✓ Branch 1 (30→32) taken 1 times.
3 else if (map_tmp.axes[saturn_axes_idx[TRIG_L]] > 0x8D) {
295 2 map_tmp.buttons &= ~BIT(SATURN_L);
296 }
297
2/2
✓ Branch 0 (32→33) taken 11 times.
✓ Branch 1 (32→34) taken 3 times.
14 if (map_tmp.axes[saturn_axes_idx[TRIG_R]] < 0x56) {
298 11 map_tmp.buttons |= BIT(SATURN_R);
299 }
300
2/2
✓ Branch 0 (34→35) taken 2 times.
✓ Branch 1 (34→36) taken 1 times.
3 else if (map_tmp.axes[saturn_axes_idx[TRIG_R]] > 0x8D) {
301 2 map_tmp.buttons &= ~BIT(SATURN_R);
302 }
303 }
304
305 14 memcpy(wired_data->output, (void *)&map_tmp, sizeof(map_tmp));
306
307 14 TESTS_CMDS_LOG("\"wired_output\": {\"axes\": [%d, %d, %d, %d], \"btns\": %d},\n",
308 map_tmp.axes[saturn_axes_idx[0]], map_tmp.axes[saturn_axes_idx[1]],
309 map_tmp.axes[saturn_axes_idx[4]], map_tmp.axes[saturn_axes_idx[5]], map_tmp.buttons);
310 BT_MON_LOG("\"wired_output\": {\"axes\": [%02X, %02X, %02X, %02X], \"btns\": %04X},\n",
311 map_tmp.axes[saturn_axes_idx[0]], map_tmp.axes[saturn_axes_idx[1]],
312 14 map_tmp.axes[saturn_axes_idx[4]], map_tmp.axes[saturn_axes_idx[5]], map_tmp.buttons);
313 14 }
314
315 static void saturn_mouse_from_generic(struct wired_ctrl *ctrl_data, struct wired_data *wired_data) {
316 struct sega_mouse_map map_tmp;
317 int32_t *raw_axes = (int32_t *)(wired_data->output + 4);
318
319 memcpy((void *)&map_tmp, wired_data->output, sizeof(map_tmp));
320
321 for (uint32_t i = 0; i < ARRAY_SIZE(generic_btns_mask); i++) {
322 if (ctrl_data->map_mask[0] & BIT(i)) {
323 if (ctrl_data->btns[0].value & generic_btns_mask[i]) {
324 map_tmp.buttons |= sega_mouse_btns_mask[i];
325 }
326 else {
327 map_tmp.buttons &= ~sega_mouse_btns_mask[i];
328 }
329 }
330 }
331
332 for (uint32_t i = 2; i < 4; i++) {
333 if (ctrl_data->map_mask[0] & (axis_to_btn_mask(i) & sega_mouse_desc[0])) {
334 if (ctrl_data->axes[i].relative) {
335 map_tmp.relative[sega_mouse_axes_idx[i]] = 1;
336 atomic_add(&raw_axes[sega_mouse_axes_idx[i]], ctrl_data->axes[i].value);
337 }
338 else {
339 map_tmp.relative[sega_mouse_axes_idx[i]] = 0;
340 raw_axes[sega_mouse_axes_idx[i]] = ctrl_data->axes[i].value;
341 }
342 }
343 }
344
345 memcpy(wired_data->output, (void *)&map_tmp, sizeof(map_tmp) - 8);
346 }
347
348 static void saturn_kb_from_generic(struct wired_ctrl *ctrl_data, struct wired_data *wired_data) {
349 uint16_t buttons = *(uint16_t *)wired_data->output;
350
351 if (!atomic_test_bit(&wired_data->flags, WIRED_KBMON_INIT)) {
352 kbmon_init(ctrl_data->index, saturn_kb_id_to_scancode);
353 atomic_set_bit(&wired_data->flags, WIRED_KBMON_INIT);
354 }
355
356 /* Use BlueRetro KB/Gamepad mapping here */
357 for (uint32_t i = 0; i < ARRAY_SIZE(generic_btns_mask); i++) {
358 if (ctrl_data->map_mask[0] & BIT(i)) {
359 if (ctrl_data->btns[0].value & generic_btns_mask[i]) {
360 buttons &= ~saturn_btns_mask[i];
361 }
362 else {
363 buttons |= saturn_btns_mask[i];
364 }
365 }
366 }
367
368 *(uint16_t *)wired_data->output = buttons;
369
370 kbmon_update(ctrl_data->index, ctrl_data);
371 }
372
373 void saturn_kb_id_to_scancode(uint32_t dev_id, uint8_t type, uint8_t id) {
374 uint8_t kb_buf[2] = {0};
375 switch (type) {
376 case KBMON_TYPE_MAKE:
377 kb_buf[0] = 0x08;
378 break;
379 case KBMON_TYPE_BREAK:
380 kb_buf[0] = 0x01;
381 break;
382 }
383 if (id < KBM_MAX) {
384 kb_buf[1] = saturn_kb_scancode[id];
385 }
386 kbmon_set_code(dev_id, kb_buf, sizeof(kb_buf));
387 }
388
389 14 void saturn_from_generic(int32_t dev_mode, struct wired_ctrl *ctrl_data, struct wired_data *wired_data) {
390
1/3
✗ Branch 0 (2→3) not taken.
✗ Branch 1 (2→5) not taken.
✓ Branch 2 (2→7) taken 14 times.
14 switch (dev_mode) {
391 case DEV_KB:
392 saturn_kb_from_generic(ctrl_data, wired_data);
393 break;
394 case DEV_MOUSE:
395 saturn_mouse_from_generic(ctrl_data, wired_data);
396 break;
397 14 default:
398 14 saturn_ctrl_from_generic(ctrl_data, wired_data);
399 14 break;
400 }
401 14 }
402
403 void IRAM_ATTR saturn_gen_turbo_mask(struct wired_data *wired_data) {
404 struct saturn_map *map_mask = (struct saturn_map *)wired_data->output_mask;
405
406 map_mask->buttons = 0x0000;
407 map_mask->sticks = 0x0000;
408 map_mask->triggers = 0xFFFF;
409
410 wired_gen_turbo_mask_btns16_neg(wired_data, &map_mask->buttons, saturn_btns_mask);
411
412 for (uint32_t i = 0; i < ADAPTER_MAX_AXES; i++) {
413 if (i == 2 || i == 3) {
414 continue;
415 }
416
417 uint8_t btn_id = axis_to_btn_id(i);
418 uint8_t mask = wired_data->cnt_mask[btn_id] >> 1;
419 if (mask) {
420 if (wired_data->cnt_mask[btn_id] & 1) {
421 if (!(mask & wired_data->frame_cnt)) {
422 map_mask->axes[saturn_axes_idx[i]] = saturn_axes_meta[i].neutral;
423 }
424 }
425 else {
426 if (!((mask & wired_data->frame_cnt) == mask)) {
427 map_mask->axes[saturn_axes_idx[i]] = saturn_axes_meta[i].neutral;
428 }
429 }
430 }
431 }
432 }
433