RetroArch/input/input_mapper.c

250 lines
7.6 KiB
C
Raw Normal View History

2017-09-07 22:30:42 -05:00
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
* Copyright (C) 2016-2017 - Andrés Suárez
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <direct.h>
#else
#include <unistd.h>
#endif
#include <compat/strl.h>
#include <compat/posix_string.h>
#include <retro_miscellaneous.h>
#include <libretro.h>
2017-12-26 22:02:11 -05:00
2017-12-31 17:53:11 +01:00
#ifdef HAVE_MENU
2017-12-26 22:02:11 -05:00
#include "../menu/menu_driver.h"
2017-12-31 17:53:11 +01:00
#endif
2017-09-07 22:30:42 -05:00
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include "input_mapper.h"
#include "../configuration.h"
#include "../msg_hash.h"
#include "../verbosity.h"
2017-09-09 14:21:00 -05:00
#define MAPPER_GET_KEY(state, key) (((state)->keys[(key) / 32] >> ((key) % 32)) & 1)
#define MAPPER_SET_KEY(state, key) (state)->keys[(key) / 32] |= 1 << ((key) % 32)
2017-09-07 22:30:42 -05:00
struct input_mapper
{
/* Left X, Left Y, Right X, Right Y */
int16_t analog_value[MAX_USERS][8];
2017-09-07 22:30:42 -05:00
/* the whole keyboard state */
uint32_t keys[RETROK_LAST / 32 + 1];
2017-11-12 17:02:14 +01:00
/* This is a bitmask of (1 << key_bind_id). */
2018-04-08 20:21:12 +02:00
input_bits_t buttons[MAX_USERS];
2017-09-09 14:21:00 -05:00
};
2018-04-04 21:33:03 -05:00
input_mapper_t *input_mapper_new(void)
2017-09-07 22:30:42 -05:00
{
2017-09-09 14:21:00 -05:00
input_mapper_t* handle = (input_mapper_t*)
calloc(1, sizeof(*handle));
2017-09-09 14:21:00 -05:00
if (!handle)
return NULL;
2017-11-12 17:02:14 +01:00
2017-09-09 14:21:00 -05:00
return handle;
2017-09-07 22:30:42 -05:00
}
void input_mapper_free(input_mapper_t *handle)
{
if (!handle)
return;
2017-09-09 14:21:00 -05:00
free (handle);
2017-09-07 22:30:42 -05:00
}
bool input_mapper_button_pressed(input_mapper_t *handle, unsigned port, unsigned id)
{
return BIT256_GET(handle->buttons[port], id);
}
2017-09-09 14:21:00 -05:00
void input_mapper_poll(input_mapper_t *handle)
2017-09-07 22:30:42 -05:00
{
2018-04-08 21:38:57 +02:00
int i, j;
2018-04-08 20:21:12 +02:00
input_bits_t current_input;
2018-04-08 21:38:57 +02:00
settings_t *settings = config_get_ptr();
unsigned max_users = *(input_driver_get_uint(INPUT_ACTION_MAX_USERS));
unsigned device = 0;
int16_t current_axis_value;
bool key_event[RARCH_CUSTOM_BIND_LIST_END];
2017-12-31 17:53:11 +01:00
#ifdef HAVE_MENU
2018-04-08 21:38:57 +02:00
if (menu_driver_is_alive())
2017-12-31 17:53:11 +01:00
return;
#endif
memset(handle->keys, 0, sizeof(handle->keys));
for (i = 0; i < max_users; i++)
{
2018-04-08 21:38:57 +02:00
device = settings->uints.input_libretro_device[i];
device &= RETRO_DEVICE_MASK;
2018-04-04 21:33:03 -05:00
/* keyboard to gamepad remapping */
if (device == RETRO_DEVICE_KEYBOARD)
2017-09-09 14:21:00 -05:00
{
input_get_state_for_port(settings, i, &current_input);
for (j = 0; j < RARCH_CUSTOM_BIND_LIST_END; j++)
2017-09-09 14:21:00 -05:00
{
2018-04-08 21:38:57 +02:00
unsigned current_button_value = BIT256_GET(current_input, j);
unsigned remap_button = settings->uints.input_keymapper_ids[i][j];
if (current_button_value == 1 && j != remap_button &&
remap_button != RETROK_UNKNOWN)
2018-04-08 21:38:57 +02:00
{
MAPPER_SET_KEY (handle,
remap_button);
2018-04-08 21:38:57 +02:00
input_keyboard_event(true,
remap_button,
0, 0, RETRO_DEVICE_KEYBOARD);
key_event[j] = true;
}
else
{
if (key_event[j] == false &&
remap_button != RETROK_UNKNOWN)
{
input_keyboard_event(false,
remap_button,
0, 0, RETRO_DEVICE_KEYBOARD);
}
}
2017-09-09 14:21:00 -05:00
}
}
2018-04-04 21:33:03 -05:00
/* gamepad remapping */
if (device == RETRO_DEVICE_JOYPAD || device == RETRO_DEVICE_ANALOG)
{
/* this loop iterates on all users and all buttons, and checks if a pressed button
is assigned to any other button than the default one, then it sets the bit on the
mapper input bitmap, later on the original input is cleared in input_state */
BIT256_CLEAR_ALL(handle->buttons[i]);
for (j = 0; j < 8; j++)
handle->analog_value[i][j] = 0;
input_get_state_for_port(settings, i, &current_input);
for (j = 0; j < RARCH_FIRST_CUSTOM_BIND; j++)
{
2018-04-08 21:38:57 +02:00
unsigned current_button_value = BIT256_GET(current_input, j);
unsigned remap_button = settings->uints.input_remap_ids[i][j];
if (current_button_value == 1 && j != remap_button &&
remap_button != RARCH_UNMAPPED && remap_button < RARCH_FIRST_CUSTOM_BIND)
BIT256_SET(handle->buttons[i], remap_button);
else if (current_button_value == 1 && j != remap_button &&
remap_button != RARCH_UNMAPPED && remap_button >= RARCH_FIRST_CUSTOM_BIND)
{
int invert = 1;
if (remap_button % 2 != 0)
invert = -1;
handle->analog_value[i][remap_button - RARCH_FIRST_CUSTOM_BIND] = 32767 * invert;
/* RARCH_LOG("axis %d(%d) remapped to axis %d val %d\n", j, k,
remap_button - RARCH_FIRST_CUSTOM_BIND, current_axis_value); */
}
}
for (j = 0; j < 8; j++)
{
2018-04-08 21:38:57 +02:00
unsigned remap_axis;
unsigned k = j + RARCH_FIRST_CUSTOM_BIND;
current_axis_value = current_input.analogs[j];
2018-04-08 21:38:57 +02:00
remap_axis = settings->uints.input_remap_ids[i][k];
if (current_axis_value != 0 && k != remap_axis && remap_axis != RARCH_UNMAPPED)
{
if (remap_axis < RARCH_FIRST_CUSTOM_BIND)
{
BIT256_SET(handle->buttons[i], remap_axis);
/* RARCH_LOG("axis %d remapped to button %d val %d\n", j,
remap_axis, current_axis_value); */
}
else
{
int invert = 1;
if ((k % 2 == 0 && remap_axis % 2 != 0) || (k % 2 != 0 && remap_axis % 2 == 0))
invert = -1;
handle->analog_value[i][remap_axis - RARCH_FIRST_CUSTOM_BIND] = current_axis_value * invert;
/* RARCH_LOG("axis %d(%d) remapped to axis %d val %d\n", j, k,
remap_axis - RARCH_FIRST_CUSTOM_BIND, current_axis_value); */
}
}
}
}
}
2017-09-07 22:30:42 -05:00
}
void input_mapper_state(
input_mapper_t *handle,
2017-09-07 22:30:42 -05:00
int16_t *ret,
unsigned port,
unsigned device,
unsigned idx,
2018-04-03 00:28:10 -05:00
unsigned id)
2017-09-07 22:30:42 -05:00
{
if (!handle)
return;
2017-09-09 14:21:00 -05:00
switch (device)
{
case RETRO_DEVICE_JOYPAD:
if (input_mapper_button_pressed(handle, port, id))
*ret = 1;
break;
case RETRO_DEVICE_ANALOG:
2018-04-08 21:38:57 +02:00
if (idx < 2 && id < 2)
{
2018-04-08 21:38:57 +02:00
int val = 0;
unsigned offset = 0 + (idx * 4) + (id * 2);
if (handle->analog_value[port][offset])
val = handle->analog_value[port][offset];
else if (handle->analog_value[port][offset+1])
val = handle->analog_value[port][offset+1];
if ( handle->analog_value[port][offset] ||
handle->analog_value[port][offset+1])
*ret |= val;
}
break;
2017-09-09 14:21:00 -05:00
case RETRO_DEVICE_KEYBOARD:
if (id < RETROK_LAST)
{
if (MAPPER_GET_KEY(handle, id))
2017-09-09 14:21:00 -05:00
*ret |= 1;
}
break;
default:
break;
2017-09-09 14:21:00 -05:00
}
return;
2017-09-16 19:06:55 -04:00
}