3rdParty: apply SDL3 and SDL3_net patch to mupen64plus-core

This commit is contained in:
Rosalie Wanders
2025-09-22 19:51:55 +02:00
parent f0a1c1f377
commit 762e24a110
17 changed files with 798 additions and 837 deletions
+20
View File
@@ -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
View File
@@ -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
+4
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+4
View File
@@ -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
View File
@@ -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)
+4
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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__)