ggpo: keyboard/mouse games support. Fix chat when keyboard disabled
ggpo: support for arcade games using keyboard (totd, luptype) and mouse/rotary encoders (waiwai drive) Chat and UI now usable when the keyboard is not set to a maple port.
This commit is contained in:
parent
db93a4c4a7
commit
ab45b5ec8a
|
@ -738,7 +738,9 @@ if(NOT LIBRETRO)
|
|||
core/input/gamepad_device.h
|
||||
core/input/keyboard_device.h
|
||||
core/input/mapping.cpp
|
||||
core/input/mapping.h)
|
||||
core/input/mapping.h
|
||||
core/input/mouse.cpp
|
||||
core/input/mouse.h)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
|
|
|
@ -120,6 +120,7 @@ Option<bool> GGPOEnable("GGPO", false, "network");
|
|||
Option<int> GGPODelay("GGPODelay", 0, "network");
|
||||
Option<bool> NetworkStats("Stats", true, "network");
|
||||
Option<int> GGPOAnalogAxes("GGPOAnalogAxes", 0, "network");
|
||||
Option<bool> GGPOChat("GGPOChat", true, "network");
|
||||
|
||||
#ifdef SUPPORT_DISPMANX
|
||||
Option<bool> DispmanxMaintainAspect("maintain_aspect", true, "dispmanx");
|
||||
|
|
|
@ -492,6 +492,7 @@ extern Option<bool> GGPOEnable;
|
|||
extern Option<int> GGPODelay;
|
||||
extern Option<bool> NetworkStats;
|
||||
extern Option<int> GGPOAnalogAxes;
|
||||
extern Option<bool> GGPOChat;
|
||||
|
||||
#ifdef SUPPORT_DISPMANX
|
||||
extern Option<bool> DispmanxMaintainAspect;
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
#include "maple_helper.h"
|
||||
#include "maple_if.h"
|
||||
#include "hw/naomi/naomi_cart.h"
|
||||
#include "input/gamepad_device.h"
|
||||
#include "cfg/option.h"
|
||||
#include "stdclass.h"
|
||||
|
||||
MapleInputState mapleInputState[4];
|
||||
|
||||
void (*MapleConfigMap::UpdateVibration)(u32 port, float power, float inclination, u32 duration_ms);
|
||||
|
||||
static u8 GetBtFromSgn(s8 val)
|
||||
{
|
||||
return val+128;
|
||||
|
@ -156,20 +157,24 @@ void MapleConfigMap::SetImage(u8 *img)
|
|||
void MapleConfigMap::GetAbsCoordinates(int& x, int& y)
|
||||
{
|
||||
const MapleInputState& inputState = mapleInputState[playerNum()];
|
||||
x = inputState.absPointerX;
|
||||
y = inputState.absPointerY;
|
||||
x = inputState.absPos.x;
|
||||
y = inputState.absPos.y;
|
||||
}
|
||||
|
||||
void MapleConfigMap::GetMouseInput(u8& buttons, int& x, int& y, int& wheel)
|
||||
{
|
||||
u32 playerNum = this->playerNum();
|
||||
buttons = mo_buttons[playerNum] & 0xff;
|
||||
x = (int)std::round(mo_x_delta[playerNum]);
|
||||
y = (int)std::round(mo_y_delta[playerNum]);
|
||||
wheel = (int)std::round(mo_wheel_delta[playerNum]);
|
||||
mo_x_delta[playerNum] = 0;
|
||||
mo_y_delta[playerNum] = 0;
|
||||
mo_wheel_delta[playerNum] = 0;
|
||||
const MapleInputState& inputState = mapleInputState[playerNum()];
|
||||
buttons = inputState.mouseButtons;
|
||||
x = inputState.relPos.x;
|
||||
y = inputState.relPos.y * (invertMouseY ? -1 : 1);
|
||||
wheel = inputState.relPos.wheel;
|
||||
}
|
||||
|
||||
void MapleConfigMap::GetKeyboardInput(u8& shift, u8 keys[6])
|
||||
{
|
||||
const MapleInputState& inputState = mapleInputState[playerNum()];
|
||||
shift = inputState.keyboard.shift;
|
||||
memcpy(keys, inputState.keyboard.key, sizeof(inputState.keyboard.key));
|
||||
}
|
||||
|
||||
bool maple_atomiswave_coin_chute(int slot)
|
||||
|
@ -201,7 +206,10 @@ static void createNaomiDevices()
|
|||
mcfg_DestroyDevices();
|
||||
mcfg_Create(MDT_NaomiJamma, 0, 5);
|
||||
if (settings.input.JammaSetup == JVS::Keyboard)
|
||||
{
|
||||
mcfg_Create(MDT_Keyboard, 1, 5, 0);
|
||||
mcfg_Create(MDT_Keyboard, 2, 5, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Connect VMU B1
|
||||
|
@ -247,6 +255,11 @@ static void createAtomiswaveDevices()
|
|||
// Waiwai drive needs two track-balls
|
||||
mcfg_Create(MDT_Mouse, 2, 5, 0);
|
||||
mcfg_Create(MDT_Mouse, 3, 5, 1);
|
||||
if (settings.content.gameId == "DRIVE")
|
||||
{
|
||||
MapleDevices[2][5]->config->invertMouseY = true;
|
||||
MapleDevices[3][5]->config->invertMouseY = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,8 +62,12 @@ public:
|
|||
void GetInput(PlainJoystickState* pjs);
|
||||
void GetAbsCoordinates(int& x, int& y);
|
||||
void GetMouseInput(u8& buttons, int& x, int& y, int& wheel);
|
||||
void GetKeyboardInput(u8& shift, u8 keys[6]);
|
||||
void SetImage(u8 *img);
|
||||
|
||||
static void (*UpdateVibration)(u32 port, float power, float inclination, u32 duration_ms);
|
||||
bool invertMouseY = false;
|
||||
|
||||
private:
|
||||
u32 playerNum();
|
||||
|
||||
|
@ -72,13 +76,27 @@ private:
|
|||
|
||||
struct MapleInputState
|
||||
{
|
||||
MapleInputState() : halfAxes{}, fullAxes{} {}
|
||||
MapleInputState() : halfAxes{}, fullAxes{} {
|
||||
memset(keyboard.key, 0, sizeof(keyboard.key));
|
||||
}
|
||||
|
||||
u32 kcode = ~0;
|
||||
u8 halfAxes[PJTI_Count]; // LT, RT
|
||||
int8_t fullAxes[PJAI_Count]; // Left X, Y, Right X, Y
|
||||
int absPointerX = -1;
|
||||
int absPointerY = -1;
|
||||
u8 mouseButtons = ~0;
|
||||
struct {
|
||||
int x = -1;
|
||||
int y = -1;
|
||||
} absPos;
|
||||
struct {
|
||||
int16_t x = 0;
|
||||
int16_t y = 0;
|
||||
int16_t wheel = 0;
|
||||
} relPos;
|
||||
struct {
|
||||
u8 shift = 0; // modifier keys bitmask
|
||||
u8 key[6]; // normal keys pressed
|
||||
} keyboard;
|
||||
};
|
||||
extern MapleInputState mapleInputState[4];
|
||||
|
||||
|
|
|
@ -1042,10 +1042,6 @@ struct maple_sega_purupuru : maple_base
|
|||
}
|
||||
};
|
||||
|
||||
u8 kb_shift[MAPLE_PORTS]; // shift keys pressed (bitmask)
|
||||
u8 kb_led[MAPLE_PORTS]; // leds currently lit
|
||||
u8 kb_key[MAPLE_PORTS][6]; // normal keys pressed
|
||||
|
||||
struct maple_keyboard : maple_base
|
||||
{
|
||||
MapleDeviceType get_device_type() override
|
||||
|
@ -1102,16 +1098,21 @@ struct maple_keyboard : maple_base
|
|||
return cmd == MDC_DeviceRequest ? MDRS_DeviceStatus : MDRS_DeviceStatusAll;
|
||||
|
||||
case MDCF_GetCondition:
|
||||
w32(MFID_6_Keyboard);
|
||||
//struct data
|
||||
//int8 shift ; shift keys pressed (bitmask) //1
|
||||
w8(kb_shift[player_num]);
|
||||
//int8 led ; leds currently lit //1
|
||||
w8(kb_led[player_num]);
|
||||
//int8 key[6] ; normal keys pressed //6
|
||||
for (int i = 0; i < 6; i++)
|
||||
w8(kb_key[player_num][i]);
|
||||
{
|
||||
u8 shift;
|
||||
u8 keys[6];
|
||||
config->GetKeyboardInput(shift, keys);
|
||||
|
||||
w32(MFID_6_Keyboard);
|
||||
//struct data
|
||||
//int8 shift ; shift keys pressed (bitmask) //1
|
||||
w8(shift);
|
||||
//int8 led ; leds currently lit //1
|
||||
w8(0);
|
||||
//int8 key[6] ; normal keys pressed //6
|
||||
for (int i = 0; i < 6; i++)
|
||||
w8(keys[i]);
|
||||
}
|
||||
return MDRS_DataTransfer;
|
||||
|
||||
case MDC_DeviceReset:
|
||||
|
@ -1127,28 +1128,6 @@ struct maple_keyboard : maple_base
|
|||
}
|
||||
};
|
||||
|
||||
// Mouse buttons
|
||||
// bit 0: Button C
|
||||
// bit 1: Right button (B)
|
||||
// bit 2: Left button (A)
|
||||
// bit 3: Wheel button
|
||||
u8 mo_buttons[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
// Relative mouse coordinates [-512:511]
|
||||
f32 mo_x_delta[4];
|
||||
f32 mo_y_delta[4];
|
||||
f32 mo_wheel_delta[4];
|
||||
// Absolute mouse coordinates
|
||||
// Range [0:639] [0:479]
|
||||
// but may be outside this range if the pointer is offscreen or outside the 4:3 window.
|
||||
s32 mo_x_abs[4];
|
||||
s32 mo_y_abs[4];
|
||||
// previous mouse coordinates for relative motion
|
||||
s32 mo_x_prev[4] = { -1, -1, -1, -1 };
|
||||
s32 mo_y_prev[4] = { -1, -1, -1, -1 };
|
||||
// last known screen/window size
|
||||
static s32 mo_width;
|
||||
static s32 mo_height;
|
||||
|
||||
struct maple_mouse : maple_base
|
||||
{
|
||||
MapleDeviceType get_device_type() override
|
||||
|
@ -1411,78 +1390,3 @@ maple_device* maple_Create(MapleDeviceType type)
|
|||
return rv;
|
||||
}
|
||||
|
||||
static void screenToNative(int& x, int& y, int width, int height)
|
||||
{
|
||||
float fx, fy;
|
||||
if (!config::Rotate90)
|
||||
{
|
||||
float scale = 480.f / height;
|
||||
fy = y * scale;
|
||||
scale /= config::ScreenStretching / 100.f;
|
||||
fx = (x - (width - 640.f / scale) / 2.f) * scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
float scale = 640.f / width;
|
||||
fx = x * scale;
|
||||
scale /= config::ScreenStretching / 100.f;
|
||||
fy = (y - (height - 480.f / scale) / 2.f) * scale;
|
||||
}
|
||||
x = (int)std::round(fx);
|
||||
y = (int)std::round(fy);
|
||||
}
|
||||
|
||||
void SetMousePosition(int x, int y, int width, int height, u32 mouseId)
|
||||
{
|
||||
if (mouseId >= MAPLE_PORTS)
|
||||
return;
|
||||
mo_width = width;
|
||||
mo_height = height;
|
||||
|
||||
if (config::Rotate90)
|
||||
{
|
||||
int t = y;
|
||||
y = x;
|
||||
x = height - 1 - t;
|
||||
std::swap(width, height);
|
||||
}
|
||||
screenToNative(x, y, width, height);
|
||||
mo_x_abs[mouseId] = x;
|
||||
mo_y_abs[mouseId] = y;
|
||||
|
||||
if (mo_x_prev[mouseId] != -1)
|
||||
{
|
||||
mo_x_delta[mouseId] += (f32)(x - mo_x_prev[mouseId]) * config::MouseSensitivity / 100.f;
|
||||
mo_y_delta[mouseId] += (f32)(y - mo_y_prev[mouseId]) * config::MouseSensitivity / 100.f;
|
||||
}
|
||||
mo_x_prev[mouseId] = x;
|
||||
mo_y_prev[mouseId] = y;
|
||||
}
|
||||
|
||||
void SetRelativeMousePosition(float xrel, float yrel, u32 mouseId)
|
||||
{
|
||||
if (mouseId >= MAPLE_PORTS)
|
||||
return;
|
||||
int width = mo_width;
|
||||
int height = mo_height;
|
||||
if (config::Rotate90)
|
||||
{
|
||||
std::swap(xrel, yrel);
|
||||
xrel = -xrel;
|
||||
std::swap(width, height);
|
||||
}
|
||||
float dx = xrel * config::MouseSensitivity / 100.f;
|
||||
float dy = yrel * config::MouseSensitivity / 100.f;
|
||||
mo_x_delta[mouseId] += dx;
|
||||
mo_y_delta[mouseId] += dy;
|
||||
int minX = -width / 32;
|
||||
int minY = -height / 32;
|
||||
int maxX = width + width / 32;
|
||||
int maxY = height + height / 32;
|
||||
screenToNative(minX, minY, width, height);
|
||||
screenToNative(maxX, maxY, width, height);
|
||||
mo_x_abs[mouseId] += (int)std::round(dx);
|
||||
mo_y_abs[mouseId] += (int)std::round(dy);
|
||||
mo_x_abs[mouseId] = std::min(std::max(mo_x_abs[mouseId], minX), maxX);
|
||||
mo_y_abs[mouseId] = std::min(std::max(mo_y_abs[mouseId], minY), maxY);
|
||||
}
|
||||
|
|
|
@ -166,20 +166,6 @@ void limit_joystick_magnitude(s8& joyx, s8& joyy)
|
|||
extern u8 EEPROM[0x100];
|
||||
void load_naomi_eeprom();
|
||||
|
||||
// Mouse position and buttons
|
||||
extern u8 mo_buttons[4];
|
||||
extern s32 mo_x_abs[4];
|
||||
extern s32 mo_y_abs[4];
|
||||
extern f32 mo_x_delta[4];
|
||||
extern f32 mo_y_delta[4];
|
||||
extern f32 mo_wheel_delta[4];
|
||||
|
||||
extern s32 mo_x_prev[4];
|
||||
extern s32 mo_y_prev[4];
|
||||
|
||||
void SetMousePosition(int x, int y, int width, int height, u32 mouseId = 0);
|
||||
void SetRelativeMousePosition(float xrel, float yrel, u32 mouseId = 0);
|
||||
|
||||
#define SWAP32(a) ((((a) & 0xff) << 24) | (((a) & 0xff00) << 8) | (((a) >> 8) & 0xff00) | (((a) >> 24) & 0xff))
|
||||
|
||||
const char *GetCurrentGameButtonName(DreamcastKey key);
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include <memory>
|
||||
#include "maple_devs.h"
|
||||
#include "hw/naomi/naomi_cart.h"
|
||||
#include "input/gamepad_device.h"
|
||||
#include <xxhash.h>
|
||||
#include "oslib/oslib.h"
|
||||
#include "stdclass.h"
|
||||
|
@ -482,7 +481,7 @@ protected:
|
|||
if (init_in_progress)
|
||||
return 0;
|
||||
const MapleInputState& inputState = mapleInputState[std::min(player_num, (int)ARRAY_SIZE(mapleInputState) - 1)];
|
||||
if (inputState.absPointerX < 0 || inputState.absPointerX > 639 || inputState.absPointerY < 0 || inputState.absPointerY > 479)
|
||||
if (inputState.absPos.x < 0 || inputState.absPos.x > 639 || inputState.absPos.y < 0 || inputState.absPos.y > 479)
|
||||
return 0;
|
||||
else
|
||||
return 0x8000;
|
||||
|
@ -1494,8 +1493,8 @@ u32 jvs_io_board::handle_jvs_message(u8 *buffer_in, u32 length_in, u8 *buffer_ou
|
|||
const MapleInputState& inputState = mapleInputState[std::min(playerNum, (int)ARRAY_SIZE(mapleInputState) - 1)];
|
||||
u16 x;
|
||||
u16 y;
|
||||
if (inputState.absPointerX < 0 || inputState.absPointerX > 639
|
||||
|| inputState.absPointerY < 0 || inputState.absPointerY > 479
|
||||
if (inputState.absPos.x < 0 || inputState.absPos.x > 639
|
||||
|| inputState.absPos.y < 0 || inputState.absPos.y > 479
|
||||
|| (buttons[playerNum] & NAOMI_RELOAD_KEY) != 0)
|
||||
{
|
||||
x = 0;
|
||||
|
@ -1503,8 +1502,8 @@ u32 jvs_io_board::handle_jvs_message(u8 *buffer_in, u32 length_in, u8 *buffer_ou
|
|||
}
|
||||
else
|
||||
{
|
||||
x = inputState.absPointerX * 0xFFFF / 639;
|
||||
y = inputState.absPointerY * 0xFFFF / 479;
|
||||
x = inputState.absPos.x * 0xFFFF / 639;
|
||||
y = inputState.absPos.y * 0xFFFF / 479;
|
||||
}
|
||||
LOGJVS("x,y:%4x,%4x ", x, y);
|
||||
JVS_OUT(x >> 8); // X, MSB
|
||||
|
@ -1571,10 +1570,8 @@ u32 jvs_io_board::handle_jvs_message(u8 *buffer_in, u32 length_in, u8 *buffer_ou
|
|||
static s16 roty = 0;
|
||||
// TODO Add more players.
|
||||
// I can't think of any naomi multiplayer game that uses rotary encoders
|
||||
rotx += mo_x_delta[first_player] * 5;
|
||||
roty -= mo_y_delta[first_player] * 5;
|
||||
mo_x_delta[first_player] = 0;
|
||||
mo_y_delta[first_player] = 0;
|
||||
rotx += mapleInputState[first_player].relPos.x * 5;
|
||||
roty -= mapleInputState[first_player].relPos.y * 5;
|
||||
LOGJVS("rotenc ");
|
||||
for (int chan = 0; chan < buffer_in[cmdi + 1]; chan++)
|
||||
{
|
||||
|
@ -1622,8 +1619,8 @@ u32 jvs_io_board::handle_jvs_message(u8 *buffer_in, u32 length_in, u8 *buffer_ou
|
|||
// Ninja Assault:
|
||||
u32 xr = 0x19d - 0x37;
|
||||
u32 yr = 0x1fe - 0x40;
|
||||
x = mapleInputState[playerNum].absPointerX * xr / 639 + 0x37;
|
||||
y = mapleInputState[playerNum].absPointerY * yr / 479 + 0x40;
|
||||
x = mapleInputState[playerNum].absPos.x * xr / 639 + 0x37;
|
||||
y = mapleInputState[playerNum].absPos.y * yr / 479 + 0x40;
|
||||
}
|
||||
LOGJVS("lightgun %4x,%4x ", x, y);
|
||||
JVS_OUT(x >> 8); // X, MSB
|
||||
|
|
|
@ -39,6 +39,9 @@ s8 joyrx[4];
|
|||
s8 joyry[4];
|
||||
u8 rt[4];
|
||||
u8 lt[4];
|
||||
// Keyboards
|
||||
u8 kb_shift[MAPLE_PORTS]; // shift keys pressed (bitmask)
|
||||
u8 kb_key[MAPLE_PORTS][6]; // normal keys pressed
|
||||
|
||||
std::vector<std::shared_ptr<GamepadDevice>> GamepadDevice::_gamepads;
|
||||
std::mutex GamepadDevice::_gamepads_mutex;
|
||||
|
@ -426,7 +429,7 @@ void GamepadDevice::save_mapping(int system)
|
|||
InputMapping::SaveMapping(filename.c_str(), input_mapper);
|
||||
}
|
||||
|
||||
void UpdateVibration(u32 port, float power, float inclination, u32 duration_ms)
|
||||
static void updateVibration(u32 port, float power, float inclination, u32 duration_ms)
|
||||
{
|
||||
int i = GamepadDevice::GetGamepadCount() - 1;
|
||||
for ( ; i >= 0; i--)
|
||||
|
@ -493,6 +496,7 @@ void GamepadDevice::Register(const std::shared_ptr<GamepadDevice>& gamepad)
|
|||
_gamepads_mutex.lock();
|
||||
_gamepads.push_back(gamepad);
|
||||
_gamepads_mutex.unlock();
|
||||
MapleConfigMap::UpdateVibration = updateVibration;
|
||||
}
|
||||
|
||||
void GamepadDevice::Unregister(const std::shared_ptr<GamepadDevice>& gamepad)
|
||||
|
@ -517,54 +521,6 @@ void GamepadDevice::SaveMaplePorts()
|
|||
}
|
||||
}
|
||||
|
||||
void Mouse::setAbsPos(int x, int y, int width, int height) {
|
||||
SetMousePosition(x, y, width, height, maple_port());
|
||||
}
|
||||
|
||||
void Mouse::setRelPos(float deltax, float deltay) {
|
||||
SetRelativeMousePosition(deltax, deltay, maple_port());
|
||||
}
|
||||
|
||||
void Mouse::setWheel(int delta) {
|
||||
if (maple_port() >= 0 && maple_port() < (int)ARRAY_SIZE(mo_wheel_delta))
|
||||
mo_wheel_delta[maple_port()] += delta;
|
||||
}
|
||||
|
||||
void Mouse::setButton(Button button, bool pressed)
|
||||
{
|
||||
if (maple_port() >= 0 && maple_port() < (int)ARRAY_SIZE(mo_buttons))
|
||||
{
|
||||
if (pressed)
|
||||
mo_buttons[maple_port()] &= ~(1 << (int)button);
|
||||
else
|
||||
mo_buttons[maple_port()] |= 1 << (int)button;
|
||||
}
|
||||
if ((gui_is_open() || gui_mouse_captured()) && !is_detecting_input())
|
||||
// Don't register mouse clicks as gamepad presses when gui is open
|
||||
// This makes the gamepad presses to be handled first and the mouse position to be ignored
|
||||
return;
|
||||
gamepad_btn_input(button, pressed);
|
||||
}
|
||||
|
||||
|
||||
void SystemMouse::setAbsPos(int x, int y, int width, int height) {
|
||||
gui_set_mouse_position(x, y);
|
||||
Mouse::setAbsPos(x, y, width, height);
|
||||
}
|
||||
|
||||
void SystemMouse::setButton(Button button, bool pressed) {
|
||||
int uiBtn = (int)button - 1;
|
||||
if (uiBtn < 2)
|
||||
uiBtn ^= 1;
|
||||
gui_set_mouse_button(uiBtn, pressed);
|
||||
Mouse::setButton(button, pressed);
|
||||
}
|
||||
|
||||
void SystemMouse::setWheel(int delta) {
|
||||
gui_set_mouse_wheel(delta * 35);
|
||||
Mouse::setWheel(delta);
|
||||
}
|
||||
|
||||
#ifdef TEST_AUTOMATION
|
||||
#include "cfg/option.h"
|
||||
static bool replay_inited;
|
||||
|
|
|
@ -156,75 +156,3 @@ extern u32 kcode[4];
|
|||
extern u8 rt[4], lt[4];
|
||||
extern s8 joyx[4], joyy[4];
|
||||
extern s8 joyrx[4], joyry[4];
|
||||
|
||||
void UpdateVibration(u32 port, float power, float inclination, u32 duration_ms);
|
||||
|
||||
class MouseInputMapping : public InputMapping
|
||||
{
|
||||
public:
|
||||
MouseInputMapping()
|
||||
{
|
||||
name = "Mouse";
|
||||
set_button(DC_BTN_A, 2); // Left
|
||||
set_button(DC_BTN_B, 1); // Right
|
||||
set_button(DC_BTN_START, 3); // Middle
|
||||
|
||||
dirty = false;
|
||||
}
|
||||
};
|
||||
|
||||
class Mouse : public GamepadDevice
|
||||
{
|
||||
protected:
|
||||
Mouse(const char *apiName, int maplePort = 0) : GamepadDevice(maplePort, apiName) {
|
||||
this->_name = "Mouse";
|
||||
}
|
||||
|
||||
virtual std::shared_ptr<InputMapping> getDefaultMapping() override {
|
||||
return std::make_shared<MouseInputMapping>();
|
||||
}
|
||||
|
||||
public:
|
||||
enum Button {
|
||||
LEFT_BUTTON = 2,
|
||||
RIGHT_BUTTON = 1,
|
||||
MIDDLE_BUTTON = 3,
|
||||
BUTTON_4 = 4,
|
||||
BUTTON_5 = 5
|
||||
};
|
||||
|
||||
virtual const char *get_button_name(u32 code) override
|
||||
{
|
||||
switch((Button)code)
|
||||
{
|
||||
case LEFT_BUTTON:
|
||||
return "Left Button";
|
||||
case RIGHT_BUTTON:
|
||||
return "Right Button";
|
||||
case MIDDLE_BUTTON:
|
||||
return "Middle Button";
|
||||
case BUTTON_4:
|
||||
return "Button 4";
|
||||
case BUTTON_5:
|
||||
return "Button 5";
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void setAbsPos(int x, int y, int width, int height);
|
||||
void setRelPos(float deltax, float deltay);
|
||||
void setButton(Button button, bool pressed);
|
||||
void setWheel(int delta);
|
||||
};
|
||||
|
||||
class SystemMouse : public Mouse
|
||||
{
|
||||
protected:
|
||||
SystemMouse(const char *apiName, int maplePort = 0) : Mouse(apiName, maplePort) {}
|
||||
|
||||
public:
|
||||
void setAbsPos(int x, int y, int width, int height);
|
||||
void setButton(Button button, bool pressed);
|
||||
void setWheel(int delta);
|
||||
};
|
||||
|
|
|
@ -404,41 +404,40 @@ static inline void setFlag(int& v, u32 bitmask, bool set)
|
|||
template <typename Keycode>
|
||||
void KeyboardDeviceTemplate<Keycode>::keyboard_input(Keycode keycode, bool pressed, int modifier_keys)
|
||||
{
|
||||
const int port = maple_port();
|
||||
if (port < 0 || port > (int)ARRAY_SIZE(kb_key))
|
||||
return;
|
||||
|
||||
u8 dc_keycode = convert_keycode(keycode);
|
||||
if (port < (int)ARRAY_SIZE(kb_key))
|
||||
// Some OSes (Mac OS) don't distinguish left and right modifier keys to we set them both.
|
||||
// But not for Alt since Right Alt is used as a special modifier keys on some international
|
||||
// keyboards.
|
||||
switch (dc_keycode)
|
||||
{
|
||||
// Some OSes (Mac OS) don't distinguish left and right modifier keys to we set them both.
|
||||
// But not for Alt since Right Alt is used as a special modifier keys on some international
|
||||
// keyboards.
|
||||
switch (dc_keycode)
|
||||
{
|
||||
case 0xE1: // Left Shift
|
||||
case 0xE5: // Right Shift
|
||||
setFlag(_modifier_keys, DC_KBMOD_LEFTSHIFT | DC_KBMOD_RIGHTSHIFT, pressed);
|
||||
break;
|
||||
case 0xE0: // Left Ctrl
|
||||
case 0xE4: // Right Ctrl
|
||||
setFlag(_modifier_keys, DC_KBMOD_LEFTCTRL | DC_KBMOD_RIGHTCTRL, pressed);
|
||||
break;
|
||||
case 0xE2: // Left Alt
|
||||
setFlag(_modifier_keys, DC_KBMOD_LEFTALT, pressed);
|
||||
break;
|
||||
case 0xE6: // Right Alt
|
||||
setFlag(_modifier_keys, DC_KBMOD_RIGHTALT, pressed);
|
||||
break;
|
||||
case 0xE7: // S2 special key
|
||||
setFlag(_modifier_keys, DC_KBMOD_S2, pressed);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case 0xE1: // Left Shift
|
||||
case 0xE5: // Right Shift
|
||||
setFlag(_modifier_keys, DC_KBMOD_LEFTSHIFT | DC_KBMOD_RIGHTSHIFT, pressed);
|
||||
break;
|
||||
case 0xE0: // Left Ctrl
|
||||
case 0xE4: // Right Ctrl
|
||||
setFlag(_modifier_keys, DC_KBMOD_LEFTCTRL | DC_KBMOD_RIGHTCTRL, pressed);
|
||||
break;
|
||||
case 0xE2: // Left Alt
|
||||
setFlag(_modifier_keys, DC_KBMOD_LEFTALT, pressed);
|
||||
break;
|
||||
case 0xE6: // Right Alt
|
||||
setFlag(_modifier_keys, DC_KBMOD_RIGHTALT, pressed);
|
||||
break;
|
||||
case 0xE7: // S2 special key
|
||||
setFlag(_modifier_keys, DC_KBMOD_S2, pressed);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
const int port = maple_port();
|
||||
if (port >= 0 && port < (int)ARRAY_SIZE(kb_shift))
|
||||
kb_shift[port] = _modifier_keys;
|
||||
|
||||
if (dc_keycode != 0 && dc_keycode < 0xE0)
|
||||
if (dc_keycode != 0 && dc_keycode < 0xE0)
|
||||
{
|
||||
gui_keyboard_key(dc_keycode, pressed, _modifier_keys);
|
||||
if (port >= 0 && port < (int)ARRAY_SIZE(kb_key))
|
||||
{
|
||||
if (pressed)
|
||||
{
|
||||
|
@ -474,7 +473,6 @@ void KeyboardDeviceTemplate<Keycode>::keyboard_input(Keycode keycode, bool press
|
|||
if (gui_keyboard_captured())
|
||||
{
|
||||
// chat: disable the keyboard controller. Only accept emu keys (menu, escape...)
|
||||
const int port = maple_port();
|
||||
set_maple_port(-1);
|
||||
gamepad_btn_input(dc_keycode, pressed);
|
||||
set_maple_port(port);
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
Copyright 2021 flyinghead
|
||||
|
||||
This file is part of Flycast.
|
||||
|
||||
Flycast 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.
|
||||
|
||||
Flycast 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 Flycast. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "mouse.h"
|
||||
#include "rend/gui.h"
|
||||
|
||||
// Mouse buttons
|
||||
// bit 0: Button C
|
||||
// bit 1: Right button (B)
|
||||
// bit 2: Left button (A)
|
||||
// bit 3: Wheel button
|
||||
u8 mo_buttons[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
// Relative mouse coordinates [-512:511]
|
||||
f32 mo_x_delta[4];
|
||||
f32 mo_y_delta[4];
|
||||
f32 mo_wheel_delta[4];
|
||||
// Absolute mouse coordinates
|
||||
// Range [0:639] [0:479]
|
||||
// but may be outside this range if the pointer is offscreen or outside the 4:3 window.
|
||||
s32 mo_x_abs[4];
|
||||
s32 mo_y_abs[4];
|
||||
// previous mouse coordinates for relative motion
|
||||
s32 mo_x_prev[4] = { -1, -1, -1, -1 };
|
||||
s32 mo_y_prev[4] = { -1, -1, -1, -1 };
|
||||
// last known screen/window size
|
||||
static s32 mo_width;
|
||||
static s32 mo_height;
|
||||
|
||||
void Mouse::setAbsPos(int x, int y, int width, int height) {
|
||||
SetMousePosition(x, y, width, height, maple_port());
|
||||
}
|
||||
|
||||
void Mouse::setRelPos(float deltax, float deltay) {
|
||||
SetRelativeMousePosition(deltax, deltay, maple_port());
|
||||
}
|
||||
|
||||
void Mouse::setWheel(int delta) {
|
||||
if (maple_port() >= 0 && maple_port() < (int)ARRAY_SIZE(mo_wheel_delta))
|
||||
mo_wheel_delta[maple_port()] += delta;
|
||||
}
|
||||
|
||||
void Mouse::setButton(Button button, bool pressed)
|
||||
{
|
||||
if (maple_port() >= 0 && maple_port() < (int)ARRAY_SIZE(mo_buttons))
|
||||
{
|
||||
if (pressed)
|
||||
mo_buttons[maple_port()] &= ~(1 << (int)button);
|
||||
else
|
||||
mo_buttons[maple_port()] |= 1 << (int)button;
|
||||
}
|
||||
if ((gui_is_open() || gui_mouse_captured()) && !is_detecting_input())
|
||||
// Don't register mouse clicks as gamepad presses when gui is open
|
||||
// This makes the gamepad presses to be handled first and the mouse position to be ignored
|
||||
return;
|
||||
gamepad_btn_input(button, pressed);
|
||||
}
|
||||
|
||||
|
||||
void SystemMouse::setAbsPos(int x, int y, int width, int height) {
|
||||
gui_set_mouse_position(x, y);
|
||||
Mouse::setAbsPos(x, y, width, height);
|
||||
}
|
||||
|
||||
void SystemMouse::setButton(Button button, bool pressed) {
|
||||
int uiBtn = (int)button - 1;
|
||||
if (uiBtn < 2)
|
||||
uiBtn ^= 1;
|
||||
gui_set_mouse_button(uiBtn, pressed);
|
||||
Mouse::setButton(button, pressed);
|
||||
}
|
||||
|
||||
void SystemMouse::setWheel(int delta) {
|
||||
gui_set_mouse_wheel(delta * 35);
|
||||
Mouse::setWheel(delta);
|
||||
}
|
||||
|
||||
|
||||
static void screenToNative(int& x, int& y, int width, int height)
|
||||
{
|
||||
float fx, fy;
|
||||
if (!config::Rotate90)
|
||||
{
|
||||
float scale = 480.f / height;
|
||||
fy = y * scale;
|
||||
scale /= config::ScreenStretching / 100.f;
|
||||
fx = (x - (width - 640.f / scale) / 2.f) * scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
float scale = 640.f / width;
|
||||
fx = x * scale;
|
||||
scale /= config::ScreenStretching / 100.f;
|
||||
fy = (y - (height - 480.f / scale) / 2.f) * scale;
|
||||
}
|
||||
x = (int)std::round(fx);
|
||||
y = (int)std::round(fy);
|
||||
}
|
||||
|
||||
void SetMousePosition(int x, int y, int width, int height, u32 mouseId)
|
||||
{
|
||||
if (mouseId >= ARRAY_SIZE(mo_x_abs))
|
||||
return;
|
||||
mo_width = width;
|
||||
mo_height = height;
|
||||
|
||||
if (config::Rotate90)
|
||||
{
|
||||
int t = y;
|
||||
y = x;
|
||||
x = height - 1 - t;
|
||||
std::swap(width, height);
|
||||
}
|
||||
screenToNative(x, y, width, height);
|
||||
mo_x_abs[mouseId] = x;
|
||||
mo_y_abs[mouseId] = y;
|
||||
|
||||
if (mo_x_prev[mouseId] != -1)
|
||||
{
|
||||
mo_x_delta[mouseId] += (f32)(x - mo_x_prev[mouseId]) * config::MouseSensitivity / 100.f;
|
||||
mo_y_delta[mouseId] += (f32)(y - mo_y_prev[mouseId]) * config::MouseSensitivity / 100.f;
|
||||
}
|
||||
mo_x_prev[mouseId] = x;
|
||||
mo_y_prev[mouseId] = y;
|
||||
}
|
||||
|
||||
void SetRelativeMousePosition(float xrel, float yrel, u32 mouseId)
|
||||
{
|
||||
if (mouseId >= ARRAY_SIZE(mo_x_delta))
|
||||
return;
|
||||
int width = mo_width;
|
||||
int height = mo_height;
|
||||
if (config::Rotate90)
|
||||
{
|
||||
std::swap(xrel, yrel);
|
||||
xrel = -xrel;
|
||||
std::swap(width, height);
|
||||
}
|
||||
float dx = xrel * config::MouseSensitivity / 100.f;
|
||||
float dy = yrel * config::MouseSensitivity / 100.f;
|
||||
mo_x_delta[mouseId] += dx;
|
||||
mo_y_delta[mouseId] += dy;
|
||||
int minX = -width / 32;
|
||||
int minY = -height / 32;
|
||||
int maxX = width + width / 32;
|
||||
int maxY = height + height / 32;
|
||||
screenToNative(minX, minY, width, height);
|
||||
screenToNative(maxX, maxY, width, height);
|
||||
mo_x_abs[mouseId] += (int)std::round(dx);
|
||||
mo_y_abs[mouseId] += (int)std::round(dy);
|
||||
mo_x_abs[mouseId] = std::min(std::max(mo_x_abs[mouseId], minX), maxX);
|
||||
mo_y_abs[mouseId] = std::min(std::max(mo_y_abs[mouseId], minY), maxY);
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
Copyright 2021 flyinghead
|
||||
|
||||
This file is part of Flycast.
|
||||
|
||||
Flycast 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.
|
||||
|
||||
Flycast 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 Flycast. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "gamepad_device.h"
|
||||
|
||||
// Mouse position and buttons
|
||||
extern u8 mo_buttons[4];
|
||||
extern s32 mo_x_abs[4];
|
||||
extern s32 mo_y_abs[4];
|
||||
extern f32 mo_x_delta[4];
|
||||
extern f32 mo_y_delta[4];
|
||||
extern f32 mo_wheel_delta[4];
|
||||
|
||||
extern s32 mo_x_prev[4];
|
||||
extern s32 mo_y_prev[4];
|
||||
|
||||
void SetMousePosition(int x, int y, int width, int height, u32 mouseId = 0);
|
||||
void SetRelativeMousePosition(float xrel, float yrel, u32 mouseId = 0);
|
||||
|
||||
class MouseInputMapping : public InputMapping
|
||||
{
|
||||
public:
|
||||
MouseInputMapping()
|
||||
{
|
||||
name = "Mouse";
|
||||
set_button(DC_BTN_A, 2); // Left
|
||||
set_button(DC_BTN_B, 1); // Right
|
||||
set_button(DC_BTN_START, 3); // Middle
|
||||
|
||||
dirty = false;
|
||||
}
|
||||
};
|
||||
|
||||
class Mouse : public GamepadDevice
|
||||
{
|
||||
protected:
|
||||
Mouse(const char *apiName, int maplePort = 0) : GamepadDevice(maplePort, apiName) {
|
||||
this->_name = "Mouse";
|
||||
}
|
||||
|
||||
virtual std::shared_ptr<InputMapping> getDefaultMapping() override {
|
||||
return std::make_shared<MouseInputMapping>();
|
||||
}
|
||||
|
||||
public:
|
||||
enum Button {
|
||||
LEFT_BUTTON = 2,
|
||||
RIGHT_BUTTON = 1,
|
||||
MIDDLE_BUTTON = 3,
|
||||
BUTTON_4 = 4,
|
||||
BUTTON_5 = 5
|
||||
};
|
||||
|
||||
virtual const char *get_button_name(u32 code) override
|
||||
{
|
||||
switch((Button)code)
|
||||
{
|
||||
case LEFT_BUTTON:
|
||||
return "Left Button";
|
||||
case RIGHT_BUTTON:
|
||||
return "Right Button";
|
||||
case MIDDLE_BUTTON:
|
||||
return "Middle Button";
|
||||
case BUTTON_4:
|
||||
return "Button 4";
|
||||
case BUTTON_5:
|
||||
return "Button 5";
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void setAbsPos(int x, int y, int width, int height);
|
||||
void setRelPos(float deltax, float deltay);
|
||||
void setButton(Button button, bool pressed);
|
||||
void setWheel(int delta);
|
||||
};
|
||||
|
||||
class SystemMouse : public Mouse
|
||||
{
|
||||
protected:
|
||||
SystemMouse(const char *apiName, int maplePort = 0) : Mouse(apiName, maplePort) {}
|
||||
|
||||
public:
|
||||
void setAbsPos(int x, int y, int width, int height);
|
||||
void setButton(Button button, bool pressed);
|
||||
void setWheel(int delta);
|
||||
};
|
|
@ -20,6 +20,8 @@
|
|||
#include "hw/maple/maple_cfg.h"
|
||||
#include "hw/maple/maple_devs.h"
|
||||
#include "input/gamepad_device.h"
|
||||
#include "input/keyboard_device.h"
|
||||
#include "input/mouse.h"
|
||||
#include "cfg/option.h"
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -42,8 +44,17 @@ static void getLocalInput(MapleInputState inputState[4])
|
|||
state.fullAxes[PJAI_Y1] = joyy[player];
|
||||
state.fullAxes[PJAI_X2] = joyrx[player];
|
||||
state.fullAxes[PJAI_Y2] = joyry[player];
|
||||
state.absPointerX = mo_x_abs[player];
|
||||
state.absPointerY = mo_y_abs[player];
|
||||
state.mouseButtons = mo_buttons[player];
|
||||
state.absPos.x = mo_x_abs[player];
|
||||
state.absPos.y = mo_y_abs[player];
|
||||
state.keyboard.shift = kb_shift[player];
|
||||
memcpy(state.keyboard.key, kb_key[player], sizeof(kb_key[player]));
|
||||
state.relPos.x = std::round(mo_x_delta[player]);
|
||||
state.relPos.y = std::round(mo_y_delta[player]);
|
||||
state.relPos.wheel = std::round(mo_wheel_delta[player]);
|
||||
mo_x_delta[player] -= state.relPos.x;
|
||||
mo_y_delta[player] -= state.relPos.y;
|
||||
mo_wheel_delta[player] -= state.relPos.wheel;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,6 +112,9 @@ static bool _endOfFrame;
|
|||
static MiniUPnP miniupnp;
|
||||
static int analogAxes;
|
||||
static bool absPointerPos;
|
||||
static bool keyboardGame;
|
||||
static bool mouseGame;
|
||||
static int inputSize;
|
||||
static bool inRollback;
|
||||
static void (*chatCallback)(int playerNum, const std::string& msg);
|
||||
|
||||
|
@ -122,6 +136,30 @@ static int lastSavedFrame = -1;
|
|||
static int timesyncOccurred;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct Inputs
|
||||
{
|
||||
u32 kcode:20;
|
||||
u32 mouseButtons:4;
|
||||
u8 kbModifiers;
|
||||
|
||||
union {
|
||||
struct {
|
||||
u8 x;
|
||||
u8 y;
|
||||
} analog;
|
||||
struct {
|
||||
s16 x;
|
||||
s16 y;
|
||||
} absPos;
|
||||
struct {
|
||||
s16 x;
|
||||
s16 y;
|
||||
s16 wheel;
|
||||
} relPos;
|
||||
u8 keys[6];
|
||||
} u;
|
||||
};
|
||||
|
||||
struct GameEvent
|
||||
{
|
||||
enum : char {
|
||||
|
@ -440,8 +478,14 @@ void startSession(int localPort, int localPlayerNum)
|
|||
{
|
||||
analogAxes = 0;
|
||||
absPointerPos = false;
|
||||
keyboardGame = false;
|
||||
mouseGame = false;
|
||||
if (settings.input.JammaSetup == JVS::LightGun || settings.input.JammaSetup == JVS::LightGunAsAnalog)
|
||||
absPointerPos = true;
|
||||
else if (settings.input.JammaSetup == JVS::Keyboard)
|
||||
keyboardGame = true;
|
||||
else if (settings.input.JammaSetup == JVS::RotaryEncoders)
|
||||
mouseGame = true;
|
||||
else if (NaomiGameInputs != nullptr)
|
||||
{
|
||||
for (const auto& axis : NaomiGameInputs->axes)
|
||||
|
@ -454,7 +498,8 @@ void startSession(int localPort, int localPlayerNum)
|
|||
}
|
||||
NOTICE_LOG(NETWORK, "GGPO: Using %d full analog axes", analogAxes);
|
||||
}
|
||||
const u32 inputSize = sizeof(kcode[0]) + analogAxes + (int)absPointerPos * 4;
|
||||
inputSize = sizeof(kcode[0]) + analogAxes + (int)absPointerPos * sizeof(Inputs::u.absPos)
|
||||
+ (int)keyboardGame * sizeof(Inputs::u.keys) + (int)mouseGame * sizeof(Inputs::u.relPos);
|
||||
|
||||
VerificationData verif;
|
||||
MD5Sum().add(settings.network.md5.bios)
|
||||
|
@ -551,10 +596,9 @@ void getInput(MapleInputState inputState[4])
|
|||
for (int player = 0; player < 4; player++)
|
||||
inputState[player] = {};
|
||||
|
||||
u32 inputSize = sizeof(u32) + analogAxes + (int)absPointerPos * 4;
|
||||
std::vector<u8> inputs(inputSize * MAX_PLAYERS);
|
||||
std::vector<u8> inputData(inputSize * MAX_PLAYERS);
|
||||
// should not call any callback
|
||||
GGPOErrorCode error = ggpo_synchronize_input(ggpoSession, (void *)&inputs[0], inputs.size(), nullptr);
|
||||
GGPOErrorCode error = ggpo_synchronize_input(ggpoSession, (void *)&inputData[0], inputData.size(), nullptr);
|
||||
if (error != GGPO_OK)
|
||||
{
|
||||
stopSession();
|
||||
|
@ -564,17 +608,30 @@ void getInput(MapleInputState inputState[4])
|
|||
for (int player = 0; player < MAX_PLAYERS; player++)
|
||||
{
|
||||
MapleInputState& state = inputState[player];
|
||||
state.kcode = ~(*(u32 *)&inputs[player * inputSize]);
|
||||
const Inputs *inputs = (Inputs *)&inputData[player * inputSize];
|
||||
state.kcode = ~inputs->kcode;
|
||||
if (analogAxes > 0)
|
||||
{
|
||||
state.fullAxes[PJAI_X1] = inputs[player * inputSize + 4];
|
||||
state.fullAxes[PJAI_X1] = inputs->u.analog.x;
|
||||
if (analogAxes >= 2)
|
||||
state.fullAxes[PJAI_Y1] = inputs[player * inputSize + 5];
|
||||
state.fullAxes[PJAI_Y1] = inputs->u.analog.y;
|
||||
}
|
||||
else if (absPointerPos)
|
||||
{
|
||||
state.absPointerX = *(s16 *)&inputs[player * inputSize + 4];
|
||||
state.absPointerY = *(s16 *)&inputs[player * inputSize + 6];
|
||||
state.absPos.x = inputs->u.absPos.x;
|
||||
state.absPos.y = inputs->u.absPos.y;
|
||||
}
|
||||
else if (keyboardGame)
|
||||
{
|
||||
memcpy(state.keyboard.key, inputs->u.keys, sizeof(state.keyboard.key));
|
||||
state.keyboard.shift = inputs->kbModifiers;
|
||||
}
|
||||
else if (mouseGame)
|
||||
{
|
||||
state.relPos.x = inputs->u.relPos.x;
|
||||
state.relPos.y = inputs->u.relPos.y;
|
||||
state.relPos.wheel = inputs->u.relPos.wheel;
|
||||
state.mouseButtons = ~inputs->mouseButtons;
|
||||
}
|
||||
state.halfAxes[PJTI_R] = (state.kcode & BTN_TRIGGER_RIGHT) == 0 ? 255 : 0;
|
||||
state.halfAxes[PJTI_L] = (state.kcode & BTN_TRIGGER_LEFT) == 0 ? 255 : 0;
|
||||
|
@ -620,30 +677,43 @@ bool nextFrame()
|
|||
do {
|
||||
if (!config::ThreadedRendering)
|
||||
UpdateInputState();
|
||||
u32 input = ~kcode[localPlayerNum];
|
||||
Inputs inputs;
|
||||
inputs.kcode = ~kcode[localPlayerNum];
|
||||
if (rt[localPlayerNum] >= 64)
|
||||
input |= BTN_TRIGGER_RIGHT;
|
||||
inputs.kcode |= BTN_TRIGGER_RIGHT;
|
||||
else
|
||||
input &= ~BTN_TRIGGER_RIGHT;
|
||||
inputs.kcode &= ~BTN_TRIGGER_RIGHT;
|
||||
if (lt[localPlayerNum] >= 64)
|
||||
input |= BTN_TRIGGER_LEFT;
|
||||
inputs.kcode |= BTN_TRIGGER_LEFT;
|
||||
else
|
||||
input &= ~BTN_TRIGGER_LEFT;
|
||||
u32 inputSize = sizeof(input) + analogAxes + (int)absPointerPos * 4;
|
||||
std::vector<u8> allInput(inputSize);
|
||||
*(u32 *)&allInput[0] = input;
|
||||
inputs.kcode &= ~BTN_TRIGGER_LEFT;
|
||||
if (analogAxes > 0)
|
||||
{
|
||||
allInput[4] = joyx[localPlayerNum];
|
||||
inputs.u.analog.x = joyx[localPlayerNum];
|
||||
if (analogAxes >= 2)
|
||||
allInput[5] = joyy[localPlayerNum];
|
||||
inputs.u.analog.y = joyy[localPlayerNum];
|
||||
}
|
||||
else if (absPointerPos)
|
||||
{
|
||||
*(s16 *)&allInput[4] = mo_x_abs[localPlayerNum];
|
||||
*(s16 *)&allInput[6] = mo_y_abs[localPlayerNum];
|
||||
inputs.u.absPos.x = mo_x_abs[localPlayerNum];
|
||||
inputs.u.absPos.y = mo_y_abs[localPlayerNum];
|
||||
}
|
||||
GGPOErrorCode result = ggpo_add_local_input(ggpoSession, localPlayer, &allInput[0], inputSize);
|
||||
else if (keyboardGame)
|
||||
{
|
||||
inputs.kbModifiers = kb_shift[localPlayerNum];
|
||||
memcpy(inputs.u.keys, kb_key[localPlayerNum], sizeof(kb_key[localPlayerNum]));
|
||||
}
|
||||
else if (mouseGame)
|
||||
{
|
||||
inputs.mouseButtons = ~mo_buttons[localPlayerNum];
|
||||
inputs.u.relPos.x = std::round(mo_x_delta[localPlayerNum]);
|
||||
inputs.u.relPos.y = std::round(mo_y_delta[localPlayerNum]);
|
||||
inputs.u.relPos.wheel = std::round(mo_wheel_delta[localPlayerNum]);
|
||||
mo_x_delta[localPlayerNum] -= inputs.u.relPos.x;
|
||||
mo_y_delta[localPlayerNum] -= inputs.u.relPos.y;
|
||||
mo_wheel_delta[localPlayerNum] -= inputs.u.relPos.wheel;
|
||||
}
|
||||
GGPOErrorCode result = ggpo_add_local_input(ggpoSession, localPlayer, &inputs, inputSize);
|
||||
if (result == GGPO_OK)
|
||||
break;
|
||||
if (result != GGPO_ERRORCODE_PREDICTION_THRESHOLD)
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "network/ggpo.h"
|
||||
#include "wsi/context.h"
|
||||
#include "input/gamepad_device.h"
|
||||
#include "input/mouse.h"
|
||||
#include "gui_util.h"
|
||||
#include "gui_android.h"
|
||||
#include "game_scanner.h"
|
||||
|
@ -46,9 +47,6 @@
|
|||
|
||||
static bool game_started;
|
||||
|
||||
extern u8 kb_shift[MAPLE_PORTS]; // shift keys pressed (bitmask)
|
||||
extern u8 kb_key[MAPLE_PORTS][6]; // normal keys pressed
|
||||
|
||||
int screen_dpi = 96;
|
||||
int insetLeft, insetRight, insetTop, insetBottom;
|
||||
|
||||
|
@ -279,6 +277,16 @@ void gui_keyboard_inputUTF8(const std::string& s)
|
|||
io.AddInputCharactersUTF8(s.c_str());
|
||||
}
|
||||
|
||||
void gui_keyboard_key(u8 keyCode, bool pressed, u8 modifiers)
|
||||
{
|
||||
if (!inited)
|
||||
return;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.KeyCtrl = (modifiers & (0x01 | 0x10)) != 0;
|
||||
io.KeyShift = (modifiers & (0x02 | 0x20)) != 0;
|
||||
io.KeysDown[keyCode] = pressed;
|
||||
}
|
||||
|
||||
bool gui_keyboard_captured()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
@ -323,21 +331,6 @@ static void ImGui_Impl_NewFrame()
|
|||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Read keyboard modifiers inputs
|
||||
io.KeyCtrl = 0;
|
||||
io.KeyShift = 0;
|
||||
io.KeyAlt = false;
|
||||
io.KeySuper = false;
|
||||
memset(&io.KeysDown[0], 0, sizeof(io.KeysDown));
|
||||
for (int port = 0; port < 4; port++)
|
||||
{
|
||||
io.KeyCtrl |= (kb_shift[port] & (0x01 | 0x10)) != 0;
|
||||
io.KeyShift |= (kb_shift[port] & (0x02 | 0x20)) != 0;
|
||||
|
||||
for (int i = 0; i < IM_ARRAYSIZE(kb_key[0]); i++)
|
||||
if (kb_key[port][i] != 0)
|
||||
io.KeysDown[kb_key[port][i]] = true;
|
||||
}
|
||||
if (mouseX < 0 || mouseX >= settings.display.width || mouseY < 0 || mouseY >= settings.display.height)
|
||||
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
||||
else
|
||||
|
@ -1895,6 +1888,7 @@ static void gui_display_settings()
|
|||
ImGui::SameLine();
|
||||
OptionRadioButton<int>("Full", config::GGPOAnalogAxes, 2, "Use the left thumbstick horizontal and vertical axes");
|
||||
|
||||
OptionCheckbox("Enable Chat", config::GGPOChat, "Open the chat window when a chat message is received");
|
||||
OptionCheckbox("Network Statistics", config::NetworkStats,
|
||||
"Display network statistics on screen");
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ void gui_refresh_files();
|
|||
void gui_cheats();
|
||||
void gui_keyboard_input(u16 wc);
|
||||
void gui_keyboard_inputUTF8(const std::string& s);
|
||||
void gui_keyboard_key(u8 keyCode, bool pressed, u8 modifiers);
|
||||
bool gui_keyboard_captured();
|
||||
bool gui_mouse_captured();
|
||||
void gui_set_mouse_position(int x, int y);
|
||||
|
|
|
@ -100,7 +100,8 @@ public:
|
|||
|
||||
void receive(int playerNum, const std::string& msg)
|
||||
{
|
||||
visible = true;
|
||||
if (config::GGPOChat)
|
||||
visible = true;
|
||||
std::string line = "<" + playerName(true) + "> " + msg;
|
||||
lines.push_back(std::make_pair(YELLOW, line));
|
||||
newMessage = true;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "../input/gamepad_device.h"
|
||||
#include "input/gamepad_device.h"
|
||||
#include "input/mouse.h"
|
||||
#include "oslib/oslib.h"
|
||||
#include "sdl.h"
|
||||
#include "rend/gui.h"
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "input/gamepad_device.h"
|
||||
#include "input/mouse.h"
|
||||
#include <algorithm>
|
||||
|
||||
static jobject input_device_manager;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include <cmath>
|
||||
#include "input/gamepad_device.h"
|
||||
#include "input/mouse.h"
|
||||
#include "rend/gui.h"
|
||||
|
||||
enum IOSButton {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#pragma once
|
||||
#import <GameController/GameController.h>
|
||||
|
||||
#include "input/gamepad_device.h"
|
||||
#include "input/mouse.h"
|
||||
|
||||
class API_AVAILABLE(ios(14.0)) IOSMouse : public SystemMouse
|
||||
{
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// Created by flyinghead on 26/02/2019.
|
||||
// Copyright © 2019 reicast. All rights reserved.
|
||||
//
|
||||
#include "input/gamepad_device.h"
|
||||
#include "input/mouse.h"
|
||||
|
||||
class OSXMouse : public SystemMouse
|
||||
{
|
||||
|
|
|
@ -116,6 +116,21 @@ u8 lt[4];
|
|||
u32 vks[4];
|
||||
s8 joyx[4], joyy[4];
|
||||
s8 joyrx[4], joyry[4];
|
||||
// Mouse buttons
|
||||
// bit 0: Button C
|
||||
// bit 1: Right button (B)
|
||||
// bit 2: Left button (A)
|
||||
// bit 3: Wheel button
|
||||
u8 mo_buttons[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
// Relative mouse coordinates [-512:511]
|
||||
f32 mo_x_delta[4];
|
||||
f32 mo_y_delta[4];
|
||||
f32 mo_wheel_delta[4];
|
||||
// Absolute mouse coordinates
|
||||
// Range [0:639] [0:479]
|
||||
// but may be outside this range if the pointer is offscreen or outside the 4:3 window.
|
||||
s32 mo_x_abs[4];
|
||||
s32 mo_y_abs[4];
|
||||
|
||||
static bool enable_purupuru = true;
|
||||
static u32 vib_stop_time[4];
|
||||
|
@ -151,6 +166,7 @@ static void init_disk_control_interface();
|
|||
static bool read_m3u(const char *file);
|
||||
void UpdateInputState();
|
||||
void gui_display_notification(const char *msg, int duration);
|
||||
static void updateVibration(u32 port, float power, float inclination, u32 durationMs);
|
||||
|
||||
static std::string game_data;
|
||||
static char g_base_name[128];
|
||||
|
@ -276,6 +292,7 @@ void retro_init()
|
|||
ERROR_LOG(VMEM, "Cannot reserve memory space");
|
||||
|
||||
os_InstallFaultHandler();
|
||||
MapleConfigMap::UpdateVibration = updateVibration;
|
||||
}
|
||||
|
||||
void retro_deinit()
|
||||
|
@ -2571,7 +2588,7 @@ void UpdateInputState()
|
|||
UpdateInputState(3);
|
||||
}
|
||||
|
||||
void UpdateVibration(u32 port, float power, float inclination, u32 durationMs)
|
||||
static void updateVibration(u32 port, float power, float inclination, u32 durationMs)
|
||||
{
|
||||
if (!rumble.set_rumble_state)
|
||||
return;
|
||||
|
@ -2583,8 +2600,8 @@ void UpdateVibration(u32 port, float power, float inclination, u32 durationMs)
|
|||
vib_delta[port] = inclination;
|
||||
}
|
||||
|
||||
extern u8 kb_key[4][6]; // normal keys pressed
|
||||
extern u8 kb_shift[4]; // modifier keys pressed (bitmask)
|
||||
u8 kb_key[4][6]; // normal keys pressed
|
||||
u8 kb_shift[4]; // modifier keys pressed (bitmask)
|
||||
static int kb_used;
|
||||
|
||||
static void release_key(unsigned dc_keycode)
|
||||
|
|
Loading…
Reference in New Issue