diff --git a/Source/3rdParty/CMakeLists.txt b/Source/3rdParty/CMakeLists.txt index cb00a475..acf474c7 100644 --- a/Source/3rdParty/CMakeLists.txt +++ b/Source/3rdParty/CMakeLists.txt @@ -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 "$") +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") diff --git a/Source/3rdParty/mupen64plus-core/projects/unix/Makefile b/Source/3rdParty/mupen64plus-core/projects/unix/Makefile index ffb12b1b..b26eb4a4 100644 --- a/Source/3rdParty/mupen64plus-core/projects/unix/Makefile +++ b/Source/3rdParty/mupen64plus-core/projects/unix/Makefile @@ -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 diff --git a/Source/3rdParty/mupen64plus-core/src/api/frontend.c b/Source/3rdParty/mupen64plus-core/src/api/frontend.c index 7fcc99a8..181502f5 100644 --- a/Source/3rdParty/mupen64plus-core/src/api/frontend.c +++ b/Source/3rdParty/mupen64plus-core/src/api/frontend.c @@ -24,7 +24,11 @@ * outside of the core library. */ +#ifdef USE_SDL3 +#include +#else #include +#endif #include #include #include diff --git a/Source/3rdParty/mupen64plus-core/src/api/vidext.c b/Source/3rdParty/mupen64plus-core/src/api/vidext.c index 1c0ebe08..cfe3b765 100644 --- a/Source/3rdParty/mupen64plus-core/src/api/vidext.c +++ b/Source/3rdParty/mupen64plus-core/src/api/vidext.c @@ -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 +#else #include +#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 +#else #include +#endif #include #endif #include @@ -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; diff --git a/Source/3rdParty/mupen64plus-core/src/api/vidext_sdl2_compat.h b/Source/3rdParty/mupen64plus-core/src/api/vidext_sdl2_compat.h deleted file mode 100644 index 20e2959b..00000000 --- a/Source/3rdParty/mupen64plus-core/src/api/vidext_sdl2_compat.h +++ /dev/null @@ -1,527 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2012 Sam Lantinga - - 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 -#include - -#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; -} diff --git a/Source/3rdParty/mupen64plus-core/src/device/controllers/paks/biopak.c b/Source/3rdParty/mupen64plus-core/src/device/controllers/paks/biopak.c index 6f5e743a..6de91c95 100644 --- a/Source/3rdParty/mupen64plus-core/src/device/controllers/paks/biopak.c +++ b/Source/3rdParty/mupen64plus-core/src/device/controllers/paks/biopak.c @@ -28,7 +28,11 @@ #include "api/m64p_types.h" #include "api/callbacks.h" +#ifdef USE_SDL3 +#include +#else #include +#endif #include diff --git a/Source/3rdParty/mupen64plus-core/src/main/cheat.c b/Source/3rdParty/mupen64plus-core/src/main/cheat.c index 8058afad..d2e140e9 100644 --- a/Source/3rdParty/mupen64plus-core/src/main/cheat.c +++ b/Source/3rdParty/mupen64plus-core/src/main/cheat.c @@ -22,8 +22,13 @@ /* gameshark and xploder64 reference: http://doc.kodewerx.net/hacking_n64.html */ +#ifdef USE_SDL3 +#include +#include +#else #include #include +#endif #define __STDC_FORMAT_MACROS #include @@ -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) diff --git a/Source/3rdParty/mupen64plus-core/src/main/cheat.h b/Source/3rdParty/mupen64plus-core/src/main/cheat.h index 20235776..06bdb37b 100644 --- a/Source/3rdParty/mupen64plus-core/src/main/cheat.h +++ b/Source/3rdParty/mupen64plus-core/src/main/cheat.h @@ -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; }; diff --git a/Source/3rdParty/mupen64plus-core/src/main/eventloop.c b/Source/3rdParty/mupen64plus-core/src/main/eventloop.c index eb0fd191..0ce2ca21 100644 --- a/Source/3rdParty/mupen64plus-core/src/main/eventloop.c +++ b/Source/3rdParty/mupen64plus-core/src/main/eventloop.c @@ -20,7 +20,11 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#ifdef USE_SDL3 +#include +#else #include +#endif #include #include #include @@ -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) diff --git a/Source/3rdParty/mupen64plus-core/src/main/main.c b/Source/3rdParty/mupen64plus-core/src/main/main.c index e317570d..f20ac265 100644 --- a/Source/3rdParty/mupen64plus-core/src/main/main.c +++ b/Source/3rdParty/mupen64plus-core/src/main/main.c @@ -28,7 +28,11 @@ * if you want to implement an interface, you should look here */ +#ifdef USE_SDL3 +#include +#else #include +#endif #include #include #include diff --git a/Source/3rdParty/mupen64plus-core/src/main/netplay.c b/Source/3rdParty/mupen64plus-core/src/main/netplay.c index 5ec92992..aa284ab8 100644 --- a/Source/3rdParty/mupen64plus-core/src/main/netplay.c +++ b/Source/3rdParty/mupen64plus-core/src/main/netplay.c @@ -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 +#else #include +#endif + #if !defined(WIN32) #include #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; } diff --git a/Source/3rdParty/mupen64plus-core/src/main/savestates.c b/Source/3rdParty/mupen64plus-core/src/main/savestates.c index 959261df..e13e5674 100644 --- a/Source/3rdParty/mupen64plus-core/src/main/savestates.c +++ b/Source/3rdParty/mupen64plus-core/src/main/savestates.c @@ -22,8 +22,13 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#ifdef USE_SDL3 +#include +#include +#else #include #include +#endif #include #include #include @@ -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; diff --git a/Source/3rdParty/mupen64plus-core/src/main/screenshot.c b/Source/3rdParty/mupen64plus-core/src/main/screenshot.c index a831571b..d088c9d0 100644 --- a/Source/3rdParty/mupen64plus-core/src/main/screenshot.c +++ b/Source/3rdParty/mupen64plus-core/src/main/screenshot.c @@ -19,7 +19,11 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#ifdef USE_SDL3 +#include +#else #include +#endif #include #include #include diff --git a/Source/3rdParty/mupen64plus-core/src/main/sdl_key_converter.h b/Source/3rdParty/mupen64plus-core/src/main/sdl_key_converter.h index 84fce4de..c90015a5 100644 --- a/Source/3rdParty/mupen64plus-core/src/main/sdl_key_converter.h +++ b/Source/3rdParty/mupen64plus-core/src/main/sdl_key_converter.h @@ -19,7 +19,11 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#ifdef USE_SDL3 +#include +#else #include +#endif #include #include "osal/preproc.h" diff --git a/Source/3rdParty/mupen64plus-core/src/main/workqueue.c b/Source/3rdParty/mupen64plus-core/src/main/workqueue.c index 8efcc573..25921b56 100644 --- a/Source/3rdParty/mupen64plus-core/src/main/workqueue.c +++ b/Source/3rdParty/mupen64plus-core/src/main/workqueue.c @@ -21,8 +21,13 @@ #include "workqueue.h" +#ifdef USE_SDL3 +#include +#include +#else #include #include +#endif #include #include #include @@ -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); diff --git a/Source/3rdParty/mupen64plus-core/src/osd/osd.c b/Source/3rdParty/mupen64plus-core/src/osd/osd.c index 684d7352..4752b8db 100644 --- a/Source/3rdParty/mupen64plus-core/src/osd/osd.c +++ b/Source/3rdParty/mupen64plus-core/src/osd/osd.c @@ -23,9 +23,15 @@ #include "oglft_c.h" +#ifdef USE_SDL3 +#include +#include +#include +#else #include #include #include +#endif #include #include @@ -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 *) = { diff --git a/Source/3rdParty/mupen64plus-core/subprojects/oglft/OGLFT.h b/Source/3rdParty/mupen64plus-core/subprojects/oglft/OGLFT.h index fb1d9017..32042406 100644 --- a/Source/3rdParty/mupen64plus-core/subprojects/oglft/OGLFT.h +++ b/Source/3rdParty/mupen64plus-core/subprojects/oglft/OGLFT.h @@ -30,7 +30,11 @@ #include #define GL_GLEXT_PROTOTYPES +#ifdef USE_SDL3 +#include +#else #include +#endif #if defined(__MACOSX__) #include #elif defined(__MACOS__)