maple: mutually exclusive btns per controller. better D2A axes
Handle mutually exclusive buttons (U/D, L/R) in each controller. Track digital X/Y axes state to allow for proper handling of U+D and L+R. Issue #334 SDL: Ignore key repeat events
This commit is contained in:
parent
6768901446
commit
5121b0df93
|
@ -38,6 +38,12 @@ maple_device::~maple_device()
|
|||
delete config;
|
||||
}
|
||||
|
||||
static inline void mutualExclusion(u32& keycode, u32 mask)
|
||||
{
|
||||
if ((keycode & mask) == 0)
|
||||
keycode |= mask;
|
||||
}
|
||||
|
||||
/*
|
||||
Sega Dreamcast Controller
|
||||
No error checking of any kind, but works just fine
|
||||
|
@ -53,7 +59,10 @@ struct maple_sega_controller: maple_base
|
|||
return 0xfe060f00; // 4 analog axes (0-3) X Y A B Start U D L R
|
||||
}
|
||||
|
||||
virtual u32 transform_kcode(u32 kcode) {
|
||||
virtual u32 transform_kcode(u32 kcode)
|
||||
{
|
||||
mutualExclusion(kcode, DC_DPAD_UP | DC_DPAD_DOWN);
|
||||
mutualExclusion(kcode, DC_DPAD_LEFT | DC_DPAD_RIGHT);
|
||||
return kcode | 0xF901; // mask off DPad2, C, D and Z;
|
||||
}
|
||||
|
||||
|
@ -189,7 +198,10 @@ struct maple_atomiswave_controller: maple_sega_controller
|
|||
return 0xff663f00; // 6 analog axes, X Y L2/D2(?) A B C Start U D L R
|
||||
}
|
||||
|
||||
u32 transform_kcode(u32 kcode) override {
|
||||
u32 transform_kcode(u32 kcode) override
|
||||
{
|
||||
mutualExclusion(kcode, AWAVE_UP_KEY | AWAVE_DOWN_KEY);
|
||||
mutualExclusion(kcode, AWAVE_LEFT_KEY | AWAVE_RIGHT_KEY);
|
||||
return kcode | AWAVE_TRIGGER_KEY;
|
||||
}
|
||||
|
||||
|
@ -215,7 +227,12 @@ struct maple_sega_twinstick: maple_sega_controller
|
|||
return 0xfefe0000; // no analog axes, X Y A B D Start U/D/L/R U2/D2/L2/R2
|
||||
}
|
||||
|
||||
u32 transform_kcode(u32 kcode) override {
|
||||
u32 transform_kcode(u32 kcode) override
|
||||
{
|
||||
mutualExclusion(kcode, DC_DPAD_UP | DC_DPAD_DOWN);
|
||||
mutualExclusion(kcode, DC_DPAD_LEFT | DC_DPAD_RIGHT);
|
||||
mutualExclusion(kcode, DC_DPAD2_UP | DC_DPAD2_DOWN);
|
||||
mutualExclusion(kcode, DC_DPAD2_LEFT | DC_DPAD2_RIGHT);
|
||||
return kcode | 0x0101;
|
||||
}
|
||||
|
||||
|
@ -247,7 +264,10 @@ struct maple_ascii_stick: maple_sega_controller
|
|||
return 0xff070000; // no analog axes, X Y Z A B C Start U/D/L/R
|
||||
}
|
||||
|
||||
u32 transform_kcode(u32 kcode) override {
|
||||
u32 transform_kcode(u32 kcode) override
|
||||
{
|
||||
mutualExclusion(kcode, DC_DPAD_UP | DC_DPAD_DOWN);
|
||||
mutualExclusion(kcode, DC_DPAD_LEFT | DC_DPAD_RIGHT);
|
||||
return kcode | 0xF800;
|
||||
}
|
||||
|
||||
|
@ -1214,7 +1234,10 @@ struct maple_mouse : maple_base
|
|||
|
||||
struct maple_lightgun : maple_base
|
||||
{
|
||||
virtual u32 transform_kcode(u32 kcode) {
|
||||
virtual u32 transform_kcode(u32 kcode)
|
||||
{
|
||||
mutualExclusion(kcode, DC_DPAD_UP | DC_DPAD_DOWN);
|
||||
mutualExclusion(kcode, DC_DPAD_LEFT | DC_DPAD_RIGHT);
|
||||
if ((kcode & DC_BTN_RELOAD) == 0)
|
||||
kcode &= ~DC_BTN_A; // trigger
|
||||
return kcode | 0xFF01;
|
||||
|
@ -1311,6 +1334,8 @@ struct maple_lightgun : maple_base
|
|||
struct atomiswave_lightgun : maple_lightgun
|
||||
{
|
||||
u32 transform_kcode(u32 kcode) override {
|
||||
mutualExclusion(kcode, AWAVE_UP_KEY | AWAVE_DOWN_KEY);
|
||||
mutualExclusion(kcode, AWAVE_LEFT_KEY | AWAVE_RIGHT_KEY);
|
||||
// No need for reload on AW
|
||||
return (kcode & AWAVE_TRIGGER_KEY) == 0 ? ~AWAVE_BTN0_KEY : ~0;
|
||||
}
|
||||
|
|
|
@ -1424,6 +1424,13 @@ u32 jvs_io_board::handle_jvs_message(u8 *buffer_in, u32 length_in, u8 *buffer_ou
|
|||
if ((kcode[p] & (1 << i)) == 0)
|
||||
buttons[p] |= naomi_button_mapping[i];
|
||||
#endif
|
||||
for (u32& button : buttons)
|
||||
{
|
||||
if ((button & (NAOMI_UP_KEY | NAOMI_DOWN_KEY)) == (NAOMI_UP_KEY | NAOMI_DOWN_KEY))
|
||||
button &= ~(NAOMI_UP_KEY | NAOMI_DOWN_KEY);
|
||||
if ((button & (NAOMI_LEFT_KEY | NAOMI_RIGHT_KEY)) == (NAOMI_LEFT_KEY | NAOMI_RIGHT_KEY))
|
||||
button &= ~(NAOMI_LEFT_KEY | NAOMI_RIGHT_KEY);
|
||||
}
|
||||
|
||||
JVS_STATUS1(); // status
|
||||
for (u32 cmdi = 0; cmdi < length_in; )
|
||||
|
|
|
@ -68,39 +68,7 @@ bool GamepadDevice::gamepad_btn_input(u32 code, bool pressed)
|
|||
if (key <= DC_BTN_RELOAD)
|
||||
{
|
||||
if (pressed)
|
||||
{
|
||||
kcode[port] &= ~key;
|
||||
// Avoid two opposite dpad keys being pressed simultaneously
|
||||
switch (key)
|
||||
{
|
||||
case DC_DPAD_UP:
|
||||
kcode[port] |= DC_DPAD_DOWN;
|
||||
break;
|
||||
case DC_DPAD_DOWN:
|
||||
kcode[port] |= DC_DPAD_UP;
|
||||
break;
|
||||
case DC_DPAD_LEFT:
|
||||
kcode[port] |= DC_DPAD_RIGHT;
|
||||
break;
|
||||
case DC_DPAD_RIGHT:
|
||||
kcode[port] |= DC_DPAD_LEFT;
|
||||
break;
|
||||
case DC_DPAD2_UP:
|
||||
kcode[port] |= DC_DPAD2_DOWN;
|
||||
break;
|
||||
case DC_DPAD2_DOWN:
|
||||
kcode[port] |= DC_DPAD2_UP;
|
||||
break;
|
||||
case DC_DPAD2_LEFT:
|
||||
kcode[port] |= DC_DPAD2_RIGHT;
|
||||
break;
|
||||
case DC_DPAD2_RIGHT:
|
||||
kcode[port] |= DC_DPAD2_LEFT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
kcode[port] |= key;
|
||||
#ifdef TEST_AUTOMATION
|
||||
|
@ -131,16 +99,36 @@ bool GamepadDevice::gamepad_btn_input(u32 code, bool pressed)
|
|||
rt[port] = pressed ? 255 : 0;
|
||||
break;
|
||||
case EMU_BTN_ANA_UP:
|
||||
joyy[port] = pressed ? -128 : 0;
|
||||
break;
|
||||
case EMU_BTN_ANA_DOWN:
|
||||
joyy[port] = pressed ? 127 : 0;
|
||||
{
|
||||
if (pressed)
|
||||
digitalToAnalogState[port] |= key;
|
||||
else
|
||||
digitalToAnalogState[port] &= ~key;
|
||||
const u32 upDown = digitalToAnalogState[port] & (EMU_BTN_ANA_UP | EMU_BTN_ANA_DOWN);
|
||||
if (upDown == 0 || upDown == (EMU_BTN_ANA_UP | EMU_BTN_ANA_DOWN))
|
||||
joyy[port] = 0;
|
||||
else if (upDown == EMU_BTN_ANA_UP)
|
||||
joyy[port] = -128;
|
||||
else
|
||||
joyy[port] = 127;
|
||||
}
|
||||
break;
|
||||
case EMU_BTN_ANA_LEFT:
|
||||
joyx[port] = pressed ? -128 : 0;
|
||||
break;
|
||||
case EMU_BTN_ANA_RIGHT:
|
||||
joyx[port] = pressed ? 127 : 0;
|
||||
{
|
||||
if (pressed)
|
||||
digitalToAnalogState[port] |= key;
|
||||
else
|
||||
digitalToAnalogState[port] &= ~key;
|
||||
const u32 leftRight = digitalToAnalogState[port] & (EMU_BTN_ANA_LEFT | EMU_BTN_ANA_RIGHT);
|
||||
if (leftRight == 0 || leftRight == (EMU_BTN_ANA_LEFT | EMU_BTN_ANA_RIGHT))
|
||||
joyx[port] = 0;
|
||||
else if (leftRight == EMU_BTN_ANA_LEFT)
|
||||
joyx[port] = -128;
|
||||
else
|
||||
joyx[port] = 127;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
|
@ -377,6 +365,8 @@ std::string GamepadDevice::make_mapping_filename(bool instance, int system)
|
|||
|
||||
bool GamepadDevice::find_mapping(int system)
|
||||
{
|
||||
if (!_remappable)
|
||||
return true;
|
||||
std::string mapping_file;
|
||||
mapping_file = make_mapping_filename(false, system);
|
||||
|
||||
|
@ -395,6 +385,8 @@ bool GamepadDevice::find_mapping(int system)
|
|||
|
||||
bool GamepadDevice::find_mapping(const char *custom_mapping /* = nullptr */)
|
||||
{
|
||||
if (!_remappable)
|
||||
return true;
|
||||
std::string mapping_file;
|
||||
if (custom_mapping != nullptr)
|
||||
mapping_file = custom_mapping;
|
||||
|
|
|
@ -73,7 +73,8 @@ public:
|
|||
bool find_mapping(int system);
|
||||
protected:
|
||||
GamepadDevice(int maple_port, const char *api_name, bool remappable = true)
|
||||
: _api_name(api_name), _maple_port(maple_port), _input_detected(nullptr), _remappable(remappable)
|
||||
: _api_name(api_name), _maple_port(maple_port), _input_detected(nullptr), _remappable(remappable),
|
||||
digitalToAnalogState{}
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -108,6 +109,7 @@ private:
|
|||
double _detection_start_time = 0.0;
|
||||
input_detected_cb _input_detected;
|
||||
bool _remappable;
|
||||
u32 digitalToAnalogState[4];
|
||||
|
||||
static std::vector<std::shared_ptr<GamepadDevice>> _gamepads;
|
||||
static std::mutex _gamepads_mutex;
|
||||
|
|
|
@ -217,29 +217,32 @@ void input_sdl_handle()
|
|||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
checkRawInput();
|
||||
if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_RETURN && (event.key.keysym.mod & KMOD_ALT))
|
||||
if (event.key.repeat == 0)
|
||||
{
|
||||
if (window_fullscreen)
|
||||
if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_RETURN && (event.key.keysym.mod & KMOD_ALT))
|
||||
{
|
||||
SDL_SetWindowFullscreen(window, 0);
|
||||
if (!gameRunning || !mouseCaptured)
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
if (window_fullscreen)
|
||||
{
|
||||
SDL_SetWindowFullscreen(window, 0);
|
||||
if (!gameRunning || !mouseCaptured)
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
if (gameRunning)
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
}
|
||||
window_fullscreen = !window_fullscreen;
|
||||
}
|
||||
else
|
||||
else if (event.type == SDL_KEYDOWN && (event.key.keysym.mod & KMOD_LALT) && (event.key.keysym.mod & KMOD_LCTRL))
|
||||
{
|
||||
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
if (gameRunning)
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
captureMouse(!mouseCaptured);
|
||||
}
|
||||
else if (!config::UseRawInput)
|
||||
{
|
||||
sdl_keyboard->keyboard_input(event.key.keysym.scancode, event.type == SDL_KEYDOWN);
|
||||
}
|
||||
window_fullscreen = !window_fullscreen;
|
||||
}
|
||||
else if (event.type == SDL_KEYDOWN && (event.key.keysym.mod & KMOD_LALT) && (event.key.keysym.mod & KMOD_LCTRL))
|
||||
{
|
||||
captureMouse(!mouseCaptured);
|
||||
}
|
||||
else if (!config::UseRawInput)
|
||||
{
|
||||
sdl_keyboard->keyboard_input(event.key.keysym.scancode, event.type == SDL_KEYDOWN);
|
||||
}
|
||||
break;
|
||||
case SDL_TEXTINPUT:
|
||||
|
|
Loading…
Reference in New Issue