From 70eb94355c6dc9b69ac9d00f3c1891004510101e Mon Sep 17 00:00:00 2001 From: sorgelig Date: Sat, 14 Nov 2020 15:47:52 +0800 Subject: [PATCH] input: support spinner from mouse. --- MiSTer.ini | 7 +++ cfg.cpp | 3 ++ cfg.h | 3 ++ input.cpp | 116 ++++++++++++++++++++++++++++++++++++------------- joymapping.cpp | 4 +- 5 files changed, 100 insertions(+), 33 deletions(-) diff --git a/MiSTer.ini b/MiSTer.ini index 64be45c..c0ff55d 100644 --- a/MiSTer.ini +++ b/MiSTer.ini @@ -137,3 +137,10 @@ shared_folder= ; Custom aspect ratio ;custom_aspect_ratio_1=16:10 ;custom_aspect_ratio_2=1:1 + +; use specific (VID/PID) mouse X movement as a spinner and paddle. +; spinner_throttle with base value 100 gives one spinner step per one tick. Higher value makes spinner slower. +; Lower than 100 makes spinner faster. Negative value gives opposite direction. +;spinner_vid=0x1BCF +;spinner_pid=0x0005 +;spinner_throttle=-50 diff --git a/cfg.cpp b/cfg.cpp index e168bc4..7aeb60c 100644 --- a/cfg.cpp +++ b/cfg.cpp @@ -76,6 +76,9 @@ static const ini_var_t ini_vars[] = { "NO_MERGE_PID", (void*)(&(cfg.no_merge_pid)), UINT16, 0, 0xFFFF }, { "CUSTOM_ASPECT_RATIO_1", (void*)(&(cfg.custom_aspect_ratio[0])), STRING, 0, sizeof(cfg.custom_aspect_ratio[0]) - 1 }, { "CUSTOM_ASPECT_RATIO_2", (void*)(&(cfg.custom_aspect_ratio[1])), STRING, 0, sizeof(cfg.custom_aspect_ratio[1]) - 1 }, + { "SPINNER_VID", (void*)(&(cfg.spinner_vid)), UINT16, 0, 0xFFFF }, + { "SPINNER_PID", (void*)(&(cfg.spinner_pid)), UINT16, 0, 0xFFFF }, + { "SPINNER_THROTTLE", (void*)(&(cfg.spinner_throttle)), INT32, -100, 100 }, }; static const int nvars = (int)(sizeof(ini_vars) / sizeof(ini_var_t)); diff --git a/cfg.h b/cfg.h index 9603c0b..85817de 100644 --- a/cfg.h +++ b/cfg.h @@ -44,6 +44,9 @@ typedef struct { uint16_t jamma_pid; uint16_t no_merge_vid; uint16_t no_merge_pid; + uint16_t spinner_vid; + uint16_t spinner_pid; + int spinner_throttle; uint8_t sniper_mode; uint8_t browse_expand; uint8_t logo; diff --git a/input.cpp b/input.cpp index f9a8325..4e06e82 100644 --- a/input.cpp +++ b/input.cpp @@ -853,6 +853,7 @@ enum QUIRK QUIRK_PDSP, QUIRK_PDSP_ARCADE, QUIRK_JAMMA, + QUIRK_MSSP, }; typedef struct @@ -885,7 +886,10 @@ typedef struct int quirk; int misc_flags; - int mc_a; + int paddle_val; + int spinner_acc; + int old_btn; + int ds_mouse_emu; int lightgun_req; int lightgun; @@ -1687,7 +1691,7 @@ void reset_players() void store_player(int num, int dev) { - devInput *player = (input[dev].quirk == QUIRK_PDSP) ? player_pdsp : player_pad; + devInput *player = (input[dev].quirk == QUIRK_PDSP || input[dev].quirk == QUIRK_MSSP) ? player_pdsp : player_pad; // remove possible old assignment for (int i = 1; i < NUMPLAYERS; i++) if (!strcmp(player[i].id, input[dev].id)) player[i].id[0] = 0; @@ -1700,7 +1704,7 @@ void restore_player(int dev) // do not restore bound devices if (dev != input[dev].bind) return; - devInput *player = (input[dev].quirk == QUIRK_PDSP) ? player_pdsp : player_pad; + devInput *player = (input[dev].quirk == QUIRK_PDSP || input[dev].quirk == QUIRK_MSSP) ? player_pdsp : player_pad; for (int k = 1; k < NUMPLAYERS; k++) { if (strlen(player[k].id) && !strcmp(player[k].id, input[dev].id)) @@ -1734,8 +1738,6 @@ void unflag_players() } } -static int ds_mouse_emu = 0; - static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int dev) { if (ev->type != EV_KEY && ev->type != EV_ABS && ev->type != EV_REL) return; @@ -1766,7 +1768,7 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int if (!input[dev].has_mmap) { - if (input[dev].quirk != QUIRK_PDSP) + if (input[dev].quirk != QUIRK_PDSP && input[dev].quirk != QUIRK_MSSP) { if (!load_map(get_map_name(dev, 1), &input[dev].mmap, sizeof(input[dev].mmap))) { @@ -1780,7 +1782,7 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int if (!input[dev].has_map) { - if (input[dev].quirk == QUIRK_PDSP) + if (input[dev].quirk == QUIRK_PDSP || input[dev].quirk == QUIRK_MSSP) { memset(input[dev].map, 0, sizeof(input[dev].map)); input[dev].map[map_paddle_btn()] = 0x120; @@ -1807,7 +1809,7 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int if (!input[dev].num) { - int assign_btn = (input[dev].quirk == QUIRK_PDSP && ev->type == EV_REL); + int assign_btn = ((input[dev].quirk == QUIRK_PDSP || input[dev].quirk == QUIRK_MSSP) && ev->type == EV_REL); if (!assign_btn && ev->type == EV_KEY && ev->value >= 1) { for (int i = SYS_BTN_RIGHT; i <= SYS_BTN_START; i++) if (ev->code == input[dev].mmap[i]) assign_btn = 1; @@ -1821,7 +1823,7 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int for (int i = 0; i < NUMDEV; i++) { // paddles/spinners overlay on top of other gamepad - if (!((input[dev].quirk == QUIRK_PDSP) ^ (input[i].quirk == QUIRK_PDSP))) + if (!((input[dev].quirk == QUIRK_PDSP || input[dev].quirk == QUIRK_MSSP) ^ (input[i].quirk == QUIRK_PDSP || input[i].quirk == QUIRK_MSSP))) { found = (input[i].num == num); if (found) break; @@ -1846,7 +1848,7 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int if (cfg.controller_info) { - if (input[dev].quirk == QUIRK_PDSP) + if (input[dev].quirk == QUIRK_PDSP || input[dev].quirk == QUIRK_MSSP) { char str[32]; sprintf(str, "P%d paddle/spinner", input[dev].num); @@ -1905,7 +1907,8 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int //mapping if (mapping && (mapping_dev >= 0 || ev->value) && !((mapping_type < 2 || !mapping_button) && (cancel || enter)) - && input[dev].quirk != QUIRK_PDSP) + && input[dev].quirk != QUIRK_PDSP + && input[dev].quirk != QUIRK_MSSP) { int idx = 0; @@ -2368,7 +2371,7 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int if (ev->code == input[dev].mmap[SYS_MS_BTN_EMU] && (ev->value <= 1) && ((!(mouse_emu & 1)) ^ (!ev->value))) { mouse_emu = ev->value ? mouse_emu | 1 : mouse_emu & ~1; - if (input[sub_dev].quirk == QUIRK_DS4) ds_mouse_emu = mouse_emu & 1; + if (input[sub_dev].quirk == QUIRK_DS4) input[dev].ds_mouse_emu = mouse_emu & 1; printf("mouse_emu = %d\n", mouse_emu); if (mouse_emu & 2) { @@ -3006,6 +3009,12 @@ int input_test(int getchar) input[n].quirk = QUIRK_JAMMA; } + //Mouse as spinner + if (cfg.spinner_vid && cfg.spinner_pid && input[n].vid == cfg.spinner_vid && input[n].pid == cfg.spinner_pid) + { + input[n].quirk = QUIRK_MSSP; + } + //Arduino and Teensy devices may share the same VID:PID, so additional field UNIQ is used to differentiate them if ((input[n].vid == 0x2341 || (input[n].vid == 0x16C0 && (input[n].pid>>8) == 0x4)) && strlen(uniq)) { @@ -3204,16 +3213,16 @@ int input_test(int getchar) { if ((input[i].misc_flags & 0x6) == 2) { - if (ev.value > 0) input[i].mc_a += 4; - if (ev.value < 0) input[i].mc_a -= 4; + if (ev.value > 0) input[i].paddle_val += 4; + if (ev.value < 0) input[i].paddle_val -= 4; - if (input[i].mc_a > 256) input[i].mc_a = 256; - if (input[i].mc_a < 0) input[i].mc_a = 0; + if (input[i].paddle_val > 256) input[i].paddle_val = 256; + if (input[i].paddle_val < 0) input[i].paddle_val = 0; absinfo.maximum = 255; absinfo.minimum = 0; ev.code = 8; - ev.value = input[i].mc_a; + ev.value = input[i].paddle_val; } else { @@ -3394,7 +3403,7 @@ int input_test(int getchar) if (!noabs) input_cb(&ev, &absinfo, i); //sumulate digital directions from analog - if (ev.type == EV_ABS && !(mapping && mapping_type <= 1 && mapping_button < -4) && !(ev.code <= 1 && input[dev].lightgun) && input[dev].quirk != QUIRK_PDSP) + if (ev.type == EV_ABS && !(mapping && mapping_type <= 1 && mapping_button < -4) && !(ev.code <= 1 && input[dev].lightgun) && input[dev].quirk != QUIRK_PDSP && input[dev].quirk != QUIRK_MSSP) { input_absinfo *pai = 0; uint8_t axis_edge = 0; @@ -3468,27 +3477,72 @@ int input_test(int getchar) continue; } - int xval, yval, throttle = 1; + int xval, yval; xval = ((data[0] & 0x10) ? -256 : 0) | data[1]; yval = ((data[0] & 0x20) ? -256 : 0) | data[2]; - if (is_menu() && !video_fb_state()) printf("%s: btn=0x%02X, dx=%d, dy=%d, scroll=%d\n", input[i].devname, data[0], xval, yval, (int8_t)data[3]); + input_absinfo absinfo = {}; + absinfo.maximum = 255; + absinfo.minimum = 0; - if (cfg.mouse_throttle) throttle = cfg.mouse_throttle; - if (ds_mouse_emu) throttle *= 4; + if (input[dev].quirk == QUIRK_MSSP) + { + int btn = (data[0] & 7) ? 1 : 0; + if (input[i].misc_flags != btn) + { + input[i].misc_flags = btn; + ev.value = btn; + ev.type = EV_KEY; + ev.code = 0x120; + input_cb(&ev, &absinfo, i); + } - accx += xval; - xval = accx / throttle; - accx -= xval * throttle; + int throttle = cfg.spinner_throttle ? abs(cfg.spinner_throttle) : 100; + int inv = cfg.spinner_throttle < 0; - accy -= yval; - yval = accy / throttle; - accy -= yval * throttle; + input[i].spinner_acc += (xval * 100); + int spinner = (input[i].spinner_acc <= -throttle || input[i].spinner_acc >= throttle) ? (input[i].spinner_acc / throttle) : 0; + input[i].spinner_acc -= spinner * throttle; - mice_btn = data[0] & 7; - if (ds_mouse_emu) mice_btn = (mice_btn & 4) | ((mice_btn & 1) << 1); + if (spinner) + { + ev.value = inv ? -spinner : spinner; + ev.type = EV_REL; + ev.code = 7; + input_cb(&ev, &absinfo, i); - mouse_cb(mouse_btn | mice_btn, xval, yval, (int8_t)data[3]); + input[i].paddle_val += ev.value; + if (input[i].paddle_val < 0) input[i].paddle_val = 0; + if (input[i].paddle_val > 255) input[i].paddle_val = 255; + + ev.value = input[i].paddle_val; + ev.type = EV_ABS; + ev.code = 8; + input_cb(&ev, &absinfo, i); + } + + if (is_menu() && !video_fb_state()) printf("%s: xval=%d, btn=%d, spinner=%d, paddle=%d\n", input[i].devname, xval, btn, spinner, input[i].paddle_val); + } + else + { + if (is_menu() && !video_fb_state()) printf("%s: btn=0x%02X, dx=%d, dy=%d, scroll=%d\n", input[i].devname, data[0], xval, yval, (int8_t)data[3]); + + int throttle = cfg.mouse_throttle ? cfg.mouse_throttle : 1; + if (input[dev].ds_mouse_emu) throttle *= 4; + + accx += xval; + xval = accx / throttle; + accx -= xval * throttle; + + accy -= yval; + yval = accy / throttle; + accy -= yval * throttle; + + mice_btn = data[0] & 7; + if (input[dev].ds_mouse_emu) mice_btn = (mice_btn & 4) | ((mice_btn & 1) << 1); + + mouse_cb(mouse_btn | mice_btn, xval, yval, (int8_t)data[3]); + } } } } diff --git a/joymapping.cpp b/joymapping.cpp index 2e13461..8ba354d 100644 --- a/joymapping.cpp +++ b/joymapping.cpp @@ -224,10 +224,10 @@ int map_paddle_btn() { if (!strcmp(joy_names[i], "-")) continue; char *p = strchr(defaults ? joy_pnames[n] : joy_nnames[n], '|'); - if (p && !strcasecmp(p, "|P")) return i + DPAD_COUNT; + if (p && !strcasecmp(p, "|P")) return i + SYS_BTN_A; n++; } - return DPAD_COUNT; + return SYS_BTN_A; } static const char* get_std_name(uint16_t code, uint32_t *mmap)