mirror of
https://github.com/Rosalie241/RMG.git
synced 2026-07-11 01:24:01 +02:00
3rdParty: apply SDL3 and SDL3_net patch to mupen64plus-core
This commit is contained in:
Vendored
+20
@@ -3,6 +3,8 @@
|
||||
#
|
||||
include(ExternalProject)
|
||||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
find_program(RUST_CARGO cargo)
|
||||
if(NO_RUST)
|
||||
set(BUILD_INPUT_GCA OFF)
|
||||
@@ -62,6 +64,20 @@ else()
|
||||
set(MAKE_DEBUG "0")
|
||||
endif()
|
||||
|
||||
# TODO: when SDL3_net has made a release,
|
||||
# remove the vendored SDL3_net
|
||||
set(SDL3NET_DIR ${CMAKE_CURRENT_SOURCE_DIR}/SDL_net)
|
||||
set(SDL3NET_SOURCES
|
||||
${SDL3NET_DIR}/src/SDL_net.c
|
||||
)
|
||||
add_library(SDL3_net STATIC ${SDL3NET_SOURCES})
|
||||
target_include_directories(SDL3_net PRIVATE ${SDL3NET_DIR}/include)
|
||||
set(SDL3NET_CFLAGS "-DUSE_SDL3NET -I${SDL3NET_DIR}/include")
|
||||
set(SDL3NET_LDLIBS "$<TARGET_FILE:SDL3_net>")
|
||||
if (WIN32)
|
||||
set(SDL3NET_LDLIBS "${SDL3NET_LDLIBS} -liphlpapi -lws2_32")
|
||||
endif (WIN32)
|
||||
|
||||
ExternalProject_Add(mupen64plus-core
|
||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/mupen64plus-core/
|
||||
|
||||
@@ -76,11 +92,15 @@ ExternalProject_Add(mupen64plus-core
|
||||
TARGET=${CORE_FILE} DEBUG=${MAKE_DEBUG}
|
||||
CC=${MAKE_CC_COMPILER} CXX=${MAKE_CXX_COMPILER}
|
||||
OPTFLAGS=${MAKE_OPTFLAGS}
|
||||
# TODO: when SDL3_net has made a release,
|
||||
# remove the vendored SDL3_net
|
||||
SDLNET_CFLAGS=${SDL3NET_CFLAGS} SDLNET_LDLIBS=${SDL3NET_LDLIBS}
|
||||
BUILD_IN_SOURCE False
|
||||
BUILD_ALWAYS True
|
||||
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/mupen64plus-core
|
||||
|
||||
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/mupen64plus-core/${CORE_FILE}
|
||||
DEPENDS SDL3_net
|
||||
)
|
||||
|
||||
set(APIDIR "${CMAKE_SOURCE_DIR}/Source/3rdParty/mupen64plus-core/src/api")
|
||||
|
||||
+28
-10
@@ -351,22 +351,40 @@ endif
|
||||
|
||||
# test for presence of SDL
|
||||
ifeq ($(origin SDL_CFLAGS) $(origin SDL_LDLIBS), undefined undefined)
|
||||
ifeq ($(shell $(PKG_CONFIG) --modversion sdl2 2>/dev/null),)
|
||||
$(error No SDL2 development libraries found!)
|
||||
endif
|
||||
ifeq ($(NETPLAY), 1)
|
||||
ifeq ($(shell $(PKG_CONFIG) --modversion SDL2_net 2>/dev/null),)
|
||||
$(error No SDL2_net development libraries found!)
|
||||
ifeq ($(shell $(PKG_CONFIG) --modversion sdl3 2>/dev/null),)
|
||||
ifeq ($(shell $(PKG_CONFIG) --modversion sdl2 2>/dev/null),)
|
||||
$(error No SDL3 or SDL2 development libraries found!)
|
||||
endif
|
||||
SDL_CFLAGS += $(shell $(PKG_CONFIG) --cflags SDL2_net)
|
||||
SDL_LDLIBS += $(shell $(PKG_CONFIG) --libs SDL2_net)
|
||||
SDL_CFLAGS += $(shell $(PKG_CONFIG) --cflags sdl2)
|
||||
SDL_LDLIBS += $(shell $(PKG_CONFIG) --libs sdl2)
|
||||
else
|
||||
SDL_CFLAGS += -DUSE_SDL3
|
||||
SDL_CFLAGS += $(shell $(PKG_CONFIG) --cflags sdl3)
|
||||
SDL_LDLIBS += $(shell $(PKG_CONFIG) --libs sdl3)
|
||||
endif
|
||||
SDL_CFLAGS += $(shell $(PKG_CONFIG) --cflags sdl2)
|
||||
SDL_LDLIBS += $(shell $(PKG_CONFIG) --libs sdl2)
|
||||
endif
|
||||
CFLAGS += $(SDL_CFLAGS)
|
||||
LDLIBS += $(SDL_LDLIBS)
|
||||
|
||||
# test for presence of SDL_net
|
||||
ifeq ($(NETPLAY), 1)
|
||||
ifeq ($(origin SDLNET_CFLAGS) $(origin SDLNET_LDLIBS), undefined undefined)
|
||||
ifeq ($(shell $(PKG_CONFIG) --modversion sdl3-net 2>/dev/null),)
|
||||
ifeq ($(shell $(PKG_CONFIG) --modversion SDL2_net 2>/dev/null),)
|
||||
$(error No SDL3_net or SDL2_net development libraries found!)
|
||||
endif
|
||||
SDLNET_CFLAGS += $(shell $(PKG_CONFIG) --cflags SDL2_net)
|
||||
SDLNET_LDLIBS += $(shell $(PKG_CONFIG) --libs SDL2_net)
|
||||
else
|
||||
SDLNET_CFLAGS += -DUSE_SDL3NET
|
||||
SDLNET_CFLAGS += $(shell $(PKG_CONFIG) --cflags sdl3-net)
|
||||
SDLNET_LDLIBS += $(shell $(PKG_CONFIG) --libs sdl3-net)
|
||||
endif
|
||||
endif
|
||||
CFLAGS += $(SDLNET_CFLAGS)
|
||||
LDLIBS += $(SDLNET_LDLIBS)
|
||||
endif
|
||||
|
||||
ifeq ($(VC), 1)
|
||||
CFLAGS += -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I/opt/vc/include/vmcs_host/linux
|
||||
LDLIBS += -L/opt/vc/lib -lbrcmEGL -lbcm_host -lvcos -lvchiq_arm
|
||||
|
||||
@@ -24,7 +24,11 @@
|
||||
* outside of the core library.
|
||||
*/
|
||||
|
||||
#ifdef USE_SDL3
|
||||
#include <SDL3/SDL.h>
|
||||
#else
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
+293
-220
@@ -22,14 +22,21 @@
|
||||
/* This file contains the Core video extension functions which will be exported
|
||||
* outside of the core library.
|
||||
*/
|
||||
|
||||
#ifdef USE_SDL3
|
||||
#include <SDL3/SDL.h>
|
||||
#else
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
/* we need at least SDL 2.0.6 for vulkan */
|
||||
#if !SDL_VERSION_ATLEAST(2,0,6)
|
||||
#undef VIDEXT_VULKAN
|
||||
#endif
|
||||
#ifdef VIDEXT_VULKAN
|
||||
#ifdef USE_SDL3
|
||||
#include <SDL3/SDL_vulkan.h>
|
||||
#else
|
||||
#include <SDL_vulkan.h>
|
||||
#endif
|
||||
#include <vulkan/vulkan.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
@@ -47,8 +54,6 @@
|
||||
static int l_ForceCompatibilityContext = 1;
|
||||
#endif
|
||||
|
||||
#include "vidext_sdl2_compat.h"
|
||||
|
||||
/* local variables */
|
||||
static m64p_video_extension_functions l_ExternalVideoFuncTable = {17, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
static int l_VideoExtensionActive = 0;
|
||||
@@ -56,11 +61,62 @@ static int l_VideoOutputActive = 0;
|
||||
static int l_Fullscreen = 0;
|
||||
static int l_SwapControl = 0;
|
||||
static m64p_render_mode l_RenderMode = M64P_RENDER_OPENGL;
|
||||
static SDL_Surface *l_pScreen = NULL;
|
||||
static SDL_Window *l_pWindow = NULL;
|
||||
#ifdef USE_SDL3
|
||||
static SDL_GLContext l_pGLContext;
|
||||
static SDL_DisplayID* l_pDisplays = NULL;
|
||||
#else
|
||||
static SDL_GLContext *l_pGLContext;
|
||||
#endif
|
||||
static char* l_pWindowTitle = NULL;
|
||||
#ifdef VIDEXT_VULKAN
|
||||
static const char** l_VulkanExtensionNames = NULL;
|
||||
#endif
|
||||
|
||||
/* local helper functions */
|
||||
|
||||
static int get_current_display_number(void)
|
||||
{
|
||||
const char *variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_DISPLAY");
|
||||
if ( !variable ) {
|
||||
variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_HEAD");
|
||||
}
|
||||
if ( variable ) {
|
||||
return SDL_atoi(variable);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_SDL3
|
||||
static SDL_DisplayID get_current_display(void)
|
||||
{
|
||||
int displayNumber = get_current_display_number();
|
||||
int displayCount = 0;
|
||||
|
||||
if (l_pDisplays == NULL)
|
||||
{
|
||||
l_pDisplays = SDL_GetDisplays(&displayCount);
|
||||
if (l_pDisplays == NULL)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "SDL_GetDisplays failed: %s", SDL_GetError());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (displayNumber > 0 && displayNumber < displayCount)
|
||||
return l_pDisplays[displayNumber];
|
||||
else
|
||||
return l_pDisplays[0];
|
||||
}
|
||||
#else
|
||||
static int get_current_display(void)
|
||||
{
|
||||
return get_current_display_number();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* global function for use by frontend.c */
|
||||
m64p_error OverrideVideoFunctions(m64p_video_extension_functions *VideoFunctionStruct)
|
||||
{
|
||||
@@ -135,16 +191,25 @@ EXPORT m64p_error CALL VidExt_InitWithRenderMode(m64p_render_mode RenderMode)
|
||||
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
|
||||
/* retrieve default swap interval/VSync */
|
||||
if (RenderMode == M64P_RENDER_OPENGL) {
|
||||
if (RenderMode == M64P_RENDER_OPENGL)
|
||||
{
|
||||
#ifdef USE_SDL3
|
||||
l_SwapControl = 1;
|
||||
#else
|
||||
l_SwapControl = SDL_GL_GetSwapInterval();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2,24,0)
|
||||
#if SDL_VERSION_ATLEAST(2,24,0) && !defined(USE_SDL3)
|
||||
/* fix DPI scaling issues on Windows */
|
||||
SDL_SetHint(SDL_HINT_WINDOWS_DPI_AWARENESS, "permonitorv2");
|
||||
#endif
|
||||
|
||||
#ifdef USE_SDL3
|
||||
if (!SDL_InitSubSystem(SDL_INIT_VIDEO))
|
||||
#else
|
||||
if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1)
|
||||
#endif
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "SDL video subsystem init failed: %s", SDL_GetError());
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
@@ -154,7 +219,11 @@ EXPORT m64p_error CALL VidExt_InitWithRenderMode(m64p_render_mode RenderMode)
|
||||
if (RenderMode == M64P_RENDER_VULKAN)
|
||||
{
|
||||
#ifdef VIDEXT_VULKAN
|
||||
#ifdef USE_SDL3
|
||||
if (!SDL_Vulkan_LoadLibrary(NULL))
|
||||
#else
|
||||
if (SDL_Vulkan_LoadLibrary(NULL) == -1)
|
||||
#endif
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "SDL_Vulkan_LoadLibrary failed: %s", SDL_GetError());
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
@@ -184,8 +253,36 @@ EXPORT m64p_error CALL VidExt_Quit(void)
|
||||
if (!SDL_WasInit(SDL_INIT_VIDEO))
|
||||
return M64ERR_NOT_INIT;
|
||||
|
||||
#ifdef USE_SDL3
|
||||
SDL_ShowCursor();
|
||||
#else
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
SDL2_DestroyWindow();
|
||||
#endif
|
||||
|
||||
if (l_pGLContext != NULL) {
|
||||
#ifdef USE_SDL3
|
||||
SDL_GL_DestroyContext(l_pGLContext);
|
||||
#else
|
||||
SDL_GL_DeleteContext(l_pGLContext);
|
||||
#endif
|
||||
l_pGLContext = NULL;
|
||||
}
|
||||
if (l_pWindow != NULL) {
|
||||
SDL_DestroyWindow(l_pWindow);
|
||||
l_pWindow = NULL;
|
||||
}
|
||||
if (l_pWindowTitle != NULL) {
|
||||
free(l_pWindowTitle);
|
||||
l_pWindowTitle = NULL;
|
||||
}
|
||||
|
||||
#ifdef USE_SDL3
|
||||
if (l_pDisplays != NULL) {
|
||||
SDL_free(l_pDisplays);
|
||||
l_pDisplays = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VIDEXT_VULKAN
|
||||
if (l_RenderMode == M64P_RENDER_VULKAN) {
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
@@ -196,60 +293,66 @@ EXPORT m64p_error CALL VidExt_Quit(void)
|
||||
}
|
||||
#endif
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
l_pScreen = NULL;
|
||||
l_VideoOutputActive = 0;
|
||||
StateChanged(M64CORE_VIDEO_MODE, M64VIDEO_NONE);
|
||||
|
||||
return M64ERR_SUCCESS;
|
||||
}
|
||||
|
||||
EXPORT m64p_error CALL VidExt_ListFullscreenModes(m64p_2d_size *SizeArray, int *NumSizes)
|
||||
{
|
||||
const SDL_VideoInfo *videoInfo;
|
||||
unsigned int videoFlags;
|
||||
SDL_Rect **modes;
|
||||
int i;
|
||||
|
||||
/* call video extension override if necessary */
|
||||
/* call video extension override if necessary */
|
||||
if (l_VideoExtensionActive)
|
||||
return (*l_ExternalVideoFuncTable.VidExtFuncListModes)(SizeArray, NumSizes);
|
||||
|
||||
#ifdef USE_SDL3
|
||||
SDL_DisplayMode** modes;
|
||||
#else
|
||||
SDL_DisplayMode mode;
|
||||
#endif
|
||||
int count = 0;
|
||||
int i;
|
||||
|
||||
if (!SDL_WasInit(SDL_INIT_VIDEO))
|
||||
return M64ERR_NOT_INIT;
|
||||
|
||||
/* get a list of SDL video modes */
|
||||
videoFlags = SDL_OPENGL | SDL_FULLSCREEN;
|
||||
|
||||
if ((videoInfo = SDL_GetVideoInfo()) == NULL)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "SDL_GetVideoInfo query failed: %s", SDL_GetError());
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
|
||||
if(videoInfo->hw_available)
|
||||
videoFlags |= SDL_HWSURFACE;
|
||||
else
|
||||
videoFlags |= SDL_SWSURFACE;
|
||||
|
||||
modes = SDL_ListModes(NULL, videoFlags);
|
||||
|
||||
if (modes == (SDL_Rect **) 0 || modes == (SDL_Rect **) -1)
|
||||
#ifdef USE_SDL3
|
||||
modes = SDL_GetFullscreenDisplayModes(get_current_display(), &count);
|
||||
#else
|
||||
count = SDL_GetNumDisplayModes(get_current_display());
|
||||
#endif
|
||||
if (count <= 0)
|
||||
{
|
||||
DebugMessage(M64MSG_WARNING, "No fullscreen SDL video modes available");
|
||||
*NumSizes = 0;
|
||||
return M64ERR_SUCCESS;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (i < *NumSizes && modes[i] != NULL)
|
||||
for (i = 0; i < count && i < *NumSizes; i++)
|
||||
{
|
||||
#ifdef USE_SDL3
|
||||
SizeArray[i].uiWidth = modes[i]->w;
|
||||
SizeArray[i].uiHeight = modes[i]->h;
|
||||
i++;
|
||||
#else
|
||||
if (SDL_GetDisplayMode(get_current_display(), i, &mode) == 0)
|
||||
{ /* assign mode when retrieval is successful */
|
||||
SizeArray[i].uiWidth = mode.w;
|
||||
SizeArray[i].uiHeight = mode.h;
|
||||
}
|
||||
else
|
||||
{ /* return error when failed */
|
||||
DebugMessage(M64MSG_ERROR, "SDL_GetDisplayMode() query failed: %s", SDL_GetError());
|
||||
*NumSizes = 0;
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
*NumSizes = i;
|
||||
#ifdef USE_SDL3
|
||||
SDL_free(modes);
|
||||
#endif
|
||||
|
||||
*NumSizes = i;
|
||||
return M64ERR_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -259,46 +362,17 @@ EXPORT m64p_error CALL VidExt_ListFullscreenRates(m64p_2d_size Size, int *NumRat
|
||||
if (l_VideoExtensionActive)
|
||||
return (*l_ExternalVideoFuncTable.VidExtFuncListRates)(Size, NumRates, Rates);
|
||||
|
||||
if (!SDL_WasInit(SDL_INIT_VIDEO))
|
||||
return M64ERR_NOT_INIT;
|
||||
|
||||
int display = GetVideoDisplay();
|
||||
int modeCount = SDL_GetNumDisplayModes(display);
|
||||
SDL_DisplayMode displayMode;
|
||||
|
||||
if (modeCount < 1)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "SDL_GetNumDisplayModes failed: %s", SDL_GetError());
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
|
||||
int rateCount = 0;
|
||||
for (int i = 0; (i < modeCount) && (rateCount < *NumRates); i++)
|
||||
{
|
||||
if (SDL_GetDisplayMode(display, i, &displayMode) < 0)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "SDL_GetDisplayMode failed: %s", SDL_GetError());
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
|
||||
/* skip when we're not at the right resolution */
|
||||
if (displayMode.w != (int)Size.uiWidth ||
|
||||
displayMode.h != (int)Size.uiHeight)
|
||||
continue;
|
||||
|
||||
Rates[rateCount] = displayMode.refresh_rate;
|
||||
rateCount++;
|
||||
}
|
||||
|
||||
*NumRates = rateCount;
|
||||
|
||||
return M64ERR_SUCCESS;
|
||||
return M64ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
EXPORT m64p_error CALL VidExt_SetVideoMode(int Width, int Height, int BitsPerPixel, m64p_video_mode ScreenMode, m64p_video_flags Flags)
|
||||
{
|
||||
const SDL_VideoInfo *videoInfo;
|
||||
int videoFlags = 0;
|
||||
int windowWidth = 0;
|
||||
int windowHeight = 0;
|
||||
Uint32 windowFlags = 0;
|
||||
#ifndef USE_SDL3
|
||||
windowFlags = SDL_WINDOW_SHOWN;
|
||||
#endif
|
||||
|
||||
/* call video extension override if necessary */
|
||||
if (l_VideoExtensionActive)
|
||||
@@ -317,59 +391,104 @@ EXPORT m64p_error CALL VidExt_SetVideoMode(int Width, int Height, int BitsPerPix
|
||||
if (!SDL_WasInit(SDL_INIT_VIDEO))
|
||||
return M64ERR_NOT_INIT;
|
||||
|
||||
/* Get SDL video flags to use */
|
||||
/* set window mode */
|
||||
if (l_RenderMode == M64P_RENDER_OPENGL)
|
||||
{
|
||||
videoFlags = SDL_OPENGL;
|
||||
windowFlags |= SDL_WINDOW_OPENGL;
|
||||
}
|
||||
#ifdef VIDEXT_VULKAN
|
||||
else
|
||||
else if (l_RenderMode == M64P_RENDER_VULKAN)
|
||||
{
|
||||
videoFlags = SDL_VULKAN;
|
||||
windowFlags |= SDL_WINDOW_VULKAN;
|
||||
}
|
||||
#endif
|
||||
if (ScreenMode == M64VIDEO_WINDOWED)
|
||||
{
|
||||
if (Flags & M64VIDEOFLAG_SUPPORT_RESIZING)
|
||||
videoFlags |= SDL_RESIZABLE;
|
||||
{
|
||||
windowFlags |= SDL_WINDOW_RESIZABLE;
|
||||
}
|
||||
}
|
||||
else if (ScreenMode == M64VIDEO_FULLSCREEN)
|
||||
{
|
||||
videoFlags |= SDL_FULLSCREEN;
|
||||
windowFlags |= SDL_WINDOW_FULLSCREEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
return M64ERR_INPUT_INVALID;
|
||||
}
|
||||
|
||||
if ((videoInfo = SDL_GetVideoInfo()) == NULL)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "SDL_GetVideoInfo query failed: %s", SDL_GetError());
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
if (videoInfo->hw_available)
|
||||
videoFlags |= SDL_HWSURFACE;
|
||||
else
|
||||
videoFlags |= SDL_SWSURFACE;
|
||||
|
||||
/* set the mode */
|
||||
if (BitsPerPixel > 0)
|
||||
DebugMessage(M64MSG_INFO, "Setting %i-bit video mode: %ix%i", BitsPerPixel, Width, Height);
|
||||
else
|
||||
DebugMessage(M64MSG_INFO, "Setting video mode: %ix%i", Width, Height);
|
||||
|
||||
l_pScreen = SDL_SetVideoMode(Width, Height, BitsPerPixel, videoFlags);
|
||||
if (l_pScreen == NULL)
|
||||
/* initialize window if needed */
|
||||
if (l_pWindow == NULL)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "SDL_SetVideoMode failed: %s", SDL_GetError());
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
if (l_RenderMode == M64P_RENDER_OPENGL)
|
||||
{
|
||||
#ifndef USE_GLES
|
||||
if (l_ForceCompatibilityContext)
|
||||
{
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
|
||||
}
|
||||
#else
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
#endif // !USE_GLES
|
||||
}
|
||||
|
||||
/* set default window title when unset */
|
||||
if (l_pWindowTitle == NULL)
|
||||
l_pWindowTitle = strdup("Mupen64Plus");
|
||||
|
||||
#ifdef USE_SDL3
|
||||
l_pWindow = SDL_CreateWindow(l_pWindowTitle, Width, Height, windowFlags);
|
||||
#else
|
||||
l_pWindow = SDL_CreateWindow(l_pWindowTitle, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, Width, Height, windowFlags);
|
||||
#endif
|
||||
if (l_pWindow == NULL)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "SDL_CreateWindow failed: %s", SDL_GetError());
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
|
||||
if (l_RenderMode == M64P_RENDER_OPENGL)
|
||||
{
|
||||
l_pGLContext = SDL_GL_CreateContext(l_pWindow);
|
||||
#ifdef USE_SDL3
|
||||
if (!SDL_GL_MakeCurrent(l_pWindow, l_pGLContext))
|
||||
#else
|
||||
if (SDL_GL_MakeCurrent(l_pWindow, l_pGLContext) != 0)
|
||||
#endif
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "SDL_GL_MakeCurrent failed: %s", SDL_GetError());
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* resize window if needed */
|
||||
SDL_GetWindowSize(l_pWindow, &windowWidth, &windowHeight);
|
||||
if (windowWidth != Width || windowHeight != Height)
|
||||
{
|
||||
SDL_SetWindowSize(l_pWindow, Width, Height);
|
||||
}
|
||||
|
||||
#ifdef USE_SDL3
|
||||
SDL_HideCursor();
|
||||
#else
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
#endif
|
||||
|
||||
/* set swap interval/VSync */
|
||||
if (l_RenderMode == M64P_RENDER_OPENGL &&
|
||||
#ifdef USE_SDL3
|
||||
!SDL_GL_SetSwapInterval(l_SwapControl))
|
||||
#else
|
||||
SDL_GL_SetSwapInterval(l_SwapControl) != 0)
|
||||
#endif
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "SDL swap interval (VSync) set failed: %s", SDL_GetError());
|
||||
}
|
||||
@@ -397,88 +516,13 @@ EXPORT m64p_error CALL VidExt_SetVideoModeWithRate(int Width, int Height, int Re
|
||||
return rval;
|
||||
}
|
||||
|
||||
if (!SDL_WasInit(SDL_INIT_VIDEO) || !SDL_VideoWindow)
|
||||
return M64ERR_NOT_INIT;
|
||||
|
||||
int videoFlags = 0;
|
||||
int display = GetVideoDisplay();
|
||||
int modeCount = SDL_GetNumDisplayModes(display);
|
||||
SDL_DisplayMode displayMode;
|
||||
int modeFound = 0;
|
||||
|
||||
/* Get SDL video flags to use */
|
||||
if (ScreenMode == M64VIDEO_WINDOWED)
|
||||
videoFlags = 0;
|
||||
else if (ScreenMode == M64VIDEO_FULLSCREEN)
|
||||
videoFlags = SDL_WINDOW_FULLSCREEN;
|
||||
else
|
||||
return M64ERR_INPUT_INVALID;
|
||||
|
||||
if (modeCount < 1)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "SDL_GetNumDisplayModes failed: %s", SDL_GetError());
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
|
||||
/* Attempt to find valid screen mode */
|
||||
for (int i = 0; i < modeCount; i++)
|
||||
{
|
||||
if (SDL_GetDisplayMode(display, i, &displayMode) < 0)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "SDL_GetDisplayMode failed: %s", SDL_GetError());
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
|
||||
/* skip when we're not at the right mode */
|
||||
if (displayMode.w != Width ||
|
||||
displayMode.h != Height ||
|
||||
displayMode.refresh_rate != RefreshRate)
|
||||
continue;
|
||||
|
||||
modeFound = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* return when no modes with specifed size have been found */
|
||||
if (modeFound == 0)
|
||||
return M64ERR_INPUT_INVALID;
|
||||
|
||||
/* Set window in specified mode */
|
||||
if (SDL_SetWindowFullscreen(SDL_VideoWindow, videoFlags) < 0)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "SDL_SetWindowFullscreen failed: %s", SDL_GetError());
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
|
||||
if (ScreenMode == M64VIDEO_FULLSCREEN)
|
||||
{
|
||||
if (SDL_SetWindowDisplayMode(SDL_VideoWindow, &displayMode) < 0)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "SDL_SetWindowDisplayMode failed: %s", SDL_GetError());
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
|
||||
/* set swap interval/VSync */
|
||||
if (SDL_GL_SetSwapInterval(l_SwapControl) != 0)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "SDL swap interval (VSync) set failed: %s", SDL_GetError());
|
||||
}
|
||||
|
||||
l_Fullscreen = (ScreenMode == M64VIDEO_FULLSCREEN);
|
||||
l_VideoOutputActive = 1;
|
||||
StateChanged(M64CORE_VIDEO_MODE, ScreenMode);
|
||||
StateChanged(M64CORE_VIDEO_SIZE, (Width << 16) | Height);
|
||||
|
||||
return M64ERR_SUCCESS;
|
||||
return M64ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
EXPORT m64p_error CALL VidExt_ResizeWindow(int Width, int Height)
|
||||
{
|
||||
const SDL_VideoInfo *videoInfo;
|
||||
int videoFlags = 0;
|
||||
int windowWidth = 0;
|
||||
int windowHeight = 0;
|
||||
|
||||
/* call video extension override if necessary */
|
||||
if (l_VideoExtensionActive)
|
||||
@@ -497,7 +541,7 @@ EXPORT m64p_error CALL VidExt_ResizeWindow(int Width, int Height)
|
||||
return rval;
|
||||
}
|
||||
|
||||
if (!l_VideoOutputActive || !SDL_WasInit(SDL_INIT_VIDEO))
|
||||
if (!l_pWindow || !SDL_WasInit(SDL_INIT_VIDEO))
|
||||
return M64ERR_NOT_INIT;
|
||||
|
||||
if (l_Fullscreen)
|
||||
@@ -506,38 +550,13 @@ EXPORT m64p_error CALL VidExt_ResizeWindow(int Width, int Height)
|
||||
return M64ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
/* Get SDL video flags to use */
|
||||
if (l_RenderMode == M64P_RENDER_OPENGL)
|
||||
videoFlags = SDL_OPENGL;
|
||||
#ifdef VIDEXT_VULKAN
|
||||
else
|
||||
videoFlags = SDL_VULKAN;
|
||||
#endif
|
||||
videoFlags |= SDL_RESIZABLE;
|
||||
if ((videoInfo = SDL_GetVideoInfo()) == NULL)
|
||||
SDL_GetWindowSize(l_pWindow, &windowWidth, &windowHeight);
|
||||
if (windowHeight != Width || windowHeight != Height)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "SDL_GetVideoInfo query failed: %s", SDL_GetError());
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
if (videoInfo->hw_available)
|
||||
videoFlags |= SDL_HWSURFACE;
|
||||
else
|
||||
videoFlags |= SDL_SWSURFACE;
|
||||
|
||||
// destroy the On-Screen Display
|
||||
osd_exit();
|
||||
|
||||
/* set the re-sizing the screen will create a new OpenGL context */
|
||||
l_pScreen = SDL_SetVideoMode(Width, Height, 0, videoFlags);
|
||||
if (l_pScreen == NULL)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "SDL_SetVideoMode failed: %s", SDL_GetError());
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
SDL_SetWindowSize(l_pWindow, Width, Height);
|
||||
}
|
||||
|
||||
StateChanged(M64CORE_VIDEO_SIZE, (Width << 16) | Height);
|
||||
// re-create the On-Screen Display
|
||||
osd_init(Width, Height);
|
||||
return M64ERR_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -550,13 +569,28 @@ EXPORT m64p_error CALL VidExt_SetCaption(const char *Title)
|
||||
if (!SDL_WasInit(SDL_INIT_VIDEO))
|
||||
return M64ERR_NOT_INIT;
|
||||
|
||||
SDL_WM_SetCaption(Title, "M64+ Video");
|
||||
/* set window title if window exists, else
|
||||
* store it for later when initializing
|
||||
* the window */
|
||||
if (l_pWindow)
|
||||
{
|
||||
SDL_SetWindowTitle(l_pWindow, Title);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (l_pWindowTitle != NULL)
|
||||
free(l_pWindowTitle);
|
||||
|
||||
l_pWindowTitle = strdup(Title);
|
||||
}
|
||||
|
||||
return M64ERR_SUCCESS;
|
||||
}
|
||||
|
||||
EXPORT m64p_error CALL VidExt_ToggleFullScreen(void)
|
||||
{
|
||||
Uint32 windowFlags = 0;
|
||||
|
||||
/* call video extension override if necessary */
|
||||
if (l_VideoExtensionActive)
|
||||
{
|
||||
@@ -569,18 +603,24 @@ EXPORT m64p_error CALL VidExt_ToggleFullScreen(void)
|
||||
return rval;
|
||||
}
|
||||
|
||||
if (!SDL_WasInit(SDL_INIT_VIDEO))
|
||||
if (!l_pWindow || !SDL_WasInit(SDL_INIT_VIDEO))
|
||||
return M64ERR_NOT_INIT;
|
||||
|
||||
/* TODO:
|
||||
* SDL_WM_ToggleFullScreen doesn't work under Windows and others
|
||||
* (see http://wiki.libsdl.org/moin.cgi/FAQWindows for explanation).
|
||||
* Instead, we should call SDL_SetVideoMode with the SDL_FULLSCREEN flag.
|
||||
* (see http://sdl.beuc.net/sdl.wiki/SDL_SetVideoMode), but on Windows
|
||||
* this resets the OpenGL context and video plugins don't support it yet.
|
||||
* Uncomment the next line to test it: */
|
||||
//return VidExt_SetVideoMode(l_pScreen->w, l_pScreen->h, l_pScreen->format->BitsPerPixel, l_Fullscreen ? M64VIDEO_WINDOWED : M64VIDEO_FULLSCREEN);
|
||||
if (SDL_WM_ToggleFullScreen(l_pScreen) == 1)
|
||||
/* set correct flags */
|
||||
if (!(SDL_GetWindowFlags(l_pWindow) & SDL_WINDOW_FULLSCREEN))
|
||||
{
|
||||
#ifdef USE_SDL3
|
||||
windowFlags = 1;
|
||||
#else
|
||||
windowFlags |= SDL_WINDOW_FULLSCREEN;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_SDL3
|
||||
if (SDL_SetWindowFullscreen(l_pWindow, windowFlags))
|
||||
#else
|
||||
if (SDL_SetWindowFullscreen(l_pWindow, windowFlags) == 0)
|
||||
#endif
|
||||
{
|
||||
l_Fullscreen = !l_Fullscreen;
|
||||
StateChanged(M64CORE_VIDEO_MODE, l_Fullscreen ? M64VIDEO_FULLSCREEN : M64VIDEO_WINDOWED);
|
||||
@@ -588,7 +628,7 @@ EXPORT m64p_error CALL VidExt_ToggleFullScreen(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "SDL_WM_ToggleFullScreen failed: %s", SDL_GetError());
|
||||
DebugMessage(M64MSG_ERROR, "SDL_SetWindowFullscreen failed: %s", SDL_GetError());
|
||||
}
|
||||
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
@@ -615,7 +655,11 @@ OSAL_WARNING_POP
|
||||
|
||||
typedef struct {
|
||||
m64p_GLattr m64Attr;
|
||||
#ifdef USE_SDL3
|
||||
SDL_GLAttr sdlAttr;
|
||||
#else
|
||||
SDL_GLattr sdlAttr;
|
||||
#endif
|
||||
} GLAttrMapNode;
|
||||
|
||||
static const GLAttrMapNode GLAttrMap[] = {
|
||||
@@ -633,7 +677,6 @@ static const GLAttrMapNode GLAttrMap[] = {
|
||||
{ M64P_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_MASK }
|
||||
};
|
||||
static const int mapSize = sizeof(GLAttrMap) / sizeof(GLAttrMapNode);
|
||||
|
||||
EXPORT m64p_error CALL VidExt_GL_SetAttribute(m64p_GLattr Attr, int Value)
|
||||
{
|
||||
int i;
|
||||
@@ -680,7 +723,11 @@ EXPORT m64p_error CALL VidExt_GL_SetAttribute(m64p_GLattr Attr, int Value)
|
||||
{
|
||||
if (GLAttrMap[i].m64Attr == Attr)
|
||||
{
|
||||
#ifdef USE_SDL3
|
||||
if (!SDL_GL_SetAttribute(GLAttrMap[i].sdlAttr, Value))
|
||||
#else
|
||||
if (SDL_GL_SetAttribute(GLAttrMap[i].sdlAttr, Value) != 0)
|
||||
#endif
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
return M64ERR_SUCCESS;
|
||||
}
|
||||
@@ -705,7 +752,14 @@ EXPORT m64p_error CALL VidExt_GL_GetAttribute(m64p_GLattr Attr, int *pValue)
|
||||
|
||||
if (Attr == M64P_GL_SWAP_CONTROL)
|
||||
{
|
||||
#ifdef USE_SDL3
|
||||
if (!SDL_GL_GetSwapInterval(pValue)) {
|
||||
DebugMessage(M64MSG_ERROR, "SDL_GL_GetSwapInterval failed: %s", SDL_GetError());
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
#else
|
||||
*pValue = SDL_GL_GetSwapInterval();
|
||||
#endif
|
||||
return M64ERR_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -714,7 +768,11 @@ EXPORT m64p_error CALL VidExt_GL_GetAttribute(m64p_GLattr Attr, int *pValue)
|
||||
if (GLAttrMap[i].m64Attr == Attr)
|
||||
{
|
||||
int NewValue = 0;
|
||||
#ifdef USE_SDL3
|
||||
if (!SDL_GL_GetAttribute(GLAttrMap[i].sdlAttr, &NewValue))
|
||||
#else
|
||||
if (SDL_GL_GetAttribute(GLAttrMap[i].sdlAttr, &NewValue) != 0)
|
||||
#endif
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
/* translate the GL context type mask if necessary */
|
||||
if (Attr == M64P_GL_CONTEXT_PROFILE_MASK)
|
||||
@@ -751,10 +809,10 @@ EXPORT m64p_error CALL VidExt_GL_SwapBuffers(void)
|
||||
if (l_RenderMode != M64P_RENDER_OPENGL)
|
||||
return M64ERR_INVALID_STATE;
|
||||
|
||||
if (!SDL_WasInit(SDL_INIT_VIDEO))
|
||||
if (!l_pWindow || !SDL_WasInit(SDL_INIT_VIDEO))
|
||||
return M64ERR_NOT_INIT;
|
||||
|
||||
SDL_GL_SwapBuffers();
|
||||
SDL_GL_SwapWindow(l_pWindow);
|
||||
return M64ERR_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -771,16 +829,21 @@ EXPORT m64p_error CALL VidExt_VK_GetSurface(void** Surface, void* Instance)
|
||||
if (l_VideoExtensionActive)
|
||||
return (*l_ExternalVideoFuncTable.VidExtFuncVKGetSurface)(Surface, Instance);
|
||||
|
||||
#ifdef VIDEXT_VULKAN
|
||||
#if defined(VIDEXT_VULKAN)
|
||||
VkSurfaceKHR vulkanSurface = VK_NULL_HANDLE;
|
||||
|
||||
if (l_RenderMode != M64P_RENDER_VULKAN)
|
||||
return M64ERR_INVALID_STATE;
|
||||
|
||||
if (!SDL_WasInit(SDL_INIT_VIDEO) || !SDL_VideoWindow)
|
||||
if (!SDL_WasInit(SDL_INIT_VIDEO) || !l_pWindow)
|
||||
return M64ERR_NOT_INIT;
|
||||
|
||||
if (SDL_Vulkan_CreateSurface(SDL_VideoWindow, (VkInstance)Instance, &vulkanSurface) == SDL_FALSE) {
|
||||
#ifdef USE_SDL3
|
||||
if (!SDL_Vulkan_CreateSurface(l_pWindow, (VkInstance)Instance, NULL, &vulkanSurface))
|
||||
#else
|
||||
if (SDL_Vulkan_CreateSurface(l_pWindow, (VkInstance)Instance, &vulkanSurface) == SDL_FALSE)
|
||||
#endif
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "SDL_Vulkan_CreateSurface failed: %s", SDL_GetError());
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
@@ -797,7 +860,7 @@ EXPORT m64p_error CALL VidExt_VK_GetInstanceExtensions(const char** Extensions[]
|
||||
if (l_VideoExtensionActive)
|
||||
return (*l_ExternalVideoFuncTable.VidExtFuncVKGetInstanceExtensions)(Extensions, NumExtensions);
|
||||
|
||||
#ifdef VIDEXT_VULKAN
|
||||
#if defined(VIDEXT_VULKAN)
|
||||
if (l_RenderMode != M64P_RENDER_VULKAN)
|
||||
return M64ERR_INVALID_STATE;
|
||||
|
||||
@@ -805,7 +868,13 @@ EXPORT m64p_error CALL VidExt_VK_GetInstanceExtensions(const char** Extensions[]
|
||||
return M64ERR_NOT_INIT;
|
||||
|
||||
unsigned int extensionCount = 0;
|
||||
if (SDL_Vulkan_GetInstanceExtensions(NULL, &extensionCount, NULL) == SDL_FALSE) {
|
||||
#ifdef USE_SDL3
|
||||
const char * const *instance_extensions;
|
||||
if (!(instance_extensions = SDL_Vulkan_GetInstanceExtensions(&extensionCount)))
|
||||
#else
|
||||
if (SDL_Vulkan_GetInstanceExtensions(NULL, &extensionCount, NULL) == SDL_FALSE)
|
||||
#endif
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "SDL_Vulkan_GetInstanceExtensions failed: %s", SDL_GetError());
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
@@ -822,10 +891,14 @@ EXPORT m64p_error CALL VidExt_VK_GetInstanceExtensions(const char** Extensions[]
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
|
||||
#ifdef USE_SDL3
|
||||
memcpy(l_VulkanExtensionNames, instance_extensions, extensionCount * sizeof(const char*));
|
||||
#else
|
||||
if (SDL_Vulkan_GetInstanceExtensions(NULL, &extensionCount, l_VulkanExtensionNames) == SDL_FALSE) {
|
||||
DebugMessage(M64MSG_ERROR, "SDL_Vulkan_GetInstanceExtensions failed: %s", SDL_GetError());
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
*NumExtensions = extensionCount;
|
||||
*Extensions = l_VulkanExtensionNames;
|
||||
|
||||
@@ -1,527 +0,0 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include <SDL_config.h>
|
||||
#include <SDL_surface.h>
|
||||
|
||||
#ifndef USE_GLES
|
||||
|
||||
#ifndef SDL_VIDEO_OPENGL
|
||||
#error SDL is not build with OpenGL support. Try USE_GLES=1
|
||||
#endif
|
||||
|
||||
#else // !USE_GLES
|
||||
|
||||
#ifndef SDL_VIDEO_OPENGL_ES2
|
||||
#error SDL is not build with OpenGL ES2 support. Try USE_GLES=0
|
||||
#endif
|
||||
|
||||
#endif // !USE_GLES
|
||||
|
||||
typedef struct SDL_VideoInfo
|
||||
{
|
||||
Uint32 hw_available:1;
|
||||
Uint32 wm_available:1;
|
||||
Uint32 UnusedBits1:6;
|
||||
Uint32 UnusedBits2:1;
|
||||
Uint32 blit_hw:1;
|
||||
Uint32 blit_hw_CC:1;
|
||||
Uint32 blit_hw_A:1;
|
||||
Uint32 blit_sw:1;
|
||||
Uint32 blit_sw_CC:1;
|
||||
Uint32 blit_sw_A:1;
|
||||
Uint32 blit_fill:1;
|
||||
Uint32 UnusedBits3:16;
|
||||
Uint32 video_mem;
|
||||
|
||||
SDL_PixelFormat *vfmt;
|
||||
|
||||
int current_w;
|
||||
int current_h;
|
||||
} SDL_VideoInfo;
|
||||
|
||||
#define SDL_FULLSCREEN 0x00800000
|
||||
#define SDL_RESIZABLE 0x01000000
|
||||
#define SDL_NOFRAME 0x02000000
|
||||
#define SDL_OPENGL 0x04000000
|
||||
#define SDL_VULKAN 0x10000000
|
||||
#define SDL_HWSURFACE 0x08000001 /**< \note Not used */
|
||||
|
||||
#define SDL_BUTTON_WHEELUP 4
|
||||
#define SDL_BUTTON_WHEELDOWN 5
|
||||
|
||||
int initialized_video = 0;
|
||||
|
||||
static SDL_Window *SDL_VideoWindow = NULL;
|
||||
static SDL_Surface *SDL_VideoSurface = NULL;
|
||||
static SDL_Surface *SDL_PublicSurface = NULL;
|
||||
static SDL_Rect SDL_VideoViewport;
|
||||
static char *wm_title = NULL;
|
||||
static Uint32 SDL_VideoFlags = 0;
|
||||
static SDL_GLContext *SDL_VideoContext = NULL;
|
||||
static SDL_Surface *SDL_VideoIcon;
|
||||
|
||||
static void
|
||||
SDL_WM_SetCaption(const char *title, const char *icon)
|
||||
{
|
||||
if (wm_title) {
|
||||
SDL_free(wm_title);
|
||||
}
|
||||
if (title) {
|
||||
wm_title = SDL_strdup(title);
|
||||
} else {
|
||||
wm_title = NULL;
|
||||
}
|
||||
SDL_SetWindowTitle(SDL_VideoWindow, wm_title);
|
||||
}
|
||||
|
||||
static int
|
||||
GetVideoDisplay()
|
||||
{
|
||||
const char *variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_DISPLAY");
|
||||
if ( !variable ) {
|
||||
variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_HEAD");
|
||||
}
|
||||
if ( variable ) {
|
||||
return SDL_atoi(variable);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const SDL_VideoInfo *
|
||||
SDL_GetVideoInfo(void)
|
||||
{
|
||||
static SDL_VideoInfo info;
|
||||
SDL_DisplayMode mode;
|
||||
|
||||
/* Memory leak, compatibility code, who cares? */
|
||||
if (!info.vfmt && SDL_GetDesktopDisplayMode(GetVideoDisplay(), &mode) == 0) {
|
||||
info.vfmt = SDL_AllocFormat(mode.format);
|
||||
info.current_w = mode.w;
|
||||
info.current_h = mode.h;
|
||||
}
|
||||
return &info;
|
||||
}
|
||||
|
||||
static SDL_Rect **
|
||||
SDL_ListModes(const SDL_PixelFormat * format, Uint32 flags)
|
||||
{
|
||||
int i, nmodes;
|
||||
SDL_Rect **modes;
|
||||
|
||||
if (!initialized_video) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(flags & SDL_FULLSCREEN)) {
|
||||
return (SDL_Rect **) (-1);
|
||||
}
|
||||
|
||||
if (!format) {
|
||||
format = SDL_GetVideoInfo()->vfmt;
|
||||
}
|
||||
|
||||
/* Memory leak, but this is a compatibility function, who cares? */
|
||||
nmodes = 0;
|
||||
modes = NULL;
|
||||
for (i = 0; i < SDL_GetNumDisplayModes(GetVideoDisplay()); ++i) {
|
||||
SDL_DisplayMode mode;
|
||||
int bpp;
|
||||
|
||||
SDL_GetDisplayMode(GetVideoDisplay(), i, &mode);
|
||||
if (!mode.w || !mode.h) {
|
||||
return (SDL_Rect **) (-1);
|
||||
}
|
||||
|
||||
/* Copied from src/video/SDL_pixels.c:SDL_PixelFormatEnumToMasks */
|
||||
if (SDL_BYTESPERPIXEL(mode.format) <= 2) {
|
||||
bpp = SDL_BITSPERPIXEL(mode.format);
|
||||
} else {
|
||||
bpp = SDL_BYTESPERPIXEL(mode.format) * 8;
|
||||
}
|
||||
|
||||
if (bpp != format->BitsPerPixel) {
|
||||
continue;
|
||||
}
|
||||
if (nmodes > 0 && modes[nmodes - 1]->w == mode.w
|
||||
&& modes[nmodes - 1]->h == mode.h) {
|
||||
continue;
|
||||
}
|
||||
|
||||
modes = SDL_realloc(modes, (nmodes + 2) * sizeof(*modes));
|
||||
if (!modes) {
|
||||
return NULL;
|
||||
}
|
||||
modes[nmodes] = (SDL_Rect *) SDL_malloc(sizeof(SDL_Rect));
|
||||
if (!modes[nmodes]) {
|
||||
return NULL;
|
||||
}
|
||||
modes[nmodes]->x = 0;
|
||||
modes[nmodes]->y = 0;
|
||||
modes[nmodes]->w = mode.w;
|
||||
modes[nmodes]->h = mode.h;
|
||||
++nmodes;
|
||||
}
|
||||
if (modes) {
|
||||
modes[nmodes] = NULL;
|
||||
}
|
||||
return modes;
|
||||
}
|
||||
|
||||
static void
|
||||
SDL_GL_SwapBuffers(void)
|
||||
{
|
||||
SDL_GL_SwapWindow(SDL_VideoWindow);
|
||||
}
|
||||
|
||||
static int
|
||||
SDL_WM_ToggleFullScreen(SDL_Surface * surface)
|
||||
{
|
||||
int window_w;
|
||||
int window_h;
|
||||
|
||||
if (
|
||||
#ifdef VIDEXT_VULKAN
|
||||
(SDL_VideoFlags & SDL_VULKAN && !SDL_VideoWindow) ||
|
||||
#endif
|
||||
(SDL_VideoFlags & SDL_OPENGL && !SDL_PublicSurface)) {
|
||||
SDL_SetError("SDL_SetVideoMode() hasn't been called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Do the physical mode switch */
|
||||
if (SDL_GetWindowFlags(SDL_VideoWindow) & SDL_WINDOW_FULLSCREEN) {
|
||||
if (SDL_SetWindowFullscreen(SDL_VideoWindow, 0) < 0) {
|
||||
return 0;
|
||||
}
|
||||
if (SDL_VideoFlags & SDL_OPENGL) {
|
||||
SDL_PublicSurface->flags &= ~SDL_FULLSCREEN;
|
||||
}
|
||||
} else {
|
||||
if (SDL_SetWindowFullscreen(SDL_VideoWindow, 1) < 0) {
|
||||
return 0;
|
||||
}
|
||||
if (SDL_VideoFlags & SDL_OPENGL) {
|
||||
SDL_PublicSurface->flags |= SDL_FULLSCREEN;
|
||||
}
|
||||
}
|
||||
|
||||
/* Center the public surface in the window surface */
|
||||
SDL_GetWindowSize(SDL_VideoWindow, &window_w, &window_h);
|
||||
SDL_VideoViewport.x = 0;
|
||||
SDL_VideoViewport.y = 0;
|
||||
SDL_VideoViewport.w = window_w;
|
||||
SDL_VideoViewport.h = window_h;
|
||||
|
||||
/* We're done! */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
SDL_ResizeVideoMode(int width, int height, int bpp, Uint32 flags)
|
||||
{
|
||||
int w, h;
|
||||
|
||||
/* We can't resize something we don't have... */
|
||||
if (
|
||||
#ifdef VIDEXT_VULKAN
|
||||
(SDL_VideoFlags & SDL_VULKAN && !SDL_VideoWindow) ||
|
||||
#endif
|
||||
(SDL_VideoFlags & SDL_OPENGL && !SDL_PublicSurface)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* We probably have to recreate the window in fullscreen mode */
|
||||
if (flags & SDL_FULLSCREEN) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* I don't think there's any change we can gracefully make in flags */
|
||||
if (flags != SDL_VideoFlags) {
|
||||
return -1;
|
||||
}
|
||||
if (bpp != SDL_VideoSurface->format->BitsPerPixel) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Resize the window */
|
||||
SDL_GetWindowSize(SDL_VideoWindow, &w, &h);
|
||||
if (w != width || h != height) {
|
||||
SDL_SetWindowSize(SDL_VideoWindow, width, height);
|
||||
}
|
||||
|
||||
SDL_VideoSurface->w = width;
|
||||
SDL_VideoSurface->h = height;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
SDL_CompatEventFilter(void *userdata, SDL_Event * event)
|
||||
{
|
||||
SDL_Event fake;
|
||||
|
||||
switch (event->type) {
|
||||
case SDL_WINDOWEVENT:
|
||||
switch (event->window.event) {
|
||||
case SDL_WINDOWEVENT_CLOSE:
|
||||
fake.type = SDL_QUIT;
|
||||
SDL_PushEvent(&fake);
|
||||
break;
|
||||
}
|
||||
case SDL_TEXTINPUT:
|
||||
{
|
||||
/* FIXME: Generate an old style key repeat event if needed */
|
||||
//printf("TEXTINPUT: '%s'\n", event->text.text);
|
||||
break;
|
||||
}
|
||||
case SDL_MOUSEMOTION:
|
||||
{
|
||||
event->motion.x -= SDL_VideoViewport.x;
|
||||
event->motion.y -= SDL_VideoViewport.y;
|
||||
break;
|
||||
}
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
{
|
||||
event->button.x -= SDL_VideoViewport.x;
|
||||
event->button.y -= SDL_VideoViewport.y;
|
||||
break;
|
||||
}
|
||||
case SDL_MOUSEWHEEL:
|
||||
{
|
||||
Uint8 button;
|
||||
int x, y;
|
||||
|
||||
if (event->wheel.y == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
SDL_GetMouseState(&x, &y);
|
||||
|
||||
if (event->wheel.y > 0) {
|
||||
button = SDL_BUTTON_WHEELUP;
|
||||
} else {
|
||||
button = SDL_BUTTON_WHEELDOWN;
|
||||
}
|
||||
|
||||
fake.button.button = button;
|
||||
fake.button.x = x;
|
||||
fake.button.y = y;
|
||||
fake.button.windowID = event->wheel.windowID;
|
||||
|
||||
fake.type = SDL_MOUSEBUTTONDOWN;
|
||||
fake.button.state = SDL_PRESSED;
|
||||
SDL_PushEvent(&fake);
|
||||
|
||||
fake.type = SDL_MOUSEBUTTONUP;
|
||||
fake.button.state = SDL_RELEASED;
|
||||
SDL_PushEvent(&fake);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
GetEnvironmentWindowPosition(int w, int h, int *x, int *y)
|
||||
{
|
||||
int display = GetVideoDisplay();
|
||||
const char *window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
|
||||
const char *center = SDL_getenv("SDL_VIDEO_CENTERED");
|
||||
if (window) {
|
||||
if (SDL_sscanf(window, "%d,%d", x, y) == 2) {
|
||||
return;
|
||||
}
|
||||
if (SDL_strcmp(window, "center") == 0) {
|
||||
center = window;
|
||||
}
|
||||
}
|
||||
if (center) {
|
||||
*x = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
|
||||
*y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDL2_DestroyWindow(void)
|
||||
{
|
||||
/* Destroy existing window */
|
||||
SDL_PublicSurface = NULL;
|
||||
if (SDL_VideoSurface) {
|
||||
SDL_VideoSurface->flags &= ~SDL_DONTFREE;
|
||||
SDL_FreeSurface(SDL_VideoSurface);
|
||||
SDL_VideoSurface = NULL;
|
||||
}
|
||||
if (SDL_VideoContext) {
|
||||
/* SDL_GL_MakeCurrent(0, NULL); *//* Doesn't do anything */
|
||||
SDL_GL_DeleteContext(SDL_VideoContext);
|
||||
SDL_VideoContext = NULL;
|
||||
}
|
||||
if (SDL_VideoWindow) {
|
||||
SDL_DestroyWindow(SDL_VideoWindow);
|
||||
SDL_VideoWindow = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_Surface *
|
||||
SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags)
|
||||
{
|
||||
SDL_DisplayMode desktop_mode;
|
||||
int display = GetVideoDisplay();
|
||||
int window_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
|
||||
int window_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
|
||||
Uint32 window_flags;
|
||||
Uint32 surface_flags;
|
||||
|
||||
if (!initialized_video) {
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
initialized_video = 1;
|
||||
}
|
||||
|
||||
SDL_GetDesktopDisplayMode(display, &desktop_mode);
|
||||
|
||||
if (width == 0) {
|
||||
width = desktop_mode.w;
|
||||
}
|
||||
if (height == 0) {
|
||||
height = desktop_mode.h;
|
||||
}
|
||||
if (bpp == 0) {
|
||||
bpp = SDL_BITSPERPIXEL(desktop_mode.format);
|
||||
}
|
||||
|
||||
/* See if we can simply resize the existing window and surface */
|
||||
if (SDL_ResizeVideoMode(width, height, bpp, flags) == 0) {
|
||||
return SDL_PublicSurface;
|
||||
}
|
||||
|
||||
/* Destroy existing window */
|
||||
if (SDL_VideoWindow)
|
||||
SDL_GetWindowPosition(SDL_VideoWindow, &window_x, &window_y);
|
||||
SDL2_DestroyWindow();
|
||||
|
||||
/* Set up the event filter */
|
||||
if (!SDL_GetEventFilter(NULL, NULL)) {
|
||||
SDL_SetEventFilter(SDL_CompatEventFilter, NULL);
|
||||
}
|
||||
|
||||
#ifndef USE_GLES
|
||||
if (flags & SDL_OPENGL && l_ForceCompatibilityContext)
|
||||
{
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
|
||||
}
|
||||
#else // !USE_GLES
|
||||
if (flags & SDL_OPENGL) {
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
}
|
||||
#endif // !USE_GLES
|
||||
|
||||
/* Create a new window */
|
||||
window_flags = SDL_WINDOW_SHOWN;
|
||||
if (flags & SDL_FULLSCREEN) {
|
||||
window_flags |= SDL_WINDOW_FULLSCREEN;
|
||||
}
|
||||
if (flags & SDL_OPENGL) {
|
||||
window_flags |= SDL_WINDOW_OPENGL;
|
||||
}
|
||||
#ifdef VIDEXT_VULKAN
|
||||
if (flags & SDL_VULKAN) {
|
||||
window_flags |= SDL_WINDOW_VULKAN;
|
||||
}
|
||||
#endif
|
||||
if (flags & SDL_RESIZABLE) {
|
||||
window_flags |= SDL_WINDOW_RESIZABLE;
|
||||
}
|
||||
if (flags & SDL_NOFRAME) {
|
||||
window_flags |= SDL_WINDOW_BORDERLESS;
|
||||
}
|
||||
GetEnvironmentWindowPosition(width, height, &window_x, &window_y);
|
||||
SDL_VideoWindow =
|
||||
SDL_CreateWindow(wm_title, window_x, window_y, width, height,
|
||||
window_flags);
|
||||
if (!SDL_VideoWindow) {
|
||||
return NULL;
|
||||
}
|
||||
SDL_SetWindowIcon(SDL_VideoWindow, SDL_VideoIcon);
|
||||
|
||||
window_flags = SDL_GetWindowFlags(SDL_VideoWindow);
|
||||
surface_flags = 0;
|
||||
if (window_flags & SDL_WINDOW_FULLSCREEN) {
|
||||
surface_flags |= SDL_FULLSCREEN;
|
||||
}
|
||||
if ((window_flags & SDL_WINDOW_OPENGL) && (flags & SDL_OPENGL)) {
|
||||
surface_flags |= SDL_OPENGL;
|
||||
}
|
||||
#ifdef VIDEXT_VULKAN
|
||||
if ((window_flags & SDL_WINDOW_VULKAN) && (flags & SDL_VULKAN)) {
|
||||
surface_flags |= SDL_VULKAN;
|
||||
}
|
||||
#endif
|
||||
if (window_flags & SDL_WINDOW_RESIZABLE) {
|
||||
surface_flags |= SDL_RESIZABLE;
|
||||
}
|
||||
if (window_flags & SDL_WINDOW_BORDERLESS) {
|
||||
surface_flags |= SDL_NOFRAME;
|
||||
}
|
||||
|
||||
SDL_VideoFlags = flags;
|
||||
|
||||
/* If we're in OpenGL mode, just create a stub surface and we're done! */
|
||||
if (flags & SDL_OPENGL) {
|
||||
SDL_VideoContext = SDL_GL_CreateContext(SDL_VideoWindow);
|
||||
if (!SDL_VideoContext) {
|
||||
return NULL;
|
||||
}
|
||||
if (SDL_GL_MakeCurrent(SDL_VideoWindow, SDL_VideoContext) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Pitch: size of of line in bytes */
|
||||
/* Add 7 to bpp before division, to ensure correct rounding towards infinity
|
||||
* in cases where bits per pixel do not cleanly divide by 8 (such as 15)
|
||||
*/
|
||||
int pitch = (bpp + 7) / 8 * width;
|
||||
SDL_VideoSurface =
|
||||
SDL_CreateRGBSurfaceFrom(NULL, width, height, bpp, pitch, 0, 0, 0, 0);
|
||||
if (!SDL_VideoSurface) {
|
||||
return NULL;
|
||||
}
|
||||
SDL_VideoSurface->flags |= surface_flags;
|
||||
SDL_PublicSurface = SDL_VideoSurface;
|
||||
return SDL_PublicSurface;
|
||||
}
|
||||
#ifdef VIDEXT_VULKAN
|
||||
else if (flags & SDL_VULKAN) {
|
||||
/* Vulkan doesn't have a video surface,
|
||||
* so just return a stub */
|
||||
return (SDL_Surface*)0x1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We're finally done! */
|
||||
return NULL;
|
||||
}
|
||||
@@ -28,7 +28,11 @@
|
||||
#include "api/m64p_types.h"
|
||||
#include "api/callbacks.h"
|
||||
|
||||
#ifdef USE_SDL3
|
||||
#include <SDL3/SDL_timer.h>
|
||||
#else
|
||||
#include <SDL_timer.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
+17
-4
@@ -22,8 +22,13 @@
|
||||
|
||||
/* gameshark and xploder64 reference: http://doc.kodewerx.net/hacking_n64.html */
|
||||
|
||||
#ifdef USE_SDL3
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_thread.h>
|
||||
#else
|
||||
#include <SDL.h>
|
||||
#include <SDL_thread.h>
|
||||
#endif
|
||||
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#include <inttypes.h>
|
||||
@@ -214,12 +219,14 @@ void cheat_apply_cheats(struct cheat_ctx* ctx, struct r4300_core* r4300, int ent
|
||||
if (list_empty(&ctx->active_cheats))
|
||||
return;
|
||||
|
||||
if (ctx->mutex == NULL || SDL_LockMutex(ctx->mutex) != 0)
|
||||
if (ctx->mutex == NULL)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "Internal error: failed to lock mutex in cheat_apply_cheats()");
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_LockMutex(ctx->mutex);
|
||||
|
||||
list_for_each_entry_t(cheat, &ctx->active_cheats, cheat_t, list) {
|
||||
if (cheat->enabled)
|
||||
{
|
||||
@@ -325,12 +332,14 @@ void cheat_delete_all(struct cheat_ctx* ctx)
|
||||
if (list_empty(&ctx->active_cheats))
|
||||
return;
|
||||
|
||||
if (ctx->mutex == NULL || SDL_LockMutex(ctx->mutex) != 0)
|
||||
if (ctx->mutex == NULL)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "Internal error: failed to lock mutex in cheat_delete_all()");
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_LockMutex(ctx->mutex);
|
||||
|
||||
list_for_each_entry_safe_t(cheat, safe_cheat, &ctx->active_cheats, cheat_t, list) {
|
||||
free(cheat->name);
|
||||
|
||||
@@ -352,12 +361,14 @@ int cheat_set_enabled(struct cheat_ctx* ctx, const char* name, int enabled)
|
||||
if (list_empty(&ctx->active_cheats))
|
||||
return 0;
|
||||
|
||||
if (ctx->mutex == NULL || SDL_LockMutex(ctx->mutex) != 0)
|
||||
if (ctx->mutex == NULL)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "Internal error: failed to lock mutex in cheat_set_enabled()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_LockMutex(ctx->mutex);
|
||||
|
||||
list_for_each_entry_t(cheat, &ctx->active_cheats, cheat_t, list) {
|
||||
if (strcmp(name, cheat->name) == 0)
|
||||
{
|
||||
@@ -376,12 +387,14 @@ int cheat_add_new(struct cheat_ctx* ctx, const char* name, m64p_cheat_code* code
|
||||
cheat_t *cheat;
|
||||
int i, j;
|
||||
|
||||
if (ctx->mutex == NULL || SDL_LockMutex(ctx->mutex) != 0)
|
||||
if (ctx->mutex == NULL)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "Internal error: failed to lock mutex in cheat_add_new()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_LockMutex(ctx->mutex);
|
||||
|
||||
/* create a new cheat function or erase the codes in an existing cheat function */
|
||||
cheat = find_or_create_cheat(ctx, name);
|
||||
if (cheat == NULL)
|
||||
|
||||
@@ -36,7 +36,11 @@ struct r4300_core;
|
||||
|
||||
struct cheat_ctx
|
||||
{
|
||||
#ifdef USE_SDL3
|
||||
struct SDL_Mutex* mutex;
|
||||
#else
|
||||
struct SDL_mutex* mutex;
|
||||
#endif
|
||||
struct list_head active_cheats;
|
||||
};
|
||||
|
||||
|
||||
+67
-15
@@ -20,7 +20,11 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifdef USE_SDL3
|
||||
#include <SDL3/SDL.h>
|
||||
#else
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -38,6 +42,26 @@ SDL_JoystickID l_iJoyInstanceID[10];
|
||||
#include "sdl_key_converter.h"
|
||||
#include "util.h"
|
||||
|
||||
/* SDL2 compatability defines */
|
||||
#ifndef USE_SDL3
|
||||
|
||||
#define SDL_EVENT_QUIT SDL_QUIT
|
||||
#define SDL_EVENT_KEY_DOWN SDL_KEYDOWN
|
||||
#define SDL_EVENT_KEY_UP SDL_KEYUP
|
||||
|
||||
#define SDL_EVENT_JOYSTICK_AXIS_MOTION SDL_JOYAXISMOTION
|
||||
#define SDL_EVENT_JOYSTICK_HAT_MOTION SDL_JOYHATMOTION
|
||||
#define SDL_EVENT_JOYSTICK_BUTTON_DOWN SDL_JOYBUTTONDOWN
|
||||
|
||||
#define SDL_EVENT_JOYSTICK_BUTTON_UP SDL_JOYBUTTONUP
|
||||
#define SDL_EVENT_JOYSTICK_BUTTON_DOWN SDL_JOYBUTTONDOWN
|
||||
|
||||
#define SDL_KMOD_LALT KMOD_LALT
|
||||
#define SDL_KMOD_RALT KMOD_RALT
|
||||
|
||||
#define SDL_SCANCODE_COUNT SDL_NUM_SCANCODES
|
||||
#endif
|
||||
|
||||
/* version number for CoreEvents config section */
|
||||
#define CONFIG_PARAM_VERSION 1.00
|
||||
|
||||
@@ -192,7 +216,7 @@ static int MatchJoyCommand(const SDL_Event *event, eJoyCommand cmd)
|
||||
{
|
||||
/* Axis */
|
||||
case 'A':
|
||||
if (event->type != SDL_JOYAXISMOTION)
|
||||
if (event->type != SDL_EVENT_JOYSTICK_AXIS_MOTION)
|
||||
break;
|
||||
if (sscanf(action_str, "A%d%c", &input_number, &axis_direction) != 2)
|
||||
break;
|
||||
@@ -217,7 +241,7 @@ static int MatchJoyCommand(const SDL_Event *event, eJoyCommand cmd)
|
||||
break;
|
||||
/* Hat */
|
||||
case 'H':
|
||||
if (event->type != SDL_JOYHATMOTION)
|
||||
if (event->type != SDL_EVENT_JOYSTICK_HAT_MOTION)
|
||||
break;
|
||||
if (sscanf(action_str, "H%dV%d", &input_number, &input_value) != 2)
|
||||
break;
|
||||
@@ -230,15 +254,15 @@ static int MatchJoyCommand(const SDL_Event *event, eJoyCommand cmd)
|
||||
break;
|
||||
/* Button. */
|
||||
case 'B':
|
||||
if (event->type != SDL_JOYBUTTONDOWN && event->type != SDL_JOYBUTTONUP)
|
||||
if (event->type != SDL_EVENT_JOYSTICK_BUTTON_DOWN && event->type != SDL_EVENT_JOYSTICK_BUTTON_UP)
|
||||
break;
|
||||
if (sscanf(action_str, "B%d", &input_number) != 1)
|
||||
break;
|
||||
if ((dev_number != -1 && dev_number != event->jbutton.which) || input_number != event->jbutton.button)
|
||||
break;
|
||||
if (event->type == SDL_JOYBUTTONDOWN)
|
||||
if (event->type == SDL_EVENT_JOYSTICK_BUTTON_DOWN)
|
||||
JoyCmdActive[cmd][iHotkey] = 1;
|
||||
else if (event->type == SDL_JOYBUTTONUP)
|
||||
else if (event->type == SDL_EVENT_JOYSTICK_BUTTON_UP)
|
||||
JoyCmdActive[cmd][iHotkey] = 0;
|
||||
break;
|
||||
default:
|
||||
@@ -267,7 +291,11 @@ static int MatchJoyCommand(const SDL_Event *event, eJoyCommand cmd)
|
||||
/*********************************************************************************************************
|
||||
* sdl event filter
|
||||
*/
|
||||
#ifdef USE_SDL3
|
||||
static bool SDLCALL event_sdl_filter(void *userdata, SDL_Event *event)
|
||||
#else
|
||||
static int SDLCALL event_sdl_filter(void *userdata, SDL_Event *event)
|
||||
#endif
|
||||
{
|
||||
#ifndef NO_KEYBINDINGS
|
||||
int cmd, action;
|
||||
@@ -276,20 +304,42 @@ static int SDLCALL event_sdl_filter(void *userdata, SDL_Event *event)
|
||||
switch(event->type)
|
||||
{
|
||||
// user clicked on window close button
|
||||
case SDL_QUIT:
|
||||
case SDL_EVENT_QUIT:
|
||||
main_stop();
|
||||
break;
|
||||
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
if (event->key.repeat)
|
||||
return 0;
|
||||
|
||||
#ifdef USE_SDL3
|
||||
event_sdl_keydown(event->key.scancode, event->key.mod);
|
||||
#else
|
||||
event_sdl_keydown(event->key.keysym.scancode, event->key.keysym.mod);
|
||||
#endif
|
||||
return 0;
|
||||
case SDL_KEYUP:
|
||||
case SDL_EVENT_KEY_UP:
|
||||
#ifdef USE_SDL3
|
||||
event_sdl_keyup(event->key.scancode, event->key.mod);
|
||||
#else
|
||||
event_sdl_keyup(event->key.keysym.scancode, event->key.keysym.mod);
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
#ifdef USE_SDL3
|
||||
case SDL_EVENT_WINDOW_RESIZED:
|
||||
// call the video plugin. if the video plugin supports resizing, it will resize its viewport and call
|
||||
// VidExt_ResizeWindow to update the window manager handling our opengl output window
|
||||
gfx.resizeVideoOutput(event->window.data1, event->window.data2);
|
||||
return 0; // consumed the event
|
||||
break;
|
||||
|
||||
case SDL_EVENT_WINDOW_MOVED:
|
||||
gfx.moveScreen(event->window.data1, event->window.data2);
|
||||
return 0; // consumed the event
|
||||
break;
|
||||
|
||||
#else
|
||||
case SDL_WINDOWEVENT:
|
||||
switch (event->window.event) {
|
||||
case SDL_WINDOWEVENT_RESIZED:
|
||||
@@ -305,13 +355,15 @@ static int SDLCALL event_sdl_filter(void *userdata, SDL_Event *event)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef NO_KEYBINDINGS
|
||||
// if joystick action is detected, check if it's mapped to a special function
|
||||
case SDL_JOYAXISMOTION:
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
case SDL_JOYBUTTONUP:
|
||||
case SDL_JOYHATMOTION:
|
||||
case SDL_EVENT_JOYSTICK_AXIS_MOTION:
|
||||
case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
|
||||
case SDL_EVENT_JOYSTICK_BUTTON_UP:
|
||||
case SDL_EVENT_JOYSTICK_HAT_MOTION:
|
||||
for (cmd = 0; cmd < NumJoyCommands; cmd++)
|
||||
{
|
||||
action = MatchJoyCommand(event, (eJoyCommand) cmd);
|
||||
@@ -374,7 +426,7 @@ static int SDLCALL event_sdl_filter(void *userdata, SDL_Event *event)
|
||||
|
||||
void event_initialize(void)
|
||||
{
|
||||
#ifndef NO_KEYBINDINGS
|
||||
#if !defined(NO_KEYBINDINGS) && !defined(USE_SDL3)
|
||||
int i, j;
|
||||
|
||||
/* set initial state of all joystick commands to 'off' */
|
||||
@@ -487,7 +539,7 @@ int event_set_core_defaults(void)
|
||||
ConfigSetDefaultInt(l_CoreEventsConfig, kbdSaveSlotStr, sdl_native2keysym(key), kbdSaveSlotHelpStr);
|
||||
}
|
||||
ConfigSetDefaultInt(l_CoreEventsConfig, kbdStop, sdl_native2keysym(SDL_SCANCODE_ESCAPE), "SDL keysym for stopping the emulator");
|
||||
ConfigSetDefaultInt(l_CoreEventsConfig, kbdFullscreen, sdl_native2keysym(SDL_NUM_SCANCODES), "SDL keysym for switching between fullscreen/windowed modes");
|
||||
ConfigSetDefaultInt(l_CoreEventsConfig, kbdFullscreen, sdl_native2keysym(SDL_SCANCODE_COUNT), "SDL keysym for switching between fullscreen/windowed modes");
|
||||
ConfigSetDefaultInt(l_CoreEventsConfig, kbdSave, sdl_native2keysym(SDL_SCANCODE_F5), "SDL keysym for saving the emulator state");
|
||||
ConfigSetDefaultInt(l_CoreEventsConfig, kbdLoad, sdl_native2keysym(SDL_SCANCODE_F7), "SDL keysym for loading the emulator state");
|
||||
ConfigSetDefaultInt(l_CoreEventsConfig, kbdIncrement, sdl_native2keysym(SDL_SCANCODE_UNKNOWN), "SDL keysym for advancing the save state slot");
|
||||
@@ -551,7 +603,7 @@ void event_sdl_keydown(int keysym, int keymod)
|
||||
int slot;
|
||||
|
||||
/* check for the only hard-coded key command: Alt-enter for fullscreen */
|
||||
if (keysym == SDL_SCANCODE_RETURN && keymod & (KMOD_LALT | KMOD_RALT))
|
||||
if (keysym == SDL_SCANCODE_RETURN && keymod & (SDL_KMOD_LALT | SDL_KMOD_RALT))
|
||||
gfx.changeWindow();
|
||||
/* check all of the configurable commands */
|
||||
else if ((slot = get_saveslot_from_keysym(keysym)) >= 0)
|
||||
|
||||
@@ -28,7 +28,11 @@
|
||||
* if you want to implement an interface, you should look here
|
||||
*/
|
||||
|
||||
#ifdef USE_SDL3
|
||||
#include <SDL3/SDL.h>
|
||||
#else
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
+297
-60
@@ -28,17 +28,48 @@
|
||||
#include "plugin/plugin.h"
|
||||
#include "backends/plugins_compat/plugins_compat.h"
|
||||
#include "netplay.h"
|
||||
#include "osal/preproc.h"
|
||||
|
||||
#ifdef USE_SDL3NET
|
||||
#include <SDL3_net/SDL_net.h>
|
||||
#else
|
||||
#include <SDL_net.h>
|
||||
#endif
|
||||
|
||||
#if !defined(WIN32)
|
||||
#include <netinet/ip.h>
|
||||
#endif
|
||||
|
||||
/* small helper structures to wrap SDL2_net/SDL3_net */
|
||||
|
||||
#ifdef USE_SDL3NET
|
||||
/* SDL3_net needs a wrapper struct */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t* data;
|
||||
int len;
|
||||
int maxlen;
|
||||
} netplay_udp_packet;
|
||||
#else
|
||||
/* SDL2_net uses UDPpacket directly */
|
||||
typedef UDPpacket netplay_udp_packet;
|
||||
#endif
|
||||
|
||||
/* local variables */
|
||||
|
||||
#ifdef USE_SDL3NET
|
||||
static NET_Address *l_resolvedAddress;
|
||||
static int l_resolvedAddressPort;
|
||||
static NET_StreamSocket *l_tcpSocket;
|
||||
static NET_DatagramSocket *l_udpSocket;
|
||||
#else
|
||||
static UDPsocket l_udpSocket;
|
||||
static TCPsocket l_tcpSocket;
|
||||
#endif
|
||||
|
||||
static int l_canFF;
|
||||
static int l_netplay_controller;
|
||||
static int l_netplay_control[4];
|
||||
static UDPsocket l_udpSocket;
|
||||
static TCPsocket l_tcpSocket;
|
||||
static int l_udpChannel;
|
||||
static int l_spectator;
|
||||
static int l_netplay_is_init = 0;
|
||||
@@ -51,10 +82,11 @@ static uint8_t l_buffer_target;
|
||||
static uint8_t l_player_lag[4];
|
||||
|
||||
//UDP packets
|
||||
static UDPpacket *l_request_input_packet;
|
||||
static UDPpacket *l_send_input_packet;
|
||||
static UDPpacket *l_process_packet;
|
||||
static UDPpacket *l_check_sync_packet;
|
||||
static netplay_udp_packet *l_request_input_packet;
|
||||
static netplay_udp_packet *l_send_input_packet;
|
||||
static netplay_udp_packet *l_process_packet;
|
||||
static netplay_udp_packet *l_check_sync_packet;
|
||||
|
||||
static const int32_t l_check_sync_packet_size = (CP0_REGS_COUNT * 4) + 5;
|
||||
|
||||
//UDP packet formats
|
||||
@@ -80,8 +112,191 @@ struct __UDPSocket {
|
||||
|
||||
#define CS4 32
|
||||
|
||||
/* small helper functions to wrap SDL2_net/SDL3_net functions */
|
||||
|
||||
#define netplay_min(x, y) (x > y ? y : x);
|
||||
|
||||
static netplay_udp_packet* alloc_udp_packet(size_t len)
|
||||
{
|
||||
#ifdef USE_SDL3NET
|
||||
netplay_udp_packet *packet = malloc(sizeof(netplay_udp_packet));
|
||||
if (packet == NULL)
|
||||
return NULL;
|
||||
|
||||
packet->len = 0;
|
||||
packet->maxlen = len;
|
||||
packet->data = malloc(len);
|
||||
if (packet->data == NULL)
|
||||
{
|
||||
free(packet);
|
||||
return NULL;
|
||||
}
|
||||
return packet;
|
||||
#else
|
||||
/* when using SDL2_net, netplay_udp_packet
|
||||
* is just a shim for UDPpacket */
|
||||
return SDLNet_AllocPacket(len);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void free_udp_packet(netplay_udp_packet* packet)
|
||||
{
|
||||
if (packet != NULL)
|
||||
{
|
||||
#ifndef USE_SDL3NET
|
||||
SDLNet_FreePacket(packet);
|
||||
#else
|
||||
if (packet->data != NULL)
|
||||
{
|
||||
free(packet->data);
|
||||
}
|
||||
free(packet);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static osal_inline int netplay_recv_udp_packet(void* udpSocket, netplay_udp_packet* packet)
|
||||
{
|
||||
#ifdef USE_SDL3NET
|
||||
NET_Datagram* udpPacket = NULL;
|
||||
if (!NET_ReceiveDatagram((NET_DatagramSocket*)udpSocket, &udpPacket))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (udpPacket != NULL)
|
||||
{
|
||||
int len = netplay_min(packet->maxlen, udpPacket->buflen);
|
||||
memcpy(packet->data, udpPacket->buf, len);
|
||||
packet->len = len;
|
||||
NET_DestroyDatagram(udpPacket);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return SDLNet_UDP_Recv((UDPsocket)udpSocket, packet);
|
||||
#endif
|
||||
}
|
||||
|
||||
static osal_inline void netplay_send_udp_packet(void* udpSocket, netplay_udp_packet* packet)
|
||||
{
|
||||
#ifdef USE_SDL3NET
|
||||
NET_SendDatagram((NET_DatagramSocket*)udpSocket, l_resolvedAddress, l_resolvedAddressPort, packet->data, packet->len);
|
||||
#else
|
||||
SDLNet_UDP_Send((UDPsocket)udpSocket, l_udpChannel, packet);
|
||||
#endif
|
||||
}
|
||||
|
||||
static osal_inline int netplay_send_tcp_packet(void* tcpSocket, const void* data, int len)
|
||||
{
|
||||
#ifdef USE_SDL3NET
|
||||
NET_WriteToStreamSocket((NET_StreamSocket*)tcpSocket, data, len);
|
||||
NET_WaitUntilStreamSocketDrained((NET_StreamSocket*)tcpSocket, -1);
|
||||
return len;
|
||||
#else
|
||||
return SDLNet_TCP_Send((TCPsocket)tcpSocket, data, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
static osal_inline int netplay_recv_tcp_packet(void* tcpSocket, void* data, int len)
|
||||
{
|
||||
#ifdef USE_SDL3NET
|
||||
int ret;
|
||||
do
|
||||
{
|
||||
ret = NET_ReadFromStreamSocket((NET_StreamSocket*)tcpSocket, data, len);
|
||||
} while (ret == 0);
|
||||
return ret;
|
||||
#else
|
||||
return SDLNet_TCP_Recv((TCPsocket)tcpSocket, data, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
static osal_inline void netplay_write32(uint32_t value, void *p)
|
||||
{
|
||||
#ifdef USE_SDL3NET
|
||||
*(uint32_t*)p = SDL_Swap32BE(value);
|
||||
#else
|
||||
*(uint32_t*)p = SDL_SwapBE32(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
static osal_inline uint32_t netplay_read32(void *p)
|
||||
{
|
||||
#ifdef USE_SDL3NET
|
||||
return SDL_Swap32BE(*(uint32_t*)p);
|
||||
#else
|
||||
return SDL_SwapBE32(*(uint32_t*)p);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* public exposed functions */
|
||||
|
||||
m64p_error netplay_start(const char* host, int port)
|
||||
{
|
||||
#ifdef USE_SDL3NET
|
||||
NET_Status status;
|
||||
|
||||
if (!NET_Init())
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "Netplay: Could not initialize SDL Net library: %s", SDL_GetError());
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
|
||||
l_resolvedAddressPort = port;
|
||||
l_resolvedAddress = NET_ResolveHostname(host);
|
||||
if (l_resolvedAddress == NULL)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "Netplay: Could not resolve host: %s", SDL_GetError());
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
|
||||
status = NET_WaitUntilResolved(l_resolvedAddress, -1);
|
||||
if (status != NET_SUCCESS)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "Netplay: Could not resolve host: %s", SDL_GetError());
|
||||
NET_UnrefAddress(l_resolvedAddress);
|
||||
l_resolvedAddress = NULL;
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
|
||||
l_udpSocket = NET_CreateDatagramSocket(NULL, 0);
|
||||
if (l_udpSocket == NULL)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "Netplay: UDP socket creation failed: %s", SDL_GetError());
|
||||
NET_UnrefAddress(l_resolvedAddress);
|
||||
l_resolvedAddress = NULL;
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
|
||||
l_tcpSocket = NET_CreateClient(l_resolvedAddress, port);
|
||||
if (l_tcpSocket == NULL)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "Netplay: TCP socket connection failed: %s", SDL_GetError());
|
||||
NET_UnrefAddress(l_resolvedAddress);
|
||||
NET_DestroyDatagramSocket(l_udpSocket);
|
||||
l_resolvedAddress = NULL;
|
||||
l_udpSocket = NULL;
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
|
||||
status = NET_WaitUntilConnected(l_tcpSocket, 120 * 1000);
|
||||
if (status != NET_SUCCESS)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "Netplay: TCP socket connection failed: %s", SDL_GetError());
|
||||
NET_UnrefAddress(l_resolvedAddress);
|
||||
NET_DestroyDatagramSocket(l_udpSocket);
|
||||
NET_DestroyStreamSocket(l_tcpSocket);
|
||||
l_resolvedAddress = NULL;
|
||||
l_udpSocket = NULL;
|
||||
l_tcpSocket = NULL;
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
|
||||
// dummy value
|
||||
l_udpChannel = 1;
|
||||
#else
|
||||
if (SDLNet_Init() < 0)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "Netplay: Could not initialize SDL Net library");
|
||||
@@ -121,28 +336,37 @@ m64p_error netplay_start(const char* host, int port)
|
||||
l_udpSocket = NULL;
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
l_request_input_packet = SDLNet_AllocPacket(12);
|
||||
l_send_input_packet = SDLNet_AllocPacket(11);
|
||||
l_process_packet = SDLNet_AllocPacket(512);
|
||||
l_check_sync_packet = SDLNet_AllocPacket(l_check_sync_packet_size);
|
||||
l_request_input_packet = alloc_udp_packet(12);
|
||||
l_send_input_packet = alloc_udp_packet(11);
|
||||
l_process_packet = alloc_udp_packet(512);
|
||||
l_check_sync_packet = alloc_udp_packet(l_check_sync_packet_size);
|
||||
if (l_request_input_packet == NULL ||
|
||||
l_send_input_packet == NULL ||
|
||||
l_process_packet == NULL ||
|
||||
l_check_sync_packet == NULL)
|
||||
{
|
||||
DebugMessage(M64MSG_ERROR, "Netplay: could not allocate UDP packets");
|
||||
#ifdef USE_SDL3NET
|
||||
NET_UnrefAddress(l_resolvedAddress);
|
||||
l_resolvedAddress = NULL;
|
||||
|
||||
NET_DestroyDatagramSocket(l_udpSocket);
|
||||
NET_DestroyStreamSocket(l_tcpSocket);
|
||||
#else
|
||||
SDLNet_UDP_Close(l_udpSocket);
|
||||
l_udpSocket = NULL;
|
||||
SDLNet_TCP_Close(l_tcpSocket);
|
||||
#endif
|
||||
l_udpSocket = NULL;
|
||||
l_tcpSocket = NULL;
|
||||
SDLNet_FreePacket(l_request_input_packet);
|
||||
free_udp_packet(l_request_input_packet);
|
||||
l_request_input_packet = NULL;
|
||||
SDLNet_FreePacket(l_send_input_packet);
|
||||
free_udp_packet(l_send_input_packet);
|
||||
l_send_input_packet = NULL;
|
||||
SDLNet_FreePacket(l_process_packet);
|
||||
free_udp_packet(l_process_packet);
|
||||
l_process_packet = NULL;
|
||||
SDLNet_FreePacket(l_check_sync_packet);
|
||||
free_udp_packet(l_check_sync_packet);
|
||||
l_check_sync_packet = NULL;
|
||||
return M64ERR_NO_MEMORY;
|
||||
}
|
||||
@@ -188,27 +412,40 @@ m64p_error netplay_stop()
|
||||
|
||||
char output_data[5];
|
||||
output_data[0] = TCP_DISCONNECT_NOTICE;
|
||||
SDLNet_Write32(l_reg_id, &output_data[1]);
|
||||
SDLNet_TCP_Send(l_tcpSocket, &output_data[0], 5);
|
||||
netplay_write32(l_reg_id, &output_data[1]);
|
||||
netplay_send_tcp_packet(l_tcpSocket, &output_data[0], 5);
|
||||
|
||||
#ifdef USE_SDL3NET
|
||||
NET_UnrefAddress(l_resolvedAddress);
|
||||
l_resolvedAddress = NULL;
|
||||
|
||||
NET_DestroyDatagramSocket(l_udpSocket);
|
||||
NET_DestroyStreamSocket(l_tcpSocket);
|
||||
#else
|
||||
SDLNet_UDP_Unbind(l_udpSocket, l_udpChannel);
|
||||
SDLNet_UDP_Close(l_udpSocket);
|
||||
SDLNet_TCP_Close(l_tcpSocket);
|
||||
#endif
|
||||
l_tcpSocket = NULL;
|
||||
l_udpSocket = NULL;
|
||||
l_udpChannel = -1;
|
||||
|
||||
SDLNet_FreePacket(l_request_input_packet);
|
||||
SDLNet_FreePacket(l_send_input_packet);
|
||||
SDLNet_FreePacket(l_process_packet);
|
||||
SDLNet_FreePacket(l_check_sync_packet);
|
||||
free_udp_packet(l_request_input_packet);
|
||||
free_udp_packet(l_send_input_packet);
|
||||
free_udp_packet(l_process_packet);
|
||||
free_udp_packet(l_check_sync_packet);
|
||||
l_request_input_packet = NULL;
|
||||
l_send_input_packet = NULL;
|
||||
l_process_packet = NULL;
|
||||
l_check_sync_packet = NULL;
|
||||
|
||||
l_netplay_is_init = 0;
|
||||
|
||||
#ifdef USE_SDL3NET
|
||||
NET_Quit();
|
||||
#else
|
||||
SDLNet_Quit();
|
||||
#endif
|
||||
return M64ERR_SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -235,12 +472,12 @@ static void netplay_request_input(uint8_t control_id)
|
||||
{
|
||||
l_request_input_packet->data[0] = UDP_REQUEST_KEY_INFO;
|
||||
l_request_input_packet->data[1] = control_id; //The player we need input for
|
||||
SDLNet_Write32(l_reg_id, &l_request_input_packet->data[2]); //our registration ID
|
||||
SDLNet_Write32(l_cin_compats[control_id].netplay_count, &l_request_input_packet->data[6]); //the current event count
|
||||
netplay_write32(l_reg_id, &l_request_input_packet->data[2]); //our registration ID
|
||||
netplay_write32(l_cin_compats[control_id].netplay_count, &l_request_input_packet->data[6]); //the current event count
|
||||
l_request_input_packet->data[10] = l_spectator; //whether we are a spectator
|
||||
l_request_input_packet->data[11] = buffer_size(control_id); //our local buffer size
|
||||
l_request_input_packet->len = 12;
|
||||
SDLNet_UDP_Send(l_udpSocket, l_udpChannel, l_request_input_packet);
|
||||
netplay_send_udp_packet(l_udpSocket, l_request_input_packet);
|
||||
}
|
||||
|
||||
static int check_valid(uint8_t control_id, uint32_t count)
|
||||
@@ -282,7 +519,7 @@ static void netplay_process()
|
||||
//In this function we process data we have received from the server
|
||||
uint32_t curr, count, keys;
|
||||
uint8_t plugin, player, current_status;
|
||||
while (SDLNet_UDP_Recv(l_udpSocket, l_process_packet) == 1)
|
||||
while (netplay_recv_udp_packet(l_udpSocket, l_process_packet) == 1)
|
||||
{
|
||||
switch (l_process_packet->data[0])
|
||||
{
|
||||
@@ -310,7 +547,7 @@ static void netplay_process()
|
||||
//it skips events that we have already recorded, or if we receive data for an event that has already happened
|
||||
for (uint8_t i = 0; i < l_process_packet->data[4]; ++i)
|
||||
{
|
||||
count = SDLNet_Read32(&l_process_packet->data[curr]);
|
||||
count = netplay_read32(&l_process_packet->data[curr]);
|
||||
curr += 4;
|
||||
|
||||
if (((count - l_cin_compats[player].netplay_count) > (UINT32_MAX / 2)) || (check_valid(player, count))) //event doesn't need to be recorded
|
||||
@@ -319,7 +556,7 @@ static void netplay_process()
|
||||
continue;
|
||||
}
|
||||
|
||||
keys = SDLNet_Read32(&l_process_packet->data[curr]);
|
||||
keys = netplay_read32(&l_process_packet->data[curr]);
|
||||
curr += 4;
|
||||
plugin = l_process_packet->data[curr];
|
||||
curr += 1;
|
||||
@@ -423,11 +660,11 @@ static void netplay_send_input(uint8_t control_id, uint32_t keys)
|
||||
{
|
||||
l_send_input_packet->data[0] = UDP_SEND_KEY_INFO;
|
||||
l_send_input_packet->data[1] = control_id; //player number
|
||||
SDLNet_Write32(l_cin_compats[control_id].netplay_count, &l_send_input_packet->data[2]); // current event count
|
||||
SDLNet_Write32(keys, &l_send_input_packet->data[6]); //key data
|
||||
netplay_write32(l_cin_compats[control_id].netplay_count, &l_send_input_packet->data[2]); // current event count
|
||||
netplay_write32(keys, &l_send_input_packet->data[6]); //key data
|
||||
l_send_input_packet->data[10] = l_plugin[control_id]; //current plugin
|
||||
l_send_input_packet->len = 11;
|
||||
SDLNet_UDP_Send(l_udpSocket, l_udpChannel, l_send_input_packet);
|
||||
netplay_send_udp_packet(l_udpSocket, l_send_input_packet);
|
||||
}
|
||||
|
||||
uint8_t netplay_register_player(uint8_t player, uint8_t plugin, uint8_t rawdata, uint32_t reg_id)
|
||||
@@ -438,14 +675,14 @@ uint8_t netplay_register_player(uint8_t player, uint8_t plugin, uint8_t rawdata,
|
||||
output_data[1] = player; //player number we'd like to register
|
||||
output_data[2] = plugin; //current plugin
|
||||
output_data[3] = rawdata; //whether we are using a RawData input plugin
|
||||
SDLNet_Write32(l_reg_id, &output_data[4]);
|
||||
netplay_write32(l_reg_id, &output_data[4]);
|
||||
|
||||
SDLNet_TCP_Send(l_tcpSocket, &output_data[0], 8);
|
||||
netplay_send_tcp_packet(l_tcpSocket, &output_data[0], 8);
|
||||
|
||||
uint8_t response[2];
|
||||
size_t recv = 0;
|
||||
while (recv < 2)
|
||||
recv += SDLNet_TCP_Recv(l_tcpSocket, &response[recv], 2 - recv);
|
||||
recv += netplay_recv_tcp_packet(l_tcpSocket, &response[recv], 2 - recv);
|
||||
l_buffer_target = response[1]; //local buffer size target
|
||||
return response[0];
|
||||
}
|
||||
@@ -497,12 +734,12 @@ file_status_t netplay_read_storage(const char *filename, void *data, size_t size
|
||||
ret = read_from_file(filename, data, size);
|
||||
if (ret == file_open_error)
|
||||
memset(data, 0, size); //all zeros means there is no save file
|
||||
SDLNet_Write32((int32_t)size, &output_data[buffer_pos]); //file data size
|
||||
netplay_write32((int32_t)size, &output_data[buffer_pos]); //file data size
|
||||
buffer_pos += 4;
|
||||
memcpy(&output_data[buffer_pos], data, size); //file data
|
||||
buffer_pos += size;
|
||||
|
||||
SDLNet_TCP_Send(l_tcpSocket, &output_data[0], buffer_pos);
|
||||
netplay_send_tcp_packet(l_tcpSocket, &output_data[0], buffer_pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -514,11 +751,11 @@ file_status_t netplay_read_storage(const char *filename, void *data, size_t size
|
||||
memcpy(&output_data[buffer_pos], file_extension, strlen(file_extension) + 1);
|
||||
buffer_pos += strlen(file_extension) + 1;
|
||||
|
||||
SDLNet_TCP_Send(l_tcpSocket, &output_data[0], buffer_pos);
|
||||
netplay_send_tcp_packet(l_tcpSocket, &output_data[0], buffer_pos);
|
||||
size_t recv = 0;
|
||||
char *data_array = data;
|
||||
while (recv < size)
|
||||
recv += SDLNet_TCP_Recv(l_tcpSocket, data_array + recv, size - recv);
|
||||
recv += netplay_recv_tcp_packet(l_tcpSocket, data_array + recv, size - recv);
|
||||
|
||||
int sum = 0;
|
||||
for (int i = 0; i < size; ++i)
|
||||
@@ -544,28 +781,28 @@ void netplay_sync_settings(uint32_t *count_per_op, uint32_t *count_per_op_denom_
|
||||
{
|
||||
request = TCP_SEND_SETTINGS;
|
||||
memcpy(&output_data[0], &request, 1);
|
||||
SDLNet_Write32(*count_per_op, &output_data[1]);
|
||||
SDLNet_Write32(*count_per_op_denom_pot, &output_data[5]);
|
||||
SDLNet_Write32(*disable_extra_mem, &output_data[9]);
|
||||
SDLNet_Write32(*si_dma_duration, &output_data[13]);
|
||||
SDLNet_Write32(*emumode, &output_data[17]);
|
||||
SDLNet_Write32(*no_compiled_jump, &output_data[21]);
|
||||
SDLNet_TCP_Send(l_tcpSocket, &output_data[0], SETTINGS_SIZE + 1);
|
||||
netplay_write32(*count_per_op, &output_data[1]);
|
||||
netplay_write32(*count_per_op_denom_pot, &output_data[5]);
|
||||
netplay_write32(*disable_extra_mem, &output_data[9]);
|
||||
netplay_write32(*si_dma_duration, &output_data[13]);
|
||||
netplay_write32(*emumode, &output_data[17]);
|
||||
netplay_write32(*no_compiled_jump, &output_data[21]);
|
||||
netplay_send_tcp_packet(l_tcpSocket, &output_data[0], SETTINGS_SIZE + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
request = TCP_RECEIVE_SETTINGS;
|
||||
memcpy(&output_data[0], &request, 1);
|
||||
SDLNet_TCP_Send(l_tcpSocket, &output_data[0], 1);
|
||||
netplay_send_tcp_packet(l_tcpSocket, &output_data[0], 1);
|
||||
int32_t recv = 0;
|
||||
while (recv < SETTINGS_SIZE)
|
||||
recv += SDLNet_TCP_Recv(l_tcpSocket, &output_data[recv], SETTINGS_SIZE - recv);
|
||||
*count_per_op = SDLNet_Read32(&output_data[0]);
|
||||
*count_per_op_denom_pot = SDLNet_Read32(&output_data[4]);
|
||||
*disable_extra_mem = SDLNet_Read32(&output_data[8]);
|
||||
*si_dma_duration = SDLNet_Read32(&output_data[12]);
|
||||
*emumode = SDLNet_Read32(&output_data[16]);
|
||||
*no_compiled_jump = SDLNet_Read32(&output_data[20]);
|
||||
recv += netplay_recv_tcp_packet(l_tcpSocket, &output_data[recv], SETTINGS_SIZE - recv);
|
||||
*count_per_op = netplay_read32(&output_data[0]);
|
||||
*count_per_op_denom_pot = netplay_read32(&output_data[4]);
|
||||
*disable_extra_mem = netplay_read32(&output_data[8]);
|
||||
*si_dma_duration = netplay_read32(&output_data[12]);
|
||||
*emumode = netplay_read32(&output_data[16]);
|
||||
*no_compiled_jump = netplay_read32(&output_data[20]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -582,13 +819,13 @@ void netplay_check_sync(struct cp0* cp0)
|
||||
const uint32_t* cp0_regs = r4300_cp0_regs(cp0);
|
||||
|
||||
l_check_sync_packet->data[0] = UDP_SYNC_DATA;
|
||||
SDLNet_Write32(l_vi_counter, &l_check_sync_packet->data[1]); //current VI count
|
||||
netplay_write32(l_vi_counter, &l_check_sync_packet->data[1]); //current VI count
|
||||
for (int i = 0; i < CP0_REGS_COUNT; ++i)
|
||||
{
|
||||
SDLNet_Write32(cp0_regs[i], &l_check_sync_packet->data[(i * 4) + 5]);
|
||||
netplay_write32(cp0_regs[i], &l_check_sync_packet->data[(i * 4) + 5]);
|
||||
}
|
||||
l_check_sync_packet->len = l_check_sync_packet_size;
|
||||
SDLNet_UDP_Send(l_udpSocket, l_udpChannel, l_check_sync_packet);
|
||||
netplay_send_udp_packet(l_udpSocket, l_check_sync_packet);
|
||||
}
|
||||
|
||||
++l_vi_counter;
|
||||
@@ -606,14 +843,14 @@ void netplay_read_registration(struct controller_input_compat* cin_compats)
|
||||
uint32_t reg_id;
|
||||
char output_data = TCP_GET_REGISTRATION;
|
||||
char input_data[24];
|
||||
SDLNet_TCP_Send(l_tcpSocket, &output_data, 1);
|
||||
netplay_send_tcp_packet(l_tcpSocket, &output_data, 1);
|
||||
size_t recv = 0;
|
||||
while (recv < 24)
|
||||
recv += SDLNet_TCP_Recv(l_tcpSocket, &input_data[recv], 24 - recv);
|
||||
recv += netplay_recv_tcp_packet(l_tcpSocket, &input_data[recv], 24 - recv);
|
||||
uint32_t curr = 0;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
reg_id = SDLNet_Read32(&input_data[curr]);
|
||||
reg_id = netplay_read32(&input_data[curr]);
|
||||
curr += 4;
|
||||
|
||||
Controls[i].Type = CONT_TYPE_STANDARD; //make sure VRU is disabled
|
||||
@@ -707,7 +944,7 @@ m64p_error netplay_send_config(char* data, int size)
|
||||
|
||||
if (l_netplay_control[0] != -1 || size == 1) //Only P1 sends settings, we allow all players to send if the size is 1, this may be a request packet
|
||||
{
|
||||
int result = SDLNet_TCP_Send(l_tcpSocket, data, size);
|
||||
int result = netplay_send_tcp_packet(l_tcpSocket, data, size);
|
||||
if (result < size)
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
return M64ERR_SUCCESS;
|
||||
@@ -726,7 +963,7 @@ m64p_error netplay_receive_config(char* data, int size)
|
||||
int recv = 0;
|
||||
while (recv < size)
|
||||
{
|
||||
recv += SDLNet_TCP_Recv(l_tcpSocket, &data[recv], size - recv);
|
||||
recv += netplay_recv_tcp_packet(l_tcpSocket, &data[recv], size - recv);
|
||||
if (recv < 1)
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
|
||||
@@ -22,8 +22,13 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifdef USE_SDL3
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_thread.h>
|
||||
#else
|
||||
#include <SDL.h>
|
||||
#include <SDL_thread.h>
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
@@ -68,7 +73,11 @@ static char *fname = NULL;
|
||||
static unsigned int slot = 0;
|
||||
static int autoinc_save_slot = 0;
|
||||
|
||||
#ifdef USE_SDL3
|
||||
static SDL_Mutex *savestates_lock;
|
||||
#else
|
||||
static SDL_mutex *savestates_lock;
|
||||
#endif
|
||||
|
||||
struct savestate_work {
|
||||
char *filepath;
|
||||
|
||||
@@ -19,7 +19,11 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifdef USE_SDL3
|
||||
#include <SDL3/SDL.h>
|
||||
#else
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include <png.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
@@ -19,7 +19,11 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifdef USE_SDL3
|
||||
#include <SDL3/SDL.h>
|
||||
#else
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#include "osal/preproc.h"
|
||||
|
||||
+29
-1
@@ -21,8 +21,13 @@
|
||||
|
||||
#include "workqueue.h"
|
||||
|
||||
#ifdef USE_SDL3
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_thread.h>
|
||||
#else
|
||||
#include <SDL.h>
|
||||
#include <SDL_thread.h>
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -37,12 +42,20 @@ struct workqueue_mgmt_globals {
|
||||
struct list_head work_queue;
|
||||
struct list_head thread_queue;
|
||||
struct list_head thread_list;
|
||||
#ifdef USE_SDL3
|
||||
SDL_Mutex *lock;
|
||||
#else
|
||||
SDL_mutex *lock;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct workqueue_thread {
|
||||
SDL_Thread *thread;
|
||||
#ifdef USE_SDL3
|
||||
SDL_Condition *work_avail;
|
||||
#else
|
||||
SDL_cond *work_avail;
|
||||
#endif
|
||||
struct list_head list;
|
||||
struct list_head list_mgmt;
|
||||
};
|
||||
@@ -67,7 +80,11 @@ static struct work_struct *workqueue_get_work(struct workqueue_thread *thread)
|
||||
list_del_init(&work->list);
|
||||
} else {
|
||||
list_add(&thread->list, &workqueue_mgmt.thread_queue);
|
||||
#ifdef USE_SDL3
|
||||
SDL_WaitCondition(thread->work_avail, workqueue_mgmt.lock);
|
||||
#else
|
||||
SDL_CondWait(thread->work_avail, workqueue_mgmt.lock);
|
||||
#endif
|
||||
}
|
||||
SDL_UnlockMutex(workqueue_mgmt.lock);
|
||||
|
||||
@@ -124,7 +141,11 @@ int workqueue_init(void)
|
||||
memset(thread, 0, sizeof(*thread));
|
||||
list_add(&thread->list_mgmt, &workqueue_mgmt.thread_list);
|
||||
INIT_LIST_HEAD(&thread->list);
|
||||
#ifdef USE_SDL3
|
||||
thread->work_avail = SDL_CreateCondition();
|
||||
#else
|
||||
thread->work_avail = SDL_CreateCond();
|
||||
#endif
|
||||
if (!thread->work_avail) {
|
||||
DebugMessage(M64MSG_ERROR, "Could not create workqueue thread work_avail condition");
|
||||
SDL_UnlockMutex(workqueue_mgmt.lock);
|
||||
@@ -160,7 +181,11 @@ void workqueue_shutdown(void)
|
||||
list_for_each_entry_safe_t(thread, safe, &workqueue_mgmt.thread_list, struct workqueue_thread, list_mgmt) {
|
||||
list_del(&thread->list_mgmt);
|
||||
SDL_WaitThread(thread->thread, &status);
|
||||
#ifdef USE_SDL3
|
||||
SDL_DestroyCondition(thread->work_avail);
|
||||
#else
|
||||
SDL_DestroyCond(thread->work_avail);
|
||||
#endif
|
||||
free(thread);
|
||||
}
|
||||
|
||||
@@ -179,8 +204,11 @@ int queue_work(struct work_struct *work)
|
||||
if (!list_empty(&workqueue_mgmt.thread_queue)) {
|
||||
thread = list_first_entry(&workqueue_mgmt.thread_queue, struct workqueue_thread, list);
|
||||
list_del_init(&thread->list);
|
||||
|
||||
#ifdef USE_SDL3
|
||||
SDL_SignalCondition(thread->work_avail);
|
||||
#else
|
||||
SDL_CondSignal(thread->work_avail);
|
||||
#endif
|
||||
}
|
||||
SDL_UnlockMutex(workqueue_mgmt.lock);
|
||||
|
||||
|
||||
+10
@@ -23,9 +23,15 @@
|
||||
|
||||
#include "oglft_c.h"
|
||||
|
||||
#ifdef USE_SDL3
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_opengl.h>
|
||||
#include <SDL3/SDL_thread.h>
|
||||
#else
|
||||
#include <SDL.h>
|
||||
#include <SDL_opengl.h>
|
||||
#include <SDL_thread.h>
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
@@ -56,7 +62,11 @@ static osd_message_t * osd_message_valid(osd_message_t *testmsg);
|
||||
|
||||
static float fCornerScroll[OSD_NUM_CORNERS];
|
||||
|
||||
#ifdef USE_SDL3
|
||||
static SDL_Mutex *osd_list_lock;
|
||||
#else
|
||||
static SDL_mutex *osd_list_lock;
|
||||
#endif
|
||||
|
||||
// animation handlers
|
||||
static void (*l_animations[OSD_NUM_ANIM_TYPES])(osd_message_t *) = {
|
||||
|
||||
@@ -30,7 +30,11 @@
|
||||
#include <vector>
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#ifdef USE_SDL3
|
||||
#include <SDL3/SDL_opengl.h>
|
||||
#else
|
||||
#include <SDL_opengl.h>
|
||||
#endif
|
||||
#if defined(__MACOSX__)
|
||||
#include <OpenGL/glu.h>
|
||||
#elif defined(__MACOS__)
|
||||
|
||||
Reference in New Issue
Block a user