flycast/core/sdl/sdl.cpp

328 lines
8.9 KiB
C++
Raw Normal View History

2015-08-29 18:23:16 +00:00
#if defined(USE_SDL)
#include "types.h"
#include "cfg/cfg.h"
#include "sdl/sdl.h"
2019-12-22 22:49:52 +00:00
#include <SDL2/SDL_syswm.h>
2015-08-29 18:23:16 +00:00
#endif
2019-02-12 14:56:44 +00:00
#include "hw/maple/maple_devs.h"
#include "sdl_gamepad.h"
#include "sdl_keyboard.h"
#include "wsi/context.h"
2015-08-29 18:23:16 +00:00
2019-10-05 09:50:14 +00:00
#ifdef USE_VULKAN
#include <SDL2/SDL_vulkan.h>
#endif
static SDL_Window* window = NULL;
2015-08-29 18:23:16 +00:00
#ifdef TARGET_PANDORA
#define WINDOW_WIDTH 800
#else
#define WINDOW_WIDTH 640
#endif
#define WINDOW_HEIGHT 480
static std::shared_ptr<SDLMouseGamepadDevice> sdl_mouse_gamepad;
static std::shared_ptr<SDLKbGamepadDevice> sdl_kb_gamepad;
static SDLKeyboardDevice* sdl_keyboard = NULL;
static bool window_fullscreen;
static bool window_maximized;
static int window_width = WINDOW_WIDTH;
static int window_height = WINDOW_HEIGHT;
2015-08-29 18:23:16 +00:00
extern void dc_exit();
2015-08-29 18:23:16 +00:00
2019-02-12 14:56:44 +00:00
static void sdl_open_joystick(int index)
{
SDL_Joystick *pJoystick = SDL_JoystickOpen(index);
2015-08-29 18:23:16 +00:00
2019-02-12 14:56:44 +00:00
if (pJoystick == NULL)
{
2019-07-01 15:41:15 +00:00
INFO_LOG(INPUT, "SDL: Cannot open joystick %d", index + 1);
2019-02-12 14:56:44 +00:00
return;
}
std::shared_ptr<SDLGamepadDevice> gamepad = std::make_shared<SDLGamepadDevice>(index < MAPLE_PORTS ? index : -1, pJoystick);
SDLGamepadDevice::AddSDLGamepad(gamepad);
2019-02-12 14:56:44 +00:00
}
2015-08-29 18:23:16 +00:00
2019-02-12 14:56:44 +00:00
static void sdl_close_joystick(SDL_JoystickID instance)
{
std::shared_ptr<SDLGamepadDevice> gamepad = SDLGamepadDevice::GetSDLGamepad(instance);
if (gamepad != NULL)
2019-02-23 00:06:10 +00:00
gamepad->close();
2019-02-12 14:56:44 +00:00
}
2015-08-29 18:23:16 +00:00
void input_sdl_init()
{
if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
{
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
2015-08-29 18:23:16 +00:00
{
die("SDL: error initializing Joystick subsystem");
2015-08-29 18:23:16 +00:00
}
}
2019-02-23 00:06:10 +00:00
if (SDL_WasInit(SDL_INIT_HAPTIC) == 0)
SDL_InitSubSystem(SDL_INIT_HAPTIC);
2019-08-14 20:48:34 +00:00
#if HOST_OS != OS_DARWIN
2019-02-07 22:44:30 +00:00
SDL_SetRelativeMouseMode(SDL_FALSE);
sdl_keyboard = new SDLKeyboardDevice(0);
sdl_kb_gamepad = std::make_shared<SDLKbGamepadDevice>(0);
GamepadDevice::Register(sdl_kb_gamepad);
sdl_mouse_gamepad = std::make_shared<SDLMouseGamepadDevice>(0);
GamepadDevice::Register(sdl_mouse_gamepad);
2019-08-14 07:20:24 +00:00
#endif
2019-02-07 22:44:30 +00:00
}
2015-09-12 18:19:28 +00:00
static int mouse_prev_x = -1;
static int mouse_prev_y = -1;
2015-08-29 18:23:16 +00:00
2019-02-07 22:44:30 +00:00
static void set_mouse_position(int x, int y)
{
int width, height;
SDL_GetWindowSize(window, &width, &height);
if (width != 0 && height != 0)
2015-08-29 18:23:16 +00:00
{
2019-02-07 22:44:30 +00:00
float scale = 480.f / height;
mo_x_abs = (x - (width - 640.f / scale) / 2.f) * scale;
mo_y_abs = y * scale;
if (mouse_prev_x != -1)
2015-08-29 18:23:16 +00:00
{
mo_x_delta += (f32)(x - mouse_prev_x) * settings.input.MouseSensitivity / 100.f;
mo_y_delta += (f32)(y - mouse_prev_y) * settings.input.MouseSensitivity / 100.f;
2015-08-29 18:23:16 +00:00
}
mouse_prev_x = x;
mouse_prev_y = y;
2019-02-07 22:44:30 +00:00
}
2015-08-29 18:23:16 +00:00
}
// FIXME this shouldn't be done by port. Need something like: handle_events() then get_port(0), get_port(2), ...
2015-08-29 18:23:16 +00:00
void input_sdl_handle(u32 port)
{
2019-02-23 00:06:10 +00:00
if (port == 0) // FIXME hack
SDLGamepadDevice::UpdateRumble();
2019-10-19 16:34:24 +00:00
#define SET_FLAG(field, mask, expr) (field) = ((expr) ? ((field) & ~(mask)) : ((field) | (mask)))
2015-08-29 18:23:16 +00:00
SDL_Event event;
while (SDL_PollEvent(&event))
{
switch (event.type)
{
2019-08-14 20:48:34 +00:00
#if HOST_OS != OS_DARWIN
case SDL_QUIT:
dc_exit();
break;
2019-08-14 20:48:34 +00:00
2015-08-29 18:23:16 +00:00
case SDL_KEYDOWN:
case SDL_KEYUP:
if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_RETURN && (event.key.keysym.mod & KMOD_LALT))
2019-02-07 22:44:30 +00:00
{
if (window_fullscreen)
SDL_SetWindowFullscreen(window, 0);
else
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
window_fullscreen = !window_fullscreen;
}
else
{
sdl_kb_gamepad->gamepad_btn_input(event.key.keysym.sym, event.type == SDL_KEYDOWN);
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);
2015-08-29 18:23:16 +00:00
}
break;
case SDL_TEXTINPUT:
for (int i = 0; event.text.text[i] != '\0'; i++)
sdl_keyboard->keyboard_character(event.text.text[i]);
break;
2019-08-14 07:20:24 +00:00
#endif
2015-08-29 18:23:16 +00:00
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
{
std::shared_ptr<SDLGamepadDevice> device = SDLGamepadDevice::GetSDLGamepad((SDL_JoystickID)event.jbutton.which);
2019-02-12 14:56:44 +00:00
if (device != NULL)
device->gamepad_btn_input(event.jbutton.button, event.type == SDL_JOYBUTTONDOWN);
2015-08-29 18:23:16 +00:00
}
break;
case SDL_JOYAXISMOTION:
{
std::shared_ptr<SDLGamepadDevice> device = SDLGamepadDevice::GetSDLGamepad((SDL_JoystickID)event.jaxis.which);
2019-02-12 14:56:44 +00:00
if (device != NULL)
device->gamepad_axis_input(event.jaxis.axis, event.jaxis.value);
2015-08-29 18:23:16 +00:00
}
break;
case SDL_JOYHATMOTION:
{
std::shared_ptr<SDLGamepadDevice> device = SDLGamepadDevice::GetSDLGamepad((SDL_JoystickID)event.jhat.which);
if (device != NULL)
{
u32 hatid = (event.jhat.hat + 1) << 8;
if (event.jhat.value & SDL_HAT_UP)
{
device->gamepad_btn_input(hatid + 0, true);
device->gamepad_btn_input(hatid + 1, false);
}
else if (event.jhat.value & SDL_HAT_DOWN)
{
device->gamepad_btn_input(hatid + 0, false);
device->gamepad_btn_input(hatid + 1, true);
}
else
{
device->gamepad_btn_input(hatid + 0, false);
device->gamepad_btn_input(hatid + 1, false);
}
if (event.jhat.value & SDL_HAT_LEFT)
{
device->gamepad_btn_input(hatid + 2, true);
device->gamepad_btn_input(hatid + 3, false);
}
else if (event.jhat.value & SDL_HAT_RIGHT)
{
device->gamepad_btn_input(hatid + 2, false);
device->gamepad_btn_input(hatid + 3, true);
}
else
{
device->gamepad_btn_input(hatid + 2, false);
device->gamepad_btn_input(hatid + 3, false);
}
}
}
break;
2019-08-14 07:20:24 +00:00
#if HOST_OS != OS_DARWIN
2015-08-29 18:23:16 +00:00
case SDL_MOUSEMOTION:
2019-02-07 22:44:30 +00:00
set_mouse_position(event.motion.x, event.motion.y);
SET_FLAG(mo_buttons, 1 << 2, event.motion.state & SDL_BUTTON_LMASK);
SET_FLAG(mo_buttons, 1 << 1, event.motion.state & SDL_BUTTON_RMASK);
SET_FLAG(mo_buttons, 1 << 3, event.motion.state & SDL_BUTTON_MMASK);
2015-08-29 18:23:16 +00:00
break;
2019-02-07 22:44:30 +00:00
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
set_mouse_position(event.button.x, event.button.y);
switch (event.button.button)
{
case SDL_BUTTON_LEFT:
SET_FLAG(mo_buttons, 1 << 2, event.button.state == SDL_PRESSED);
break;
case SDL_BUTTON_RIGHT:
SET_FLAG(mo_buttons, 1 << 1, event.button.state == SDL_PRESSED);
break;
case SDL_BUTTON_MIDDLE:
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);
2015-08-29 18:23:16 +00:00
break;
case SDL_MOUSEWHEEL:
mo_wheel_delta -= event.wheel.y * 35;
break;
2019-08-14 07:20:24 +00:00
#endif
2019-02-12 14:56:44 +00:00
case SDL_JOYDEVICEADDED:
sdl_open_joystick(event.jdevice.which);
break;
2019-02-12 14:56:44 +00:00
case SDL_JOYDEVICEREMOVED:
sdl_close_joystick((SDL_JoystickID)event.jdevice.which);
break;
2015-08-29 18:23:16 +00:00
}
}
}
2015-08-29 18:23:16 +00:00
void sdl_window_set_text(const char* text)
{
2019-08-14 07:20:24 +00:00
if (window)
{
SDL_SetWindowTitle(window, text); // *TODO* Set Icon also...
}
2015-08-29 18:23:16 +00:00
}
2019-08-14 07:20:24 +00:00
#if HOST_OS != OS_DARWIN
static void get_window_state()
{
u32 flags = SDL_GetWindowFlags(window);
window_fullscreen = flags & SDL_WINDOW_FULLSCREEN_DESKTOP;
window_maximized = flags & SDL_WINDOW_MAXIMIZED;
if (!window_fullscreen && !window_maximized)
SDL_GetWindowSize(window, &window_width, &window_height);
}
void sdl_recreate_window(u32 flags)
2015-08-29 18:23:16 +00:00
{
int x = SDL_WINDOWPOS_UNDEFINED;
int y = SDL_WINDOWPOS_UNDEFINED;
window_width = cfgLoadInt("window", "width", window_width);
window_height = cfgLoadInt("window", "height", window_height);
window_fullscreen = cfgLoadBool("window", "fullscreen", window_fullscreen);
window_maximized = cfgLoadBool("window", "maximized", window_maximized);
if (window != nullptr)
2015-08-29 18:23:16 +00:00
{
SDL_GetWindowPosition(window, &x, &y);
get_window_state();
SDL_DestroyWindow(window);
2015-08-29 18:23:16 +00:00
}
2019-10-05 09:50:14 +00:00
#ifdef TARGET_PANDORA
flags |= SDL_FULLSCREEN;
2019-10-05 09:50:14 +00:00
#else
flags |= SDL_SWSURFACE | SDL_WINDOW_RESIZABLE;
if (window_fullscreen)
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
else if (window_maximized)
flags |= SDL_WINDOW_MAXIMIZED;
2019-10-05 09:50:14 +00:00
#endif
window = SDL_CreateWindow("Flycast", x, y, window_width, window_height, flags);
if (!window)
die("error creating SDL window");
#ifdef USE_VULKAN
theVulkanContext.SetWindow(window, nullptr);
2019-10-05 09:50:14 +00:00
#endif
theGLContext.SetWindow(window);
2015-08-29 18:23:16 +00:00
}
2015-09-12 18:19:28 +00:00
void sdl_window_create()
{
if (SDL_WasInit(SDL_INIT_VIDEO) == 0)
{
if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0)
{
die("error initializing SDL Video subsystem");
}
}
2019-10-19 16:34:24 +00:00
InitRenderApi();
}
2019-10-05 09:50:14 +00:00
void sdl_window_destroy()
{
get_window_state();
cfgSaveInt("window", "width", window_width);
cfgSaveInt("window", "height", window_height);
cfgSaveBool("window", "maximized", window_maximized);
cfgSaveBool("window", "fullscreen", window_fullscreen);
TermRenderApi();
2019-10-05 09:50:14 +00:00
SDL_DestroyWindow(window);
}
2019-12-22 22:49:52 +00:00
#ifdef _WIN32
#include <windows.h>
2019-12-22 22:49:52 +00:00
HWND sdl_get_native_hwnd()
{
SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
SDL_GetWindowWMInfo(window, &wmInfo);
return wmInfo.info.win.window;
}
2019-08-14 07:20:24 +00:00
#endif
#endif // HOST_OS != OS_DARWIN