mirror of
https://github.com/libretro/RetroArch
synced 2025-02-09 00:40:09 +00:00
Add WGL context.
This commit is contained in:
parent
9a07e23ecb
commit
dd6d27c108
28
Makefile.win
28
Makefile.win
@ -20,14 +20,14 @@ OBJ = retroarch.o \
|
||||
audio/utils.o \
|
||||
audio/null.o \
|
||||
input/null.o \
|
||||
fifo_buffer.o \
|
||||
gfx/null.o
|
||||
|
||||
JOBJ := conf/config_file.o \
|
||||
tools/retroarch-joyconfig.o \
|
||||
compat/compat.o \
|
||||
input/input_common.o \
|
||||
input/dinput.o \
|
||||
input/sdl_joypad.o
|
||||
input/dinput.o
|
||||
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
@ -35,7 +35,6 @@ CXX = g++
|
||||
HAVE_DINPUT = 1
|
||||
HAVE_XAUDIO = 1
|
||||
HAVE_DSOUND = 1
|
||||
HAVE_SDL = 1
|
||||
HAVE_OPENGL = 1
|
||||
HAVE_DYLIB = 1
|
||||
HAVE_NETPLAY = 1
|
||||
@ -44,6 +43,7 @@ HAVE_THREADS = 1
|
||||
DYNAMIC = 1
|
||||
|
||||
ifeq ($(SLIM),)
|
||||
HAVE_SDL = 1
|
||||
HAVE_SDL_IMAGE = 1
|
||||
HAVE_XML = 1
|
||||
HAVE_FREETYPE = 1
|
||||
@ -57,21 +57,28 @@ endif
|
||||
libretro ?= -lretro
|
||||
|
||||
LIBS = -lm
|
||||
DEFINES = -I. -DHAVE_CONFIGFILE -DHAVE_SDL -DHAVE_SCREENSHOTS -DHAVE_BSV_MOVIE -DPACKAGE_VERSION=\"0.9.7\"
|
||||
DEFINES = -I. -DHAVE_CONFIGFILE -DHAVE_SCREENSHOTS -DHAVE_BSV_MOVIE -DPACKAGE_VERSION=\"0.9.7\"
|
||||
LDFLAGS = -L. -static-libgcc
|
||||
|
||||
ifeq ($(TDM_GCC),)
|
||||
LDCXXFLAGS += -static-libstdc++
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_SDL), 1)
|
||||
OBJ += gfx/sdl_gfx.o gfx/gl.o gfx/math/matrix.o gfx/fonts/freetype.o gfx/context/sdl_ctx.o gfx/gfx_context.o input/sdl_input.o input/sdl_joypad.o audio/sdl_audio.o fifo_buffer.o
|
||||
OBJ += gfx/scaler/scaler.o gfx/scaler/pixconv.o gfx/scaler/scaler_int.o gfx/scaler/filter.o
|
||||
LIBS += -lSDL
|
||||
DEFINES += -ISDL -DHAVE_SDL
|
||||
ifeq ($(SCALER_NO_SIMD), 1)
|
||||
DEFINES += -DSCALER_NO_SIMD
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_SDL), 1)
|
||||
OBJ += gfx/scaler/scaler.o gfx/scaler/pixconv.o gfx/scaler/scaler_int.o gfx/scaler/filter.o
|
||||
else ifeq ($(HAVE_FFMPEG), 1)
|
||||
OBJ += gfx/scaler/scaler.o gfx/scaler/pixconv.o gfx/scaler/scaler_int.o gfx/scaler/filter.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_SDL), 1)
|
||||
OBJ += gfx/sdl_gfx.o gfx/context/sdl_ctx.o input/sdl_input.o input/sdl_joypad.o audio/sdl_audio.o
|
||||
JOBJ += input/sdl_joypad.o
|
||||
LIBS += -lSDL
|
||||
DEFINES += -ISDL -DHAVE_SDL
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_THREADS), 1)
|
||||
@ -80,8 +87,9 @@ ifeq ($(HAVE_THREADS), 1)
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_OPENGL), 1)
|
||||
OBJ += gfx/gl.o gfx/math/matrix.o gfx/fonts/freetype.o gfx/gfx_context.o gfx/context/wgl_ctx.o
|
||||
DEFINES += -DHAVE_OPENGL
|
||||
LIBS += -lopengl32
|
||||
LIBS += -lopengl32 -lgdi32
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_SDL_IMAGE), 1)
|
||||
|
@ -60,6 +60,7 @@ enum
|
||||
|
||||
INPUT_SDL,
|
||||
INPUT_X,
|
||||
INPUT_DINPUT,
|
||||
INPUT_PS3,
|
||||
INPUT_XENON360,
|
||||
INPUT_WII,
|
||||
@ -130,6 +131,8 @@ enum
|
||||
#define INPUT_DEFAULT_DRIVER INPUT_XENON360
|
||||
#elif defined(_XBOX360) || defined(_XBOX) || defined(HAVE_XINPUT2) || defined(HAVE_XINPUT_XBOX1)
|
||||
#define INPUT_DEFAULT_DRIVER INPUT_XINPUT
|
||||
#elif defined(_WIN32)
|
||||
#define INPUT_DEFAULT_DRIVER INPUT_DINPUT
|
||||
#elif defined(HAVE_SDL)
|
||||
#define INPUT_DEFAULT_DRIVER INPUT_SDL
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
|
1
driver.h
1
driver.h
@ -278,6 +278,7 @@ extern const video_driver_t video_vg;
|
||||
extern const video_driver_t video_ext;
|
||||
extern const video_driver_t video_null;
|
||||
extern const input_driver_t input_sdl;
|
||||
extern const input_driver_t input_dinput;
|
||||
extern const input_driver_t input_x;
|
||||
extern const input_driver_t input_ps3;
|
||||
extern const input_driver_t input_xenon360;
|
||||
|
@ -312,7 +312,7 @@ static bool gfx_ctx_set_video_mode(
|
||||
|
||||
driver.display_type = RARCH_DISPLAY_X11;
|
||||
driver.video_display = (uintptr_t)g_dpy;
|
||||
driver.video_window = (Window)g_win;
|
||||
driver.video_window = (uintptr_t)g_win;
|
||||
|
||||
return true;
|
||||
|
||||
|
@ -24,6 +24,8 @@
|
||||
#ifdef __APPLE__
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#include <OpenGL/gl.h>
|
||||
#else
|
||||
#include "SDL/SDL_syswm.h"
|
||||
#endif
|
||||
|
||||
#include "SDL.h"
|
||||
|
371
gfx/context/wgl_ctx.c
Normal file
371
gfx/context/wgl_ctx.c
Normal file
@ -0,0 +1,371 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2012 - Daniel De Matteis
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Win32/WGL context.
|
||||
|
||||
#include "../../driver.h"
|
||||
#include "../gfx_context.h"
|
||||
#include "../gl_common.h"
|
||||
#include "../gfx_common.h"
|
||||
#include <windows.h>
|
||||
|
||||
static HWND g_hwnd;
|
||||
static HGLRC g_hrc;
|
||||
static HDC g_hdc;
|
||||
|
||||
static bool g_quit;
|
||||
static bool g_inited;
|
||||
static unsigned g_interval;
|
||||
|
||||
static unsigned g_resize_width;
|
||||
static unsigned g_resize_height;
|
||||
static bool g_resized;
|
||||
|
||||
static bool g_restore_desktop;
|
||||
|
||||
static void gfx_ctx_get_video_size(unsigned *width, unsigned *height);
|
||||
static void gfx_ctx_destroy(void);
|
||||
|
||||
static BOOL (APIENTRY *p_swap_interval)(int);
|
||||
|
||||
static void setup_pixel_format(HDC hdc)
|
||||
{
|
||||
PIXELFORMATDESCRIPTOR pfd = {0};
|
||||
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
||||
pfd.nVersion = 1;
|
||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
|
||||
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||
pfd.cColorBits = 32;
|
||||
pfd.cDepthBits = 0;
|
||||
pfd.cStencilBits = 0;
|
||||
pfd.iLayerType = PFD_MAIN_PLANE;
|
||||
|
||||
SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd);
|
||||
}
|
||||
|
||||
static void create_gl_context(HWND hwnd)
|
||||
{
|
||||
g_hdc = GetDC(hwnd);
|
||||
setup_pixel_format(g_hdc);
|
||||
|
||||
g_hrc = wglCreateContext(g_hdc);
|
||||
if (g_hrc)
|
||||
{
|
||||
if (wglMakeCurrent(g_hdc, g_hrc))
|
||||
g_inited = true;
|
||||
else
|
||||
g_quit = true;
|
||||
}
|
||||
else
|
||||
g_quit = true;
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
|
||||
WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_SYSCOMMAND:
|
||||
// Prevent screensavers, etc, while running.
|
||||
switch (wparam)
|
||||
{
|
||||
case SC_SCREENSAVE:
|
||||
case SC_MONITORPOWER:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_CREATE:
|
||||
create_gl_context(hwnd);
|
||||
return 0;
|
||||
|
||||
case WM_CLOSE:
|
||||
case WM_DESTROY:
|
||||
case WM_QUIT:
|
||||
g_quit = true;
|
||||
return 0;
|
||||
|
||||
case WM_SIZE:
|
||||
// Do not send resize message if we minimize.
|
||||
if (wparam != SIZE_MAXHIDE && wparam != SIZE_MINIMIZED)
|
||||
{
|
||||
g_resize_width = LOWORD(lparam);
|
||||
g_resize_height = HIWORD(lparam);
|
||||
g_resized = true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return DefWindowProc(hwnd, message, wparam, lparam);
|
||||
}
|
||||
|
||||
static void gfx_ctx_swap_interval(unsigned interval)
|
||||
{
|
||||
g_interval = interval;
|
||||
|
||||
if (g_hrc && p_swap_interval)
|
||||
{
|
||||
RARCH_LOG("[WGL]: wglSwapInterval(%u)\n", g_interval);
|
||||
if (!p_swap_interval(g_interval))
|
||||
RARCH_WARN("[WGL]: wglSwapInterval() failed.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_ctx_check_window(bool *quit,
|
||||
bool *resize, unsigned *width, unsigned *height, unsigned frame_count)
|
||||
{
|
||||
(void)frame_count;
|
||||
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, g_hwnd, 0, 0, PM_REMOVE))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
*quit = g_quit;
|
||||
if (g_resized)
|
||||
{
|
||||
*resize = true;
|
||||
*width = g_resize_width;
|
||||
*height = g_resize_height;
|
||||
g_resized = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_ctx_swap_buffers(void)
|
||||
{
|
||||
SwapBuffers(g_hdc);
|
||||
}
|
||||
|
||||
static void gfx_ctx_set_resize(unsigned width, unsigned height)
|
||||
{
|
||||
(void)width;
|
||||
(void)height;
|
||||
}
|
||||
|
||||
static void gfx_ctx_update_window_title(bool reset)
|
||||
{
|
||||
if (reset)
|
||||
gfx_window_title_reset();
|
||||
|
||||
char buf[128];
|
||||
if (gfx_window_title(buf, sizeof(buf)))
|
||||
SetWindowText(g_hwnd, buf);
|
||||
}
|
||||
|
||||
static void gfx_ctx_get_video_size(unsigned *width, unsigned *height)
|
||||
{
|
||||
if (!g_hwnd)
|
||||
{
|
||||
RECT screen_rect;
|
||||
GetClientRect(GetDesktopWindow(), &screen_rect);
|
||||
*width = screen_rect.right - screen_rect.left;
|
||||
*height = screen_rect.bottom - screen_rect.top;
|
||||
}
|
||||
else
|
||||
{
|
||||
*width = g_resize_width;
|
||||
*height = g_resize_height;
|
||||
}
|
||||
}
|
||||
|
||||
static bool gfx_ctx_init(void)
|
||||
{
|
||||
if (g_inited)
|
||||
return false;
|
||||
|
||||
g_quit = false;
|
||||
g_restore_desktop = false;
|
||||
|
||||
WNDCLASSEX wndclass = {0};
|
||||
wndclass.cbSize = sizeof(wndclass);
|
||||
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
||||
wndclass.lpfnWndProc = WndProc;
|
||||
wndclass.hInstance = GetModuleHandle(NULL);
|
||||
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wndclass.lpszClassName = "RetroArch";
|
||||
|
||||
if (!RegisterClassEx(&wndclass))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool set_fullscreen(unsigned width, unsigned height)
|
||||
{
|
||||
DEVMODE devmode;
|
||||
memset(&devmode, 0, sizeof(devmode));
|
||||
devmode.dmSize = sizeof(DEVMODE);
|
||||
devmode.dmPelsWidth = width;
|
||||
devmode.dmPelsHeight = height;
|
||||
devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
|
||||
|
||||
return ChangeDisplaySettings(&devmode, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static bool gfx_ctx_set_video_mode(
|
||||
unsigned width, unsigned height,
|
||||
unsigned bits, bool fullscreen)
|
||||
{
|
||||
(void)bits;
|
||||
|
||||
DWORD style;
|
||||
RECT screen_rect;
|
||||
GetClientRect(GetDesktopWindow(), &screen_rect);
|
||||
|
||||
g_resize_width = width;
|
||||
g_resize_height = height;
|
||||
|
||||
if (fullscreen)
|
||||
{
|
||||
style = WS_POPUP | WS_VISIBLE;
|
||||
|
||||
AdjustWindowRect(&screen_rect, style, FALSE);
|
||||
width = screen_rect.right - screen_rect.left;
|
||||
height = screen_rect.bottom - screen_rect.top;
|
||||
|
||||
if (!set_fullscreen(width, height))
|
||||
goto error;
|
||||
|
||||
g_restore_desktop = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
style = WS_OVERLAPPEDWINDOW;
|
||||
RECT rect = {0};
|
||||
rect.right = width;
|
||||
rect.bottom = height;
|
||||
AdjustWindowRect(&rect, style, FALSE);
|
||||
width = rect.right - rect.left;
|
||||
height = rect.bottom - rect.top;
|
||||
}
|
||||
|
||||
g_hwnd = CreateWindowEx(0, "RetroArch", "RetroArch", style,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, width, height,
|
||||
NULL, NULL, NULL, NULL);
|
||||
|
||||
if (!g_hwnd)
|
||||
goto error;
|
||||
|
||||
if (!fullscreen)
|
||||
{
|
||||
ShowWindow(g_hwnd, SW_RESTORE);
|
||||
UpdateWindow(g_hwnd);
|
||||
SetForegroundWindow(g_hwnd);
|
||||
SetFocus(g_hwnd);
|
||||
}
|
||||
|
||||
// Wait until GL context is created (or failed to do so ...)
|
||||
MSG msg;
|
||||
while (!g_inited && !g_quit && GetMessage(&msg, g_hwnd, 0, 0))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
if (g_quit)
|
||||
goto error;
|
||||
|
||||
p_swap_interval = (BOOL (APIENTRY *)(int))wglGetProcAddress("wglSwapIntervalEXT");
|
||||
|
||||
gfx_ctx_swap_interval(g_interval);
|
||||
|
||||
driver.display_type = RARCH_DISPLAY_WIN32;
|
||||
driver.video_display = 0;
|
||||
driver.video_window = (uintptr_t)g_hwnd;
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
gfx_ctx_destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
static void gfx_ctx_destroy(void)
|
||||
{
|
||||
if (g_hrc)
|
||||
{
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
wglDeleteContext(g_hrc);
|
||||
g_hrc = NULL;
|
||||
}
|
||||
|
||||
if (g_hwnd && g_hdc)
|
||||
{
|
||||
ReleaseDC(g_hwnd, g_hdc);
|
||||
g_hdc = NULL;
|
||||
}
|
||||
|
||||
if (g_hwnd)
|
||||
{
|
||||
DestroyWindow(g_hwnd);
|
||||
UnregisterClass("RetroArch", GetModuleHandle(NULL));
|
||||
g_hwnd = NULL;
|
||||
}
|
||||
|
||||
if (g_restore_desktop)
|
||||
{
|
||||
ChangeDisplaySettings(NULL, 0);
|
||||
g_restore_desktop = false;
|
||||
}
|
||||
|
||||
g_inited = false;
|
||||
}
|
||||
|
||||
static void gfx_ctx_input_driver(const input_driver_t **input, void **input_data)
|
||||
{
|
||||
void *dinput = input_dinput.init();
|
||||
*input = dinput ? &input_dinput : NULL;
|
||||
*input_data = dinput;
|
||||
}
|
||||
|
||||
static bool gfx_ctx_has_focus(void)
|
||||
{
|
||||
if (!g_inited)
|
||||
return false;
|
||||
|
||||
return GetFocus() == g_hwnd;
|
||||
}
|
||||
|
||||
static gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol)
|
||||
{
|
||||
return (gfx_ctx_proc_t)wglGetProcAddress(symbol);
|
||||
}
|
||||
|
||||
static bool gfx_ctx_bind_api(enum gfx_ctx_api api)
|
||||
{
|
||||
return api == GFX_CTX_OPENGL_API;
|
||||
}
|
||||
|
||||
const gfx_ctx_driver_t gfx_ctx_wgl = {
|
||||
gfx_ctx_init,
|
||||
gfx_ctx_destroy,
|
||||
gfx_ctx_bind_api,
|
||||
gfx_ctx_swap_interval,
|
||||
gfx_ctx_set_video_mode,
|
||||
gfx_ctx_get_video_size,
|
||||
NULL,
|
||||
gfx_ctx_update_window_title,
|
||||
gfx_ctx_check_window,
|
||||
gfx_ctx_set_resize,
|
||||
gfx_ctx_has_focus,
|
||||
gfx_ctx_swap_buffers,
|
||||
gfx_ctx_input_driver,
|
||||
gfx_ctx_get_proc_address,
|
||||
"wgl",
|
||||
};
|
||||
|
@ -334,7 +334,7 @@ static bool gfx_ctx_set_video_mode(
|
||||
|
||||
driver.display_type = RARCH_DISPLAY_X11;
|
||||
driver.video_display = (uintptr_t)g_dpy;
|
||||
driver.video_window = (Window)g_win;
|
||||
driver.video_window = (uintptr_t)g_win;
|
||||
|
||||
return true;
|
||||
|
||||
|
@ -27,6 +27,9 @@ static const gfx_ctx_driver_t *gfx_ctx_drivers[] = {
|
||||
#if defined(HAVE_VIDEOCORE)
|
||||
&gfx_ctx_videocore,
|
||||
#endif
|
||||
#if defined(_WIN32) && defined(HAVE_OPENGL)
|
||||
&gfx_ctx_wgl,
|
||||
#endif
|
||||
#if defined(HAVE_X11) && defined(HAVE_OPENGL) && !defined(HAVE_OPENGLES)
|
||||
&gfx_ctx_glx,
|
||||
#endif
|
||||
|
@ -23,10 +23,6 @@
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SDL) && !defined(__APPLE__)
|
||||
#include "SDL_syswm.h"
|
||||
#endif
|
||||
|
||||
enum gfx_ctx_api
|
||||
{
|
||||
GFX_CTX_OPENGL_API,
|
||||
@ -102,6 +98,7 @@ extern const gfx_ctx_driver_t gfx_ctx_x_egl;
|
||||
extern const gfx_ctx_driver_t gfx_ctx_glx;
|
||||
extern const gfx_ctx_driver_t gfx_ctx_drm_egl;
|
||||
extern const gfx_ctx_driver_t gfx_ctx_ps3;
|
||||
extern const gfx_ctx_driver_t gfx_ctx_wgl;
|
||||
extern const gfx_ctx_driver_t gfx_ctx_videocore;
|
||||
|
||||
const gfx_ctx_driver_t *gfx_ctx_find_driver(const char *ident); // Finds driver with ident. Does not initialize.
|
||||
|
@ -34,6 +34,10 @@
|
||||
#include "fonts/fonts.h"
|
||||
#endif
|
||||
|
||||
#ifndef __APPLE__ // Broken on OSX.
|
||||
#include "SDL/SDL_syswm.h"
|
||||
#endif
|
||||
|
||||
static void convert_15bit_15bit_direct(uint16_t *out, unsigned outpitch, const uint16_t *input, unsigned width, unsigned height, unsigned pitch, const SDL_PixelFormat *fmt);
|
||||
static void convert_32bit_32bit_direct(uint32_t *out, unsigned outpitch, const uint32_t *input, unsigned width, unsigned height, unsigned pitch, const SDL_PixelFormat *fmt);
|
||||
static void convert_15bit_15bit_shift(uint16_t *out, unsigned outpitch, const uint16_t *input, unsigned width, unsigned height, unsigned pitch, const SDL_PixelFormat *fmt);
|
||||
|
360
input/dinput.c
360
input/dinput.c
@ -24,18 +24,291 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
// Context has to be global as joypads also ride on this context.
|
||||
static LPDIRECTINPUT8 g_ctx;
|
||||
|
||||
struct dinput_input
|
||||
{
|
||||
LPDIRECTINPUTDEVICE8 keyboard;
|
||||
LPDIRECTINPUTDEVICE8 mouse; // TODO.
|
||||
const rarch_joypad_driver_t *joypad;
|
||||
uint8_t state[256];
|
||||
int rk_to_di_lut[RETROK_LAST];
|
||||
};
|
||||
|
||||
struct dinput_joypad
|
||||
{
|
||||
LPDIRECTINPUTDEVICE8 joypad;
|
||||
DIJOYSTATE2 joy_state;
|
||||
};
|
||||
|
||||
struct key_map
|
||||
{
|
||||
int di;
|
||||
int rk;
|
||||
};
|
||||
|
||||
static const struct key_map rk_to_di[] = {
|
||||
{ DIK_LEFT, RETROK_LEFT },
|
||||
{ DIK_RIGHT, RETROK_RIGHT },
|
||||
{ DIK_UP, RETROK_UP },
|
||||
{ DIK_DOWN, RETROK_DOWN },
|
||||
{ DIK_RETURN, RETROK_RETURN },
|
||||
{ DIK_TAB, RETROK_TAB },
|
||||
{ DIK_INSERT, RETROK_INSERT },
|
||||
{ DIK_DELETE, RETROK_DELETE },
|
||||
{ DIK_RSHIFT, RETROK_RSHIFT },
|
||||
{ DIK_LSHIFT, RETROK_LSHIFT },
|
||||
{ DIK_LCONTROL, RETROK_LCTRL },
|
||||
{ DIK_END, RETROK_END },
|
||||
{ DIK_HOME, RETROK_HOME },
|
||||
{ DIK_NEXT, RETROK_PAGEDOWN },
|
||||
{ DIK_PRIOR, RETROK_PAGEUP },
|
||||
{ DIK_LALT, RETROK_LALT },
|
||||
{ DIK_SPACE, RETROK_SPACE },
|
||||
{ DIK_ESCAPE, RETROK_ESCAPE },
|
||||
{ DIK_BACKSPACE, RETROK_BACKSPACE },
|
||||
{ DIK_NUMPADENTER, RETROK_KP_ENTER },
|
||||
{ DIK_NUMPADPLUS, RETROK_KP_PLUS },
|
||||
{ DIK_NUMPADMINUS, RETROK_KP_MINUS },
|
||||
{ DIK_NUMPADSTAR, RETROK_KP_MULTIPLY },
|
||||
{ DIK_NUMPADSLASH, RETROK_KP_DIVIDE },
|
||||
{ DIK_GRAVE, RETROK_BACKQUOTE },
|
||||
{ DIK_PAUSE, RETROK_PAUSE },
|
||||
{ DIK_NUMPAD0, RETROK_KP0 },
|
||||
{ DIK_NUMPAD1, RETROK_KP1 },
|
||||
{ DIK_NUMPAD2, RETROK_KP2 },
|
||||
{ DIK_NUMPAD3, RETROK_KP3 },
|
||||
{ DIK_NUMPAD4, RETROK_KP4 },
|
||||
{ DIK_NUMPAD5, RETROK_KP5 },
|
||||
{ DIK_NUMPAD6, RETROK_KP6 },
|
||||
{ DIK_NUMPAD7, RETROK_KP7 },
|
||||
{ DIK_NUMPAD8, RETROK_KP8 },
|
||||
{ DIK_NUMPAD9, RETROK_KP9 },
|
||||
{ DIK_0, RETROK_0 },
|
||||
{ DIK_1, RETROK_1 },
|
||||
{ DIK_2, RETROK_2 },
|
||||
{ DIK_3, RETROK_3 },
|
||||
{ DIK_4, RETROK_4 },
|
||||
{ DIK_5, RETROK_5 },
|
||||
{ DIK_6, RETROK_6 },
|
||||
{ DIK_7, RETROK_7 },
|
||||
{ DIK_8, RETROK_8 },
|
||||
{ DIK_9, RETROK_9 },
|
||||
{ DIK_F1, RETROK_F1 },
|
||||
{ DIK_F2, RETROK_F2 },
|
||||
{ DIK_F3, RETROK_F3 },
|
||||
{ DIK_F4, RETROK_F4 },
|
||||
{ DIK_F5, RETROK_F5 },
|
||||
{ DIK_F6, RETROK_F6 },
|
||||
{ DIK_F7, RETROK_F7 },
|
||||
{ DIK_F8, RETROK_F8 },
|
||||
{ DIK_F9, RETROK_F9 },
|
||||
{ DIK_F10, RETROK_F10 },
|
||||
{ DIK_F11, RETROK_F11 },
|
||||
{ DIK_F12, RETROK_F12 },
|
||||
{ DIK_A, RETROK_a },
|
||||
{ DIK_B, RETROK_b },
|
||||
{ DIK_C, RETROK_c },
|
||||
{ DIK_D, RETROK_d },
|
||||
{ DIK_E, RETROK_e },
|
||||
{ DIK_F, RETROK_f },
|
||||
{ DIK_G, RETROK_g },
|
||||
{ DIK_H, RETROK_h },
|
||||
{ DIK_I, RETROK_i },
|
||||
{ DIK_J, RETROK_j },
|
||||
{ DIK_K, RETROK_k },
|
||||
{ DIK_L, RETROK_l },
|
||||
{ DIK_M, RETROK_m },
|
||||
{ DIK_N, RETROK_n },
|
||||
{ DIK_O, RETROK_o },
|
||||
{ DIK_P, RETROK_p },
|
||||
{ DIK_Q, RETROK_q },
|
||||
{ DIK_R, RETROK_r },
|
||||
{ DIK_S, RETROK_s },
|
||||
{ DIK_T, RETROK_t },
|
||||
{ DIK_U, RETROK_u },
|
||||
{ DIK_V, RETROK_v },
|
||||
{ DIK_W, RETROK_w },
|
||||
{ DIK_X, RETROK_x },
|
||||
{ DIK_Y, RETROK_y },
|
||||
{ DIK_Z, RETROK_z },
|
||||
};
|
||||
|
||||
static void init_lut(int *lut)
|
||||
{
|
||||
for (unsigned i = 0; i < sizeof(rk_to_di) / sizeof(rk_to_di[0]); i++)
|
||||
lut[rk_to_di[i].rk] = rk_to_di[i].di;
|
||||
}
|
||||
|
||||
static unsigned g_joypad_cnt;
|
||||
static struct dinput_joypad g_pads[MAX_PLAYERS];
|
||||
|
||||
static void dinput_destroy(void)
|
||||
static void dinput_destroy_context(void)
|
||||
{
|
||||
if (g_ctx)
|
||||
{
|
||||
IDirectInput8_Release(g_ctx);
|
||||
g_ctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static bool dinput_init_context(void)
|
||||
{
|
||||
if (g_ctx)
|
||||
return true;
|
||||
|
||||
if (driver.display_type != RARCH_DISPLAY_WIN32)
|
||||
{
|
||||
RARCH_ERR("Cannot open DInput as no Win32 window is present.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
CoInitialize(NULL);
|
||||
|
||||
// Who said we shouldn't have same call signature in a COM API? <_<
|
||||
#ifdef __cplusplus
|
||||
if (FAILED(DirectInput8Create(
|
||||
GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8,
|
||||
(void**)&g_ctx, NULL)))
|
||||
#else
|
||||
if (FAILED(DirectInput8Create(
|
||||
GetModuleHandle(NULL), DIRECTINPUT_VERSION, &IID_IDirectInput8,
|
||||
(void**)&g_ctx, NULL)))
|
||||
#endif
|
||||
{
|
||||
RARCH_ERR("Failed to init DirectInput.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void *dinput_init(void)
|
||||
{
|
||||
if (!dinput_init_context())
|
||||
return NULL;
|
||||
|
||||
struct dinput_input *di = (struct dinput_input*)calloc(1, sizeof(*di));
|
||||
if (!di)
|
||||
return NULL;
|
||||
|
||||
#ifdef __cplusplus
|
||||
if (FAILED(IDirectInput8_CreateDevice(g_ctx, GUID_SysKeyboard, &di->keyboard, NULL)))
|
||||
#else
|
||||
if (FAILED(IDirectInput8_CreateDevice(g_ctx, &GUID_SysKeyboard, &di->keyboard, NULL)))
|
||||
#endif
|
||||
goto error;
|
||||
|
||||
IDirectInputDevice8_SetDataFormat(di->keyboard, &c_dfDIKeyboard);
|
||||
IDirectInputDevice8_SetCooperativeLevel(di->keyboard,
|
||||
(HWND)driver.video_window, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
|
||||
IDirectInputDevice8_Acquire(di->keyboard);
|
||||
|
||||
init_lut(di->rk_to_di_lut);
|
||||
di->joypad = input_joypad_init_first();
|
||||
|
||||
return di;
|
||||
|
||||
error:
|
||||
dinput_destroy_context();
|
||||
free(di);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void dinput_poll(void *data)
|
||||
{
|
||||
struct dinput_input *di = (struct dinput_input*)data;
|
||||
|
||||
memset(di->state, 0, sizeof(di->state));
|
||||
if (FAILED(IDirectInputDevice8_GetDeviceState(di->keyboard,
|
||||
sizeof(di->state), di->state)))
|
||||
{
|
||||
IDirectInputDevice8_Acquire(di->keyboard);
|
||||
IDirectInputDevice8_GetDeviceState(di->keyboard, sizeof(di->state), di->state);
|
||||
}
|
||||
|
||||
input_joypad_poll(di->joypad);
|
||||
}
|
||||
|
||||
static bool dinput_keyboard_pressed(struct dinput_input *di, unsigned key)
|
||||
{
|
||||
if (key >= RETROK_LAST)
|
||||
return false;
|
||||
|
||||
return di->state[di->rk_to_di_lut[key]] & 0x80;
|
||||
}
|
||||
|
||||
static bool dinput_is_pressed(struct dinput_input *di, const struct retro_keybind *binds,
|
||||
unsigned port, unsigned id)
|
||||
{
|
||||
if (id >= RARCH_BIND_LIST_END)
|
||||
return false;
|
||||
|
||||
const struct retro_keybind *bind = &binds[id];
|
||||
return dinput_keyboard_pressed(di, bind->key) || input_joypad_pressed(di->joypad, port, bind);
|
||||
}
|
||||
|
||||
static bool dinput_key_pressed(void *data, int key)
|
||||
{
|
||||
return dinput_is_pressed((struct dinput_input*)data, g_settings.input.binds[0], 0, key);
|
||||
}
|
||||
|
||||
static int16_t dinput_input_state(void *data,
|
||||
const struct retro_keybind **binds, unsigned port,
|
||||
unsigned device, unsigned index, unsigned id)
|
||||
{
|
||||
struct dinput_input *di = (struct dinput_input*)data;
|
||||
switch (device)
|
||||
{
|
||||
case RETRO_DEVICE_JOYPAD:
|
||||
return dinput_is_pressed(di, binds[port], port, id);
|
||||
|
||||
case RETRO_DEVICE_KEYBOARD:
|
||||
return dinput_keyboard_pressed(di, id);
|
||||
|
||||
case RETRO_DEVICE_ANALOG:
|
||||
return input_joypad_analog(di->joypad, port, index, id, g_settings.input.binds[port]);
|
||||
|
||||
case RETRO_DEVICE_MOUSE: // TODO.
|
||||
case RETRO_DEVICE_LIGHTGUN:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void dinput_free(void *data)
|
||||
{
|
||||
struct dinput_input *di = (struct dinput_input*)data;
|
||||
LPDIRECTINPUT8 hold_ctx = g_ctx;
|
||||
|
||||
if (di)
|
||||
{
|
||||
g_ctx = NULL; // Prevent a joypad driver to kill our context prematurely.
|
||||
di->joypad->destroy();
|
||||
g_ctx = hold_ctx;
|
||||
|
||||
if (di->keyboard)
|
||||
IDirectInputDevice8_Release(di->keyboard);
|
||||
|
||||
free(di);
|
||||
}
|
||||
|
||||
dinput_destroy_context();
|
||||
}
|
||||
|
||||
const input_driver_t input_dinput = {
|
||||
dinput_init,
|
||||
dinput_poll,
|
||||
dinput_input_state,
|
||||
dinput_key_pressed,
|
||||
dinput_free,
|
||||
"dinput",
|
||||
};
|
||||
|
||||
static void dinput_joypad_destroy(void)
|
||||
{
|
||||
for (unsigned i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
@ -46,12 +319,11 @@ static void dinput_destroy(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (g_ctx)
|
||||
IDirectInput8_Release(g_ctx);
|
||||
|
||||
g_ctx = NULL;
|
||||
g_joypad_cnt = 0;
|
||||
memset(g_pads, 0, sizeof(g_pads));
|
||||
|
||||
// Can be blocked by global Dinput context.
|
||||
dinput_destroy_context();
|
||||
}
|
||||
|
||||
static BOOL CALLBACK enum_axes_cb(const DIDEVICEOBJECTINSTANCE *inst, void *p)
|
||||
@ -64,8 +336,8 @@ static BOOL CALLBACK enum_axes_cb(const DIDEVICEOBJECTINSTANCE *inst, void *p)
|
||||
range.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||
range.diph.dwHow = DIPH_BYID;
|
||||
range.diph.dwObj = inst->dwType;
|
||||
range.lMin = -32768;
|
||||
range.lMax = 32767;
|
||||
range.lMin = -0x7fff;
|
||||
range.lMax = 0x7fff;
|
||||
IDirectInputDevice8_SetProperty(joypad, DIPROP_RANGE, &range.diph);
|
||||
|
||||
return DIENUM_CONTINUE;
|
||||
@ -98,42 +370,19 @@ static BOOL CALLBACK enum_joypad_cb(const DIDEVICEINSTANCE *inst, void *p)
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
static bool dinput_init(void)
|
||||
static bool dinput_joypad_init(void)
|
||||
{
|
||||
if (driver.display_type != RARCH_DISPLAY_WIN32)
|
||||
{
|
||||
RARCH_ERR("Cannot open DInput as no Win32 window is present.\n");
|
||||
if (!dinput_init_context())
|
||||
return false;
|
||||
}
|
||||
|
||||
CoInitialize(NULL);
|
||||
|
||||
#ifdef __cplusplus
|
||||
if (FAILED(DirectInput8Create(
|
||||
GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8,
|
||||
(void**)&g_ctx, NULL)))
|
||||
#else
|
||||
if (FAILED(DirectInput8Create(
|
||||
GetModuleHandle(NULL), DIRECTINPUT_VERSION, &IID_IDirectInput8,
|
||||
(void**)&g_ctx, NULL)))
|
||||
#endif
|
||||
{
|
||||
RARCH_ERR("Failed to init DirectInput.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
RARCH_LOG("Enumerating DInput devices ...\n");
|
||||
IDirectInput8_EnumDevices(g_ctx, DI8DEVCLASS_GAMECTRL, enum_joypad_cb, NULL, DIEDFL_ATTACHEDONLY);
|
||||
RARCH_LOG("Done enumerating DInput devices ...\n");
|
||||
|
||||
RARCH_LOG("Enumerating DInput joypads ...\n");
|
||||
IDirectInput8_EnumDevices(g_ctx, DI8DEVCLASS_GAMECTRL,
|
||||
enum_joypad_cb, NULL, DIEDFL_ATTACHEDONLY);
|
||||
RARCH_LOG("Done enumerating DInput joypads ...\n");
|
||||
return true;
|
||||
|
||||
error:
|
||||
dinput_destroy();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool dinput_button(unsigned port_num, uint16_t joykey)
|
||||
static bool dinput_joypad_button(unsigned port_num, uint16_t joykey)
|
||||
{
|
||||
if (joykey == NO_BTN)
|
||||
return false;
|
||||
@ -180,7 +429,7 @@ static bool dinput_button(unsigned port_num, uint16_t joykey)
|
||||
return false;
|
||||
}
|
||||
|
||||
static int16_t dinput_axis(unsigned port_num, uint32_t joyaxis)
|
||||
static int16_t dinput_joypad_axis(unsigned port_num, uint32_t joyaxis)
|
||||
{
|
||||
if (joyaxis == AXIS_NONE)
|
||||
return 0;
|
||||
@ -214,9 +463,6 @@ static int16_t dinput_axis(unsigned port_num, uint32_t joyaxis)
|
||||
case 5: val = pad->joy_state.lRz; break;
|
||||
}
|
||||
|
||||
if (val < -0x7fff) // So abs() of -0x8000 can't mess us up.
|
||||
val = -0x7fff;
|
||||
|
||||
if (is_neg && val > 0)
|
||||
val = 0;
|
||||
else if (is_pos && val < 0)
|
||||
@ -225,7 +471,7 @@ static int16_t dinput_axis(unsigned port_num, uint32_t joyaxis)
|
||||
return val;
|
||||
}
|
||||
|
||||
static void dinput_poll(void)
|
||||
static void dinput_joypad_poll(void)
|
||||
{
|
||||
for (unsigned i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
@ -237,27 +483,35 @@ static void dinput_poll(void)
|
||||
|
||||
if (FAILED(IDirectInputDevice8_Poll(pad->joypad)))
|
||||
{
|
||||
IDirectInputDevice8_Acquire(pad->joypad);
|
||||
continue;
|
||||
if (FAILED(IDirectInputDevice8_Acquire(pad->joypad)))
|
||||
{
|
||||
memset(&pad->joy_state, 0, sizeof(DIJOYSTATE2));
|
||||
continue;
|
||||
}
|
||||
|
||||
// If this fails, something *really* bad must have happened.
|
||||
if (FAILED(IDirectInputDevice8_Poll(pad->joypad)))
|
||||
continue;
|
||||
}
|
||||
|
||||
IDirectInputDevice8_GetDeviceState(pad->joypad, sizeof(DIJOYSTATE2), &pad->joy_state);
|
||||
IDirectInputDevice8_GetDeviceState(pad->joypad,
|
||||
sizeof(DIJOYSTATE2), &pad->joy_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool dinput_query_pad(unsigned pad)
|
||||
static bool dinput_joypad_query_pad(unsigned pad)
|
||||
{
|
||||
return pad < MAX_PLAYERS && g_pads[pad].joypad;
|
||||
}
|
||||
|
||||
const rarch_joypad_driver_t dinput_joypad = {
|
||||
dinput_init,
|
||||
dinput_query_pad,
|
||||
dinput_destroy,
|
||||
dinput_button,
|
||||
dinput_axis,
|
||||
dinput_poll,
|
||||
"DInput",
|
||||
dinput_joypad_init,
|
||||
dinput_joypad_query_pad,
|
||||
dinput_joypad_destroy,
|
||||
dinput_joypad_button,
|
||||
dinput_joypad_axis,
|
||||
dinput_joypad_poll,
|
||||
"dinput",
|
||||
};
|
||||
|
||||
|
@ -109,6 +109,8 @@ const char *config_get_default_input(void)
|
||||
return "ps3";
|
||||
case INPUT_SDL:
|
||||
return "sdl";
|
||||
case INPUT_DINPUT:
|
||||
return "dinput";
|
||||
case INPUT_X:
|
||||
return "x";
|
||||
case INPUT_XENON360:
|
||||
|
Loading…
x
Reference in New Issue
Block a user