New input handling/mapping system, SDL only for now. Gui wip
This commit is contained in:
parent
66dc13b376
commit
8b5c2a3fac
|
@ -11,7 +11,7 @@ RZDCY_MODULES := cfg/ hw/arm7/ hw/aica/ hw/holly/ hw/ hw/gdrom/ hw/maple/ hw/mod
|
|||
hw/extdev/ hw/arm/ hw/naomi/ imgread/ ./ deps/coreio/ deps/zlib/ deps/chdr/ deps/crypto/ \
|
||||
deps/libelf/ deps/chdpsr/ arm_emitter/ rend/ reios/ deps/libpng/ deps/xbrz/ \
|
||||
deps/picotcp/modules/ deps/picotcp/stack/ deps/xxhash/ deps/libzip/ deps/imgui/ \
|
||||
archive/
|
||||
archive/ input/
|
||||
|
||||
ifdef CHD5_LZMA
|
||||
RZDCY_MODULES += deps/lzma/
|
||||
|
|
|
@ -113,36 +113,35 @@ void mcfg_CreateAtomisWaveControllers()
|
|||
// Sega Bass Fishing Challenge needs a mouse (track-ball) on port 3
|
||||
}
|
||||
|
||||
void mcfg_CreateController(u32 bus, MapleDeviceType maple_type1, MapleDeviceType maple_type2)
|
||||
void mcfg_CreateDevices()
|
||||
{
|
||||
mcfg_Create(MDT_SegaController, bus, 5);
|
||||
for (int bus = 0; bus < MAPLE_PORTS; ++bus)
|
||||
{
|
||||
switch ((MapleDeviceType)settings.input.maple_devices[bus])
|
||||
{
|
||||
case MDT_SegaController:
|
||||
mcfg_Create(MDT_SegaController, bus, 5);
|
||||
if (settings.input.maple_expansion_devices[bus][0] != MDT_None)
|
||||
mcfg_Create((MapleDeviceType)settings.input.maple_expansion_devices[bus][0], bus, 0);
|
||||
if (settings.input.maple_expansion_devices[bus][1] != MDT_None)
|
||||
mcfg_Create((MapleDeviceType)settings.input.maple_expansion_devices[bus][1], bus, 1);
|
||||
break;
|
||||
|
||||
if (maple_type1 != MDT_None)
|
||||
mcfg_Create(maple_type1, bus, 0);
|
||||
case MDT_Keyboard:
|
||||
mcfg_Create(MDT_Keyboard, bus, 5);
|
||||
break;
|
||||
|
||||
if (maple_type2 != MDT_None)
|
||||
mcfg_Create(maple_type2, bus, 1);
|
||||
}
|
||||
case MDT_Mouse:
|
||||
mcfg_Create(MDT_Mouse, bus, 5);
|
||||
break;
|
||||
|
||||
void mcfg_CreateDevicesFromConfig()
|
||||
{
|
||||
// Create the configure controller count
|
||||
int numberOfControl = cfgLoadInt("players", "nb", 1);
|
||||
|
||||
if (numberOfControl <= 0)
|
||||
numberOfControl = 1;
|
||||
if (numberOfControl > 4)
|
||||
numberOfControl = 4;
|
||||
|
||||
for (int i = 0; i < numberOfControl; i++)
|
||||
// Default to two VMUs on each controller
|
||||
mcfg_CreateController(i, MDT_SegaVMU, MDT_SegaVMU);
|
||||
|
||||
if (settings.input.DCKeyboard && numberOfControl < 4)
|
||||
mcfg_Create(MDT_Keyboard, numberOfControl++, 5);
|
||||
|
||||
if (settings.input.DCMouse != 0 && numberOfControl < 4)
|
||||
mcfg_Create(MDT_Mouse, numberOfControl++, 5);
|
||||
case MDT_LightGun:
|
||||
mcfg_Create(MDT_LightGun, bus, 5);
|
||||
if (settings.input.maple_expansion_devices[bus][0] != MDT_None)
|
||||
mcfg_Create((MapleDeviceType)settings.input.maple_expansion_devices[bus][0], bus, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mcfg_DestroyDevices()
|
||||
|
|
|
@ -59,8 +59,7 @@ struct IMapleConfigMap
|
|||
};
|
||||
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
void mcfg_CreateDevicesFromConfig();
|
||||
void mcfg_CreateController(u32 bus, MapleDeviceType maple_type1, MapleDeviceType maple_type2);
|
||||
void mcfg_CreateDevices();
|
||||
#else
|
||||
void mcfg_CreateNAOMIJamma();
|
||||
void mcfg_CreateAtomisWaveControllers();
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
This file is part of reicast.
|
||||
|
||||
reicast 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 Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
reicast 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 reicast. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
enum DreamcastKey
|
||||
{
|
||||
// Real buttons
|
||||
DC_BTN_C = 1 << 0,
|
||||
DC_BTN_B = 1 << 1,
|
||||
DC_BTN_A = 1 << 2,
|
||||
DC_BTN_START = 1 << 3,
|
||||
DC_DPAD_UP = 1 << 4,
|
||||
DC_DPAD_DOWN = 1 << 5,
|
||||
DC_DPAD_LEFT = 1 << 6,
|
||||
DC_DPAD_RIGHT = 1 << 7,
|
||||
DC_BTN_Z = 1 << 8,
|
||||
DC_BTN_Y = 1 << 9,
|
||||
DC_BTN_X = 1 << 10,
|
||||
DC_BTN_D = 1 << 11,
|
||||
DC_DPAD2_UP = 1 << 12,
|
||||
DC_DPAD2_DOWN = 1 << 13,
|
||||
DC_DPAD2_LEFT = 1 << 14,
|
||||
DC_DPAD2_RIGHT = 1 << 15,
|
||||
|
||||
// System buttons
|
||||
EMU_BTN_NONE = 0,
|
||||
EMU_BTN_ESCAPE = 1 << 16,
|
||||
EMU_BTN_TRIGGER_LEFT = 1 << 17,
|
||||
EMU_BTN_TRIGGER_RIGHT = 1 << 18,
|
||||
EMU_BTN_MENU = 1 << 19,
|
||||
|
||||
// Real axes
|
||||
DC_AXIS_LT = 0x10000,
|
||||
DC_AXIS_RT = 0x10001,
|
||||
DC_AXIS_X = 0x20000,
|
||||
DC_AXIS_Y = 0x20001,
|
||||
DC_AXIS_X2 = 0x20002,
|
||||
DC_AXIS_Y2 = 0x20003,
|
||||
|
||||
// System axes
|
||||
EMU_AXIS_NONE = 0x00000,
|
||||
EMU_AXIS_DPAD1_X = 0x00001,
|
||||
EMU_AXIS_DPAD1_Y = 0x00002,
|
||||
EMU_AXIS_DPAD2_X = 0x00003,
|
||||
EMU_AXIS_DPAD2_Y = 0x00004,
|
||||
};
|
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
Copyright 2019 flyinghead
|
||||
|
||||
This file is part of reicast.
|
||||
|
||||
reicast 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 Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
reicast 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 reicast. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <algorithm>
|
||||
#include <limits.h>
|
||||
#include "gamepad_device.h"
|
||||
#include "rend/gui.h"
|
||||
|
||||
extern void dc_stop();
|
||||
|
||||
extern u16 kcode[4];
|
||||
extern u8 rt[4], lt[4];
|
||||
extern s8 joyx[4], joyy[4];
|
||||
|
||||
std::vector<GamepadDevice *> GamepadDevice::_gamepads;
|
||||
std::mutex GamepadDevice::_gamepads_mutex;
|
||||
|
||||
void GamepadDevice::gamepad_btn_input(u32 code, bool pressed)
|
||||
{
|
||||
if (_input_detected != NULL && _detecting_button && pressed)
|
||||
{
|
||||
_input_detected(code);
|
||||
_input_detected = NULL;
|
||||
}
|
||||
if (input_mapper == NULL || _maple_port < 0 || _maple_port >= ARRAY_SIZE(kcode))
|
||||
return;
|
||||
DreamcastKey key = input_mapper->get_button_id(code);
|
||||
|
||||
printf("%d: BUTTON %x -> %d\n", _maple_port, code, key);
|
||||
|
||||
if (key < 0x10000)
|
||||
{
|
||||
if (pressed)
|
||||
kcode[_maple_port] &= ~(u16)key;
|
||||
else
|
||||
kcode[_maple_port] |= (u16)key;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case EMU_BTN_ESCAPE:
|
||||
dc_stop();
|
||||
break;
|
||||
case EMU_BTN_MENU:
|
||||
gui_open_settings();
|
||||
break;
|
||||
case EMU_BTN_TRIGGER_LEFT:
|
||||
lt[_maple_port] = pressed ? 255 : 0;
|
||||
break;
|
||||
case EMU_BTN_TRIGGER_RIGHT:
|
||||
rt[_maple_port] = pressed ? 255 : 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GamepadDevice::gamepad_axis_input(u32 code, int value)
|
||||
{
|
||||
s32 v = (value - get_axis_min_value(code)) * 255 / get_axis_range(code) - 128; //-128 ... + 127 range
|
||||
if (_input_detected != NULL && !_detecting_button && (v >= 64 || v <= -64))
|
||||
{
|
||||
_input_detected(code);
|
||||
_input_detected = NULL;
|
||||
}
|
||||
if (input_mapper == NULL || _maple_port < 0 || _maple_port >= ARRAY_SIZE(kcode))
|
||||
return;
|
||||
DreamcastKey key = input_mapper->get_axis_id(code);
|
||||
|
||||
if ((int)key < 0x10000)
|
||||
{
|
||||
kcode[_maple_port] |= key | (key << 1);
|
||||
if (v <= -64)
|
||||
kcode[_maple_port] &= ~key;
|
||||
else if (v >= 64)
|
||||
kcode[_maple_port] &= ~(key << 1);
|
||||
|
||||
// printf("Mapped to %d %d %d\n",mo,kcode[port]&mo,kcode[port]&(mo*2));
|
||||
}
|
||||
else if (((int)key >> 16) == 1) // Triggers
|
||||
{
|
||||
//printf("T-AXIS %d Mapped to %d -> %d\n",key, value, v + 128);
|
||||
|
||||
if (key == DC_AXIS_LT)
|
||||
lt[_maple_port] = (u8)(v + 128);
|
||||
else if (key == DC_AXIS_RT)
|
||||
rt[_maple_port] = (u8)(v + 128);
|
||||
}
|
||||
else if (((int)key >> 16) == 2) // Analog axes
|
||||
{
|
||||
//printf("AXIS %d Mapped to %d -> %d\n", key, value, v);
|
||||
if (key == DC_AXIS_X)
|
||||
joyx[_maple_port] = (s8)v;
|
||||
else if (key == DC_AXIS_Y)
|
||||
joyy[_maple_port] = (s8)v;
|
||||
}
|
||||
}
|
||||
|
||||
int GamepadDevice::get_axis_min_value(u32 axis) {
|
||||
auto it = axis_min_values.find(axis);
|
||||
if (it == axis_min_values.end()) {
|
||||
load_axis_min_max(axis);
|
||||
it = axis_min_values.find(axis);
|
||||
if (it == axis_min_values.end())
|
||||
return INT_MIN;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
unsigned int GamepadDevice::get_axis_range(u32 axis) {
|
||||
auto it = axis_ranges.find(axis);
|
||||
if (it == axis_ranges.end()) {
|
||||
load_axis_min_max(axis);
|
||||
it = axis_ranges.find(axis);
|
||||
if (it == axis_ranges.end())
|
||||
return UINT_MAX;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
std::string GamepadDevice::make_mapping_filename()
|
||||
{
|
||||
std::string mapping_file = std::string(api_name()) + "_" + name();
|
||||
std::replace(mapping_file.begin(), mapping_file.end(), '/', '-');
|
||||
std::replace(mapping_file.begin(), mapping_file.end(), '\\', '-');
|
||||
std::replace(mapping_file.begin(), mapping_file.end(), ':', '-');
|
||||
std::replace(mapping_file.begin(), mapping_file.end(), '?', '-');
|
||||
std::replace(mapping_file.begin(), mapping_file.end(), '*', '-');
|
||||
std::replace(mapping_file.begin(), mapping_file.end(), '|', '-');
|
||||
std::replace(mapping_file.begin(), mapping_file.end(), '"', '-');
|
||||
std::replace(mapping_file.begin(), mapping_file.end(), '<', '-');
|
||||
std::replace(mapping_file.begin(), mapping_file.end(), '>', '-');
|
||||
mapping_file += ".cfg";
|
||||
|
||||
return mapping_file;
|
||||
}
|
||||
|
||||
bool GamepadDevice::find_mapping(const char *custom_mapping /* = NULL */)
|
||||
{
|
||||
std::string mapping_file;
|
||||
if (custom_mapping != NULL)
|
||||
mapping_file = custom_mapping;
|
||||
else
|
||||
mapping_file = make_mapping_filename();
|
||||
|
||||
input_mapper = InputMapping::LoadMapping(mapping_file.c_str());
|
||||
return input_mapper != NULL;
|
||||
}
|
||||
|
||||
int GamepadDevice::GetGamepadCount()
|
||||
{
|
||||
_gamepads_mutex.lock();
|
||||
int count = _gamepads.size();
|
||||
_gamepads_mutex.unlock();
|
||||
return count;
|
||||
}
|
||||
|
||||
GamepadDevice *GamepadDevice::GetGamepad(int index)
|
||||
{
|
||||
_gamepads_mutex.lock();
|
||||
GamepadDevice *dev;
|
||||
if (index >= 0 && index < _gamepads.size())
|
||||
dev = _gamepads[index];
|
||||
else
|
||||
dev = NULL;
|
||||
_gamepads_mutex.unlock();
|
||||
return dev;
|
||||
}
|
||||
|
||||
void GamepadDevice::save_mapping()
|
||||
{
|
||||
if (input_mapper == NULL)
|
||||
return;
|
||||
std::string filename = make_mapping_filename();
|
||||
if (!input_mapper->is_dirty())
|
||||
return;
|
||||
input_mapper->save(make_mapping_filename().c_str());
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
Copyright 2019 flyinghead
|
||||
|
||||
This file is part of reicast.
|
||||
|
||||
reicast 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 Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
reicast 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 reicast. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <mutex>
|
||||
#include "types.h"
|
||||
#include "mapping.h"
|
||||
|
||||
class GamepadDevice
|
||||
{
|
||||
typedef void (*input_detected_cb)(u32 code);
|
||||
public:
|
||||
virtual const char* api_name() = 0;
|
||||
virtual const char* name() = 0;
|
||||
int maple_port() { return _maple_port; }
|
||||
void set_maple_port(int port) { _maple_port = port; }
|
||||
void gamepad_btn_input(u32 code, bool pressed);
|
||||
void gamepad_axis_input(u32 code, int value);
|
||||
virtual ~GamepadDevice() {
|
||||
save_mapping();
|
||||
_gamepads_mutex.lock();
|
||||
for (auto it = _gamepads.begin(); it != _gamepads.end(); it++)
|
||||
if (*it == this)
|
||||
{
|
||||
_gamepads.erase(it);
|
||||
break;
|
||||
}
|
||||
_gamepads_mutex.unlock();
|
||||
}
|
||||
void detect_btn_input(input_detected_cb button_pressed)
|
||||
{
|
||||
_input_detected = button_pressed;
|
||||
_detecting_button = true;
|
||||
}
|
||||
void detect_axis_input(input_detected_cb axis_moved)
|
||||
{
|
||||
_input_detected = axis_moved;
|
||||
_detecting_button = false;
|
||||
}
|
||||
void cancel_detect_input()
|
||||
{
|
||||
_input_detected = NULL;
|
||||
}
|
||||
InputMapping *get_input_mapping() { return input_mapper; }
|
||||
void save_mapping();
|
||||
|
||||
static int GetGamepadCount();
|
||||
static GamepadDevice *GetGamepad(int index);
|
||||
|
||||
protected:
|
||||
GamepadDevice(int maple_port) : _maple_port(maple_port), input_mapper(NULL), _input_detected(NULL) {
|
||||
_gamepads_mutex.lock();
|
||||
_gamepads.push_back(this);
|
||||
_gamepads_mutex.unlock();
|
||||
}
|
||||
bool find_mapping(const char *custom_mapping = NULL);
|
||||
|
||||
virtual void load_axis_min_max(u32 axis) {}
|
||||
|
||||
InputMapping *input_mapper;
|
||||
std::map<u32, int> axis_min_values;
|
||||
std::map<u32, unsigned int> axis_ranges;
|
||||
|
||||
private:
|
||||
int get_axis_min_value(u32 axis);
|
||||
unsigned int get_axis_range(u32 axis);
|
||||
std::string make_mapping_filename();
|
||||
|
||||
int _maple_port;
|
||||
bool _detecting_button = false;
|
||||
input_detected_cb _input_detected;
|
||||
|
||||
static std::vector<GamepadDevice *> _gamepads;
|
||||
static std::mutex _gamepads_mutex;
|
||||
};
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
Copyright 2019 flyinghead
|
||||
|
||||
This file is part of reicast.
|
||||
|
||||
reicast 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 Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
reicast 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 reicast. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "types.h"
|
||||
#include "mapping.h"
|
||||
|
||||
template <typename Keycode>
|
||||
class KeyboardDevice
|
||||
{
|
||||
public:
|
||||
virtual const char* name() = 0;
|
||||
int maple_port() { return _maple_port; }
|
||||
virtual void keyboard_input(Keycode keycode, bool pressed, int modifier_keys = 0);
|
||||
virtual ~KeyboardDevice() {}
|
||||
|
||||
protected:
|
||||
KeyboardDevice(int maple_port) : _maple_port(maple_port), _kb_used(0), _modifier_keys(0) {}
|
||||
virtual u8 convert_keycode(Keycode keycode) = 0;
|
||||
|
||||
private:
|
||||
int _maple_port;
|
||||
int _modifier_keys;
|
||||
int _kb_used;
|
||||
};
|
||||
|
||||
extern u8 kb_key[6]; // normal keys pressed
|
||||
extern u8 kb_shift; // shift keys pressed (bitmask)
|
||||
|
||||
template <typename Keycode>
|
||||
void KeyboardDevice<Keycode>::keyboard_input(Keycode keycode, bool pressed, int modifier_keys)
|
||||
{
|
||||
u8 dc_keycode = convert_keycode(keycode);
|
||||
if (dc_keycode == 0xE1 || dc_keycode == 0xE5) // SHIFT
|
||||
{
|
||||
if (pressed)
|
||||
_modifier_keys |= 0x02 | 0x20;
|
||||
else
|
||||
_modifier_keys &= ~(0x02 | 0x20);
|
||||
}
|
||||
else if (dc_keycode == 0xE0 || dc_keycode == 0xE4) // CTRL
|
||||
{
|
||||
if (pressed)
|
||||
_modifier_keys |= 0x01 | 0x10;
|
||||
else
|
||||
_modifier_keys &= ~(0x01 | 0x10);
|
||||
}
|
||||
else if (dc_keycode != 0)
|
||||
{
|
||||
if (pressed)
|
||||
{
|
||||
if (_kb_used < ARRAY_SIZE(kb_key))
|
||||
{
|
||||
bool found = false;
|
||||
for (int i = 0; !found && i < _kb_used; i++)
|
||||
{
|
||||
if (kb_key[i] == dc_keycode)
|
||||
found = true;
|
||||
}
|
||||
if (!found)
|
||||
kb_key[_kb_used++] = dc_keycode;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < _kb_used; i++)
|
||||
{
|
||||
if (kb_key[i] == dc_keycode)
|
||||
{
|
||||
_kb_used--;
|
||||
for (int j = i; j < ARRAY_SIZE(kb_key) - 1; j++)
|
||||
kb_key[j] = kb_key[j + 1];
|
||||
kb_key[ARRAY_SIZE(kb_key) - 1] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
kb_shift = modifier_keys | _modifier_keys;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
Copyright 2019 flyinghead
|
||||
|
||||
This file is part of reicast.
|
||||
|
||||
reicast 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 Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
reicast 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 reicast. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "mapping.h"
|
||||
#include "cfg/ini.h"
|
||||
|
||||
static struct
|
||||
{
|
||||
DreamcastKey id;
|
||||
string section;
|
||||
string option;
|
||||
}
|
||||
button_list[] =
|
||||
{
|
||||
{ DC_BTN_A, "dreamcast", "btn_a" },
|
||||
{ DC_BTN_B, "dreamcast", "btn_b" },
|
||||
{ DC_BTN_C, "dreamcast", "btn_c" },
|
||||
{ DC_BTN_D, "dreamcast", "btn_d" },
|
||||
{ DC_BTN_X, "dreamcast", "btn_x" },
|
||||
{ DC_BTN_Y, "dreamcast", "btn_y" },
|
||||
{ DC_BTN_Z, "dreamcast", "btn_z" },
|
||||
{ DC_BTN_START, "dreamcast", "btn_start" },
|
||||
{ DC_DPAD_LEFT, "dreamcast", "btn_dpad1_left" },
|
||||
{ DC_DPAD_RIGHT, "dreamcast", "btn_dpad1_right" },
|
||||
{ DC_DPAD_UP, "dreamcast", "btn_dpad1_up" },
|
||||
{ DC_DPAD_DOWN, "dreamcast", "btn_dpad1_down" },
|
||||
{ DC_DPAD2_LEFT, "dreamcast", "btn_dpad2_left" },
|
||||
{ DC_DPAD2_RIGHT, "dreamcast", "btn_dpad2_right" },
|
||||
{ DC_DPAD2_UP, "dreamcast", "btn_dpad2_up" },
|
||||
{ DC_DPAD2_DOWN, "dreamcast", "btn_dpad2_down" },
|
||||
{ EMU_BTN_ESCAPE, "emulator", "btn_escape" },
|
||||
{ EMU_BTN_MENU, "emulator", "btn_menu" },
|
||||
{ EMU_BTN_TRIGGER_LEFT, "compat", "btn_trigger_left" },
|
||||
{ EMU_BTN_TRIGGER_RIGHT, "compat", "btn_trigger_right" }
|
||||
};
|
||||
|
||||
static struct
|
||||
{
|
||||
DreamcastKey id;
|
||||
string section;
|
||||
string option;
|
||||
string section_inverted;
|
||||
string option_inverted;
|
||||
}
|
||||
axis_list[] =
|
||||
{
|
||||
{ DC_AXIS_X, "dreamcast", "axis_x", "compat", "axis_x_inverted" },
|
||||
{ DC_AXIS_Y, "dreamcast", "axis_y", "compat", "axis_y_inverted" },
|
||||
{ DC_AXIS_LT, "dreamcast", "axis_trigger_left", "compat", "axis_trigger_left_inverted" },
|
||||
{ DC_AXIS_RT, "dreamcast", "axis_trigger_right", "compat", "axis_trigger_right_inverted" },
|
||||
{ EMU_AXIS_DPAD1_X, "compat", "axis_dpad1_x", "compat", "axis_dpad1_x_inverted" },
|
||||
{ EMU_AXIS_DPAD1_Y, "compat", "axis_dpad1_y", "compat", "axis_dpad1_y_inverted" },
|
||||
{ EMU_AXIS_DPAD2_X, "compat", "axis_dpad2_x", "compat", "axis_dpad2_x_inverted" },
|
||||
{ EMU_AXIS_DPAD2_Y, "compat", "axis_dpad2_y", "compat", "axis_dpad2_y_inverted" }
|
||||
};
|
||||
|
||||
std::map<std::string, InputMapping *> InputMapping::loaded_mappings;
|
||||
|
||||
void InputMapping::set_button(DreamcastKey id, u32 code)
|
||||
{
|
||||
if (id != EMU_BTN_NONE)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
u32 code = get_button_code(id);
|
||||
if (code == -1)
|
||||
break;
|
||||
buttons[code] = EMU_BTN_NONE;
|
||||
}
|
||||
buttons[code] = id;
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void InputMapping::set_axis(DreamcastKey id, u32 code, bool is_inverted)
|
||||
{
|
||||
if (id != EMU_AXIS_NONE)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
u32 code = get_axis_code(id);
|
||||
if (code == -1)
|
||||
break;
|
||||
axes[code] = EMU_AXIS_NONE;
|
||||
}
|
||||
axes[code] = id;
|
||||
axes_inverted[code] = is_inverted;
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void InputMapping::load(FILE* fp)
|
||||
{
|
||||
ConfigFile mf;
|
||||
mf.parse(fp);
|
||||
|
||||
this->name = mf.get("emulator", "mapping_name", "<Unknown>");
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(button_list); i++)
|
||||
{
|
||||
int button_code = mf.get_int(button_list[i].section, button_list[i].option, -1);
|
||||
if (button_code >= 0)
|
||||
{
|
||||
this->set_button(button_list[i].id, button_code);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(axis_list); i++)
|
||||
{
|
||||
int axis_code = mf.get_int(axis_list[i].section, axis_list[i].option, -1);
|
||||
if (axis_code >= 0)
|
||||
{
|
||||
this->set_axis(axis_list[i].id, axis_code, mf.get_bool(axis_list[i].section_inverted, axis_list[i].option_inverted, false));
|
||||
}
|
||||
}
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
u32 InputMapping::get_button_code(DreamcastKey key)
|
||||
{
|
||||
for (auto it : buttons)
|
||||
{
|
||||
if (it.second == key)
|
||||
return it.first;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
u32 InputMapping::get_axis_code(DreamcastKey key)
|
||||
{
|
||||
for (auto it : axes)
|
||||
{
|
||||
if (it.second == key)
|
||||
return it.first;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
InputMapping *InputMapping::LoadMapping(const char *name)
|
||||
{
|
||||
auto it = loaded_mappings.find(name);
|
||||
if (it != loaded_mappings.end())
|
||||
return it->second;
|
||||
std::string path = get_readonly_data_path((std::string("/mappings/") + name).c_str());
|
||||
FILE *fp = fopen(path.c_str(), "r");
|
||||
if (fp == NULL)
|
||||
return NULL;
|
||||
InputMapping *mapping = new InputMapping();
|
||||
mapping->load(fp);
|
||||
fclose(fp);
|
||||
loaded_mappings[name] = mapping;
|
||||
|
||||
return mapping;
|
||||
}
|
||||
|
||||
bool InputMapping::save(const char *name)
|
||||
{
|
||||
if (!is_dirty())
|
||||
return true;
|
||||
|
||||
std::string path = get_writable_config_path((std::string("/mappings/") + name).c_str());
|
||||
FILE *fp = fopen(path.c_str(), "w");
|
||||
if (fp == NULL)
|
||||
return false;
|
||||
ConfigFile mf;
|
||||
|
||||
mf.set("emulator", "mapping_name", this->name);
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(button_list); i++)
|
||||
{
|
||||
for (auto it : buttons)
|
||||
{
|
||||
if (it.second == button_list[i].id)
|
||||
mf.set_int(button_list[i].section, button_list[i].option, (int)it.first);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(axis_list); i++)
|
||||
{
|
||||
for (auto it : axes)
|
||||
{
|
||||
if (it.second == axis_list[i].id)
|
||||
{
|
||||
mf.set_int(axis_list[i].section, axis_list[i].option, (int)it.first);
|
||||
mf.set_bool(axis_list[i].section_inverted, axis_list[i].option_inverted, axes_inverted[it.first]);
|
||||
}
|
||||
}
|
||||
}
|
||||
mf.save(fp);
|
||||
dirty = false;
|
||||
fclose(fp);
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
Copyright 2019 flyinghead
|
||||
|
||||
This file is part of reicast.
|
||||
|
||||
reicast 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 Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
reicast 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 reicast. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <map>
|
||||
#include <stdio.h>
|
||||
#include "types.h"
|
||||
#include "gamepad.h"
|
||||
|
||||
class InputMapping
|
||||
{
|
||||
public:
|
||||
std::string name;
|
||||
|
||||
DreamcastKey get_button_id(u32 code)
|
||||
{
|
||||
auto it = buttons.find(code);
|
||||
if (it != buttons.end())
|
||||
return it->second;
|
||||
else
|
||||
return EMU_BTN_NONE;
|
||||
}
|
||||
void set_button(DreamcastKey id, u32 code);
|
||||
u32 get_button_code(DreamcastKey key);
|
||||
|
||||
DreamcastKey get_axis_id(u32 code)
|
||||
{
|
||||
auto it = axes.find(code);
|
||||
if (it != axes.end())
|
||||
return it->second;
|
||||
else
|
||||
return EMU_AXIS_NONE;
|
||||
}
|
||||
bool get_axis_inverted(u32 code)
|
||||
{
|
||||
auto it = axes_inverted.find(code);
|
||||
if (it != axes_inverted.end())
|
||||
return it->second;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
u32 get_axis_code(DreamcastKey key);
|
||||
void set_axis(DreamcastKey id, u32 code, bool inverted);
|
||||
|
||||
void load(FILE* fp);
|
||||
bool save(const char *name);
|
||||
|
||||
bool is_dirty() { return dirty; }
|
||||
|
||||
static InputMapping *LoadMapping(const char *name);
|
||||
|
||||
protected:
|
||||
bool dirty;
|
||||
|
||||
private:
|
||||
std::map<u32, DreamcastKey> buttons;
|
||||
std::map<u32, DreamcastKey> axes;
|
||||
std::map<u32, bool> axes_inverted;
|
||||
|
||||
static std::map<std::string, InputMapping *> loaded_mappings;
|
||||
};
|
|
@ -4,10 +4,10 @@
|
|||
#include "linux-dist/evdev.h"
|
||||
#include "linux-dist/main.h"
|
||||
#include "hw/maple/maple_devs.h"
|
||||
#include "hw/maple/maple_cfg.h"
|
||||
#include "cfg/cfg.h"
|
||||
#include "cfg/ini.h"
|
||||
#include "rend/gui.h"
|
||||
#include "input/gamepad.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <dlfcn.h>
|
||||
|
@ -504,9 +504,6 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
mcfg_CreateController(port, GetMapleDeviceType(evdev_controllers[port].mapping->Maple_Device1, port), GetMapleDeviceType(evdev_controllers[port].mapping->Maple_Device2, port));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,7 +124,7 @@ void os_SetupInput()
|
|||
#endif
|
||||
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
mcfg_CreateDevicesFromConfig();
|
||||
mcfg_CreateDevices();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -8,28 +8,3 @@ extern s8 joyx[4], joyy[4];
|
|||
|
||||
extern void* x11_win;
|
||||
extern void* x11_disp;
|
||||
|
||||
enum DreamcastController
|
||||
{
|
||||
DC_BTN_C = 1,
|
||||
DC_BTN_B = 1<<1,
|
||||
DC_BTN_A = 1<<2,
|
||||
DC_BTN_START = 1<<3,
|
||||
DC_DPAD_UP = 1<<4,
|
||||
DC_DPAD_DOWN = 1<<5,
|
||||
DC_DPAD_LEFT = 1<<6,
|
||||
DC_DPAD_RIGHT = 1<<7,
|
||||
DC_BTN_Z = 1<<8,
|
||||
DC_BTN_Y = 1<<9,
|
||||
DC_BTN_X = 1<<10,
|
||||
DC_BTN_D = 1<<11,
|
||||
DC_DPAD2_UP = 1<<12,
|
||||
DC_DPAD2_DOWN = 1<<13,
|
||||
DC_DPAD2_LEFT = 1<<14,
|
||||
DC_DPAD2_RIGHT = 1<<15,
|
||||
|
||||
DC_AXIS_LT = 0X10000,
|
||||
DC_AXIS_RT = 0X10001,
|
||||
DC_AXIS_X = 0X20000,
|
||||
DC_AXIS_Y = 0X20001,
|
||||
};
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "linux-dist/x11.h"
|
||||
#include "linux-dist/main.h"
|
||||
#include "rend/gui.h"
|
||||
#include "input/gamepad.h"
|
||||
|
||||
#if FEAT_HAS_NIXPROF
|
||||
#include "profiler/profiler.h"
|
||||
|
|
|
@ -255,7 +255,7 @@ void os_DoEvents() {
|
|||
|
||||
void os_SetupInput() {
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
mcfg_CreateDevicesFromConfig();
|
||||
mcfg_CreateDevices();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -554,6 +554,16 @@ void LoadSettings()
|
|||
settings.input.DCMouse = cfgLoadInt("input", "DCMouse", 0);
|
||||
settings.input.MouseSensitivity = cfgLoadInt("input", "MouseSensitivity", 100);
|
||||
settings.input.JammaSetup = cfgLoadInt("input", "JammaSetup", 0);
|
||||
for (int i = 0; i < MAPLE_PORTS; i++)
|
||||
{
|
||||
char device_name[32];
|
||||
sprintf(device_name, "device%d", i + 1);
|
||||
settings.input.maple_devices[i] = (MapleDeviceType)cfgLoadInt("input", device_name, i == 0 ? MDT_SegaController : MDT_None);
|
||||
sprintf(device_name, "device%d.1", i + 1);
|
||||
settings.input.maple_expansion_devices[i][0] = (MapleDeviceType)cfgLoadInt("input", device_name, i == 0 ? MDT_SegaVMU : MDT_None);
|
||||
sprintf(device_name, "device%d.2", i + 1);
|
||||
settings.input.maple_expansion_devices[i][1] = (MapleDeviceType)cfgLoadInt("input", device_name, i == 0 ? MDT_SegaVMU : MDT_None);
|
||||
}
|
||||
#else
|
||||
settings.rend.RenderToTextureUpscale = max(1, settings.rend.RenderToTextureUpscale);
|
||||
settings.rend.TextureUpscale = max(1, settings.rend.TextureUpscale);
|
||||
|
@ -663,6 +673,17 @@ void SaveSettings()
|
|||
cfgSaveInt("input", "DCKeyboard", settings.input.DCKeyboard);
|
||||
cfgSaveInt("input", "DCMouse", settings.input.DCMouse);
|
||||
cfgSaveInt("input", "MouseSensitivity", settings.input.MouseSensitivity);
|
||||
for (int i = 0; i < MAPLE_PORTS; i++)
|
||||
{
|
||||
char device_name[32];
|
||||
sprintf(device_name, "device%d", i + 1);
|
||||
cfgSaveInt("input", device_name, (s32)settings.input.maple_devices[i]);
|
||||
sprintf(device_name, "device%d.1", i + 1);
|
||||
cfgSaveInt("input", device_name, (s32)settings.input.maple_expansion_devices[i][0]);
|
||||
sprintf(device_name, "device%d.2", i + 1);
|
||||
cfgSaveInt("input", device_name, (s32)settings.input.maple_expansion_devices[i][1]);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
#include "imgui/imgui_impl_opengl3.h"
|
||||
#include "imgui/roboto_medium.h"
|
||||
#include "gles/gles.h"
|
||||
#include "linux-dist/main.h" // FIXME for kcode[] and DC_BTN_x
|
||||
#include "input/gamepad_device.h"
|
||||
#include "linux-dist/main.h" // FIXME for kcode[]
|
||||
|
||||
extern bool dc_pause_emu();
|
||||
extern void dc_resume_emu(bool continue_running);
|
||||
|
@ -45,7 +46,7 @@ extern bool renderer_changed;
|
|||
int screen_dpi = 96;
|
||||
|
||||
static bool inited = false;
|
||||
static float scaling = 1.f;
|
||||
static float scaling = 1;
|
||||
static enum { Closed, Commands, Settings, ClosedNoResume } gui_state;
|
||||
static bool settings_opening;
|
||||
static bool touch_up;
|
||||
|
@ -61,6 +62,8 @@ void gui_init()
|
|||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
|
||||
io.IniFilename = NULL;
|
||||
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
|
||||
|
@ -89,10 +92,10 @@ void gui_init()
|
|||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsClassic();
|
||||
ImGui::GetStyle().TabRounding = 0.f;
|
||||
ImGui::GetStyle().TabRounding = 0;
|
||||
ImGui::GetStyle().ItemSpacing = ImVec2(8, 8); // from 8,4
|
||||
ImGui::GetStyle().ItemInnerSpacing = ImVec2(4, 6); // from 4,4
|
||||
//ImGui::GetStyle().WindowRounding = 0.f;
|
||||
//ImGui::GetStyle().WindowRounding = 0;
|
||||
#ifdef _ANDROID
|
||||
ImGui::GetStyle().GrabMinSize = 20.0f; // from 10
|
||||
ImGui::GetStyle().ScrollbarSize = 24.0f; // from 16
|
||||
|
@ -317,6 +320,128 @@ static void gui_display_commands()
|
|||
settings_opening = false;
|
||||
}
|
||||
|
||||
const char *maple_device_types[] = { "None", "Sega Controller", "Light Gun", "Keyboard", "Mouse" };
|
||||
const char *maple_expansion_device_types[] = { "None", "Sega VMU", "Purupuru", "Microphone" };
|
||||
|
||||
static const char *maple_device_name(MapleDeviceType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MDT_SegaController:
|
||||
return maple_device_types[1];
|
||||
case MDT_LightGun:
|
||||
return maple_device_types[2];
|
||||
case MDT_Keyboard:
|
||||
return maple_device_types[3];
|
||||
case MDT_Mouse:
|
||||
return maple_device_types[4];
|
||||
case MDT_None:
|
||||
default:
|
||||
return maple_device_types[0];
|
||||
}
|
||||
}
|
||||
|
||||
static MapleDeviceType maple_device_type_from_index(int idx)
|
||||
{
|
||||
switch (idx)
|
||||
{
|
||||
case 1:
|
||||
return MDT_SegaController;
|
||||
case 2:
|
||||
return MDT_LightGun;
|
||||
case 3:
|
||||
return MDT_Keyboard;
|
||||
case 4:
|
||||
return MDT_Mouse;
|
||||
case 0:
|
||||
default:
|
||||
return MDT_None;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *maple_expansion_device_name(MapleDeviceType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MDT_SegaVMU:
|
||||
return maple_expansion_device_types[1];
|
||||
case MDT_PurupuruPack:
|
||||
return maple_expansion_device_types[2];
|
||||
case MDT_Microphone:
|
||||
return maple_expansion_device_types[3];
|
||||
case MDT_None:
|
||||
default:
|
||||
return maple_expansion_device_types[0];
|
||||
}
|
||||
}
|
||||
|
||||
const char *maple_ports[] = { "None", "A", "B", "C", "D" };
|
||||
const DreamcastKey button_keys[] = { DC_BTN_START, DC_BTN_A, DC_BTN_B, DC_BTN_X, DC_BTN_Y, DC_DPAD_UP, DC_DPAD_DOWN, DC_DPAD_LEFT, DC_DPAD_RIGHT,
|
||||
EMU_BTN_MENU, EMU_BTN_ESCAPE, EMU_BTN_TRIGGER_LEFT, EMU_BTN_TRIGGER_RIGHT,
|
||||
DC_BTN_C, DC_BTN_D, DC_BTN_Z, DC_DPAD2_UP, DC_DPAD2_DOWN, DC_DPAD2_LEFT, DC_DPAD2_RIGHT };
|
||||
const char *button_names[] = { "Start", "A", "B", "X", "Y", "DPad Up", "DPad Down", "DPad Left", "DPad Right",
|
||||
"Menu", "Exit", "Left Trigger", "Right Trigger",
|
||||
"C", "D", "Z", "Right Dpad Up", "Right DPad Down", "Right DPad Left", "Right DPad Right" };
|
||||
const DreamcastKey axis_keys[] = { DC_AXIS_X, DC_AXIS_Y, DC_AXIS_LT, DC_AXIS_RT, EMU_AXIS_DPAD1_X, EMU_AXIS_DPAD1_Y, EMU_AXIS_DPAD2_X, EMU_AXIS_DPAD2_Y };
|
||||
const char *axis_names[] = { "Stick X", "Stick Y", "Left Trigger", "Right Trigger", "DPad X", "DPad Y", "Right DPad X", "Right DPad Y" };
|
||||
|
||||
static MapleDeviceType maple_expansion_device_type_from_index(int idx)
|
||||
{
|
||||
switch (idx)
|
||||
{
|
||||
case 1:
|
||||
return MDT_SegaVMU;
|
||||
case 2:
|
||||
return MDT_PurupuruPack;
|
||||
case 3:
|
||||
return MDT_Microphone;
|
||||
case 0:
|
||||
default:
|
||||
return MDT_None;
|
||||
}
|
||||
}
|
||||
|
||||
static GamepadDevice *mapped_device;
|
||||
static u32 mapped_code;
|
||||
static double map_start_time;
|
||||
|
||||
static void input_detected(u32 code)
|
||||
{
|
||||
mapped_code = code;
|
||||
}
|
||||
|
||||
static void detect_input_popup(int index, bool analog)
|
||||
{
|
||||
ImVec2 padding = ImVec2(20 * scaling, 20 * scaling);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, padding);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, padding);
|
||||
if (ImGui::BeginPopupModal(analog ? "Map Axis" : "Map Button", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove))
|
||||
{
|
||||
ImGui::Text("Waiting for %s '%s'...", analog ? "axis" : "button", analog ? axis_names[index] : button_names[index]);
|
||||
double now = os_GetSeconds();
|
||||
ImGui::Text("Time out in %d s", (int)(5 - (now - map_start_time)));
|
||||
if (mapped_code != -1)
|
||||
{
|
||||
if (analog)
|
||||
{
|
||||
u32 previous_mapping = mapped_device->get_input_mapping()->get_axis_code(axis_keys[index]);
|
||||
bool inverted = false;
|
||||
if (previous_mapping != -1)
|
||||
inverted = mapped_device->get_input_mapping()->get_axis_inverted(previous_mapping);
|
||||
// FIXME Allow inverted to be set
|
||||
mapped_device->get_input_mapping()->set_axis(axis_keys[index], mapped_code, inverted);
|
||||
}
|
||||
else
|
||||
mapped_device->get_input_mapping()->set_button(button_keys[index], mapped_code);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
else if (now - map_start_time >= 5)
|
||||
ImGui::CloseCurrentPopup();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
ImGui::PopStyleVar(2);
|
||||
}
|
||||
|
||||
static void gui_display_settings()
|
||||
{
|
||||
ImGui_Impl_NewFrame();
|
||||
|
@ -324,7 +449,6 @@ static void gui_display_settings()
|
|||
|
||||
int dynarec_enabled = settings.dynarec.Enable;
|
||||
u32 renderer = settings.pvr.rend;
|
||||
int playerCount = cfgLoadInt("players", "nb", 1);
|
||||
|
||||
if (!settings_opening)
|
||||
ImGui_ImplOpenGL3_DrawBackground();
|
||||
|
@ -342,12 +466,9 @@ static void gui_display_settings()
|
|||
{
|
||||
gui_state = Commands;
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
if (playerCount != cfgLoadInt("players", "nb", 1))
|
||||
{
|
||||
cfgSaveInt("players", "nb", playerCount);
|
||||
mcfg_DestroyDevices();
|
||||
mcfg_CreateDevicesFromConfig();
|
||||
}
|
||||
// TODO only if changed? sleep time on emu thread?
|
||||
mcfg_DestroyDevices();
|
||||
mcfg_CreateDevices();
|
||||
#endif
|
||||
SaveSettings();
|
||||
}
|
||||
|
@ -430,15 +551,189 @@ static void gui_display_settings()
|
|||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, normal_padding);
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
ImGui::SliderInt("Players", (int *)&playerCount, 1, 4);
|
||||
ImGui::Checkbox("Emulate keyboard", &settings.input.DCKeyboard);
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("Emulate a Dreamcast keyboard");
|
||||
ImGui::Checkbox("Emulate mouse", &settings.input.DCMouse);
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("Emulate a Dreamcast mouse");
|
||||
if (ImGui::CollapsingHeader("Dreamcast Devices", ImGuiTreeNodeFlags_DefaultOpen))
|
||||
{
|
||||
for (int bus = 0; bus < MAPLE_PORTS; bus++)
|
||||
{
|
||||
ImGui::Text("Device %c", bus + 'A');
|
||||
ImGui::SameLine();
|
||||
char device_name[32];
|
||||
sprintf(device_name, "##device%d", bus);
|
||||
float w = ImGui::CalcItemWidth() / 3;
|
||||
ImGui::PushItemWidth(w);
|
||||
if (ImGui::BeginCombo(device_name, maple_device_name((MapleDeviceType)settings.input.maple_devices[bus]), ImGuiComboFlags_None))
|
||||
{
|
||||
for (int i = 0; i < IM_ARRAYSIZE(maple_device_types); i++)
|
||||
{
|
||||
bool is_selected = settings.input.maple_devices[bus] == maple_device_type_from_index(i);
|
||||
if (ImGui::Selectable(maple_device_types[i], &is_selected))
|
||||
settings.input.maple_devices[bus] = maple_device_type_from_index(i);
|
||||
if (is_selected)
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
int port_count = settings.input.maple_devices[bus] == MDT_SegaController ? 2 : settings.input.maple_devices[bus] == MDT_LightGun ? 1 : 0;
|
||||
for (int port = 0; port < port_count; port++)
|
||||
{
|
||||
ImGui::SameLine();
|
||||
sprintf(device_name, "##device%d.%d", bus, port + 1);
|
||||
ImGui::PushID(device_name);
|
||||
if (ImGui::BeginCombo(device_name, maple_expansion_device_name((MapleDeviceType)settings.input.maple_expansion_devices[bus][port]), ImGuiComboFlags_None))
|
||||
{
|
||||
for (int i = 0; i < IM_ARRAYSIZE(maple_expansion_device_types); i++)
|
||||
{
|
||||
bool is_selected = settings.input.maple_expansion_devices[bus][port] == maple_expansion_device_type_from_index(i);
|
||||
if (ImGui::Selectable(maple_expansion_device_types[i], &is_selected))
|
||||
settings.input.maple_expansion_devices[bus][port] = maple_expansion_device_type_from_index(i);
|
||||
if (is_selected)
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
ImGui::Spacing();
|
||||
}
|
||||
#endif
|
||||
if (ImGui::CollapsingHeader("Physical Devices", ImGuiTreeNodeFlags_DefaultOpen))
|
||||
{
|
||||
ImGui::Columns(4, "renderers", false);
|
||||
ImGui::Text("System");
|
||||
ImGui::SetColumnWidth(-1, ImGui::CalcTextSize("System").x + ImGui::GetStyle().FramePadding.x * 2.0f + ImGui::GetStyle().ItemSpacing.x);
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("Name");
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("Port");
|
||||
ImGui::SetColumnWidth(-1, ImGui::CalcTextSize("None").x * 1.6f + ImGui::GetStyle().FramePadding.x * 2.0f + ImGui::GetFrameHeight()
|
||||
+ ImGui::GetStyle().ItemInnerSpacing.x + ImGui::GetStyle().ItemSpacing.x);
|
||||
ImGui::NextColumn();
|
||||
ImGui::NextColumn();
|
||||
for (int i = 0; i < GamepadDevice::GetGamepadCount(); i++)
|
||||
{
|
||||
GamepadDevice *gamepad = GamepadDevice::GetGamepad(i);
|
||||
if (gamepad == NULL)
|
||||
continue;
|
||||
ImGui::Text("%s", gamepad->api_name());
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("%s", gamepad->name());
|
||||
ImGui::NextColumn();
|
||||
char port_name[32];
|
||||
sprintf(port_name, "##mapleport%d", i);
|
||||
ImGui::PushID(port_name);
|
||||
if (ImGui::BeginCombo(port_name, maple_ports[gamepad->maple_port() + 1]))
|
||||
{
|
||||
for (int j = -1; j < MAPLE_PORTS; j++)
|
||||
{
|
||||
bool is_selected = gamepad->maple_port() == j;
|
||||
if (ImGui::Selectable(maple_ports[j + 1], &is_selected))
|
||||
gamepad->set_maple_port(j);
|
||||
if (is_selected)
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
ImGui::NextColumn();
|
||||
if (ImGui::Button("Map"))
|
||||
ImGui::OpenPopup("Controller Mapping");
|
||||
|
||||
if (ImGui::BeginPopupModal("Controller Mapping", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove))
|
||||
{
|
||||
const float width = 350 * scaling;
|
||||
const float height = 450 * scaling;
|
||||
const float col0_width = ImGui::CalcTextSize("Right DPad Downxxx").x + ImGui::GetStyle().FramePadding.x * 2.0f + ImGui::GetStyle().ItemSpacing.x;
|
||||
const float col1_width = width
|
||||
- ImGui::GetStyle().GrabMinSize
|
||||
- (col0_width + ImGui::GetStyle().ItemSpacing.x)
|
||||
- (ImGui::CalcTextSize("Map").x + ImGui::GetStyle().FramePadding.x * 2.0f + ImGui::GetStyle().ItemSpacing.x);
|
||||
|
||||
if (ImGui::Button("Done", ImVec2(100 * scaling, 30 * scaling)))
|
||||
{
|
||||
ImGui::CloseCurrentPopup();
|
||||
gamepad->save_mapping();
|
||||
}
|
||||
ImGui::SetItemDefaultFocus();
|
||||
|
||||
char key_id[32];
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Text(" Buttons ");
|
||||
|
||||
ImGui::BeginChildFrame(ImGui::GetID("buttons"), ImVec2(width, height), ImGuiWindowFlags_None);
|
||||
ImGui::Columns(3, "bindings", false);
|
||||
ImGui::SetColumnWidth(0, col0_width);
|
||||
ImGui::SetColumnWidth(1, col1_width);
|
||||
for (int j = 0; j < ARRAY_SIZE(button_keys); j++)
|
||||
{
|
||||
sprintf(key_id, "key_id%d", j);
|
||||
ImGui::PushID(key_id);
|
||||
ImGui::Text("%s", button_names[j]);
|
||||
ImGui::NextColumn();
|
||||
u32 code = gamepad->get_input_mapping()->get_button_code(button_keys[j]);
|
||||
if (code != -1)
|
||||
ImGui::Text("%d", code);
|
||||
ImGui::NextColumn();
|
||||
if (ImGui::Button("Map"))
|
||||
{
|
||||
map_start_time = os_GetSeconds();
|
||||
ImGui::OpenPopup("Map Button");
|
||||
mapped_device = gamepad;
|
||||
mapped_code = -1;
|
||||
gamepad->detect_btn_input(&input_detected);
|
||||
}
|
||||
detect_input_popup(j, false);
|
||||
ImGui::NextColumn();
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::EndChildFrame();
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Text(" Analog Axes ");
|
||||
ImGui::BeginChildFrame(ImGui::GetID("analog"), ImVec2(width, height), ImGuiWindowFlags_None);
|
||||
ImGui::Columns(3, "bindings", false);
|
||||
ImGui::SetColumnWidth(0, col0_width);
|
||||
ImGui::SetColumnWidth(1, col1_width);
|
||||
|
||||
for (int j = 0; j < ARRAY_SIZE(axis_keys); j++)
|
||||
{
|
||||
sprintf(key_id, "axis_id%d", j);
|
||||
ImGui::PushID(key_id);
|
||||
ImGui::Text("%s", axis_names[j]);
|
||||
ImGui::NextColumn();
|
||||
u32 code = gamepad->get_input_mapping()->get_axis_code(axis_keys[j]);
|
||||
if (code != -1)
|
||||
ImGui::Text("%d", code);
|
||||
ImGui::NextColumn();
|
||||
if (ImGui::Button("Map"))
|
||||
{
|
||||
map_start_time = os_GetSeconds();
|
||||
ImGui::OpenPopup("Map Axis");
|
||||
mapped_device = gamepad;
|
||||
mapped_code = -1;
|
||||
gamepad->detect_axis_input(&input_detected);
|
||||
}
|
||||
detect_input_popup(j, true);
|
||||
ImGui::NextColumn();
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::EndChildFrame();
|
||||
ImGui::EndGroup();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
ImGui::NextColumn();
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
ImGui::Columns(1, NULL, false);
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::SliderInt("Mouse sensitivity", (int *)&settings.input.MouseSensitivity, 1, 500);
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
|
450
core/sdl/sdl.cpp
450
core/sdl/sdl.cpp
|
@ -1,3 +1,4 @@
|
|||
|
||||
#if defined(USE_SDL)
|
||||
#include <map>
|
||||
#include "types.h"
|
||||
|
@ -9,6 +10,8 @@
|
|||
#include "khronos/GL3/gl3w.h"
|
||||
#endif
|
||||
#endif
|
||||
#include "sdl_gamepad.h"
|
||||
#include "sdl_keyboard.h"
|
||||
|
||||
static SDL_Window* window = NULL;
|
||||
static SDL_GLContext glcontext;
|
||||
|
@ -20,11 +23,13 @@ static SDL_GLContext glcontext;
|
|||
#endif
|
||||
#define WINDOW_HEIGHT 480
|
||||
|
||||
static SDL_Joystick* JoySDL = 0;
|
||||
static SDLGamepadDevice* sdl_gamepads[4] = { NULL };
|
||||
static SDL_JoystickID joystick_ids[ARRAY_SIZE(sdl_gamepads)] = { 0 };
|
||||
static SDLMouseGamepadDevice* sdl_mouse_gamepad = NULL;
|
||||
static SDLKbGamepadDevice* sdl_kb_gamepad = NULL;
|
||||
static SDLKeyboardDevice* sdl_keyboard = NULL;
|
||||
|
||||
extern bool FrameSkipping;
|
||||
extern void dc_stop();
|
||||
extern bool KillTex;
|
||||
|
||||
#ifdef TARGET_PANDORA
|
||||
extern char OSD_Info[128];
|
||||
|
@ -33,169 +38,11 @@ extern bool KillTex;
|
|||
extern int OSD_Counter;
|
||||
#endif
|
||||
|
||||
#define SDL_MAP_SIZE 32
|
||||
|
||||
const u32 sdl_map_btn_usb[SDL_MAP_SIZE] =
|
||||
{ DC_BTN_Y, DC_BTN_B, DC_BTN_A, DC_BTN_X, 0, 0, 0, 0, 0, DC_BTN_START };
|
||||
|
||||
const u32 sdl_map_axis_usb[SDL_MAP_SIZE] =
|
||||
{ DC_AXIS_X, DC_AXIS_Y, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
const u32 sdl_map_btn_xbox360[SDL_MAP_SIZE] =
|
||||
{ DC_BTN_A, DC_BTN_B, DC_BTN_X, DC_BTN_Y, 0, 0, 0, DC_BTN_START, 0, 0 };
|
||||
|
||||
const u32 sdl_map_axis_xbox360[SDL_MAP_SIZE] =
|
||||
{ DC_AXIS_X, DC_AXIS_Y, DC_AXIS_LT, 0, 0, DC_AXIS_RT, DC_DPAD_LEFT, DC_DPAD_UP, 0, 0 };
|
||||
|
||||
const u32* sdl_map_btn = sdl_map_btn_usb;
|
||||
const u32* sdl_map_axis = sdl_map_axis_usb;
|
||||
|
||||
#ifdef TARGET_PANDORA
|
||||
u32 JSensitivity[256]; // To have less sensitive value on nubs
|
||||
#endif
|
||||
|
||||
static std::map<int, u8> kb_map;
|
||||
static u32 kb_used = 0;
|
||||
extern u8 kb_key[6]; // normal keys pressed
|
||||
extern u8 kb_shift; // shift keys pressed (bitmask)
|
||||
extern u32 mo_buttons;
|
||||
extern s32 mo_x_abs;
|
||||
extern s32 mo_y_abs;
|
||||
|
||||
static void init_kb_map()
|
||||
{
|
||||
//04-1D Letter keys A-Z (in alphabetic order)
|
||||
kb_map[SDLK_a] = 0x04;
|
||||
kb_map[SDLK_b] = 0x05;
|
||||
kb_map[SDLK_c] = 0x06;
|
||||
kb_map[SDLK_d] = 0x07;
|
||||
kb_map[SDLK_e] = 0x08;
|
||||
kb_map[SDLK_f] = 0x09;
|
||||
kb_map[SDLK_g] = 0x0A;
|
||||
kb_map[SDLK_h] = 0x0B;
|
||||
kb_map[SDLK_i] = 0x0C;
|
||||
kb_map[SDLK_j] = 0x0D;
|
||||
kb_map[SDLK_k] = 0x0E;
|
||||
kb_map[SDLK_l] = 0x0F;
|
||||
kb_map[SDLK_m] = 0x10;
|
||||
kb_map[SDLK_n] = 0x11;
|
||||
kb_map[SDLK_o] = 0x12;
|
||||
kb_map[SDLK_p] = 0x13;
|
||||
kb_map[SDLK_q] = 0x14;
|
||||
kb_map[SDLK_r] = 0x15;
|
||||
kb_map[SDLK_s] = 0x16;
|
||||
kb_map[SDLK_t] = 0x17;
|
||||
kb_map[SDLK_u] = 0x18;
|
||||
kb_map[SDLK_v] = 0x19;
|
||||
kb_map[SDLK_w] = 0x1A;
|
||||
kb_map[SDLK_x] = 0x1B;
|
||||
kb_map[SDLK_y] = 0x1C;
|
||||
kb_map[SDLK_z] = 0x1D;
|
||||
|
||||
//1E-27 Number keys 1-0
|
||||
kb_map[SDLK_1] = 0x1E;
|
||||
kb_map[SDLK_2] = 0x1F;
|
||||
kb_map[SDLK_3] = 0x20;
|
||||
kb_map[SDLK_4] = 0x21;
|
||||
kb_map[SDLK_5] = 0x22;
|
||||
kb_map[SDLK_6] = 0x23;
|
||||
kb_map[SDLK_7] = 0x24;
|
||||
kb_map[SDLK_8] = 0x25;
|
||||
kb_map[SDLK_9] = 0x26;
|
||||
kb_map[SDLK_0] = 0x27;
|
||||
|
||||
kb_map[SDLK_RETURN] = 0x28;
|
||||
kb_map[SDLK_ESCAPE] = 0x29;
|
||||
kb_map[SDLK_BACKSPACE] = 0x2A;
|
||||
kb_map[SDLK_TAB] = 0x2B;
|
||||
kb_map[SDLK_SPACE] = 0x2C;
|
||||
|
||||
kb_map[SDLK_MINUS] = 0x2D; // -
|
||||
kb_map[SDLK_EQUALS] = 0x2E; // =
|
||||
kb_map[SDLK_LEFTBRACKET] = 0x2F; // [
|
||||
kb_map[SDLK_RIGHTBRACKET] = 0x30; // ]
|
||||
|
||||
kb_map[SDLK_BACKSLASH] = 0x31; // \ (US) unsure of keycode
|
||||
|
||||
//32-34 "]", ";" and ":" (the 3 keys right of L)
|
||||
kb_map[SDLK_ASTERISK] = 0x32; // ~ (non-US) *,µ in FR layout
|
||||
kb_map[SDLK_SEMICOLON] = 0x33; // ;
|
||||
kb_map[SDLK_QUOTE] = 0x34; // '
|
||||
|
||||
//35 hankaku/zenkaku / kanji (top left)
|
||||
kb_map[SDLK_BACKQUOTE] = 0x35; // `~ (US)
|
||||
|
||||
//36-38 ",", "." and "/" (the 3 keys right of M)
|
||||
kb_map[SDLK_COMMA] = 0x36;
|
||||
kb_map[SDLK_PERIOD] = 0x37;
|
||||
kb_map[SDLK_SLASH] = 0x38;
|
||||
|
||||
// CAPSLOCK
|
||||
kb_map[SDLK_CAPSLOCK] = 0x39;
|
||||
|
||||
//3A-45 Function keys F1-F12
|
||||
for (int i = 0;i < 10; i++)
|
||||
kb_map[SDLK_F1 + i] = 0x3A + i;
|
||||
kb_map[SDLK_F11] = 0x44;
|
||||
kb_map[SDLK_F12] = 0x45;
|
||||
|
||||
//46-4E Control keys above cursor keys
|
||||
kb_map[SDLK_PRINTSCREEN] = 0x46; // Print Screen
|
||||
kb_map[SDLK_SCROLLLOCK] = 0x47; // Scroll Lock
|
||||
kb_map[SDLK_PAUSE] = 0x48; // Pause
|
||||
kb_map[SDLK_INSERT] = 0x49;
|
||||
kb_map[SDLK_HOME] = 0x4A;
|
||||
kb_map[SDLK_PAGEUP] = 0x4B;
|
||||
kb_map[SDLK_DELETE] = 0x4C;
|
||||
kb_map[SDLK_END] = 0x4D;
|
||||
kb_map[SDLK_PAGEDOWN] = 0x4E;
|
||||
|
||||
//4F-52 Cursor keys
|
||||
kb_map[SDLK_RIGHT] = 0x4F;
|
||||
kb_map[SDLK_LEFT] = 0x50;
|
||||
kb_map[SDLK_DOWN] = 0x51;
|
||||
kb_map[SDLK_UP] = 0x52;
|
||||
|
||||
//53 Num Lock (Numeric keypad)
|
||||
kb_map[SDLK_NUMLOCKCLEAR] = 0x53;
|
||||
//54 "/" (Numeric keypad)
|
||||
kb_map[SDLK_KP_DIVIDE] = 0x54;
|
||||
//55 "*" (Numeric keypad)
|
||||
kb_map[SDLK_KP_MULTIPLY] = 0x55;
|
||||
//56 "-" (Numeric keypad)
|
||||
kb_map[SDLK_KP_MINUS] = 0x56;
|
||||
//57 "+" (Numeric keypad)
|
||||
kb_map[SDLK_KP_PLUS] = 0x57;
|
||||
//58 Enter (Numeric keypad)
|
||||
kb_map[SDLK_KP_ENTER] = 0x58;
|
||||
//59-62 Number keys 1-0 (Numeric keypad)
|
||||
kb_map[SDLK_KP_1] = 0x59;
|
||||
kb_map[SDLK_KP_2] = 0x5A;
|
||||
kb_map[SDLK_KP_3] = 0x5B;
|
||||
kb_map[SDLK_KP_4] = 0x5C;
|
||||
kb_map[SDLK_KP_5] = 0x5D;
|
||||
kb_map[SDLK_KP_6] = 0x5E;
|
||||
kb_map[SDLK_KP_7] = 0x5F;
|
||||
kb_map[SDLK_KP_8] = 0x60;
|
||||
kb_map[SDLK_KP_9] = 0x61;
|
||||
kb_map[SDLK_KP_0] = 0x62;
|
||||
//63 "." (Numeric keypad)
|
||||
kb_map[SDLK_KP_PERIOD] = 0x63;
|
||||
//64 #| (non-US)
|
||||
//kb_map[94] = 0x64;
|
||||
//65 S3 key
|
||||
//66-A4 Not used
|
||||
//A5-DF Reserved
|
||||
//E0 Left Control
|
||||
//E1 Left Shift
|
||||
//E2 Left Alt
|
||||
//E3 Left S1
|
||||
//E4 Right Control
|
||||
//E5 Right Shift
|
||||
//E6 Right Alt
|
||||
//E7 Right S3
|
||||
//E8-FF Reserved
|
||||
}
|
||||
extern int screen_width, screen_height;
|
||||
|
||||
void input_sdl_init()
|
||||
{
|
||||
|
@ -209,60 +56,24 @@ void input_sdl_init()
|
|||
// Open joystick device
|
||||
int numjoys = SDL_NumJoysticks();
|
||||
printf("Number of Joysticks found = %i\n", numjoys);
|
||||
if (numjoys > 0)
|
||||
for (int i = 0; i < numjoys && i < ARRAY_SIZE(sdl_gamepads); i++)
|
||||
{
|
||||
JoySDL = SDL_JoystickOpen(0);
|
||||
}
|
||||
SDL_Joystick *pJoystick = SDL_JoystickOpen(i);
|
||||
|
||||
printf("Joystick opened\n");
|
||||
|
||||
if (JoySDL)
|
||||
{
|
||||
int AxisCount,ButtonCount;
|
||||
const char* Name;
|
||||
|
||||
AxisCount = 0;
|
||||
ButtonCount = 0;
|
||||
//Name[0] = '\0';
|
||||
|
||||
AxisCount = SDL_JoystickNumAxes(JoySDL);
|
||||
ButtonCount = SDL_JoystickNumButtons(JoySDL);
|
||||
Name = SDL_JoystickName(JoySDL);
|
||||
|
||||
printf("SDK: Found '%s' joystick with %d axes and %d buttons\n", Name, AxisCount, ButtonCount);
|
||||
|
||||
if (Name != NULL && strcmp(Name,"Microsoft X-Box 360 pad")==0)
|
||||
if (pJoystick == NULL)
|
||||
{
|
||||
sdl_map_btn = sdl_map_btn_xbox360;
|
||||
sdl_map_axis = sdl_map_axis_xbox360;
|
||||
printf("Using Xbox 360 map\n");
|
||||
printf("Cannot open joystick %d\n", i + 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("SDK: No Joystick Found\n");
|
||||
}
|
||||
|
||||
#ifdef TARGET_PANDORA
|
||||
float v;
|
||||
int j;
|
||||
for (int i=0; i<128; i++)
|
||||
{
|
||||
v = ((float)i)/127.0f;
|
||||
v = (v+v*v)/2.0f;
|
||||
j = (int)(v*127.0f);
|
||||
if (j > 127)
|
||||
{
|
||||
j = 127;
|
||||
}
|
||||
JSensitivity[128-i] = -j;
|
||||
JSensitivity[128+i] = j;
|
||||
}
|
||||
#endif
|
||||
joystick_ids[i] = SDL_JoystickInstanceID(pJoystick);
|
||||
|
||||
sdl_gamepads[i] = new SDLGamepadDevice(i, pJoystick);
|
||||
}
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
|
||||
init_kb_map();
|
||||
sdl_keyboard = new SDLKeyboardDevice(0); // FIXME ports!
|
||||
sdl_kb_gamepad = new SDLKbGamepadDevice(0);
|
||||
sdl_mouse_gamepad = new SDLMouseGamepadDevice(0);
|
||||
}
|
||||
|
||||
static void set_mouse_position(int x, int y)
|
||||
|
@ -281,7 +92,6 @@ void input_sdl_handle(u32 port)
|
|||
{
|
||||
#define SET_FLAG(field, mask, expr) field =((expr) ? (field & ~mask) : (field | mask))
|
||||
SDL_Event event;
|
||||
int k, value;
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
switch (event.type)
|
||||
|
@ -291,204 +101,32 @@ void input_sdl_handle(u32 port)
|
|||
break;
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
k = event.key.keysym.sym;
|
||||
value = (event.type == SDL_KEYDOWN) ? 1 : 0;
|
||||
switch (k) {
|
||||
case SDLK_SPACE:
|
||||
SET_FLAG(kcode[port], DC_BTN_C, value);
|
||||
break;
|
||||
case SDLK_UP:
|
||||
SET_FLAG(kcode[port], DC_DPAD_UP, value);
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
SET_FLAG(kcode[port], DC_DPAD_DOWN, value);
|
||||
break;
|
||||
case SDLK_LEFT:
|
||||
SET_FLAG(kcode[port], DC_DPAD_LEFT, value);
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
SET_FLAG(kcode[port], DC_DPAD_RIGHT, value);
|
||||
break;
|
||||
case SDLK_d:
|
||||
SET_FLAG(kcode[port], DC_BTN_Y, value);
|
||||
break;
|
||||
case SDLK_x:
|
||||
SET_FLAG(kcode[port], DC_BTN_A, value);
|
||||
break;
|
||||
case SDLK_c:
|
||||
SET_FLAG(kcode[port], DC_BTN_B, value);
|
||||
break;
|
||||
case SDLK_s:
|
||||
SET_FLAG(kcode[port], DC_BTN_X, value);
|
||||
break;
|
||||
case SDLK_MENU:
|
||||
case SDLK_TAB:
|
||||
gui_open_settings();
|
||||
break;
|
||||
case SDLK_f:
|
||||
lt[port] = (value ? 255 : 0);
|
||||
break;
|
||||
case SDLK_v:
|
||||
rt[port] = (value ? 255 : 0);;
|
||||
break;
|
||||
case SDLK_RETURN:
|
||||
SET_FLAG(kcode[port], DC_BTN_START, value);
|
||||
break;
|
||||
|
||||
#if defined(TARGET_PANDORA)
|
||||
case SDLK_s:
|
||||
if (value)
|
||||
{
|
||||
settings.aica.NoSound = !settings.aica.NoSound;
|
||||
snprintf(OSD_Info, 128, "Sound %s\n", (settings.aica.NoSound) ? "Off" : "On");
|
||||
OSD_Delay=300;
|
||||
}
|
||||
break;
|
||||
case SDLK_f:
|
||||
if (value)
|
||||
{
|
||||
FrameSkipping = !FrameSkipping;
|
||||
snprintf(OSD_Info, 128, "FrameSkipping %s\n", (FrameSkipping) ? "On" : "Off");
|
||||
OSD_Delay = 300;
|
||||
}
|
||||
break;
|
||||
case SDLK_c:
|
||||
if (value)
|
||||
{
|
||||
OSD_Counter = 1 - OSD_Counter;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
sdl_kb_gamepad->gamepad_btn_input(event.key.keysym.sym, event.type == SDL_KEYDOWN);
|
||||
{
|
||||
auto it = kb_map.find(k);
|
||||
if (it != kb_map.end())
|
||||
{
|
||||
u8 dc_keycode = it->second;
|
||||
if (event.type == SDL_KEYDOWN)
|
||||
{
|
||||
if (kb_used < ARRAY_SIZE(kb_key))
|
||||
{
|
||||
bool found = false;
|
||||
for (int i = 0; !found && i < kb_used; i++)
|
||||
{
|
||||
if (kb_key[i] == dc_keycode)
|
||||
found = true;
|
||||
}
|
||||
if (!found)
|
||||
kb_key[kb_used++] = dc_keycode;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < kb_used; i++)
|
||||
{
|
||||
if (kb_key[i] == dc_keycode)
|
||||
{
|
||||
kb_used--;
|
||||
for (int j = i; j < ARRAY_SIZE(kb_key) - 1; j++)
|
||||
kb_key[j] = kb_key[j + 1];
|
||||
kb_key[ARRAY_SIZE(kb_key) - 1] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (event.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT))
|
||||
SET_FLAG(kb_shift, (0x02 | 0x20), event.type == SDL_KEYUP);
|
||||
if (event.key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL))
|
||||
SET_FLAG(kb_shift, (0x01 | 0x10), event.type == SDL_KEYUP);
|
||||
}
|
||||
int modifier_keys = 0;
|
||||
if (event.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT))
|
||||
SET_FLAG(modifier_keys, (0x02 | 0x20), event.type == SDL_KEYUP);
|
||||
if (event.key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL))
|
||||
SET_FLAG(modifier_keys, (0x01 | 0x10), event.type == SDL_KEYUP);
|
||||
sdl_keyboard->keyboard_input(event.key.keysym.sym, event.type == SDL_KEYDOWN, modifier_keys);
|
||||
}
|
||||
break;
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
case SDL_JOYBUTTONUP:
|
||||
value = (event.type == SDL_JOYBUTTONDOWN) ? 1 : 0;
|
||||
k = event.jbutton.button;
|
||||
{
|
||||
u32 mt = sdl_map_btn[k] >> 16;
|
||||
u32 mo = sdl_map_btn[k] & 0xFFFF;
|
||||
|
||||
// printf("BUTTON %d,%d\n",JE.number,JE.value);
|
||||
|
||||
if (mt == 0)
|
||||
for (int i = 0; i < ARRAY_SIZE(sdl_gamepads); i++)
|
||||
if (joystick_ids[i] == event.jbutton.which)
|
||||
{
|
||||
// printf("Mapped to %d\n",mo);
|
||||
if (value)
|
||||
kcode[port] &= ~mo;
|
||||
else
|
||||
kcode[port] |= mo;
|
||||
sdl_gamepads[i]->gamepad_btn_input(event.jbutton.button, event.type == SDL_JOYBUTTONDOWN);
|
||||
break;
|
||||
}
|
||||
else if (mt == 1)
|
||||
{
|
||||
// printf("Mapped to %d %d\n",mo,JE.value?255:0);
|
||||
if (mo == 0)
|
||||
{
|
||||
lt[port] = value ? 255 : 0;
|
||||
}
|
||||
else if (mo == 1)
|
||||
{
|
||||
rt[port] = value ? 255 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case SDL_JOYAXISMOTION:
|
||||
k = event.jaxis.axis;
|
||||
value = event.jaxis.value;
|
||||
{
|
||||
u32 mt = sdl_map_axis[k] >> 16;
|
||||
u32 mo = sdl_map_axis[k] & 0xFFFF;
|
||||
|
||||
//printf("AXIS %d,%d\n",JE.number,JE.value);
|
||||
s8 v=(s8)(value/256); //-127 ... + 127 range
|
||||
#ifdef TARGET_PANDORA
|
||||
v = JSensitivity[128+v];
|
||||
#endif
|
||||
|
||||
if (mt == 0)
|
||||
for (int i = 0; i < ARRAY_SIZE(sdl_gamepads); i++)
|
||||
if (joystick_ids[i] == event.jaxis.which)
|
||||
{
|
||||
kcode[port] |= mo;
|
||||
kcode[port] |= mo*2;
|
||||
if (v < -64)
|
||||
{
|
||||
kcode[port] &= ~mo;
|
||||
}
|
||||
else if (v > 64)
|
||||
{
|
||||
kcode[port] &= ~(mo*2);
|
||||
}
|
||||
|
||||
// printf("Mapped to %d %d %d\n",mo,kcode[port]&mo,kcode[port]&(mo*2));
|
||||
sdl_gamepads[i]->gamepad_axis_input(event.jaxis.axis, event.jaxis.value);
|
||||
break;
|
||||
}
|
||||
else if (mt == 1)
|
||||
{
|
||||
if (v >= 0) v++; //up to 255
|
||||
|
||||
// printf("AXIS %d,%d Mapped to %d %d %d\n",JE.number,JE.value,mo,v,v+127);
|
||||
|
||||
if (mo == 0)
|
||||
{
|
||||
lt[port] = v + 127;
|
||||
}
|
||||
else if (mo == 1)
|
||||
{
|
||||
rt[port] = v + 127;
|
||||
}
|
||||
}
|
||||
else if (mt == 2)
|
||||
{
|
||||
// printf("AXIS %d,%d Mapped to %d %d [%d]",JE.number,JE.value,mo,v);
|
||||
if (mo == 0)
|
||||
{
|
||||
joyx[port] = v;
|
||||
}
|
||||
else if (mo==1)
|
||||
{
|
||||
joyy[port] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SDL_MOUSEMOTION:
|
||||
|
@ -513,6 +151,7 @@ void input_sdl_handle(u32 port)
|
|||
SET_FLAG(mo_buttons, 1 << 3, event.button.state == SDL_PRESSED);
|
||||
break;
|
||||
}
|
||||
sdl_mouse_gamepad->gamepad_btn_input(event.button.button, event.button.state == SDL_PRESSED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -581,11 +220,15 @@ void sdl_window_create()
|
|||
}
|
||||
SDL_GL_MakeCurrent(window, NULL);
|
||||
|
||||
SDL_GL_GetDrawableSize(window, &screen_width, &screen_height);
|
||||
|
||||
float ddpi, hdpi, vdpi;
|
||||
if (!SDL_GetDisplayDPI(SDL_GetWindowDisplayIndex(window), &ddpi, &hdpi, &vdpi))
|
||||
screen_dpi = (int)roundf(max(hdpi, vdpi));
|
||||
|
||||
printf("Created SDL Window (%ix%i) and GL Context successfully\n", window_width, window_height);
|
||||
}
|
||||
|
||||
extern int screen_width, screen_height;
|
||||
|
||||
bool gl_init(void* wind, void* disp)
|
||||
{
|
||||
SDL_GL_MakeCurrent(window, glcontext);
|
||||
|
@ -601,14 +244,7 @@ void gl_swap()
|
|||
SDL_GL_SwapWindow(window);
|
||||
|
||||
/* Check if drawable has been resized */
|
||||
int new_width, new_height;
|
||||
SDL_GL_GetDrawableSize(window, &new_width, &new_height);
|
||||
|
||||
if (new_width != screen_width || new_height != screen_height)
|
||||
{
|
||||
screen_width = new_width;
|
||||
screen_height = new_height;
|
||||
}
|
||||
SDL_GL_GetDrawableSize(window, &screen_width, &screen_height);
|
||||
}
|
||||
|
||||
void gl_term()
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include <SDL2/SDL.h>
|
||||
#include "types.h"
|
||||
|
||||
extern void input_sdl_init();
|
||||
extern void input_sdl_handle(u32 port);
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
#include "../input/gamepad_device.h"
|
||||
#include "sdl.h"
|
||||
|
||||
class DefaultInputMapping : public InputMapping
|
||||
{
|
||||
public:
|
||||
DefaultInputMapping()
|
||||
{
|
||||
name = "Default";
|
||||
set_button(DC_BTN_Y, 0);
|
||||
set_button(DC_BTN_B, 1);
|
||||
set_button(DC_BTN_A, 2);
|
||||
set_button(DC_BTN_X, 3);
|
||||
set_button(DC_BTN_START, 9);
|
||||
|
||||
set_axis(DC_AXIS_X, 0, false);
|
||||
set_axis(DC_AXIS_Y, 1, false);
|
||||
dirty = false;
|
||||
}
|
||||
};
|
||||
|
||||
class Xbox360InputMapping : public InputMapping
|
||||
{
|
||||
public:
|
||||
Xbox360InputMapping()
|
||||
{
|
||||
name = "Xbox 360";
|
||||
set_button(DC_BTN_A, 0);
|
||||
set_button(DC_BTN_B, 1);
|
||||
set_button(DC_BTN_X, 2);
|
||||
set_button(DC_BTN_Y, 3);
|
||||
set_button(DC_BTN_START, 7);
|
||||
|
||||
set_axis(DC_AXIS_X, 0, false);
|
||||
set_axis(DC_AXIS_Y, 1, false);
|
||||
set_axis(DC_AXIS_LT, 2, false);
|
||||
set_axis(DC_AXIS_RT, 5, false);
|
||||
set_axis(DC_DPAD_LEFT, 6, false);
|
||||
set_axis(DC_DPAD_UP, 7, false);
|
||||
dirty = false;
|
||||
}
|
||||
};
|
||||
|
||||
class SDLGamepadDevice : public GamepadDevice
|
||||
{
|
||||
public:
|
||||
SDLGamepadDevice(int maple_port, SDL_Joystick* sdl_joystick) : GamepadDevice(maple_port), sdl_joystick(sdl_joystick)
|
||||
{
|
||||
_name = SDL_JoystickName(sdl_joystick);
|
||||
if (!find_mapping())
|
||||
{
|
||||
if (_name == "Microsoft X-Box 360 pad")
|
||||
{
|
||||
input_mapper = new Xbox360InputMapping();
|
||||
printf("Using Xbox 360 mapping\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
input_mapper = new DefaultInputMapping();
|
||||
printf("Using default mapping\n");
|
||||
}
|
||||
save_mapping();
|
||||
}
|
||||
}
|
||||
virtual const char* api_name() override { return "SDL"; }
|
||||
virtual const char* name() override { return _name.c_str(); }
|
||||
virtual ~SDLGamepadDevice() override
|
||||
{
|
||||
SDL_JoystickClose(sdl_joystick);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void load_axis_min_max(u32 axis) override
|
||||
{
|
||||
axis_min_values[axis] = -32768;
|
||||
axis_ranges[axis] = 65535;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _name;
|
||||
SDL_Joystick* sdl_joystick;
|
||||
};
|
||||
|
||||
class KbInputMapping : public InputMapping
|
||||
{
|
||||
public:
|
||||
KbInputMapping()
|
||||
{
|
||||
name = "SDL Keyboard";
|
||||
set_button(DC_BTN_A, SDLK_x);
|
||||
set_button(DC_BTN_B, SDLK_c);
|
||||
set_button(DC_BTN_X, SDLK_s);
|
||||
set_button(DC_BTN_Y, SDLK_d);
|
||||
set_button(DC_DPAD_UP, SDLK_UP);
|
||||
set_button(DC_DPAD_DOWN, SDLK_DOWN);
|
||||
set_button(DC_DPAD_LEFT, SDLK_LEFT);
|
||||
set_button(DC_DPAD_RIGHT, SDLK_RIGHT);
|
||||
set_button(DC_BTN_START, SDLK_RETURN);
|
||||
set_button(EMU_BTN_TRIGGER_LEFT, SDLK_f);
|
||||
set_button(EMU_BTN_TRIGGER_RIGHT, SDLK_v);
|
||||
set_button(EMU_BTN_MENU, SDLK_TAB);
|
||||
|
||||
dirty = false;
|
||||
}
|
||||
};
|
||||
|
||||
class SDLKbGamepadDevice : public GamepadDevice
|
||||
{
|
||||
public:
|
||||
SDLKbGamepadDevice(int maple_port) : GamepadDevice(maple_port)
|
||||
{
|
||||
if (!find_mapping())
|
||||
input_mapper = new KbInputMapping();
|
||||
}
|
||||
virtual const char* api_name() override { return "SDL"; }
|
||||
virtual const char* name() override { return "Keyboard"; }
|
||||
virtual ~SDLKbGamepadDevice() {}
|
||||
};
|
||||
|
||||
class MouseInputMapping : public InputMapping
|
||||
{
|
||||
public:
|
||||
MouseInputMapping()
|
||||
{
|
||||
name = "SDL Mouse";
|
||||
set_button(DC_BTN_A, SDL_BUTTON_LEFT);
|
||||
set_button(DC_BTN_B, SDL_BUTTON_RIGHT);
|
||||
set_button(DC_BTN_START, SDL_BUTTON_MIDDLE);
|
||||
|
||||
dirty = false;
|
||||
}
|
||||
};
|
||||
|
||||
class SDLMouseGamepadDevice : public GamepadDevice
|
||||
{
|
||||
public:
|
||||
SDLMouseGamepadDevice(int maple_port) : GamepadDevice(maple_port)
|
||||
{
|
||||
if (!find_mapping())
|
||||
input_mapper = new MouseInputMapping();
|
||||
}
|
||||
virtual const char* api_name() override { return "SDL"; }
|
||||
virtual const char* name() override { return "Mouse"; }
|
||||
virtual ~SDLMouseGamepadDevice() {}
|
||||
};
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
#pragma once
|
||||
#include "input/keyboard_device.h"
|
||||
#include "sdl.h"
|
||||
|
||||
class SDLKeyboardDevice : public KeyboardDevice<SDL_Keycode>
|
||||
{
|
||||
public:
|
||||
SDLKeyboardDevice(int maple_port) : KeyboardDevice(maple_port)
|
||||
{
|
||||
//04-1D Letter keys A-Z (in alphabetic order)
|
||||
kb_map[SDLK_a] = 0x04;
|
||||
kb_map[SDLK_b] = 0x05;
|
||||
kb_map[SDLK_c] = 0x06;
|
||||
kb_map[SDLK_d] = 0x07;
|
||||
kb_map[SDLK_e] = 0x08;
|
||||
kb_map[SDLK_f] = 0x09;
|
||||
kb_map[SDLK_g] = 0x0A;
|
||||
kb_map[SDLK_h] = 0x0B;
|
||||
kb_map[SDLK_i] = 0x0C;
|
||||
kb_map[SDLK_j] = 0x0D;
|
||||
kb_map[SDLK_k] = 0x0E;
|
||||
kb_map[SDLK_l] = 0x0F;
|
||||
kb_map[SDLK_m] = 0x10;
|
||||
kb_map[SDLK_n] = 0x11;
|
||||
kb_map[SDLK_o] = 0x12;
|
||||
kb_map[SDLK_p] = 0x13;
|
||||
kb_map[SDLK_q] = 0x14;
|
||||
kb_map[SDLK_r] = 0x15;
|
||||
kb_map[SDLK_s] = 0x16;
|
||||
kb_map[SDLK_t] = 0x17;
|
||||
kb_map[SDLK_u] = 0x18;
|
||||
kb_map[SDLK_v] = 0x19;
|
||||
kb_map[SDLK_w] = 0x1A;
|
||||
kb_map[SDLK_x] = 0x1B;
|
||||
kb_map[SDLK_y] = 0x1C;
|
||||
kb_map[SDLK_z] = 0x1D;
|
||||
|
||||
//1E-27 Number keys 1-0
|
||||
kb_map[SDLK_1] = 0x1E;
|
||||
kb_map[SDLK_2] = 0x1F;
|
||||
kb_map[SDLK_3] = 0x20;
|
||||
kb_map[SDLK_4] = 0x21;
|
||||
kb_map[SDLK_5] = 0x22;
|
||||
kb_map[SDLK_6] = 0x23;
|
||||
kb_map[SDLK_7] = 0x24;
|
||||
kb_map[SDLK_8] = 0x25;
|
||||
kb_map[SDLK_9] = 0x26;
|
||||
kb_map[SDLK_0] = 0x27;
|
||||
|
||||
kb_map[SDLK_RETURN] = 0x28;
|
||||
kb_map[SDLK_ESCAPE] = 0x29;
|
||||
kb_map[SDLK_BACKSPACE] = 0x2A;
|
||||
kb_map[SDLK_TAB] = 0x2B;
|
||||
kb_map[SDLK_SPACE] = 0x2C;
|
||||
|
||||
kb_map[SDLK_MINUS] = 0x2D; // -
|
||||
kb_map[SDLK_EQUALS] = 0x2E; // =
|
||||
kb_map[SDLK_LEFTBRACKET] = 0x2F; // [
|
||||
kb_map[SDLK_RIGHTBRACKET] = 0x30; // ]
|
||||
|
||||
kb_map[SDLK_BACKSLASH] = 0x31; // \ (US) unsure of keycode
|
||||
|
||||
//32-34 "]", ";" and ":" (the 3 keys right of L)
|
||||
kb_map[SDLK_ASTERISK] = 0x32; // ~ (non-US) *,µ in FR layout
|
||||
kb_map[SDLK_SEMICOLON] = 0x33; // ;
|
||||
kb_map[SDLK_QUOTE] = 0x34; // '
|
||||
|
||||
//35 hankaku/zenkaku / kanji (top left)
|
||||
kb_map[SDLK_BACKQUOTE] = 0x35; // `~ (US)
|
||||
|
||||
//36-38 ",", "." and "/" (the 3 keys right of M)
|
||||
kb_map[SDLK_COMMA] = 0x36;
|
||||
kb_map[SDLK_PERIOD] = 0x37;
|
||||
kb_map[SDLK_SLASH] = 0x38;
|
||||
|
||||
// CAPSLOCK
|
||||
kb_map[SDLK_CAPSLOCK] = 0x39;
|
||||
|
||||
//3A-45 Function keys F1-F12
|
||||
for (int i = 0;i < 10; i++)
|
||||
kb_map[SDLK_F1 + i] = 0x3A + i;
|
||||
kb_map[SDLK_F11] = 0x44;
|
||||
kb_map[SDLK_F12] = 0x45;
|
||||
|
||||
//46-4E Control keys above cursor keys
|
||||
kb_map[SDLK_PRINTSCREEN] = 0x46; // Print Screen
|
||||
kb_map[SDLK_SCROLLLOCK] = 0x47; // Scroll Lock
|
||||
kb_map[SDLK_PAUSE] = 0x48; // Pause
|
||||
kb_map[SDLK_INSERT] = 0x49;
|
||||
kb_map[SDLK_HOME] = 0x4A;
|
||||
kb_map[SDLK_PAGEUP] = 0x4B;
|
||||
kb_map[SDLK_DELETE] = 0x4C;
|
||||
kb_map[SDLK_END] = 0x4D;
|
||||
kb_map[SDLK_PAGEDOWN] = 0x4E;
|
||||
|
||||
//4F-52 Cursor keys
|
||||
kb_map[SDLK_RIGHT] = 0x4F;
|
||||
kb_map[SDLK_LEFT] = 0x50;
|
||||
kb_map[SDLK_DOWN] = 0x51;
|
||||
kb_map[SDLK_UP] = 0x52;
|
||||
|
||||
//53 Num Lock (Numeric keypad)
|
||||
kb_map[SDLK_NUMLOCKCLEAR] = 0x53;
|
||||
//54 "/" (Numeric keypad)
|
||||
kb_map[SDLK_KP_DIVIDE] = 0x54;
|
||||
//55 "*" (Numeric keypad)
|
||||
kb_map[SDLK_KP_MULTIPLY] = 0x55;
|
||||
//56 "-" (Numeric keypad)
|
||||
kb_map[SDLK_KP_MINUS] = 0x56;
|
||||
//57 "+" (Numeric keypad)
|
||||
kb_map[SDLK_KP_PLUS] = 0x57;
|
||||
//58 Enter (Numeric keypad)
|
||||
kb_map[SDLK_KP_ENTER] = 0x58;
|
||||
//59-62 Number keys 1-0 (Numeric keypad)
|
||||
kb_map[SDLK_KP_1] = 0x59;
|
||||
kb_map[SDLK_KP_2] = 0x5A;
|
||||
kb_map[SDLK_KP_3] = 0x5B;
|
||||
kb_map[SDLK_KP_4] = 0x5C;
|
||||
kb_map[SDLK_KP_5] = 0x5D;
|
||||
kb_map[SDLK_KP_6] = 0x5E;
|
||||
kb_map[SDLK_KP_7] = 0x5F;
|
||||
kb_map[SDLK_KP_8] = 0x60;
|
||||
kb_map[SDLK_KP_9] = 0x61;
|
||||
kb_map[SDLK_KP_0] = 0x62;
|
||||
//63 "." (Numeric keypad)
|
||||
kb_map[SDLK_KP_PERIOD] = 0x63;
|
||||
//64 #| (non-US)
|
||||
//kb_map[94] = 0x64;
|
||||
//65 S3 key
|
||||
//66-A4 Not used
|
||||
//A5-DF Reserved
|
||||
//E0 Left Control
|
||||
//E1 Left Shift
|
||||
//E2 Left Alt
|
||||
//E3 Left S1
|
||||
//E4 Right Control
|
||||
//E5 Right Shift
|
||||
//E6 Right Alt
|
||||
//E7 Right S3
|
||||
//E8-FF Reserved
|
||||
}
|
||||
virtual ~SDLKeyboardDevice() {}
|
||||
virtual const char* name() override { return "SDL Keyboard"; }
|
||||
|
||||
protected:
|
||||
virtual u8 convert_keycode(SDL_Keycode keycode) override
|
||||
{
|
||||
return kb_map[keycode];
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<SDL_Keycode, u8> kb_map;
|
||||
};
|
|
@ -846,6 +846,8 @@ struct settings_t
|
|||
u32 MouseSensitivity;
|
||||
u32 JammaSetup; // 0: standard, 1: 4-players, 2: rotary encoders, 3: Sega Marine Fishing,
|
||||
// 4: dual I/O boards (4P), 5: Namco JYU board (Ninja Assault)
|
||||
int maple_devices[4];
|
||||
int maple_expansion_devices[4][2];
|
||||
} input;
|
||||
};
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ void os_SetupInput()
|
|||
{
|
||||
init_kb_map();
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
mcfg_CreateDevicesFromConfig();
|
||||
mcfg_CreateDevices();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -105,7 +105,6 @@ int dc_init();
|
|||
void dc_run();
|
||||
void dc_pause();
|
||||
void dc_term();
|
||||
void mcfg_Create(MapleDeviceType type,u32 bus,u32 port);
|
||||
|
||||
bool VramLockedWrite(u8* address);
|
||||
|
||||
|
@ -214,16 +213,23 @@ void os_SetupInput()
|
|||
{
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
// Create first controller
|
||||
mcfg_CreateController(0, MDT_SegaVMU, GetMapleDeviceType(controller_periphs[0][1]));
|
||||
settings.input.maple_devices[0] = MDT_SegaController;
|
||||
settings.input.maple_expansion_devices[0][0] = MDT_SegaVMU;
|
||||
settings.input.maple_expansion_devices[0][1] = GetMapleDeviceType(controller_periphs[0][1]);
|
||||
|
||||
// Add additonal controllers
|
||||
for (int i = 0; i < 3; i++)
|
||||
// Add additional controllers
|
||||
for (int i = 1; i < 4; i++)
|
||||
{
|
||||
if (add_controllers[i])
|
||||
mcfg_CreateController(i + 1,
|
||||
GetMapleDeviceType(controller_periphs[i + 1][0]),
|
||||
GetMapleDeviceType(controller_periphs[i + 1][1]));
|
||||
if (add_controllers[i - 1])
|
||||
{
|
||||
settings.input.maple_devices[i] = MDT_SegaController;
|
||||
settings.input.maple_expansion_devices[i][0] = GetMapleDeviceType(controller_periphs[i][0]);
|
||||
settings.input.maple_expansion_devices[i][1] = GetMapleDeviceType(controller_periphs[i][1]);
|
||||
}
|
||||
else
|
||||
settings.input.maple_devices[i] = MDT_None;
|
||||
}
|
||||
mcfg_CreateDevices();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -450,6 +456,7 @@ JNIEXPORT jint JNICALL Java_com_reicast_emulator_emu_JNIdc_send(JNIEnv *env,jobj
|
|||
else if (cmd==2)
|
||||
{
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_com_reicast_emulator_emu_JNIdc_data(JNIEnv *env, jobject obj, jint id, jbyteArray d)
|
||||
|
@ -654,4 +661,4 @@ void SaveSettings()
|
|||
|
||||
if (detach_thread)
|
||||
g_jvm->DetachCurrentThread();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ void os_CreateWindow() {
|
|||
|
||||
void os_SetupInput() {
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
mcfg_CreateDevicesFromConfig();
|
||||
mcfg_CreateDevices();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ void os_CreateWindow() {
|
|||
|
||||
void os_SetupInput() {
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
mcfg_CreateDevicesFromConfig();
|
||||
mcfg_CreateDevices();
|
||||
#endif
|
||||
init_kb_map();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue