Added virtual SNES gamepad
* Added virtual SNES gamepad * Added "magic" joy mapping logic based on button names and core name * minor fixes after testing
This commit is contained in:
85
input.cpp
85
input.cpp
@@ -24,8 +24,8 @@
|
||||
#include "fpga_io.h"
|
||||
#include "osd.h"
|
||||
#include "video.h"
|
||||
#include "joymapping.h"
|
||||
|
||||
#define NUMDEV 30
|
||||
#define NUMPLAYERS 6
|
||||
#define UINPUT_NAME "MiSTer virtual input"
|
||||
|
||||
@@ -988,41 +988,6 @@ enum QUIRK
|
||||
QUIRK_DS4TOUCH,
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t vid, pid;
|
||||
uint8_t led;
|
||||
uint8_t mouse;
|
||||
uint8_t axis_edge[256];
|
||||
int8_t axis_pos[256];
|
||||
|
||||
uint8_t num;
|
||||
uint8_t has_map;
|
||||
uint32_t map[32];
|
||||
|
||||
uint8_t osd_combo;
|
||||
|
||||
uint8_t has_mmap;
|
||||
uint32_t mmap[32];
|
||||
uint16_t jkmap[1024];
|
||||
|
||||
uint8_t has_kbdmap;
|
||||
uint8_t kbdmap[256];
|
||||
|
||||
uint16_t guncal[4];
|
||||
|
||||
int accx, accy;
|
||||
int quirk;
|
||||
|
||||
int lightgun_req;
|
||||
int lightgun;
|
||||
|
||||
int bind;
|
||||
char devname[32];
|
||||
char uniq[32];
|
||||
char name[128];
|
||||
} devInput;
|
||||
|
||||
static devInput input[NUMDEV] = {};
|
||||
|
||||
#define BTN_NUM (sizeof(devInput::map) / sizeof(devInput::map[0]))
|
||||
@@ -1251,6 +1216,15 @@ void finish_map_setting(int dismiss)
|
||||
}
|
||||
}
|
||||
|
||||
int convert_from_menu_mapping(int dev) {
|
||||
//attempts to map from Menu joystick config file
|
||||
//returns: 0 if failed to map or 1 if success
|
||||
if(!FileLoadConfig(get_map_name(dev, 1), &input[dev].map, sizeof(input[dev].map))) {
|
||||
return 0;
|
||||
}
|
||||
return map_joystick (user_io_get_core_name_ex(), input, dev);
|
||||
}
|
||||
|
||||
void input_lightgun_cal(uint16_t *cal)
|
||||
{
|
||||
FileSaveConfig("wiimote_cal.cfg", cal, 4 * sizeof(uint16_t));
|
||||
@@ -1730,16 +1704,19 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int
|
||||
{
|
||||
if (!FileLoadConfig(get_map_name(dev, 0), &input[dev].map, sizeof(input[dev].map)))
|
||||
{
|
||||
if (is_menu_core() || !FileLoadConfig(get_map_name(dev, 1), &input[dev].map, sizeof(input[dev].map)))
|
||||
{
|
||||
memset(input[dev].map, 0, sizeof(input[dev].map));
|
||||
input[dev].has_map++;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint i = 8; i < sizeof(input[0].map) / sizeof(input[0].map[0]); i++)
|
||||
if(!convert_from_menu_mapping(dev)) {
|
||||
if (is_menu_core() || !FileLoadConfig(get_map_name(dev, 1), &input[dev].map, sizeof(input[dev].map)))
|
||||
{
|
||||
input[dev].map[i] = 0;
|
||||
// nothing found so blank out everything
|
||||
memset(input[dev].map, 0, sizeof(input[dev].map));
|
||||
input[dev].has_map++;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint i = 8; i < sizeof(input[0].map) / sizeof(input[0].map[0]); i++)
|
||||
{
|
||||
input[dev].map[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
input[dev].has_map++;
|
||||
@@ -1849,24 +1826,24 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int
|
||||
input[dev].osd_combo = 0;
|
||||
|
||||
int found = 0;
|
||||
for (int i = (mapping_button >= 8) ? 8 : 0; i < mapping_button; i++) if (input[dev].map[i] == ev->code) found = 1;
|
||||
for (int i = (mapping_button >= BUTTON_DPAD_COUNT) ? BUTTON_DPAD_COUNT : 0; i < mapping_button; i++) if (input[dev].map[i] == ev->code) found = 1;
|
||||
|
||||
if (!found || (mapping_button == 16 && mapping_type))
|
||||
if (!found || (mapping_button == BUTTON_IDX_OSD && mapping_type))
|
||||
{
|
||||
input[dev].map[(mapping_button == 16) ? 16 + mapping_type : mapping_button] = ev->code;
|
||||
input[dev].map[18] = input[dev].map[17];
|
||||
input[dev].map[(mapping_button == BUTTON_IDX_OSD) ? BUTTON_IDX_OSD + mapping_type : mapping_button] = ev->code;
|
||||
input[dev].map[BUTTON_IDX_OSD+2] = input[dev].map[BUTTON_IDX_OSD+1];
|
||||
|
||||
key_mapped = ev->code;
|
||||
|
||||
//check if analog stick has been used for mouse
|
||||
if (mapping_button == 9 || mapping_button == 11)
|
||||
if (mapping_button == BUTTON_DPAD_COUNT+1 || mapping_button == BUTTON_DPAD_COUNT+3)
|
||||
{
|
||||
if (input[dev].map[mapping_button] >= KEY_EMU &&
|
||||
input[dev].map[mapping_button - 1] >= KEY_EMU &&
|
||||
(input[dev].map[mapping_button - 1] - input[dev].map[mapping_button] == 1) && // same axis
|
||||
absinfo)
|
||||
{
|
||||
input[dev].map[AXIS_MX + (mapping_button - 9)/2] = ((input[dev].map[mapping_button] - KEY_EMU)/2) | 0x20000;
|
||||
input[dev].map[AXIS_MX + (mapping_button - (BUTTON_DPAD_COUNT+1))/2] = ((input[dev].map[mapping_button] - KEY_EMU)/2) | 0x20000;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1907,10 +1884,10 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int
|
||||
}
|
||||
}
|
||||
//combo for osd button
|
||||
if (ev->value == 1 && key_mapped && key_mapped != ev->code && is_menu_core() && mapping_button == 16 && mapping_type)
|
||||
if (ev->value == 1 && key_mapped && key_mapped != ev->code && is_menu_core() && mapping_button == BUTTON_IDX_OSD && mapping_type)
|
||||
{
|
||||
input[dev].map[18] = ev->code;
|
||||
printf("Set combo: %x + %x\n", input[dev].map[17], input[dev].map[18]);
|
||||
input[dev].map[BUTTON_IDX_OSD+2] = ev->code;
|
||||
printf("Set combo: %x + %x\n", input[dev].map[BUTTON_IDX_OSD+1], input[dev].map[BUTTON_IDX_OSD+2]);
|
||||
}
|
||||
else if(mapping_dev == dev && ev->value == 0 && key_mapped == ev->code)
|
||||
{
|
||||
|
||||
4
input.h
4
input.h
@@ -29,6 +29,10 @@
|
||||
|
||||
#define UPSTROKE 0x400000
|
||||
|
||||
#define BUTTON_IDX_OSD 16
|
||||
#define BUTTON_DPAD_COUNT 12 // dpad + 8 buttons
|
||||
|
||||
|
||||
void set_kbdled(int mask, int state);
|
||||
int get_kbdled(int mask);
|
||||
int toggle_kbdled(int mask);
|
||||
|
||||
134
joymapping.cpp
Normal file
134
joymapping.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
This file contains lookup information on known controllers
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "joymapping.h"
|
||||
#include "menu.h"
|
||||
#include "input.h"
|
||||
#include "user_io.h"
|
||||
|
||||
#define DPAD_COUNT 4
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int swap_face_buttons(const char *core_name) {
|
||||
//flags cores where B A should be swapped to A B and Y X to X Y (SNES vs. Genesis/NG)
|
||||
return (!strcmp(core_name, "Genesis")
|
||||
|| !strcmp(core_name, "NEOGEO")
|
||||
|| !strcmp(core_name, "SMS"));
|
||||
}
|
||||
|
||||
int map_joystick(const char *core_name, devInput (&input)[NUMDEV], int dev) {
|
||||
/*
|
||||
attemps to centrally defined core joy mapping to the joystick declaredy by a core config string
|
||||
we use the names declared by core with some special handling for specific edge cases
|
||||
|
||||
Input button order is "virtual SNES" i.e.:
|
||||
A, B, X, Y, L, R, Select, Start
|
||||
*/
|
||||
uint32_t new_map[NUMBUTTONS];
|
||||
// first copy directions (not really needed but helps keep things consistent)
|
||||
for(int i=0; i<DPAD_COUNT; i++) {
|
||||
new_map[i] = input[dev].map[i];
|
||||
}
|
||||
// loop through core requested buttons and construct result map
|
||||
for (int i=0; i<joy_bcount; i++) {
|
||||
int new_index = i+DPAD_COUNT;
|
||||
std::string button_name = joy_bnames[i];
|
||||
if (button_name.find("(") != std::string::npos) {
|
||||
button_name = button_name.substr(0, button_name.find("("));
|
||||
}
|
||||
const char*btn_name = button_name.c_str();
|
||||
printf(" ...mapping button %s\n", btn_name);
|
||||
if(!strcmp(btn_name, "A")
|
||||
|| !strcmp(btn_name, "Fire")
|
||||
|| !strcmp(btn_name, "Jump")
|
||||
|| !strcmp(btn_name, "Fire1")
|
||||
|| !strcmp(btn_name, "Fire 1")
|
||||
|| !strcmp(btn_name, "Button 1")
|
||||
|| !strcmp(btn_name, "Button I")) {
|
||||
if(swap_face_buttons(core_name)) {
|
||||
new_map[new_index] = input[dev].map[MENU_JOY_B];
|
||||
} else {
|
||||
new_map[new_index] = input[dev].map[MENU_JOY_A];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(btn_name, "B")
|
||||
|| !strcmp(btn_name, "Fire2")
|
||||
|| !strcmp(btn_name, "Fire 2")
|
||||
|| !strcmp(btn_name, "Button 2")
|
||||
|| !strcmp(btn_name, "Button II")) {
|
||||
if(swap_face_buttons(core_name)) {
|
||||
new_map[new_index] = input[dev].map[MENU_JOY_A];
|
||||
} else {
|
||||
new_map[new_index] = input[dev].map[MENU_JOY_B];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(btn_name, "X")
|
||||
|| !strcmp(btn_name, "Fire3")
|
||||
|| !strcmp(btn_name, "Fire 3")
|
||||
|| !strcmp(btn_name, "Button 3")
|
||||
|| !strcmp(btn_name, "Button III")) {
|
||||
if(swap_face_buttons(core_name)) {
|
||||
new_map[new_index] = input[dev].map[MENU_JOY_Y];
|
||||
} else {
|
||||
new_map[new_index] = input[dev].map[MENU_JOY_X];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(btn_name, "Y")
|
||||
|| !strcmp(btn_name, "Button IV")) {
|
||||
if(swap_face_buttons(core_name)) {
|
||||
new_map[new_index] = input[dev].map[MENU_JOY_X];
|
||||
} else {
|
||||
new_map[new_index] = input[dev].map[MENU_JOY_Y];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// Genesis C and Z and TG16 V and VI
|
||||
if(!strcmp(btn_name, "C")
|
||||
|| !strcmp(btn_name, "Button V")
|
||||
|| !strcmp(btn_name, "Coin")
|
||||
) {
|
||||
new_map[new_index] = input[dev].map[MENU_JOY_R];
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(btn_name, "Z")
|
||||
|| !strcmp(btn_name, "Button VI")
|
||||
|| !strcmp(btn_name, "ABC")) {
|
||||
new_map[new_index] = input[dev].map[MENU_JOY_L];
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(btn_name, "Select")
|
||||
|| !strcmp(btn_name, "Game Select")) {
|
||||
new_map[new_index] = input[dev].map[MENU_JOY_SELECT];
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(btn_name, "Start")
|
||||
|| !strcmp(btn_name, "Run")
|
||||
|| !strcmp(btn_name, "Pause")
|
||||
|| !strcmp(btn_name, "Start 1P")) {
|
||||
new_map[new_index] = input[dev].map[MENU_JOY_START];
|
||||
continue;
|
||||
}
|
||||
//nothing found so just map by position
|
||||
printf(" [no mapping found, using default map by position]\n");
|
||||
new_map[new_index] = input[dev].map[new_index];
|
||||
}
|
||||
//finally swap result map into input map
|
||||
for (int i=0; i<NUMBUTTONS; i++) {
|
||||
if (i<joy_bcount+DPAD_COUNT)
|
||||
input[dev].map[i] = new_map[i];
|
||||
else
|
||||
input[dev].map[i] = 0;
|
||||
}
|
||||
return 1; //success
|
||||
}
|
||||
65
joymapping.h
Normal file
65
joymapping.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*****************************************************************************/
|
||||
// Handle mapping of various joystick controllers
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef JOYMAPPING_H
|
||||
#define JOYMAPPING_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string>
|
||||
|
||||
#define NUMDEV 30
|
||||
#define NUMBUTTONS 32
|
||||
|
||||
//Defined as per main menu USB joypad mapping, see menu.cpp
|
||||
#define MENU_JOY_A 4
|
||||
#define MENU_JOY_B 5
|
||||
#define MENU_JOY_X 6
|
||||
#define MENU_JOY_Y 7
|
||||
#define MENU_JOY_L 8 // menu.cpp skips 4 buttons for mouse directions
|
||||
#define MENU_JOY_R 9
|
||||
#define MENU_JOY_SELECT 10
|
||||
#define MENU_JOY_START 11
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t vid, pid;
|
||||
uint8_t led;
|
||||
uint8_t mouse;
|
||||
uint8_t axis_edge[256];
|
||||
int8_t axis_pos[256];
|
||||
|
||||
uint8_t num;
|
||||
uint8_t has_map;
|
||||
uint32_t map[NUMBUTTONS];
|
||||
|
||||
uint8_t osd_combo;
|
||||
|
||||
uint8_t has_mmap;
|
||||
uint32_t mmap[NUMBUTTONS];
|
||||
uint16_t jkmap[1024];
|
||||
|
||||
uint8_t has_kbdmap;
|
||||
uint8_t kbdmap[256];
|
||||
|
||||
uint16_t guncal[4];
|
||||
|
||||
int accx, accy;
|
||||
int quirk;
|
||||
|
||||
int lightgun_req;
|
||||
int lightgun;
|
||||
|
||||
int bind;
|
||||
char devname[32];
|
||||
char uniq[32];
|
||||
char name[128];
|
||||
} devInput;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int map_joystick(const char *core_name, devInput (&input)[NUMDEV], int dev);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif // JOYMAPPING_H
|
||||
54
menu.cpp
54
menu.cpp
@@ -55,8 +55,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "bootcore.h"
|
||||
#include "cheats.h"
|
||||
#include "video.h"
|
||||
|
||||
#include "support.h"
|
||||
#include "joymapping.h"
|
||||
|
||||
/*menu states*/
|
||||
enum MENU
|
||||
@@ -191,13 +191,17 @@ const char *config_autofire_msg[] = { " AUTOFIRE OFF", " AUTOFIRE
|
||||
const char *config_cd32pad_msg[] = { "OFF", "ON" };
|
||||
const char *config_button_turbo_msg[] = { "OFF", "FAST", "MEDIUM", "SLOW" };
|
||||
const char *config_button_turbo_choice_msg[] = { "A only", "B only", "A & B" };
|
||||
const char *joy_button_map[] = { "RIGHT", "LEFT", "DOWN", "UP", "BUTTON 1", "BUTTON 2", "BUTTON 3", "BUTTON 4", "KBD TOGGLE", "MENU", " Stick X: Tilt RIGHT", " Stick Y: Tilt DOWN", " Mouse emu X: Tilt RIGHT", " Mouse emu Y: Tilt DOWN" };
|
||||
const char *joy_ana_map[] = { " DPAD test: Press RIGHT", " DPAD test: Press DOWN", " Stick 1: Tilt RIGHT", " Stick 1: Tilt DOWN", " Stick 2: Tilt RIGHT", " Stick 2: Tilt DOWN" };
|
||||
const char *joy_button_map[] = { "RIGHT", "LEFT", "DOWN", "UP", "BUTTON A", "BUTTON B", "BUTTON X", "BUTTON Y", "BUTTON L", "BUTTON R", "SELECT", "START", "KBD TOGGLE", "MENU", " Stick X: Tilt RIGHT", " Stick Y: Tilt DOWN", " Mouse emu X: Tilt RIGHT", " Mouse emu Y: Tilt DOWN" };
|
||||
const char *joy_ana_map[] = { " DPAD test: Press RIGHT", " DPAD test: Press DOWN", " Stick 1 Test: Tilt RIGHT", " Stick 1 Test: Tilt DOWN", " Stick 2 Test: Tilt RIGHT", " Stick 2 Test: Tilt DOWN" };
|
||||
const char *config_stereo_msg[] = { "0%", "25%", "50%", "100%" };
|
||||
const char *config_uart_msg[] = { " None", " PPP", " Console", " MIDI" };
|
||||
const char *config_scaler_msg[] = { "Internal","Custom" };
|
||||
const char *config_gamma_msg[] = { "Off","On" };
|
||||
|
||||
#define DPAD_NAMES 4
|
||||
#define DPAD_BUTTON_NAMES 12 //DPAD_NAMES + 6 buttons + start/select
|
||||
|
||||
|
||||
char joy_bnames[32][32];
|
||||
int joy_bcount = 0;
|
||||
|
||||
@@ -2150,22 +2154,22 @@ void HandleUI(void)
|
||||
{
|
||||
strcpy(s, joy_ana_map[get_map_button() + 6]);
|
||||
}
|
||||
else if (get_map_button() < 4)
|
||||
else if (get_map_button() < DPAD_NAMES)
|
||||
{
|
||||
p = joy_button_map[get_map_button()];
|
||||
}
|
||||
else if (joy_bcount)
|
||||
{
|
||||
p = joy_bnames[get_map_button() - 4];
|
||||
p = joy_bnames[get_map_button() - DPAD_NAMES];
|
||||
if (is_menu_core())
|
||||
{
|
||||
if (get_map_type()) joy_bcount = 15;
|
||||
if (get_map_button() == 16)
|
||||
{
|
||||
p = joy_button_map[8 + get_map_type()];
|
||||
p = joy_button_map[DPAD_BUTTON_NAMES + get_map_type()];
|
||||
if (get_map_type())
|
||||
{
|
||||
OsdWrite(12, " Allowed 2-buttons combo");
|
||||
OsdWrite(12, " (can use 2-button combo)");
|
||||
line_info = 1;
|
||||
}
|
||||
}
|
||||
@@ -2173,14 +2177,14 @@ void HandleUI(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
p = (get_map_button() < 8) ? joy_button_map[get_map_button()] : joy_button_map[8 + get_map_type()];
|
||||
p = (get_map_button() < DPAD_BUTTON_NAMES) ? joy_button_map[get_map_button()] : joy_button_map[DPAD_BUTTON_NAMES + get_map_type()];
|
||||
}
|
||||
|
||||
if (get_map_button() >= 0)
|
||||
{
|
||||
if (is_menu_core() && get_map_button() > 16)
|
||||
{
|
||||
strcpy(s, joy_button_map[10 + get_map_button() - 17]);
|
||||
strcpy(s, joy_button_map[14 + get_map_button() - 17]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3989,20 +3993,24 @@ void HandleUI(void)
|
||||
menusub = 0;
|
||||
break;
|
||||
case 2:
|
||||
joy_bcount = 13;
|
||||
strcpy(joy_bnames[0], "Btn 1 (OK/Enter)");
|
||||
strcpy(joy_bnames[1], "Btn 2 (ESC/Back)");
|
||||
strcpy(joy_bnames[2], "Btn 3 (Backspace)");
|
||||
strcpy(joy_bnames[3], "Btn 4");
|
||||
strcpy(joy_bnames[4], "Mouse Move RIGHT");
|
||||
strcpy(joy_bnames[5], "Mouse Move LEFT");
|
||||
strcpy(joy_bnames[6], "Mouse Move DOWN");
|
||||
strcpy(joy_bnames[7], "Mouse Move UP");
|
||||
strcpy(joy_bnames[8], "Mouse Left Btn");
|
||||
strcpy(joy_bnames[9], "Mouse Right Btn");
|
||||
strcpy(joy_bnames[10], "Mouse Middle Btn");
|
||||
strcpy(joy_bnames[11], "Mouse Emu/Sniper");
|
||||
start_map_setting(19);
|
||||
joy_bcount = 16;
|
||||
strcpy(joy_bnames[MENU_JOY_A - DPAD_NAMES], "Btn A (OK/Enter)");
|
||||
strcpy(joy_bnames[MENU_JOY_B - DPAD_NAMES], "Btn B (ESC/Back)");
|
||||
strcpy(joy_bnames[MENU_JOY_X - DPAD_NAMES], "Btn X (Backspace");
|
||||
strcpy(joy_bnames[MENU_JOY_Y - DPAD_NAMES], "Btn Y ");
|
||||
strcpy(joy_bnames[MENU_JOY_L - DPAD_NAMES], "Btn L (Z)");
|
||||
strcpy(joy_bnames[MENU_JOY_R - DPAD_NAMES], "Btn R (C)");
|
||||
strcpy(joy_bnames[MENU_JOY_SELECT - DPAD_NAMES], "Btn Select");
|
||||
strcpy(joy_bnames[MENU_JOY_START - DPAD_NAMES], "Btn Start");
|
||||
strcpy(joy_bnames[8], "Mouse Move RIGHT");
|
||||
strcpy(joy_bnames[9], "Mouse Move LEFT");
|
||||
strcpy(joy_bnames[10], "Mouse Move DOWN");
|
||||
strcpy(joy_bnames[11], "Mouse Move UP");
|
||||
strcpy(joy_bnames[12], "Mouse Left Btn");
|
||||
strcpy(joy_bnames[13], "Mouse Right Btn");
|
||||
strcpy(joy_bnames[14], "Mouse Middle Btn");
|
||||
strcpy(joy_bnames[15], "Mouse Emu / Sniper");
|
||||
start_map_setting(joy_bcount + DPAD_NAMES);
|
||||
menustate = MENU_JOYDIGMAP;
|
||||
menusub = 0;
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user