diff --git a/Makefile b/Makefile index 077d01a80..9a48dce58 100644 --- a/Makefile +++ b/Makefile @@ -83,6 +83,33 @@ include arch/compat.inc ifneq (${BUILD_SDL},) +# +# SDL 3 +# +ifeq (${BUILD_SDL},3) +# Check SDL_PKG_CONFIG_PATH and PREFIX/lib/pkgconfig for sdl3.pc. +# Note --with-path is a pkgconf extension. +ifneq ($(and ${SDL_PKG_CONFIG_PATH},$(wildcard ${SDL_PKG_CONFIG_PATH}/sdl3.pc)),) +# nop +else +# Check dependencies prefix instead for LIBDIR=. platforms. +# This is useless for unix/darwin, which should have sdl3.pc in a +# place pkgconf can find through normal means. +ifeq (${LIBDIR},.) +ifneq ($(wildcard ${PREFIX}/lib/pkgconfig/sdl3.pc),) +SDL_PKG_CONFIG_PATH ?= ${PREFIX}/lib/pkgconfig +endif +endif # LIBDIR=. +endif +ifneq (${SDL_PKG_CONFIG_PATH},) +SDL_PKG_CONFIG_FLAGS = --with-path=${SDL_PKG_CONFIG_PATH} +endif + +SDL_PREFIX := $(shell ${PKGCONF} ${SDL_PKG_CONFIG_FLAGS} sdl3 --variable=prefix) +SDL_CFLAGS ?= $(shell ${PKGCONF} ${SDL_PKG_CONFIG_FLAGS} sdl3 --cflags) +SDL_LDFLAGS ?= $(shell ${PKGCONF} ${SDL_PKG_CONFIG_FLAGS} sdl3 --libs) +endif # SDL3 + # # SDL 2 # diff --git a/arch/compat.inc b/arch/compat.inc index fb14c00bf..5b5df6033 100644 --- a/arch/compat.inc +++ b/arch/compat.inc @@ -158,3 +158,12 @@ ifeq (${CLANG_VER_GE_3_3},0) HAS_F_STACK_PROTECTOR_STRONG ?= 1 endif endif # clang + +# +# Get pkgconf or pkg-config (prefer pkgconf). +# +PKGCONF ?= ${shell \ + result=false; \ + command -v pkg-config >/dev/null && result=pkg-config; \ + command -v pkgconf >/dev/null && result=pkgconf; \ + echo $$result; } diff --git a/config.sh b/config.sh index 084e33af6..d79536b83 100755 --- a/config.sh +++ b/config.sh @@ -67,6 +67,7 @@ usage() { echo echo "Platform-dependent options:" echo " --enable-sdl Enable SDL backend, typically SDL2 (default)." + echo " --enable-sdl3 Enable SDL3 backend (any version)." echo " --enable-sdl2 Enable SDL2 backend (any version)." echo " --enable-sdl1 Enable SDL1 backend (1.2.x)." echo " --disable-sdl Disable SDL dependencies and features." @@ -446,6 +447,7 @@ while [ "$1" != "" ]; do [ "$1" = "--enable-sdl" ] && SDL="true" [ "$1" = "--enable-sdl1" ] && SDL="1" [ "$1" = "--enable-sdl2" ] && SDL="2" + [ "$1" = "--enable-sdl3" ] && SDL="3" [ "$1" = "--enable-egl" ] && EGL="true" [ "$1" = "--disable-egl" ] && EGL="false" @@ -821,7 +823,7 @@ else # # If no specific version of SDL is selected, select SDL2. # - if [ "$SDL" != "1" ] && [ "$SDL" != "2" ]; then + if [ "$SDL" != "1" ] && [ "$SDL" != "2" ] && [ "$SDL" != "3" ]; then SDL="2" fi echo "Enabling SDL $SDL.x." @@ -1139,7 +1141,7 @@ fi # Force-disable the softscale renderer for SDL 1.2 (requires SDL_Renderer). # if [ "$SDL" = "1" ] && [ "$SOFTSCALE" = "true" ]; then - echo "Force-disabling softscale renderer (requires SDL 2)." + echo "Force-disabling softscale renderer (requires SDL 2+)." SOFTSCALE="false" SDLACCEL="false" fi @@ -1546,7 +1548,7 @@ else fi # -# Softscale renderer (SDL 2) +# Softscale renderer (SDL 2+) # if [ "$SOFTSCALE" = "true" ]; then echo "Softscale renderer enabled." @@ -1940,7 +1942,7 @@ else fi # -# SDL_GameControllerDB, if enabled. This depends on SDL 2. +# SDL_GameControllerDB, if enabled. This depends on SDL 2+. # if [ "$SDL" != "false" ] && [ "$SDL" -ge "2" ] && \ [ "$GAMECONTROLLERDB" = "true" ]; then diff --git a/docs/STYLE.md b/docs/STYLE.md index 0f16f2853..5823fcc7c 100644 --- a/docs/STYLE.md +++ b/docs/STYLE.md @@ -258,6 +258,25 @@ original condition in a block comment after `#endif`. // more code ``` +In complex cases where there is no other option, left-hash indentation is OK: + +``` +#ifdef CONFIG_GLES +# ifdef CONFIG_RENDER_GL_FIXED +# if SDL_VERSION_ATLEAST(3,0,0) +# include +# else +# ... +# endif +# endif +# ifdef CONFIG_RENDER_GL_PROGRAM +# ... +# endif +#else +# ... +#endif +``` + ### Tabulated definitions In some places where many values or repetitive structs or enums are defined, diff --git a/docs/changelog.txt b/docs/changelog.txt index 6c1b46841..0101a9576 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -7,6 +7,8 @@ FIXES GIT - MZX 2.93c +Initial support for SDL3 has been added, but as it has not been +released yet, no MegaZeux release builds use it currently. As part of the preparation for SDL3, this release includes many long-belated changes to the way MegaZeux resizes windows and calculates the scaled display area within the window (including @@ -56,6 +58,9 @@ USERS DEVELOPERS ++ Added initial support for SDL3. No platforms select SDL3 by + default, but it is now possible to build and test MegaZeux for + platforms that already support the current prerelease (3.1.6). + Split the renderer function "set_video_mode" into two renderer functions "create_window" and "resize_window" to more closely reflect the reality of SDL2/3. The former is used during diff --git a/src/Makefile.in b/src/Makefile.in index bc86a51c0..20bf801a2 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -368,8 +368,12 @@ core_cobjs += ${core_obj}/event_sdl.o ${core_obj}/platform_sdl.o core_cobjs += ${core_obj}/render_sdl.o ifeq (${BUILD_AUDIO},1) +ifeq (${BUILD_SDL},3) +core_cobjs += ${audio_obj}/driver_sdl3.o +else core_cobjs += ${audio_obj}/audio_sdl.o endif +endif core_flags += $(SDL_CFLAGS) core_ldflags += $(SDL_LDFLAGS) diff --git a/src/SDLmzx.h b/src/SDLmzx.h index 042cb9675..f64b7d503 100644 --- a/src/SDLmzx.h +++ b/src/SDLmzx.h @@ -1,6 +1,7 @@ /* MegaZeux * * Copyright (C) 2007 Alistair John Strachan + * Copyright (C) 2024 Alice Rowan * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -17,22 +18,27 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -// Split from compat.h because it's only needed in one place and it was making -// the build process much slower. - -#ifndef __COMPAT_SDL_H -#define __COMPAT_SDL_H +#ifndef __SDLMZX_H +#define __SDLMZX_H #include "compat.h" __M_BEGIN_DECLS #if defined(CONFIG_SDL) - +#if CONFIG_SDL == 3 +#include +#include +#else #include #if defined(_WIN32) || defined(CONFIG_X11) #include #endif +#endif + +#include + +/* SDL1 backwards compatibility for SDL2 ************************************/ #if !SDL_VERSION_ATLEAST(2,0,0) @@ -40,7 +46,6 @@ __M_BEGIN_DECLS // counterpart. More complex changes are handled with #ifdefs "in situ". // Data types - typedef SDLKey SDL_Keycode; typedef int (*SDL_ThreadFunction)(void *); typedef Uint32 SDL_threadID; @@ -130,7 +135,7 @@ static inline HWND SDL_GetWindowProperty_HWND(SDL_Window *window) } #endif /* _WIN32 */ -#else /* SDL_VERSION_ATLEAST(2,0,0) */ +#elif !SDL_VERSION_ATLEAST(3,0,0) #ifdef _WIN32 static inline HWND SDL_GetWindowProperty_HWND(SDL_Window *window) @@ -142,10 +147,359 @@ static inline HWND SDL_GetWindowProperty_HWND(SDL_Window *window) } #endif /* _WIN32 */ -#endif /* SDL_VERSION_ATLEAST(2,0,0) */ +#else /* SDL_VERSION_ATLEAST(3,0,0) */ + +#ifdef _WIN32 +static inline void *SDL_GetWindowProperty_HWND(SDL_Window *window) +{ + return SDL_GetPointerProperty(SDL_GetWindowProperties(window), + SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL); +} +#endif /* _WIN32 */ + +#endif /* SDL_VERSION_ATLEAST(3,0,0) */ + + +/* SDL 1/2 backwards compatibility for SDL3 *********************************/ + +/** + * SDL_audio.h + */ +#if !SDL_VERSION_ATLEAST(3,0,0) +#define SDL_AUDIO_U8 AUDIO_U8 +#define SDL_AUDIO_S8 AUDIO_S8 +#define SDL_AUDIO_S16 AUDIO_S16SYS +#define SDL_AUDIO_S16LE AUDIO_S16LSB +#define SDL_AUDIO_S16BE AUDIO_S16MSB +#else +/* SDL3 defines SDL_FreeWAV to an old name type, but MZX needs to keep it to + * transparently support older versions. */ +#undef SDL_FreeWAV +#define SDL_FreeWAV(w) SDL_free(w) +#endif + +/** + * SDL_event.h + */ +#if !SDL_VERSION_ATLEAST(3,0,0) +#define SDL_EVENT_GAMEPAD_AXIS_MOTION SDL_CONTROLLERAXISMOTION +#define SDL_EVENT_JOYSTICK_ADDED SDL_JOYDEVICEADDED +#define SDL_EVENT_JOYSTICK_REMOVED SDL_JOYDEVICEREMOVED +#define SDL_EVENT_JOYSTICK_AXIS_MOTION SDL_JOYAXISMOTION +#define SDL_EVENT_JOYSTICK_BUTTON_DOWN SDL_JOYBUTTONDOWN +#define SDL_EVENT_JOYSTICK_BUTTON_UP SDL_JOYBUTTONUP +#define SDL_EVENT_JOYSTICK_HAT_MOTION SDL_JOYHATMOTION +#define SDL_EVENT_KEY_DOWN SDL_KEYDOWN +#define SDL_EVENT_KEY_UP SDL_KEYUP +#define SDL_EVENT_MOUSE_BUTTON_DOWN SDL_MOUSEBUTTONDOWN +#define SDL_EVENT_MOUSE_BUTTON_UP SDL_MOUSEBUTTONUP +#define SDL_EVENT_MOUSE_MOTION SDL_MOUSEMOTION +#define SDL_EVENT_MOUSE_WHEEL SDL_MOUSEWHEEL +#define SDL_EVENT_TEXT_INPUT SDL_TEXTINPUT +#define SDL_EVENT_QUIT SDL_QUIT +#define SDL_EVENT_FIRST SDL_FIRSTEVENT +#define SDL_EVENT_LAST SDL_LASTEVENT +#endif + +/** + * SDL_gamepad.h (formerly SDL_gamecontroller.h) + */ +#if !SDL_VERSION_ATLEAST(3,0,0) && SDL_VERSION_ATLEAST(2,0,0) +typedef SDL_GameController SDL_Gamepad; +typedef SDL_GameControllerAxis SDL_GamepadAxis; +typedef SDL_GameControllerButton SDL_GamepadButton; +#define SDL_INIT_GAMEPAD SDL_INIT_GAMECONTROLLER +#define SDL_GAMEPAD_AXIS_INVALID SDL_CONTROLLER_AXIS_INVALID +#define SDL_GAMEPAD_AXIS_LEFTX SDL_CONTROLLER_AXIS_LEFTX +#define SDL_GAMEPAD_AXIS_LEFTY SDL_CONTROLLER_AXIS_LEFTY +#define SDL_GAMEPAD_AXIS_RIGHTX SDL_CONTROLLER_AXIS_RIGHTX +#define SDL_GAMEPAD_AXIS_RIGHTY SDL_CONTROLLER_AXIS_RIGHTY +#define SDL_GAMEPAD_AXIS_LEFT_TRIGGER SDL_CONTROLLER_AXIS_TRIGGERLEFT +#define SDL_GAMEPAD_AXIS_RIGHT_TRIGGER SDL_CONTROLLER_AXIS_TRIGGERRIGHT +#define SDL_GAMEPAD_AXIS_COUNT SDL_CONTROLLER_AXIS_MAX +#define SDL_GAMEPAD_BUTTON_INVALID SDL_CONTROLLER_BUTTON_INVALID +#define SDL_GAMEPAD_BUTTON_SOUTH SDL_CONTROLLER_BUTTON_A +#define SDL_GAMEPAD_BUTTON_EAST SDL_CONTROLLER_BUTTON_B +#define SDL_GAMEPAD_BUTTON_WEST SDL_CONTROLLER_BUTTON_X +#define SDL_GAMEPAD_BUTTON_NORTH SDL_CONTROLLER_BUTTON_Y +#define SDL_GAMEPAD_BUTTON_BACK SDL_CONTROLLER_BUTTON_BACK +#define SDL_GAMEPAD_BUTTON_GUIDE SDL_CONTROLLER_BUTTON_GUIDE +#define SDL_GAMEPAD_BUTTON_START SDL_CONTROLLER_BUTTON_START +#define SDL_GAMEPAD_BUTTON_LEFT_STICK SDL_CONTROLLER_BUTTON_LEFTSTICK +#define SDL_GAMEPAD_BUTTON_RIGHT_STICK SDL_CONTROLLER_BUTTON_RIGHTSTICK +#define SDL_GAMEPAD_BUTTON_LEFT_SHOULDER SDL_CONTROLLER_BUTTON_LEFTSHOULDER +#define SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER SDL_CONTROLLER_BUTTON_RIGHTSHOULDER +#define SDL_GAMEPAD_BUTTON_DPAD_UP SDL_CONTROLLER_BUTTON_DPAD_UP +#define SDL_GAMEPAD_BUTTON_DPAD_DOWN SDL_CONTROLLER_BUTTON_DPAD_DOWN +#define SDL_GAMEPAD_BUTTON_DPAD_LEFT SDL_CONTROLLER_BUTTON_DPAD_LEFT +#define SDL_GAMEPAD_BUTTON_DPAD_RIGHT SDL_CONTROLLER_BUTTON_DPAD_RIGHT +#define SDL_GAMEPAD_BUTTON_MISC1 SDL_CONTROLLER_BUTTON_MISC1 +#define SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1 SDL_CONTROLLER_BUTTON_PADDLE1 +#define SDL_GAMEPAD_BUTTON_LEFT_PADDLE1 SDL_CONTROLLER_BUTTON_PADDLE2 +#define SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2 SDL_CONTROLLER_BUTTON_PADDLE3 +#define SDL_GAMEPAD_BUTTON_LEFT_PADDLE2 SDL_CONTROLLER_BUTTON_PADDLE4 +#define SDL_GAMEPAD_BUTTON_TOUCHPAD SDL_CONTROLLER_BUTTON_TOUCHPAD +#define SDL_GAMEPAD_BUTTON_COUNT SDL_CONTROLLER_BUTTON_MAX +#define SDL_IsGamepad(device_id) SDL_IsGameController(device_id) +#define SDL_OpenGamepad(device_id) SDL_GameControllerOpen(device_id) +#define SDL_CloseGamepad(g) SDL_GameControllerClose(g) +#define SDL_GetGamepadAxisFromString(s) SDL_GameControllerGetAxisFromString(s) +#define SDL_GetGamepadButtonFromString(s) SDL_GameControllerGetButtonFromString(s) +#define SDL_AddGamepadMapping(m) SDL_GameControllerAddMapping(m) +#define SDL_AddGamepadMappingsFromFile(f) SDL_GameControllerAddMappingsFromFile(f) + +static inline void SDL_SetGamepadEventsEnabled(boolean enabled) +{ + SDL_GameControllerEventState(enabled ? SDL_ENABLE : SDL_DISABLE); +} +#endif + +/** + * SDL_joystick.h + */ +#if !SDL_VERSION_ATLEAST(3,0,0) +#define SDL_GUID SDL_JoystickGUID +#define SDL_GUIDToString SDL_GetJoystickGUIDString +#define SDL_OpenJoystick(device_id) SDL_JoystickOpen(device_id) +#define SDL_CloseJoystick(j) SDL_JoystickClose(j) +#define SDL_GetJoystickGUID(j) SDL_JoystickGetGUID(j) +#define SDL_GetJoystickGUIDString(g,b,l) SDL_JoystickGetGUIDString(g,b,l) +#define SDL_GetJoystickID(j) SDL_JoystickInstanceID(j) + +static inline void SDL_SetJoystickEventsEnabled(boolean enabled) +{ + SDL_JoystickEventState(enabled ? SDL_ENABLE : SDL_DISABLE); +} +#endif + +/** + * SDL_keyboard.h and SDL_keycode.h + */ +#if !SDL_VERSION_ATLEAST(3,0,0) +#define SDLK_A SDLK_a +#define SDLK_B SDLK_b +#define SDLK_C SDLK_c +#define SDLK_D SDLK_d +#define SDLK_E SDLK_e +#define SDLK_F SDLK_f +#define SDLK_G SDLK_g +#define SDLK_H SDLK_h +#define SDLK_I SDLK_i +#define SDLK_J SDLK_j +#define SDLK_K SDLK_k +#define SDLK_L SDLK_l +#define SDLK_M SDLK_m +#define SDLK_N SDLK_n +#define SDLK_O SDLK_o +#define SDLK_P SDLK_p +#define SDLK_Q SDLK_q +#define SDLK_R SDLK_r +#define SDLK_S SDLK_s +#define SDLK_T SDLK_t +#define SDLK_U SDLK_u +#define SDLK_V SDLK_v +#define SDLK_W SDLK_w +#define SDLK_X SDLK_x +#define SDLK_Y SDLK_y +#define SDLK_Z SDLK_z +#define SDLK_APOSTROPHE SDLK_QUOTE +#define SDLK_GRAVE SDLK_BACKQUOTE +#define SDL_KMOD_CTRL KMOD_CTRL +#define SDL_KMOD_ALT KMOD_ALT +#define SDL_KMOD_NUM KMOD_NUM +#define SDL_KMOD_CAPS KMOD_CAPS +#endif + +/** + * SDL_pixels.h + */ +#if !SDL_VERSION_ATLEAST(2,0,5) +/* Convenience macros added in 2.0.5. */ +#if SDL_BYTEORDER == SDL_BIG_ENDIAN +#define SDL_PIXELFORMAT_RGBA32 SDL_PIXELFORMAT_RGBA8888 +#else +#define SDL_PIXELFORMAT_RGBA32 SDL_PIXELFORMAT_ABGR8888 +#endif +#endif +#if !SDL_VERSION_ATLEAST(2,0,14) +/* Added in 2.0.14 with the old names remaining; old names removed in SDL3. */ +#define SDL_PIXELFORMAT_XRGB4444 SDL_PIXELFORMAT_RGB444 +#define SDL_PIXELFORMAT_XBGR4444 SDL_PIXELFORMAT_BGR444 +#define SDL_PIXELFORMAT_XRGB1555 SDL_PIXELFORMAT_RGB555 +#define SDL_PIXELFORMAT_XBGR1555 SDL_PIXELFORMAT_BGR555 +#define SDL_PIXELFORMAT_XRGB8888 SDL_PIXELFORMAT_RGB888 +#define SDL_PIXELFORMAT_XBGR8888 SDL_PIXELFORMAT_BGR888 +#endif +#if !SDL_VERSION_ATLEAST(3,0,0) +#define SDL_PixelFormatDetails SDL_PixelFormat +#define SDL_CreatePalette(s) SDL_AllocPalette(s) +#define SDL_DestroyPalette(p) SDL_FreePalette(p) +#define SDL_GetMasksForPixelFormat(f,b,R,G,B,A) SDL_PixelFormatEnumToMasks(f,b,R,G,B,A) + +static inline Uint32 SDL_MapSurfaceRGBA(SDL_Surface *surface, + Uint8 r, Uint8 g, Uint8 b, Uint8 a) +{ + return SDL_MapRGBA(surface->format, r, g, b, a); +} +#endif + +/** + * SDL_rect.h + */ +#if !SDL_VERSION_ATLEAST(2,0,10) +typedef struct { float x; float y; float w; float h; } SDL_FRect; +#endif + +#if SDL_VERSION_ATLEAST(3,0,0) +typedef SDL_FRect SDL_Rect_mzx; +static inline SDL_Rect_mzx sdl_render_rect(int x, int y, int w, int h) +{ + SDL_FRect tmp = { (float)x, (float)y, (float)w, (float)h }; + return tmp; +} +#elif SDL_VERSION_ATLEAST(2,0,0) +typedef SDL_Rect SDL_Rect_mzx; +static inline SDL_Rect_mzx sdl_render_rect(int x, int y, int w, int h) +{ + SDL_Rect tmp = { x, y, w, h }; + return tmp; +} +#endif + +/** + * SDL_render.h + */ +#if !SDL_VERSION_ATLEAST(3,0,0) && SDL_VERSION_ATLEAST(2,0,0) +typedef int SDL_RendererLogicalPresentation; +#define SDL_LOGICAL_PRESENTATION_DISABLED 0 +#define SDL_SCALEMODE_BEST SDL_ScaleModeBest +#define SDL_SCALEMODE_LINEAR SDL_ScaleModeLinear +#define SDL_SCALEMODE_NEAREST SDL_ScaleModeNearest + +#if !SDL_VERSION_ATLEAST(2,0,12) +typedef int SDL_ScaleMode; +#endif + +static inline boolean SDL_SetRenderClipRect(SDL_Renderer *render, + SDL_Rect *rect) +{ + return SDL_RenderSetClipRect(render, rect) == 0; +} + +static inline boolean SDL_SetRenderLogicalPresentation(SDL_Renderer *render, + int w, int h, SDL_RendererLogicalPresentation p, SDL_ScaleMode s) +{ + return SDL_RenderSetLogicalSize(render, w, h) == 0; +} + +static inline boolean SDL_RenderTexture(SDL_Renderer *renderer, + SDL_Texture *texture, const SDL_Rect_mzx *src_rect, const SDL_Rect_mzx *dest_rect) +{ + return SDL_RenderCopy(renderer, texture, src_rect, dest_rect) == 0; +} +#endif + +/** + * SDL_surface.h + */ +#if !SDL_VERSION_ATLEAST(3,0,0) +#define SDL_SCALEMODE_NEAREST SDL_ScaleModeNearest +#define SDL_SCALEMODE_LINEAR SDL_ScaleModeLinear +#define SDL_DestroySurface(s) SDL_FreeSurface(s) + +static inline boolean SDL_FillSurfaceRect(SDL_Surface *surface, SDL_Rect *rect, + Uint32 color) +{ + return SDL_FillRect(surface, rect, color) == 0; +} + +static inline boolean SDL_GetSurfaceClipRect(SDL_Surface *surface, SDL_Rect *rect) +{ + *rect = surface->clip_rect; + return true; +} + +#if SDL_VERSION_ATLEAST(2,0,0) +static inline SDL_Surface *SDL_CreateSurface(int width, int height, Uint32 format) +{ + Uint32 rmask, gmask, bmask, amask; + int bpp; + + SDL_PixelFormatEnumToMasks(format, &bpp, &rmask, &gmask, &bmask, &amask); + return SDL_CreateRGBSurface(0, width, height, bpp, rmask, gmask, bmask, amask); +} +#endif +#endif + +/** + * SDL_thread.h symbols were mostly the same for SDL 1 and SDL 2. + */ +#if !SDL_VERSION_ATLEAST(3,0,0) +typedef SDL_cond SDL_Condition; +typedef SDL_mutex SDL_Mutex; +typedef SDL_sem SDL_Semaphore; +#define SDL_CreateCondition() SDL_CreateCond() +#define SDL_DestroyCondition(c) SDL_DestroyCond(c) +#define SDL_WaitCondition(c,m) SDL_CondWait(c,m) +#define SDL_WaitConditionTimeout(c,m,t) SDL_CondWaitTimeout(c,m,t) +#define SDL_SignalCondition(c) SDL_CondSignal(c) +#define SDL_BroadcastCondition(c) SDL_CondBroadcast(c) +#define SDL_WaitSemaphore(s) SDL_SemWait(s) +#define SDL_SignalSemaphore(s) SDL_SemPost(s) +#define SDL_GetCurrentThreadID() SDL_ThreadID() +#endif + +/** + * SDL_version.h + */ +#if !SDL_VERSION_ATLEAST(3,0,0) +#define SDL_MICRO_VERSION SDL_PATCHLEVEL +// This macro *should* be identical to SDL3's SDL_VERSIONNUM. +#define SDL_VERSIONNUM_MZX(x,y,z) ((x) * 1000000 + (y) * 1000 + (z)) +#define SDL_VERSIONNUM_MAJOR(v) ((v) / 1000000) +#define SDL_VERSIONNUM_MINOR(v) (((v) / 1000) % 1000) +#define SDL_VERSIONNUM_MICRO(v) ((v) % 1000) +#else +#define SDL_VERSIONNUM_MZX(x,y,z) SDL_VERSIONNUM((x),(y),(z)) +#endif + +static inline int sdl_compiled_version(void) +{ + return SDL_VERSIONNUM_MZX(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_MICRO_VERSION); +} + +static inline int sdl_linked_version(void) +{ +#if SDL_VERSION_ATLEAST(3,0,0) + return SDL_GetVersion(); +#else + SDL_version ver; +#if SDL_VERSION_ATLEAST(2,0,0) + SDL_GetVersion(&ver); +#else + ver = *SDL_Linked_Version(); +#endif + return SDL_VERSIONNUM_MZX(ver.major, ver.minor, ver.patch); +#endif +} + +/** + * SDL_video.h + */ +#if !SDL_VERSION_ATLEAST(2,0,16) +#define SDL_SetWindowMouseGrab(w,b) SDL_SetWindowGrab(w,b) +#endif +#if !SDL_VERSION_ATLEAST(3,0,0) +#define SDL_GL_DestroyContext(gl) SDL_GL_DeleteContext(gl) + +/* SDL3 removed the coordinate arguments to SDL_CreateWindow. + * Windows are created centered by default instead. */ +#define SDL_CreateWindow(title, w, h, flags) SDL_CreateWindow((title), \ + SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (w), (h), (flags)) +#endif #endif /* CONFIG_SDL */ __M_END_DECLS -#endif /* __COMPAT_SDL_H */ +#endif /* __SDLMZX_H */ diff --git a/src/about.c b/src/about.c index 8de938c41..3552db72d 100644 --- a/src/about.c +++ b/src/about.c @@ -112,21 +112,22 @@ static char **about_text(int *num_lines) #ifdef CONFIG_SDL { - SDL_version compiled; - SDL_version ver; - SDL_VERSION(&compiled); -#if SDL_VERSION_ATLEAST(2,0,0) - SDL_GetVersion(&ver); -#else - ver = *SDL_Linked_Version(); -#endif - if(memcmp(&compiled, &ver, sizeof(SDL_version))) + int ver_compiled = sdl_compiled_version(); + int ver_linked = sdl_linked_version(); + + if(ver_compiled != ver_linked) { lines[i++] = about_line("SDL: %u.%u.%u (compiled: %u.%u.%u)", - ver.major, ver.minor, ver.patch, compiled.major, compiled.minor, compiled.patch); + SDL_VERSIONNUM_MAJOR(ver_linked), + SDL_VERSIONNUM_MINOR(ver_linked), + SDL_VERSIONNUM_MICRO(ver_linked), + SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_MICRO_VERSION); } else - lines[i++] = about_line("SDL: %u.%u.%u", ver.major, ver.minor, ver.patch); + { + lines[i++] = about_line("SDL: %u.%u.%u", + SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_MICRO_VERSION); + } } #endif diff --git a/src/audio/audio_struct.h b/src/audio/audio_struct.h index 0c0c6df74..2ce276707 100644 --- a/src/audio/audio_struct.h +++ b/src/audio/audio_struct.h @@ -35,17 +35,17 @@ __M_BEGIN_DECLS #endif #if PLATFORM_BYTE_ORDER == PLATFORM_BIG_ENDIAN -#define SAMPLE_S16 SAMPLE_S16MSB +#define SAMPLE_S16 SAMPLE_S16BE #else -#define SAMPLE_S16 SAMPLE_S16LSB +#define SAMPLE_S16 SAMPLE_S16LE #endif enum wav_format { SAMPLE_U8, SAMPLE_S8, - SAMPLE_S16LSB, - SAMPLE_S16MSB + SAMPLE_S16LE, + SAMPLE_S16BE }; struct wav_info diff --git a/src/audio/audio_wav.c b/src/audio/audio_wav.c index 1351f1f7c..2cea97aa6 100644 --- a/src/audio/audio_wav.c +++ b/src/audio/audio_wav.c @@ -106,8 +106,8 @@ static uint32_t wav_read_data(struct wav_stream *w_stream, break; } - case SAMPLE_S16LSB: - case SAMPLE_S16MSB: + case SAMPLE_S16LE: + case SAMPLE_S16BE: { uint8_t *dest = (uint8_t *)buffer; @@ -454,18 +454,18 @@ static boolean load_wav_file_sdl(const char *filename, struct wav_info *spec) spec->freq = sdlspec.freq; switch(sdlspec.format) { - case AUDIO_U8: + case SDL_AUDIO_U8: spec->format = SAMPLE_U8; break; - case AUDIO_S8: + case SDL_AUDIO_S8: spec->format = SAMPLE_S8; break; - case AUDIO_S16LSB: - spec->format = SAMPLE_S16LSB; + case SDL_AUDIO_S16LE: + spec->format = SAMPLE_S16LE; break; // May be returned by SDL on big endian machines. - case AUDIO_S16MSB: - spec->format = SAMPLE_S16MSB; + case SDL_AUDIO_S16BE: + spec->format = SAMPLE_S16BE; break; /** * TODO: SDL 2.0 can technically return AUDIO_S32LSB or AUDIO_F32LSB. @@ -591,7 +591,7 @@ static boolean load_wav_file(vfile *vf, const char *filename, struct wav_info *s if(sbytes == 1) spec->format = SAMPLE_U8; else - spec->format = SAMPLE_S16LSB; + spec->format = SAMPLE_S16LE; spec->channels = channels; // Check for "smpl" chunk for looping info diff --git a/src/audio/driver_sdl3.c b/src/audio/driver_sdl3.c new file mode 100644 index 000000000..d460c6c0a --- /dev/null +++ b/src/audio/driver_sdl3.c @@ -0,0 +1,122 @@ +/* MegaZeux + * + * Copyright (C) 2024 Alice Rowan + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "../SDLmzx.h" +#include "../util.h" + +#include "audio.h" +#include "audio_struct.h" + +static SDL_AudioSpec audio_settings; +static SDL_AudioStream *audio_stream; +static void *audio_buffer; +static unsigned audio_format; + +static void sdl_audio_callback(void *userdata, SDL_AudioStream *stream, + int required_bytes, int requested_bytes) +{ + size_t framesize = SDL_AUDIO_FRAMESIZE(audio_settings); + size_t frames = MAX(0, required_bytes) / framesize; + + while(frames > 0) + { + size_t out = audio_mixer_render_frames(userdata, frames, + audio_settings.channels, audio_format); + + assert(out <= frames); + SDL_PutAudioStreamData(audio_stream, userdata, out * framesize); + frames -= out; + } +} + +void init_audio_platform(struct config_info *conf) +{ + SDL_AudioDeviceID audio_device = SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK; + int frames = 0; + char hint[16]; + void *tmp; + // TODO: 8-bit? + + audio_format = SAMPLE_S16; + + memset(&audio_settings, 0, sizeof(audio_settings)); + if(!SDL_GetAudioDeviceFormat(audio_device, &audio_settings, &frames)) + { + // Can't query, try to continue anyway... + audio_settings.freq = 48000; + frames = 1024; + } + audio_settings.format = SDL_AUDIO_S16; + audio_settings.channels = 2; + + if(conf->audio_sample_rate != 0) + { + // Reject very low sample rates to avoid PulseAudio hangs. + audio_settings.freq = MAX(conf->audio_sample_rate, 2048); + } + + if(conf->audio_buffer_samples != 0) + frames = conf->audio_buffer_samples; + + if(conf->audio_output_channels != 0) + audio_settings.channels = MIN(conf->audio_output_channels, 2); + + if(!audio_mixer_init(audio_settings.freq, frames, audio_settings.channels)) + return; + + audio_settings.freq = audio.output_frequency; + + tmp = crealloc(audio_buffer, + audio.buffer_frames * audio.buffer_channels * sizeof(int16_t)); + if(!tmp) + return; + + // The buffer frames need to be configured with this hack. + // This value may be ignored or modified by some platforms. + snprintf(hint, sizeof(hint), "%u", audio.buffer_frames); + SDL_SetHint(SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES, hint); + + audio_buffer = tmp; + audio_stream = SDL_OpenAudioDeviceStream(audio_device, &audio_settings, + sdl_audio_callback, tmp); + if(!audio_stream) + goto err; + + SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(audio_stream)); + return; + +err: + free(tmp); + audio_buffer = NULL; + return; +} + +void quit_audio_platform(void) +{ + if(audio_stream) + { + SDL_DestroyAudioStream(audio_stream); + audio_stream = NULL; + } + free(audio_buffer); + audio_buffer = NULL; +} diff --git a/src/editor/clipboard.h b/src/editor/clipboard.h index db9a1743e..a1edba8df 100644 --- a/src/editor/clipboard.h +++ b/src/editor/clipboard.h @@ -27,6 +27,7 @@ __M_BEGIN_DECLS void copy_buffer_to_clipboard(char **buffer, int lines, int total_length); char *get_clipboard_buffer(void); +void free_clipboard_buffer(char *buffer); __M_END_DECLS diff --git a/src/editor/clipboard_carbon.c b/src/editor/clipboard_carbon.c index 1e9e66fbf..ea8807a51 100644 --- a/src/editor/clipboard_carbon.c +++ b/src/editor/clipboard_carbon.c @@ -125,7 +125,7 @@ char *get_clipboard_buffer(void) src_data = (char *)CFDataGetBytePtr(flavorData); length = (size_t)CFDataGetLength(flavorData); - dest_data = cmalloc(length + 1); + dest_data = (char *)cmalloc(length + 1); memcpy(dest_data, src_data, length); dest_data[length] = 0; @@ -137,3 +137,8 @@ char *get_clipboard_buffer(void) CFRelease(clipboard); return dest_data; } + +void free_clipboard_buffer(char *buffer) +{ + free(buffer); +} diff --git a/src/editor/clipboard_cocoa.m b/src/editor/clipboard_cocoa.m index 565f9367a..ccb8636de 100644 --- a/src/editor/clipboard_cocoa.m +++ b/src/editor/clipboard_cocoa.m @@ -115,7 +115,7 @@ void copy_buffer_to_clipboard(char **buffer, int lines, int total_length) goto err; size_t buf_len = [chrdata length]; - char *buf = cmalloc(buf_len + 1); + char *buf = (char *)cmalloc(buf_len + 1); [chrdata getBytes:buf length:buf_len]; buf[buf_len] = '\0'; @@ -126,3 +126,8 @@ void copy_buffer_to_clipboard(char **buffer, int lines, int total_length) [pool release]; return NULL; } + +void free_clipboard_buffer(char *buffer) +{ + free(buffer); +} diff --git a/src/editor/clipboard_null.c b/src/editor/clipboard_null.c index ffb3bb56e..c76e6e9cf 100644 --- a/src/editor/clipboard_null.c +++ b/src/editor/clipboard_null.c @@ -18,6 +18,7 @@ */ #include "clipboard.h" +#include void copy_buffer_to_clipboard(char **buffer, int lines, int total_length) {} @@ -25,3 +26,8 @@ char *get_clipboard_buffer(void) { return NULL; } + +void free_clipboard_buffer(char *buffer) +{ + free(buffer); +} diff --git a/src/editor/clipboard_sdl2.c b/src/editor/clipboard_sdl2.c index 41fd2a394..a537362f0 100644 --- a/src/editor/clipboard_sdl2.c +++ b/src/editor/clipboard_sdl2.c @@ -44,7 +44,11 @@ void copy_buffer_to_clipboard(char **buffer, int lines, int total_length) } dest_ptr[-1] = 0; +#if SDL_VERSION_ATLEAST(3,0,0) + if(!SDL_SetClipboardText(dest_data)) +#else if(SDL_SetClipboardText(dest_data) < 0) +#endif warn("SDL_SetClipboardText failed: %s\n", SDL_GetError()); free(dest_data); @@ -54,3 +58,8 @@ char *get_clipboard_buffer(void) { return SDL_GetClipboardText(); } + +void free_clipboard_buffer(char *buffer) +{ + SDL_free(buffer); +} diff --git a/src/editor/clipboard_win32.c b/src/editor/clipboard_win32.c index 881ccfc71..d34d048e8 100644 --- a/src/editor/clipboard_win32.c +++ b/src/editor/clipboard_win32.c @@ -86,7 +86,7 @@ char *get_clipboard_buffer(void) // CF_TEXT is guaranteed to be null-terminated. length = strlen(src_data); - dest_data = cmalloc(length + 1); + dest_data = (char *)cmalloc(length + 1); strcpy(dest_data, src_data); GlobalUnlock(global_memory); @@ -97,3 +97,8 @@ char *get_clipboard_buffer(void) return NULL; } + +void free_clipboard_buffer(char *buffer) +{ + free(buffer); +} diff --git a/src/editor/clipboard_x11.c b/src/editor/clipboard_x11.c index 500907832..df6550fb3 100644 --- a/src/editor/clipboard_x11.c +++ b/src/editor/clipboard_x11.c @@ -37,7 +37,7 @@ static int copy_buffer_total_length; static int copy_buffer_to_X11_selection(Display *display, XEvent *xevent); #ifdef CONFIG_SDL -#if SDL_VERSION_ATLEAST(1,2,0) +#if SDL_VERSION_ATLEAST(1,2,0) && !SDL_VERSION_ATLEAST(3,0,0) static inline boolean get_X11_display_and_window(SDL_Window *window, Display **display, Window *xwindow) @@ -92,7 +92,7 @@ static inline void set_X11_event_callback(void) SDL_SetEventFilter(event_callback, sdl_get_current_window()); } -#endif /* SDL_VERSION_ATLEAST(1,2,0) */ +#endif /* SDL_VERSION_ATLEAST(1,2,0) && !SDL_VERSION_ATLEAST(3,0,0) */ #endif /* CONFIG_SDL */ @@ -202,3 +202,8 @@ char *get_clipboard_buffer(void) XUnlockDisplay(display); return dest_data; } + +void free_clipboard_buffer(char *buffer) +{ + free(buffer); +} diff --git a/src/editor/robo_ed.c b/src/editor/robo_ed.c index d4a5e393c..45ebe5a99 100644 --- a/src/editor/robo_ed.c +++ b/src/editor/robo_ed.c @@ -1537,7 +1537,8 @@ static void paste_buffer(struct robot_editor_context *rstate) #endif } - free(ext_buffer); + /* This may need SDL_free if it was allocated by SDL. */ + free_clipboard_buffer(ext_buffer); } else diff --git a/src/event_sdl.c b/src/event_sdl.c index 918f61bb9..ec8a9e9db 100644 --- a/src/event_sdl.c +++ b/src/event_sdl.c @@ -2,7 +2,7 @@ * * Copyright (C) 2004 Gilead Kutnick * Copyright (C) 2007 Kevin Vance - * Copyright (C) 2019 Alice Rowan + * Copyright (C) 2019, 2024 Alice Rowan * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -23,10 +23,12 @@ #include "configure.h" #include "event.h" #include "graphics.h" +#include "platform.h" #include "render_sdl.h" #include "util.h" #include +#include #include #include @@ -57,7 +59,7 @@ static enum keycode convert_SDL_internal(SDL_Keycode key) case SDLK_RETURN: return IKEY_RETURN; case SDLK_ESCAPE: return IKEY_ESCAPE; case SDLK_SPACE: return IKEY_SPACE; - case SDLK_QUOTE: return IKEY_QUOTE; + case SDLK_APOSTROPHE: return IKEY_QUOTE; case SDLK_PLUS: return IKEY_EQUALS; case SDLK_COMMA: return IKEY_COMMA; case SDLK_MINUS: return IKEY_MINUS; @@ -78,33 +80,33 @@ static enum keycode convert_SDL_internal(SDL_Keycode key) case SDLK_LEFTBRACKET: return IKEY_LEFTBRACKET; case SDLK_BACKSLASH: return IKEY_BACKSLASH; case SDLK_RIGHTBRACKET: return IKEY_RIGHTBRACKET; - case SDLK_BACKQUOTE: return IKEY_BACKQUOTE; - case SDLK_a: return IKEY_a; - case SDLK_b: return IKEY_b; - case SDLK_c: return IKEY_c; - case SDLK_d: return IKEY_d; - case SDLK_e: return IKEY_e; - case SDLK_f: return IKEY_f; - case SDLK_g: return IKEY_g; - case SDLK_h: return IKEY_h; - case SDLK_i: return IKEY_i; - case SDLK_j: return IKEY_j; - case SDLK_k: return IKEY_k; - case SDLK_l: return IKEY_l; - case SDLK_m: return IKEY_m; - case SDLK_n: return IKEY_n; - case SDLK_o: return IKEY_o; - case SDLK_p: return IKEY_p; - case SDLK_q: return IKEY_q; - case SDLK_r: return IKEY_r; - case SDLK_s: return IKEY_s; - case SDLK_t: return IKEY_t; - case SDLK_u: return IKEY_u; - case SDLK_v: return IKEY_v; - case SDLK_w: return IKEY_w; - case SDLK_x: return IKEY_x; - case SDLK_y: return IKEY_y; - case SDLK_z: return IKEY_z; + case SDLK_GRAVE: return IKEY_BACKQUOTE; + case SDLK_A: return IKEY_a; + case SDLK_B: return IKEY_b; + case SDLK_C: return IKEY_c; + case SDLK_D: return IKEY_d; + case SDLK_E: return IKEY_e; + case SDLK_F: return IKEY_f; + case SDLK_G: return IKEY_g; + case SDLK_H: return IKEY_h; + case SDLK_I: return IKEY_i; + case SDLK_J: return IKEY_j; + case SDLK_K: return IKEY_k; + case SDLK_L: return IKEY_l; + case SDLK_M: return IKEY_m; + case SDLK_N: return IKEY_n; + case SDLK_O: return IKEY_o; + case SDLK_P: return IKEY_p; + case SDLK_Q: return IKEY_q; + case SDLK_R: return IKEY_r; + case SDLK_S: return IKEY_s; + case SDLK_T: return IKEY_t; + case SDLK_U: return IKEY_u; + case SDLK_V: return IKEY_v; + case SDLK_W: return IKEY_w; + case SDLK_X: return IKEY_x; + case SDLK_Y: return IKEY_y; + case SDLK_Z: return IKEY_z; case SDLK_DELETE: return IKEY_DELETE; case SDLK_KP_0: return IKEY_KP0; case SDLK_KP_1: return IKEY_KP1; @@ -260,45 +262,45 @@ static int get_pandora_joystick_button(SDL_Keycode key) * No equivalent of this API exists for SDL 1.x. */ -static SDL_GameController *gamepads[MAX_JOYSTICKS]; +static SDL_Gamepad *gamepads[MAX_JOYSTICKS]; -static enum joystick_special_axis sdl_axis_map[SDL_CONTROLLER_AXIS_MAX] = +static enum joystick_special_axis sdl_axis_map[SDL_GAMEPAD_AXIS_COUNT] = { - [SDL_CONTROLLER_AXIS_LEFTX] = JOY_AXIS_LEFT_X, - [SDL_CONTROLLER_AXIS_LEFTY] = JOY_AXIS_LEFT_Y, - [SDL_CONTROLLER_AXIS_RIGHTX] = JOY_AXIS_RIGHT_X, - [SDL_CONTROLLER_AXIS_RIGHTY] = JOY_AXIS_RIGHT_Y, - [SDL_CONTROLLER_AXIS_TRIGGERLEFT] = JOY_AXIS_LEFT_TRIGGER, - [SDL_CONTROLLER_AXIS_TRIGGERRIGHT] = JOY_AXIS_RIGHT_TRIGGER + [SDL_GAMEPAD_AXIS_LEFTX] = JOY_AXIS_LEFT_X, + [SDL_GAMEPAD_AXIS_LEFTY] = JOY_AXIS_LEFT_Y, + [SDL_GAMEPAD_AXIS_RIGHTX] = JOY_AXIS_RIGHT_X, + [SDL_GAMEPAD_AXIS_RIGHTY] = JOY_AXIS_RIGHT_Y, + [SDL_GAMEPAD_AXIS_LEFT_TRIGGER] = JOY_AXIS_LEFT_TRIGGER, + [SDL_GAMEPAD_AXIS_RIGHT_TRIGGER] = JOY_AXIS_RIGHT_TRIGGER }; -static int16_t sdl_axis_action_map[SDL_CONTROLLER_AXIS_MAX][2] = +static int16_t sdl_axis_action_map[SDL_GAMEPAD_AXIS_COUNT][2] = { - [SDL_CONTROLLER_AXIS_LEFTX] = { -JOY_L_LEFT, -JOY_L_RIGHT }, - [SDL_CONTROLLER_AXIS_LEFTY] = { -JOY_L_UP, -JOY_L_DOWN }, - [SDL_CONTROLLER_AXIS_RIGHTX] = { -JOY_R_LEFT, -JOY_R_RIGHT }, - [SDL_CONTROLLER_AXIS_RIGHTY] = { -JOY_R_UP, -JOY_R_DOWN }, - [SDL_CONTROLLER_AXIS_TRIGGERLEFT] = { 0, -JOY_LTRIGGER }, - [SDL_CONTROLLER_AXIS_TRIGGERRIGHT] = { 0, -JOY_RTRIGGER }, + [SDL_GAMEPAD_AXIS_LEFTX] = { -JOY_L_LEFT, -JOY_L_RIGHT }, + [SDL_GAMEPAD_AXIS_LEFTY] = { -JOY_L_UP, -JOY_L_DOWN }, + [SDL_GAMEPAD_AXIS_RIGHTX] = { -JOY_R_LEFT, -JOY_R_RIGHT }, + [SDL_GAMEPAD_AXIS_RIGHTY] = { -JOY_R_UP, -JOY_R_DOWN }, + [SDL_GAMEPAD_AXIS_LEFT_TRIGGER] = { 0, -JOY_LTRIGGER }, + [SDL_GAMEPAD_AXIS_RIGHT_TRIGGER] = { 0, -JOY_RTRIGGER }, }; -static int16_t sdl_action_map[SDL_CONTROLLER_BUTTON_MAX] = +static int16_t sdl_action_map[SDL_GAMEPAD_BUTTON_COUNT] = { - [SDL_CONTROLLER_BUTTON_A] = -JOY_A, - [SDL_CONTROLLER_BUTTON_B] = -JOY_B, - [SDL_CONTROLLER_BUTTON_X] = -JOY_X, - [SDL_CONTROLLER_BUTTON_Y] = -JOY_Y, - [SDL_CONTROLLER_BUTTON_BACK] = -JOY_SELECT, -//[SDL_CONTROLLER_BUTTON_GUIDE] = -JOY_GUIDE, - [SDL_CONTROLLER_BUTTON_START] = -JOY_START, - [SDL_CONTROLLER_BUTTON_LEFTSTICK] = -JOY_LSTICK, - [SDL_CONTROLLER_BUTTON_RIGHTSTICK] = -JOY_RSTICK, - [SDL_CONTROLLER_BUTTON_LEFTSHOULDER] = -JOY_LSHOULDER, - [SDL_CONTROLLER_BUTTON_RIGHTSHOULDER] = -JOY_RSHOULDER, - [SDL_CONTROLLER_BUTTON_DPAD_UP] = -JOY_UP, - [SDL_CONTROLLER_BUTTON_DPAD_DOWN] = -JOY_DOWN, - [SDL_CONTROLLER_BUTTON_DPAD_LEFT] = -JOY_LEFT, - [SDL_CONTROLLER_BUTTON_DPAD_RIGHT] = -JOY_RIGHT + [SDL_GAMEPAD_BUTTON_SOUTH] = -JOY_A, + [SDL_GAMEPAD_BUTTON_EAST] = -JOY_B, + [SDL_GAMEPAD_BUTTON_WEST] = -JOY_X, + [SDL_GAMEPAD_BUTTON_NORTH] = -JOY_Y, + [SDL_GAMEPAD_BUTTON_BACK] = -JOY_SELECT, +//[SDL_GAMEPAD_BUTTON_GUIDE] = -JOY_GUIDE, + [SDL_GAMEPAD_BUTTON_START] = -JOY_START, + [SDL_GAMEPAD_BUTTON_LEFT_STICK] = -JOY_LSTICK, + [SDL_GAMEPAD_BUTTON_RIGHT_STICK] = -JOY_RSTICK, + [SDL_GAMEPAD_BUTTON_LEFT_SHOULDER] = -JOY_LSHOULDER, + [SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER] = -JOY_RSHOULDER, + [SDL_GAMEPAD_BUTTON_DPAD_UP] = -JOY_UP, + [SDL_GAMEPAD_BUTTON_DPAD_DOWN] = -JOY_DOWN, + [SDL_GAMEPAD_BUTTON_DPAD_LEFT] = -JOY_LEFT, + [SDL_GAMEPAD_BUTTON_DPAD_RIGHT] = -JOY_RIGHT }; enum @@ -475,8 +477,8 @@ static void parse_gamepad_read_value(char *key, char *value, static void parse_gamepad_read_entry(char *key, char *value, struct gamepad_axis_map *axes, struct gamepad_map *buttons) { - SDL_GameControllerAxis a; - SDL_GameControllerButton b; + SDL_GamepadAxis a; + SDL_GamepadButton b; struct gamepad_map *single = NULL; struct gamepad_map *neg = NULL; struct gamepad_map *pos = NULL; @@ -486,9 +488,9 @@ static void parse_gamepad_read_entry(char *key, char *value, if(*key == '+' || *key == '-') half_axis = *(key++); - a = SDL_GameControllerGetAxisFromString(key); - b = SDL_GameControllerGetButtonFromString(key); - if(a != SDL_CONTROLLER_AXIS_INVALID) + a = SDL_GetGamepadAxisFromString(key); + b = SDL_GetGamepadButtonFromString(key); + if(a != SDL_GAMEPAD_AXIS_INVALID) { if(half_axis == '+') single = &(axes[a].pos); @@ -504,10 +506,10 @@ static void parse_gamepad_read_entry(char *key, char *value, } else - if(b != SDL_CONTROLLER_BUTTON_INVALID) + if(b != SDL_GAMEPAD_BUTTON_INVALID) { // This button isn't really useful to MZX. - if(b == SDL_CONTROLLER_BUTTON_GUIDE) + if(b == SDL_GAMEPAD_BUTTON_GUIDE) return; single = &(buttons[b]); @@ -618,8 +620,8 @@ static void parse_gamepad_apply(int joy, int16_t mapping, static void parse_gamepad_map(int joystick_index, char *map) { - struct gamepad_axis_map axes[SDL_CONTROLLER_AXIS_MAX]; - struct gamepad_map buttons[SDL_CONTROLLER_BUTTON_MAX]; + struct gamepad_axis_map axes[SDL_GAMEPAD_AXIS_COUNT]; + struct gamepad_map buttons[SDL_GAMEPAD_BUTTON_COUNT]; boolean select_mapped = false; boolean select_used = false; size_t i; @@ -630,7 +632,7 @@ static void parse_gamepad_map(int joystick_index, char *map) parse_gamepad_read_string(map, axes, buttons); // Apply axes. - for(i = 0; i < SDL_CONTROLLER_AXIS_MAX; i++) + for(i = 0; i < SDL_GAMEPAD_AXIS_COUNT; i++) { parse_gamepad_apply(joystick_index, sdl_axis_action_map[i][0], &(axes[i].neg), &select_mapped, &select_used); @@ -640,7 +642,7 @@ static void parse_gamepad_map(int joystick_index, char *map) } // Apply buttons. - for(i = 0; i < SDL_CONTROLLER_BUTTON_MAX; i++) + for(i = 0; i < SDL_GAMEPAD_BUTTON_COUNT; i++) { parse_gamepad_apply(joystick_index, sdl_action_map[i], &(buttons[i]), &select_mapped, &select_used); @@ -664,15 +666,15 @@ static void parse_gamepad_map(int joystick_index, char *map) static void init_gamepad(SDL_Joystick *joystick, int sdl_joystick_id, int joystick_index) { - SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); + SDL_GUID guid = SDL_GetJoystickGUID(joystick); char guid_string[33]; - SDL_JoystickGetGUIDString(guid, guid_string, 33); + SDL_GUIDToString(guid, guid_string, 33); gamepads[joystick_index] = NULL; - if(SDL_IsGameController(sdl_joystick_id)) + if(SDL_IsGamepad(sdl_joystick_id)) { - SDL_GameController *gamepad = SDL_GameControllerOpen(sdl_joystick_id); + SDL_Gamepad *gamepad = SDL_OpenGamepad(sdl_joystick_id); if(gamepad) { @@ -680,7 +682,11 @@ static void init_gamepad(SDL_Joystick *joystick, int sdl_joystick_id, char *mapping = NULL; gamepads[joystick_index] = gamepad; -#if SDL_VERSION_ATLEAST(2,0,9) +#if SDL_VERSION_ATLEAST(3,0,0) + // This is the equivalent to [...]ForDeviceIndex() and is also currently + // the only way to get the default generated mapping. + mapping = (char *)SDL_GetGamepadMappingForID(sdl_joystick_id); +#elif SDL_VERSION_ATLEAST(2,0,9) // NOTE: the other functions for this will not return the default mapping // string; this is the only one that can return everything. Right now, // this only matters for the Emscripten port. @@ -786,7 +792,7 @@ static void load_gamecontrollerdb(void) if(path) { - int result = SDL_GameControllerAddMappingsFromFile(path); + int result = SDL_AddGamepadMappingsFromFile(path); if(result >= 0) debug("--JOYSTICK-- Added %d mappings from '%s'.\n", result, path); } @@ -801,8 +807,8 @@ static void load_gamecontrollerdb(void) */ void gamepad_map_sym(const char *sym, const char *value) { - SDL_GameControllerAxis a; - SDL_GameControllerButton b; + SDL_GamepadAxis a; + SDL_GamepadButton b; int16_t binding = 0; if(joystick_parse_map_value(value, &binding)) @@ -812,16 +818,16 @@ void gamepad_map_sym(const char *sym, const char *value) dir = *(sym++); // Digital axis (default to + if no dir specified). - a = SDL_GameControllerGetAxisFromString(sym); - if(a != SDL_CONTROLLER_AXIS_INVALID) + a = SDL_GetGamepadAxisFromString(sym); + if(a != SDL_GAMEPAD_AXIS_INVALID) { int pos = (dir != '-') ? 1 : 0; sdl_axis_action_map[a][pos] = binding; } // Button - b = SDL_GameControllerGetButtonFromString(sym); - if(b != SDL_CONTROLLER_BUTTON_INVALID) + b = SDL_GetGamepadButtonFromString(sym); + if(b != SDL_GAMEPAD_BUTTON_INVALID) sdl_action_map[b] = binding; } @@ -836,7 +842,7 @@ void gamepad_add_mapping(const char *mapping) // Make sure this is loaded first so it doesn't override the user mapping. load_gamecontrollerdb(); - if(SDL_GameControllerAddMapping(mapping) < 0) + if(SDL_AddGamepadMapping(mapping) < 0) warn("Failed to add gamepad mapping: %s\n", SDL_GetError()); } @@ -878,10 +884,10 @@ static void init_joystick(int sdl_joystick_id) if(joystick_index >= 0) { - SDL_Joystick *joystick = SDL_JoystickOpen(sdl_joystick_id); + SDL_Joystick *joystick = SDL_OpenJoystick(sdl_joystick_id); if(joystick) { - joystick_instance_ids[joystick_index] = SDL_JoystickInstanceID(joystick); + joystick_instance_ids[joystick_index] = SDL_GetJoystickID(joystick); joysticks[joystick_index] = joystick; joystick_set_active(status, joystick_index, true); @@ -907,12 +913,12 @@ static void close_joystick(int joystick_index) // SDL_GameControllerClose also closes the joystick. if(gamepads[joystick_index]) { - SDL_GameControllerClose(gamepads[joystick_index]); + SDL_CloseGamepad(gamepads[joystick_index]); gamepad_clean_map(joystick_index); gamepads[joystick_index] = NULL; } else - SDL_JoystickClose(joysticks[joystick_index]); + SDL_CloseJoystick(joysticks[joystick_index]); joystick_instance_ids[joystick_index] = -1; joysticks[joystick_index] = NULL; @@ -920,6 +926,20 @@ static void close_joystick(int joystick_index) } #endif +static inline void read_key_event(int *key, int *mod, int *scancode, + const SDL_KeyboardEvent *ev) +{ +#if SDL_VERSION_ATLEAST(3,0,0) + *key = ev->key; + *mod = ev->mod; + *scancode = ev->scancode; +#else + *key = ev->keysym.sym; + *mod = ev->keysym.mod; + *scancode = ev->keysym.scancode; +#endif +} + static inline uint32_t utf8_next_char(uint8_t **_src) { uint8_t *src = *_src; @@ -974,6 +994,7 @@ static inline uint32_t utf8_next_char(uint8_t **_src) static boolean process_event(SDL_Event *event) { struct buffered_status *status = store_status(); + int key, mod, scancode; enum keycode ckey; /* SDL's numlock keyboard modifier handling seems to be broken on X11, @@ -989,21 +1010,49 @@ static boolean process_event(SDL_Event *event) */ if(!numlock_status_initialized) { - status->numlock_status = !!(SDL_GetModState() & KMOD_NUM); + status->numlock_status = !!(SDL_GetModState() & SDL_KMOD_NUM); numlock_status_initialized = true; } switch(event->type) { - case SDL_QUIT: + case SDL_EVENT_QUIT: { - trace("--EVENT_SDL-- SDL_QUIT\n"); + trace("--EVENT_SDL-- SDL_EVENT_QUIT\n"); // Set the exit status status->exit_status = true; break; } -#if SDL_VERSION_ATLEAST(2,0,0) +#if SDL_VERSION_ATLEAST(3,0,0) + case SDL_EVENT_WINDOW_RESIZED: + { + unsigned window_id = video_window_by_platform_id(event->window.windowID); + + trace("--EVENT_SDL-- SDL_EVENT_WINDOW_RESIZED: %u (%d,%d)\n", + event->window.windowID, event->window.data1, event->window.data2); + video_sync_window_size(window_id, + event->window.data1, event->window.data2); + break; + } + + case SDL_EVENT_WINDOW_FOCUS_LOST: + { + trace("--EVENT_SDL-- SDL_EVENT_WINDOW_FOCUS_LOST\n"); + // Pause while minimized + if(input.unfocus_pause) + { + while(1) + { + SDL_WaitEvent(event); + if(event->type == SDL_EVENT_WINDOW_FOCUS_GAINED) + break; + } + trace("--EVENT_SDL-- SDL_WINDOWEVENT_FOCUS_GAINED\n"); + } + break; + } +#elif SDL_VERSION_ATLEAST(2,0,0) case SDL_WINDOWEVENT: { Uint32 sdl_window_id = event->window.windowID; @@ -1035,12 +1084,11 @@ static boolean process_event(SDL_Event *event) event->window.event == SDL_WINDOWEVENT_FOCUS_GAINED) break; } + trace("--EVENT_SDL-- SDL_WINDOWEVENT_FOCUS_GAINED: %u\n", sdl_window_id); } - trace("--EVENT_SDL-- SDL_WINDOWEVENT_FOCUS_GAINED: %u\n", sdl_window_id); break; } } - break; } #else // !SDL_VERSION_ATLEAST(2,0,0) @@ -1075,7 +1123,7 @@ static boolean process_event(SDL_Event *event) } #endif // !SDL_VERSION_ATLEAST(2,0,0) - case SDL_MOUSEMOTION: + case SDL_EVENT_MOUSE_MOTION: { SDL_Window *window = sdl_get_current_window(); int mx_real = event->motion.x; @@ -1109,7 +1157,7 @@ static boolean process_event(SDL_Event *event) } trace( - "--EVENT_SDL-- SDL_MOUSEMOTION: (%d,%d) -> (%d,%d)\n", + "--EVENT_SDL-- SDL_EVENT_MOUSE_MOTION: (%d,%d) -> (%d,%d)\n", mx_real, my_real, mx, my ); status->mouse_pixel_x = mx; @@ -1120,23 +1168,23 @@ static boolean process_event(SDL_Event *event) break; } - case SDL_MOUSEBUTTONDOWN: + case SDL_EVENT_MOUSE_BUTTON_DOWN: { enum mouse_button button = convert_SDL_mouse_internal(event->button.button); - trace("--EVENT_SDL-- SDL_MOUSEBUTTONDOWN: %u\n", event->button.button); + trace("--EVENT_SDL-- SDL_EVENT_MOUSE_BUTTON_DOWN: %u\n", event->button.button); status->mouse_button = button; status->mouse_repeat = button; status->mouse_button_state |= MOUSE_BUTTON(button); status->mouse_repeat_state = 1; status->mouse_drag_state = -1; - status->mouse_time = SDL_GetTicks(); + status->mouse_time = get_ticks(); break; } - case SDL_MOUSEBUTTONUP: + case SDL_EVENT_MOUSE_BUTTON_UP: { enum mouse_button button = convert_SDL_mouse_internal(event->button.button); - trace("--EVENT_SDL-- SDL_MOUSEBUTTONUP: %u\n", event->button.button); + trace("--EVENT_SDL-- SDL_EVENT_MOUSE_BUTTON_UP: %u\n", event->button.button); status->mouse_button_state &= ~MOUSE_BUTTON(button); status->mouse_repeat = MOUSE_NO_BUTTON; status->mouse_drag_state = 0; @@ -1146,24 +1194,28 @@ static boolean process_event(SDL_Event *event) #if SDL_VERSION_ATLEAST(2,0,0) // emulate the X11-style "wheel is a button" that SDL 1.2 used - case SDL_MOUSEWHEEL: + // SDL3 uses floats, SDL2 uses ints. + case SDL_EVENT_MOUSE_WHEEL: { uint32_t button; + float wheel_x = (float)event->wheel.x; + float wheel_y = (float)event->wheel.y; + trace( - "--EVENT_SDL-- SDL_MOUSEWHEEL: x=%d y=%d\n", - event->wheel.x, event->wheel.y + "--EVENT_SDL-- SDL_EVENT_MOUSE_WHEEL: x=%.2f y=%.2f\n", + wheel_x, wheel_y ); - if(abs(event->wheel.x) > abs(event->wheel.y)) + if(fabsf(wheel_x) > fabsf(wheel_y)) { - if(event->wheel.x < 0) + if(wheel_x < 0.0f) button = MOUSE_BUTTON_WHEELLEFT; else button = MOUSE_BUTTON_WHEELRIGHT; } else { - if(event->wheel.y < 0) + if(wheel_y < 0.0f) button = MOUSE_BUTTON_WHEELDOWN; else button = MOUSE_BUTTON_WHEELUP; @@ -1175,14 +1227,15 @@ static boolean process_event(SDL_Event *event) status->mouse_repeat = MOUSE_NO_BUTTON; status->mouse_repeat_state = 0; status->mouse_drag_state = 0; - status->mouse_time = SDL_GetTicks(); + status->mouse_time = get_ticks(); break; } #endif // SDL_VERSION_ATLEAST(2,0,0) - case SDL_KEYDOWN: + case SDL_EVENT_KEY_DOWN: { uint32_t unicode = 0; + read_key_event(&key, &mod, &scancode, &event->key); #if SDL_VERSION_ATLEAST(2,0,0) // SDL 2.0 uses proper key repeat, but derives its timing from the OS. @@ -1199,7 +1252,7 @@ static boolean process_event(SDL_Event *event) #ifdef CONFIG_PANDORA { // Pandora hack. Certain keys are actually joystick buttons. - int button = get_pandora_joystick_button(event->key.keysym.sym); + int button = get_pandora_joystick_button(key); if(button >= 0) { joystick_button_press(status, 0, button); @@ -1208,12 +1261,10 @@ static boolean process_event(SDL_Event *event) } #endif - ckey = convert_SDL_internal(event->key.keysym.sym); + ckey = convert_SDL_internal(key); trace( - "--EVENT_SDL-- SDL_KEYDOWN: scancode:%d sym:%d -> %d\n", - event->key.keysym.scancode, - event->key.keysym.sym, - ckey + "--EVENT_SDL-- SDL_EVENT_KEY_DOWN: scancode:%d sym:%d -> %d\n", + scancode, key, ckey ); if(!ckey) { @@ -1239,9 +1290,11 @@ static boolean process_event(SDL_Event *event) // using the internal keycode. if(unicode_fallback && KEYCODE_IS_ASCII(ckey)) { - boolean caps_lock = !!(SDL_GetModState() & KMOD_CAPS); + boolean caps_lock = !!(SDL_GetModState() & SDL_KMOD_CAPS); unicode = convert_internal_unicode(ckey, caps_lock); } + if(unicode) + trace("--EVENT_SDL-- unicode:%d\n", (int)unicode); if((ckey == IKEY_RETURN) && get_alt_status(keycode_internal) && @@ -1304,12 +1357,14 @@ static boolean process_event(SDL_Event *event) break; } - case SDL_KEYUP: + case SDL_EVENT_KEY_UP: { + read_key_event(&key, &mod, &scancode, &event->key); + #ifdef CONFIG_PANDORA { // Pandora hack. Certain keys are actually joystick buttons. - int button = get_pandora_joystick_button(event->key.keysym.sym); + int button = get_pandora_joystick_button(key); if(button >= 0) { joystick_button_release(status, 0, button); @@ -1318,12 +1373,10 @@ static boolean process_event(SDL_Event *event) } #endif - ckey = convert_SDL_internal(event->key.keysym.sym); + ckey = convert_SDL_internal(key); trace( - "--EVENT_SDL-- SDL_KEYUP: scancode:%d sym:%d -> %d\n", - event->key.keysym.scancode, - event->key.keysym.sym, - ckey + "--EVENT_SDL-- SDL_EVENT_KEY_UP: scancode:%d sym:%d -> %d\n", + scancode, key, ckey ); if(!ckey) { @@ -1358,15 +1411,18 @@ static boolean process_event(SDL_Event *event) * can't be distinguished from regular key presses, so key_press_unicode * needs to be called without repeating enabled. */ - case SDL_TEXTINPUT: + case SDL_EVENT_TEXT_INPUT: { uint8_t *text = (uint8_t *)event->text.text; - trace("--EVENT_SDL-- SDL_TEXTINPUT: %s\n", text); + trace("--EVENT_SDL-- SDL_EVENT_TEXT_INPUT: %s\n", text); - // This should never happen; ignore. if(unicode_fallback) - break; + { + // Clear any unicode keys on the buffer generated from the fallback... + status->unicode_length = 0; + unicode_fallback = false; + } // Decode the input UTF-8 string into UTF-32 for the event buffer. while(*text) @@ -1379,28 +1435,28 @@ static boolean process_event(SDL_Event *event) break; } - case SDL_JOYDEVICEADDED: + case SDL_EVENT_JOYSTICK_ADDED: { // Add a new joystick. // "which" for this event (but not for any other joystick event) is not // a joystick instance ID, but instead an index for SDL_JoystickOpen(). trace( - "--EVENT_SDL-- SDL_JOYDEVICEADDED\n" + "--EVENT_SDL-- SDL_EVENT_JOYSTICK_ADDED\n" ); init_joystick(event->jdevice.which); break; } - case SDL_JOYDEVICEREMOVED: + case SDL_EVENT_JOYSTICK_REMOVED: { // Close a disconnected joystick. int which = event->jdevice.which; int joystick_index = get_joystick_index(which); trace( - "--EVENT_SDL-- SDL_JOYDEVICEREMOVED: j%d\n", + "--EVENT_SDL-- SDL_EVENT_JOYSTICK_REMOVED: j%d\n", joystick_index ); @@ -1413,14 +1469,20 @@ static boolean process_event(SDL_Event *event) break; } - case SDL_CONTROLLERAXISMOTION: + case SDL_EVENT_GAMEPAD_AXIS_MOTION: { // Since gamepad axis mappings can be complicated, use // the gamepad events to update the named axis values. struct config_info *conf = get_config(); +#if SDL_VERSION_ATLEAST(3,0,0) + int value = event->gaxis.value; + int which = event->gaxis.which; + int axis = event->gaxis.axis; +#else int value = event->caxis.value; int which = event->caxis.which; int axis = event->caxis.axis; +#endif enum joystick_special_axis special_axis = sdl_axis_map[axis]; int joystick_index = get_joystick_index(which); @@ -1428,7 +1490,7 @@ static boolean process_event(SDL_Event *event) break; trace( - "--EVENT_SDL-- SDL_CONTROLLERAXISMOTION: j%d sa%d = %d\n", + "--EVENT_SDL-- SDL_EVENT_GAMEPAD_AXIS_MOTION: j%d sa%d = %d\n", joystick_index, special_axis, value ); @@ -1437,7 +1499,7 @@ static boolean process_event(SDL_Event *event) } #endif - case SDL_JOYAXISMOTION: + case SDL_EVENT_JOYSTICK_AXIS_MOTION: { int axis_value = event->jaxis.value; int which = event->jaxis.which; @@ -1449,7 +1511,7 @@ static boolean process_event(SDL_Event *event) break; trace( - "--EVENT_SDL-- SDL_JOYAXISMOTION: j%d a%d = %d\n", + "--EVENT_SDL-- SDL_EVENT_JOYSTICK_AXIS_MOTION: j%d a%d = %d\n", joystick_index, axis, axis_value ); @@ -1457,7 +1519,7 @@ static boolean process_event(SDL_Event *event) break; } - case SDL_JOYBUTTONDOWN: + case SDL_EVENT_JOYSTICK_BUTTON_DOWN: { int which = event->jbutton.which; int button = event->jbutton.button; @@ -1468,7 +1530,7 @@ static boolean process_event(SDL_Event *event) break; trace( - "--EVENT_SDL-- SDL_JOYBUTTONDOWN: j%d b%d\n", + "--EVENT_SDL-- SDL_EVENT_JOYSTICK_BUTTON_DOWN: j%d b%d\n", joystick_index, button ); @@ -1482,7 +1544,7 @@ static boolean process_event(SDL_Event *event) break; } - case SDL_JOYBUTTONUP: + case SDL_EVENT_JOYSTICK_BUTTON_UP: { int which = event->jbutton.which; int button = event->jbutton.button; @@ -1499,7 +1561,7 @@ static boolean process_event(SDL_Event *event) #endif trace( - "--EVENT_SDL-- SDL_JOYBUTTONUP: j%d b%d\n", + "--EVENT_SDL-- SDL_EVENT_JOYSTICK_BUTTON_UP: j%d b%d\n", joystick_index, button ); @@ -1507,7 +1569,7 @@ static boolean process_event(SDL_Event *event) break; } - case SDL_JOYHATMOTION: + case SDL_EVENT_JOYSTICK_HAT_MOTION: { int which = event->jhat.which; int dir = event->jhat.value; @@ -1522,7 +1584,8 @@ static boolean process_event(SDL_Event *event) break; trace( - "--EVENT_SDL-- SDL_JOYHATMOTION: j%d up:%u down:%u left:%u right:%u\n", + "--EVENT_SDL-- SDL_EVENT_JOYSTICK_HAT_MOTION: " + "j%d up:%u down:%u left:%u right:%u\n", joystick_index, hat_u, hat_d, hat_l, hat_r ); @@ -1584,33 +1647,34 @@ boolean __peek_exit_input(void) { SDL_Event events[256]; int num_events; + int key, mod, scancode; int i; SDL_PumpEvents(); #if SDL_VERSION_ATLEAST(2,0,0) num_events = - SDL_PeepEvents(events, 256, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT); + SDL_PeepEvents(events, 256, SDL_PEEKEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST); #else /* !SDL_VERSION_ATLEAST(2,0,0) */ num_events = SDL_PeepEvents(events, 256, SDL_PEEKEVENT, SDL_ALLEVENTS); #endif /* SDL_VERSION_ATLEAST(2,0,0) */ for(i = 0; i < num_events; i++) { - if(events[i].type == SDL_QUIT) + if(events[i].type == SDL_EVENT_QUIT) return true; - if(events[i].type == SDL_KEYDOWN) + if(events[i].type == SDL_EVENT_KEY_DOWN) { - SDL_KeyboardEvent *ev = &(events[i].key); + read_key_event(&key, &mod, &scancode, &(events[i].key)); - if(ev->keysym.sym == SDLK_ESCAPE) + if(key == SDLK_ESCAPE) return true; - if(ev->keysym.sym == SDLK_c && (ev->keysym.mod & KMOD_CTRL)) + if(key == SDLK_C && (mod & SDL_KMOD_CTRL)) return true; - if(ev->keysym.sym == SDLK_F4 && (ev->keysym.mod & KMOD_ALT)) + if(key == SDLK_F4 && (mod & SDL_KMOD_ALT)) return true; } } @@ -1645,7 +1709,11 @@ void __warp_mouse(int x, int y) if((x < 0) || (y < 0)) { +#if SDL_VERSION_ATLEAST(3,0,0) + float current_x, current_y; +#else int current_x, current_y; +#endif SDL_GetMouseState(¤t_x, ¤t_y); if(x < 0) @@ -1664,7 +1732,6 @@ void __warp_mouse(int x, int y) */ void sdl_init_window_text_events(unsigned sdl_window_id) { -#if SDL_VERSION_ATLEAST(2,0,0) /* Most platforms want text input events always on so they can generate * convenient unicode text values, but in Android this causes some problems: * @@ -1676,10 +1743,19 @@ void sdl_init_window_text_events(unsigned sdl_window_id) * * TODO: Instead, enable text input on demand at text prompts. */ +#if SDL_VERSION_ATLEAST(3,0,0) +#ifdef ANDROID +/* This is largely wishful thinking and needs thorough Android testing. */ +#error See above comments. +#endif + SDL_Window *window = SDL_GetWindowFromID(sdl_window_id); + SDL_StopTextInput(window); + SDL_SetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD, "0"); + SDL_StartTextInput(window); +#elif SDL_VERSION_ATLEAST(2,0,0) if(!SDL_HasScreenKeyboardSupport()) { SDL_StartTextInput(); - unicode_fallback = false; } else { @@ -1688,9 +1764,6 @@ void sdl_init_window_text_events(unsigned sdl_window_id) } #else SDL_EnableUNICODE(1); - /* SDL 1.2 might also need this (Pandora? doesn't generate unicode presses). - * If it isn't required, real unicode events will turn this off. */ - unicode_fallback = true; #endif } @@ -1703,6 +1776,19 @@ void platform_init_event(void) // and 3DS appear to have the same issue. int i, count; +#if SDL_VERSION_ATLEAST(3,0,0) + SDL_JoystickID *instance_ids = SDL_GetJoysticks(&count); + if(instance_ids) + { + if(count > MAX_JOYSTICKS) + count = MAX_JOYSTICKS; + + for(i = 0; i < count; i++) + init_joystick(instance_ids[i]); + + SDL_free(instance_ids); + } +#else count = SDL_NumJoysticks(); if(count > MAX_JOYSTICKS) @@ -1711,11 +1797,18 @@ void platform_init_event(void) for(i = 0; i < count; i++) init_joystick(i); #endif +#endif #if SDL_VERSION_ATLEAST(2,0,0) - SDL_GameControllerEventState(SDL_ENABLE); + SDL_SetGamepadEventsEnabled(true); load_gamecontrollerdb(); #endif - SDL_JoystickEventState(SDL_ENABLE); + SDL_SetJoystickEventsEnabled(true); + + /* It's not clear which ports do and don't implement SDL text events, so + * enable the unicode fallback at startup until proven otherwise. + * SDL 1.2 might also need this (Pandora? doesn't generate unicode presses). + * If it isn't required, real unicode events will turn this off. */ + unicode_fallback = true; } diff --git a/src/graphics.c b/src/graphics.c index 86a99833a..bb4cea2cb 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -1491,6 +1491,9 @@ static boolean icon_w_h_constraint(png_uint_32 w, png_uint_32 h) static void *sdl_alloc_rgba_surface(png_uint_32 w, png_uint_32 h, png_uint_32 *stride, void **pixels) { +#if SDL_VERSION_ATLEAST(2,0,0) + SDL_Surface *s = SDL_CreateSurface(w, h, SDL_PIXELFORMAT_RGBA32); +#else Uint32 rmask, gmask, bmask, amask; SDL_Surface *s; @@ -1507,6 +1510,7 @@ static void *sdl_alloc_rgba_surface(png_uint_32 w, png_uint_32 h, #endif s = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, rmask, gmask, bmask, amask); +#endif if(!s) return NULL; @@ -1551,7 +1555,7 @@ static void set_window_icon(void) if(icon) { SDL_Window *window = SDL_GetWindowFromID(graphics.window.platform_id); - SendMessage(SDL_GetWindowProperty_HWND(window), + SendMessage((HWND)SDL_GetWindowProperty_HWND(window), WM_SETICON, ICON_BIG, (LPARAM)icon); } } @@ -1563,7 +1567,7 @@ static void set_window_icon(void) { SDL_Window *window = SDL_GetWindowFromID(graphics.window.platform_id); SDL_SetWindowIcon(window, icon); - SDL_FreeSurface(icon); + SDL_DestroySurface(icon); } } #endif // CONFIG_PNG diff --git a/src/main.c b/src/main.c index af60a8ef9..6116c5801 100644 --- a/src/main.c +++ b/src/main.c @@ -55,8 +55,16 @@ #include "network/network.h" #ifdef CONFIG_SDL +#if CONFIG_SDL == 3 +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif +#include +#else #include /* SDL_main */ #endif +#endif #ifndef VERSION #error Must define VERSION for MegaZeux version string diff --git a/src/platform_sdl.c b/src/platform_sdl.c index 0cc1f5026..bd2637d1c 100644 --- a/src/platform_sdl.c +++ b/src/platform_sdl.c @@ -59,7 +59,9 @@ void delay(uint32_t ms) uint64_t get_ticks(void) { -#if SDL_VERSION_ATLEAST(2,0,18) + // SDL_GetTicks returns a 64-bit value in SDL3, but + // SDL_GetTicks64 had to be used prior to that. +#if SDL_VERSION_ATLEAST(2,0,18) && !SDL_VERSION_ATLEAST(3,0,0) return SDL_GetTicks64(); #else return SDL_GetTicks(); @@ -146,12 +148,21 @@ static void set_dpi_aware(void) } #endif +static inline boolean sdl_init(Uint32 flags) +{ +#if SDL_VERSION_ATLEAST(3,0,0) + return SDL_Init(flags); +#else + return SDL_Init(flags) >= 0; +#endif +} + boolean platform_init(void) { Uint32 flags = SDL_INIT_VIDEO | SDL_INIT_JOYSTICK; #if SDL_VERSION_ATLEAST(2,0,0) - flags |= SDL_INIT_GAMECONTROLLER; + flags |= SDL_INIT_GAMEPAD; #endif #ifdef CONFIG_PSP @@ -163,7 +174,8 @@ boolean platform_init(void) return false; #endif -#ifdef DEBUG +#if defined(DEBUG) && !SDL_VERSION_ATLEAST(3,0,0) + // Removed in SDL 3. flags |= SDL_INIT_NOPARACHUTE; #endif @@ -175,17 +187,17 @@ boolean platform_init(void) set_dpi_aware(); #endif - if(SDL_Init(flags) < 0) + if(!sdl_init(flags)) { debug("Failed to initialize SDL; attempting with joystick support disabled: %s\n", SDL_GetError()); // try again without joystick support flags &= ~SDL_INIT_JOYSTICK; #if SDL_VERSION_ATLEAST(2,0,0) - flags &= ~SDL_INIT_GAMECONTROLLER; + flags &= ~SDL_INIT_GAMEPAD; #endif - if(SDL_Init(flags) < 0) + if(!sdl_init(flags)) { warn("Failed to initialize SDL: %s\n", SDL_GetError()); return false; diff --git a/src/render_gl.h b/src/render_gl.h index 459b535c1..fd532df9b 100644 --- a/src/render_gl.h +++ b/src/render_gl.h @@ -3,6 +3,7 @@ * Copyright (C) 2004-2006 Gilead Kutnick * Copyright (C) 2007,2009 Alistair John Strachan * Copyright (C) 2007 Alan Williams + * Copyright (C) 2024 Alice Rowan * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -32,16 +33,29 @@ __M_BEGIN_DECLS #include "util.h" #ifdef CONFIG_SDL -#ifdef CONFIG_GLES -#ifdef CONFIG_RENDER_GL_FIXED -#include -#endif -#ifdef CONFIG_RENDER_GL_PROGRAM -#include -#endif -#else -#include -#endif +# include "SDLmzx.h" +# ifdef CONFIG_GLES +# ifdef CONFIG_RENDER_GL_FIXED +# if SDL_VERSION_ATLEAST(3,0,0) +# include +# else +# include +# endif +# endif +# ifdef CONFIG_RENDER_GL_PROGRAM +# if SDL_VERSION_ATLEAST(3,0,0) +# include +# else +# include +# endif +# endif +# else +# if SDL_VERSION_ATLEAST(3,0,0) +# include +# else +# include +# endif +# endif #endif #ifndef GLAPIENTRY diff --git a/src/render_glsl.c b/src/render_glsl.c index 470c67bb9..d8e6e99d6 100644 --- a/src/render_glsl.c +++ b/src/render_glsl.c @@ -40,9 +40,13 @@ #ifdef CONFIG_SDL #include "render_sdl.h" #ifdef ENABLE_GL_DEBUG_OUTPUT +#if SDL_VERSION_ATLEAST(3,0,0) +#include +#else #include #endif #endif +#endif #ifdef CONFIG_EGL #include diff --git a/src/render_gp2x.c b/src/render_gp2x.c index 24020b6d3..87511485e 100644 --- a/src/render_gp2x.c +++ b/src/render_gp2x.c @@ -186,7 +186,7 @@ static boolean gp2x_create_window(struct graphics_data *graphics, struct video_window *window) { struct gp2x_render_data *render_data = graphics->render_data; - const SDL_PixelFormat *format; + const SDL_PixelFormatDetails *format; uint32_t halfmask; if(!sdl_create_window_soft(graphics, window)) @@ -295,8 +295,10 @@ static void gp2x_sync_screen(struct graphics_data *graphics, if(render_data->sdl.shadow) { - SDL_Rect src_rect = render_data->sdl.shadow->clip_rect; - SDL_Rect dest_rect = render_data->sdl.screen->clip_rect; + SDL_Rect src_rect; + SDL_Rect dest_rect; + SDL_GetSurfaceClipRect(render_data->sdl.shadow, &src_rect); + SDL_GetSurfaceClipRect(render_data->sdl.screen, &dest_rect); SDL_BlitSurface(render_data->sdl.shadow, &src_rect, render_data->sdl.screen, &dest_rect); } diff --git a/src/render_sdl.c b/src/render_sdl.c index 2e7f9042d..37cb2e978 100644 --- a/src/render_sdl.c +++ b/src/render_sdl.c @@ -26,6 +26,7 @@ #include "yuv.h" #include +#include static void sdl_set_system_cursor(struct graphics_data *graphics) { @@ -71,7 +72,8 @@ int sdl_flags(const struct video_window *window) if(window->is_fullscreen) { -#if SDL_VERSION_ATLEAST(2,0,0) +#if SDL_VERSION_ATLEAST(2,0,0) && !SDL_VERSION_ATLEAST(3,0,0) + /* SDL3 removed the ability to specify this at window creation time. */ if(window->is_fullscreen_windowed) flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; else @@ -94,6 +96,40 @@ int sdl_flags(const struct video_window *window) // Get the current desktop resolution, if possible. static boolean sdl_get_desktop_display_mode(SDL_DisplayMode *display_mode) { +#if SDL_VERSION_ATLEAST(3,0,0) + + const SDL_DisplayMode **list; + const SDL_DisplayMode *mode; + int count; + + SDL_DisplayID id = SDL_GetPrimaryDisplay(); + if(id == 0) + return false; + + mode = SDL_GetDesktopDisplayMode(id); + if(mode) + { + *display_mode = *mode; + return true; + } + + warn("Failed to query desktop display mode: %s\n", SDL_GetError()); + list = (const SDL_DisplayMode **)SDL_GetFullscreenDisplayModes(0, &count); + if(list) + { + if(count) + mode = list[0]; + + SDL_free(list); + if(mode) + { + *display_mode = *mode; + return true; + } + } + +#else + if(SDL_GetDesktopDisplayMode(0, display_mode) == 0) { debug("Queried desktop mode: %d x %d, %dHz, %s\n", @@ -108,6 +144,8 @@ static boolean sdl_get_desktop_display_mode(SDL_DisplayMode *display_mode) if(SDL_GetDisplayMode(0, 0, display_mode) == 0) return true; +#endif + return false; } @@ -116,6 +154,45 @@ static boolean sdl_get_desktop_display_mode(SDL_DisplayMode *display_mode) static boolean sdl_get_closest_usable_display_mode(SDL_DisplayMode *display_mode, int width, int height) { +#if SDL_VERSION_ATLEAST(3,0,0) + + int min_size = INT_MAX; + int count; + int i; + + const SDL_DisplayMode **list; + SDL_DisplayID id = SDL_GetPrimaryDisplay(); + if(id == 0) + return false; + + list = (const SDL_DisplayMode **)SDL_GetFullscreenDisplayModes(id, &count); + if(!list) + return false; + + debug("Display modes:\n"); + + for(i = 0; i < count; i++) + { + if(!list[i]) + continue; + + debug("%d: %d x %d, %.2fHz, %s\n", i, list[i]->w, list[i]->h, + list[i]->refresh_rate, SDL_GetPixelFormatName(list[i]->format)); + + if((list[i]->w * list[i]->h < min_size) && + (list[i]->w >= width) && (list[i]->h >= height)) + { + min_size = list[i]->w * list[i]->h; + *display_mode = *list[i]; + } + } + SDL_free(list); + + if(min_size < INT_MAX) + return true; + +#else + SDL_DisplayMode mode; int min_size = INT_MAX; int count; @@ -142,6 +219,8 @@ static boolean sdl_get_closest_usable_display_mode(SDL_DisplayMode *display_mode if(min_size < INT_MAX) return true; +#endif /* !SDL_VERSION_ATLEAST(3,0,0) */ + return false; } #endif /* SDL_VERSION_ATLEAST(2,0,0) */ @@ -236,9 +315,9 @@ static uint32_t sdl_pixel_format_priority(uint32_t pixel_format, } #if SDL_VERSION_ATLEAST(2,0,12) - case SDL_PIXELFORMAT_BGR444: + case SDL_PIXELFORMAT_XBGR4444: #endif - case SDL_PIXELFORMAT_RGB444: + case SDL_PIXELFORMAT_XRGB4444: case SDL_PIXELFORMAT_ARGB4444: case SDL_PIXELFORMAT_RGBA4444: case SDL_PIXELFORMAT_ABGR4444: @@ -251,8 +330,8 @@ static uint32_t sdl_pixel_format_priority(uint32_t pixel_format, break; } - case SDL_PIXELFORMAT_RGB555: - case SDL_PIXELFORMAT_BGR555: + case SDL_PIXELFORMAT_XRGB1555: + case SDL_PIXELFORMAT_XBGR1555: case SDL_PIXELFORMAT_ARGB1555: case SDL_PIXELFORMAT_RGBA5551: case SDL_PIXELFORMAT_ABGR1555: @@ -273,8 +352,8 @@ static uint32_t sdl_pixel_format_priority(uint32_t pixel_format, break; } - case SDL_PIXELFORMAT_RGB888: - case SDL_PIXELFORMAT_BGR888: + case SDL_PIXELFORMAT_XRGB8888: + case SDL_PIXELFORMAT_XBGR8888: case SDL_PIXELFORMAT_RGBX8888: case SDL_PIXELFORMAT_BGRX8888: case SDL_PIXELFORMAT_ARGB8888: @@ -282,6 +361,11 @@ static uint32_t sdl_pixel_format_priority(uint32_t pixel_format, case SDL_PIXELFORMAT_ABGR8888: case SDL_PIXELFORMAT_BGRA8888: case SDL_PIXELFORMAT_ARGB2101010: +#if SDL_VERSION_ATLEAST(3,0,0) + case SDL_PIXELFORMAT_XRGB2101010: + case SDL_PIXELFORMAT_XBGR2101010: + case SDL_PIXELFORMAT_ABGR2101010: +#endif { // Any 32-bit RGB format is okay. if(bits_per_pixel == BPP_AUTO || bits_per_pixel == 32) @@ -305,7 +389,6 @@ static uint32_t sdl_pixel_format_priority(uint32_t pixel_format, break; } } - return 0; } #endif /* SDL_VERSION_ATLEAST(2,0,0) */ @@ -387,23 +470,28 @@ void sdl_destruct_window(struct graphics_data *graphics) // match the pixel format MZX wants. if(render_data->shadow) { - SDL_FreeSurface(render_data->shadow); + SDL_DestroySurface(render_data->shadow); render_data->shadow = NULL; } // Used for 8bpp support for the software renderer. + // This is attached to the surface in SDL3 and should not be destroyed. if(render_data->palette) { - SDL_FreePalette(render_data->palette); +#if !SDL_VERSION_ATLEAST(3,0,0) + SDL_DestroyPalette(render_data->palette); +#endif render_data->palette = NULL; } +#if !SDL_VERSION_ATLEAST(3,0,0) // Used for generating mapped colors for the SDL_Renderer renderers. if(render_data->pixel_format) { SDL_FreeFormat(render_data->pixel_format); render_data->pixel_format = NULL; } +#endif // Used by the SDL renderer-based renderers for HW acceleration. for(i = 0; i < ARRAY_SIZE(render_data->texture); i++) @@ -426,7 +514,7 @@ void sdl_destruct_window(struct graphics_data *graphics) // Used by the OpenGL renderers. if(render_data->context) { - SDL_GL_DeleteContext(render_data->context); + SDL_GL_DestroyContext(render_data->context); render_data->context = NULL; } @@ -500,9 +588,15 @@ void sdl_update_colors(struct graphics_data *graphics, return; for(i = 0; i < count; i++) { +#if SDL_VERSION_ATLEAST(3,0,0) + graphics->flat_intensity_palette[i] = + SDL_MapRGBA(render_data->flat_format, NULL, + palette[i].r, palette[i].g, palette[i].b, SDL_ALPHA_OPAQUE); +#else graphics->flat_intensity_palette[i] = SDL_MapRGBA(render_data->flat_format, palette[i].r, palette[i].g, palette[i].b, SDL_ALPHA_OPAQUE); +#endif } } else @@ -526,7 +620,7 @@ boolean sdl_create_window_soft(struct graphics_data *graphics, struct sdl_render_data *render_data = graphics->render_data; #if SDL_VERSION_ATLEAST(2,0,0) - SDL_PixelFormat *format; + SDL_Surface *target; int depth = window->bits_per_pixel; boolean matched = false; Uint32 fmt; @@ -541,7 +635,6 @@ boolean sdl_create_window_soft(struct graphics_data *graphics, #endif render_data->window = SDL_CreateWindow("MegaZeux", - SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window->width_px, window->height_px, sdl_flags(window)); if(!render_data->window) @@ -602,14 +695,8 @@ boolean sdl_create_window_soft(struct graphics_data *graphics, if(!matched) { - Uint32 Rmask, Gmask, Bmask, Amask; - int bpp; - - SDL_PixelFormatEnumToMasks(fmt, &bpp, &Rmask, &Gmask, &Bmask, &Amask); - - render_data->shadow = SDL_CreateRGBSurface(0, - window->width_px, window->height_px, bpp, Rmask, Gmask, Bmask, Amask); - + render_data->shadow = SDL_CreateSurface(window->width_px, + window->height_px, fmt); debug("Blitting enabled. Rendering performance will be reduced.\n"); } else @@ -617,35 +704,49 @@ boolean sdl_create_window_soft(struct graphics_data *graphics, render_data->shadow = NULL; } - format = render_data->shadow ? render_data->shadow->format : - render_data->screen->format; - render_data->flat_format = format; + target = render_data->shadow ? render_data->shadow : render_data->screen; +#if SDL_VERSION_ATLEAST(3,0,0) + render_data->flat_format = SDL_GetPixelFormatDetails(target->format); +#else + render_data->flat_format = target->format; +#endif if(fmt == SDL_PIXELFORMAT_INDEX8) { +#if SDL_VERSION_ATLEAST(3,0,0) + render_data->palette = SDL_CreateSurfacePalette(target); + if(!render_data->palette) + { + warn("Failed to create surface palette: %s\n", SDL_GetError()); + goto err_free; + } +#else render_data->palette = SDL_AllocPalette(SMZX_PAL_SIZE); if(!render_data->palette) { warn("Failed to allocate palette: %s\n", SDL_GetError()); goto err_free; } - render_data->palette_colors = - (SDL_Color *)ccalloc(SMZX_PAL_SIZE, sizeof(SDL_Color)); - if(!render_data->palette_colors) + + if(SDL_SetPixelFormatPalette(target->format, render_data->palette)) { - warn("Failed to allocate palette colors\n"); + warn("Failed to set pixel format palette: %s\n", SDL_GetError()); goto err_free; } +#endif - if(SDL_SetPixelFormatPalette(format, render_data->palette)) + render_data->palette_colors = + (SDL_Color *)ccalloc(SMZX_PAL_SIZE, sizeof(SDL_Color)); + if(!render_data->palette_colors) { - warn("Failed to set pixel format palette: %s\n", SDL_GetError()); + warn("Failed to allocate palette colors\n"); goto err_free; } } else { render_data->palette = NULL; + render_data->palette_colors = NULL; } window->platform_id = SDL_GetWindowID(render_data->window); @@ -676,7 +777,7 @@ boolean sdl_create_window_soft(struct graphics_data *graphics, #endif // !SDL_VERSION_ATLEAST(2,0,0) // Wipe the letterbox area, if any. - SDL_FillRect(render_data->screen, NULL, 0); + SDL_FillSurfaceRect(render_data->screen, NULL, 0); sdl_set_system_cursor(graphics); sdl_set_window_grab(render_data, window->grab_mouse); @@ -772,19 +873,23 @@ boolean sdl_resize_window(struct graphics_data *graphics, #if defined(CONFIG_RENDER_SOFTSCALE) || defined(CONFIG_RENDER_SDLACCEL) +#if SDL_VERSION_ATLEAST(3,0,0) +#define BEST_RENDERER NULL +#else #define BEST_RENDERER -1 +#endif static uint32_t get_format_amask(uint32_t format) { Uint32 rmask, gmask, bmask, amask; int bpp; - SDL_PixelFormatEnumToMasks(format, &bpp, &rmask, &gmask, &bmask, &amask); + SDL_GetMasksForPixelFormat(format, &bpp, &rmask, &gmask, &bmask, &amask); return amask; } static void find_texture_format(struct graphics_data *graphics, - uint32_t sdl_rendererflags) + boolean requires_blend_ops) { struct sdl_render_data *render_data = (struct sdl_render_data *)graphics->render_data; uint32_t texture_format = SDL_PIXELFORMAT_UNKNOWN; @@ -794,30 +899,68 @@ static void find_texture_format(struct graphics_data *graphics, boolean need_alpha = false; uint32_t yuv_priority = YUV_PRIORITY; uint32_t priority = 0; + boolean is_software_renderer = false; + const char *renderer_name; + int num_formats; + +#if SDL_VERSION_ATLEAST(3,0,0) + + SDL_PropertiesID props = SDL_GetRendererProperties(render_data->renderer); + const SDL_PixelFormat *formats = NULL; + const SDL_PixelFormat *pos; + + renderer_name = SDL_GetRendererName(render_data->renderer); + if(!strcmp(renderer_name, SDL_SOFTWARE_RENDERER)) + is_software_renderer = true; + + formats = (const SDL_PixelFormat *)SDL_GetPointerProperty(props, + SDL_PROP_RENDERER_TEXTURE_FORMATS_POINTER, NULL); + num_formats = 0; + for(pos = formats; pos && *pos != SDL_PIXELFORMAT_UNKNOWN; pos++) + num_formats++; + +#else + SDL_RendererInfo rinfo; + const uint32_t *formats = NULL; if(!SDL_GetRendererInfo(render_data->renderer, &rinfo)) + { + renderer_name = rinfo.name; + num_formats = rinfo.num_texture_formats; + formats = rinfo.texture_formats; + + if(rinfo.flags & SDL_RENDERER_SOFTWARE) + is_software_renderer = true; + } + else + warn("Failed to get renderer info!\n"); + +#endif /* !SDL_VERSION_ATLEAST(3,0,0) */ + + if(formats) { unsigned int depth = graphics->bits_per_pixel; - unsigned int i; + int i; - info("SDL render driver: '%s'\n", rinfo.name); + info("SDL render driver: '%s'\n", renderer_name); + if(is_software_renderer) + warn("Accelerated renderer not available. Rendering will be SLOW!\n"); #ifdef __MACOSX__ // Not clear if Metal supports the custom Apple YUV texture format. - if(!strcasecmp(rinfo.name, "opengl")) + if(!strcasecmp(renderer_name, "opengl")) yuv_priority = YUV_PRIORITY_APPLE; #endif // Anything using hardware blending must support alpha. - // Blending doesn't require targeting a texture, but this works for now. - if(sdl_rendererflags & SDL_RENDERER_TARGETTEXTURE) + if(requires_blend_ops) need_alpha = true; // Try to use a native texture format to improve performance. - for(i = 0; i < rinfo.num_texture_formats; i++) + for(i = 0; i < num_formats; i++) { - uint32_t format = rinfo.texture_formats[i]; + uint32_t format = formats[i]; unsigned int format_priority; debug("%d: %s\n", i, SDL_GetPixelFormatName(format)); @@ -835,8 +978,6 @@ static void find_texture_format(struct graphics_data *graphics, } } } - else - warn("Failed to get renderer info!\n"); if(texture_format == SDL_PIXELFORMAT_UNKNOWN) { @@ -914,7 +1055,7 @@ static void find_texture_format(struct graphics_data *graphics, * on the scaling ratio and window size. */ boolean sdl_create_window_renderer(struct graphics_data *graphics, - struct video_window *window, uint32_t sdl_rendererflags) + struct video_window *window, boolean requires_blend_ops) { struct sdl_render_data *render_data = graphics->render_data; @@ -943,7 +1084,6 @@ boolean sdl_create_window_renderer(struct graphics_data *graphics, } render_data->window = SDL_CreateWindow("MegaZeux", - SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window->width_px, window->height_px, sdl_flags(window)); if(!render_data->window) @@ -952,30 +1092,27 @@ boolean sdl_create_window_renderer(struct graphics_data *graphics, goto err_free; } - render_data->renderer = - SDL_CreateRenderer(render_data->window, BEST_RENDERER, - SDL_RENDERER_ACCELERATED | sdl_rendererflags); - +#if SDL_VERSION_ATLEAST(3,0,0) + render_data->renderer = SDL_CreateRenderer(render_data->window, BEST_RENDERER); +#else + render_data->renderer = SDL_CreateRenderer(render_data->window, BEST_RENDERER, + requires_blend_ops ? SDL_RENDERER_TARGETTEXTURE : 0); +#endif if(!render_data->renderer) { - render_data->renderer = - SDL_CreateRenderer(render_data->window, BEST_RENDERER, - SDL_RENDERER_SOFTWARE | sdl_rendererflags); - - if(!render_data->renderer) - { - warn("Failed to create renderer: %s\n", SDL_GetError()); - goto err_free; - } - - warn("Accelerated renderer not available. Rendering will be SLOW!\n"); + warn("Failed to create renderer: %s\n", SDL_GetError()); + goto err_free; } - find_texture_format(graphics, sdl_rendererflags); + find_texture_format(graphics, requires_blend_ops); window->bits_per_pixel = graphics->bits_per_pixel; if(!render_data->rgb_to_yuv) { +#if SDL_VERSION_ATLEAST(3,0,0) + render_data->flat_format = + SDL_GetPixelFormatDetails(render_data->texture_format); +#else // This is required for SDL_MapRGBA to work, but YUV formats can ignore it. render_data->pixel_format = SDL_AllocFormat(render_data->texture_format); if(!render_data->pixel_format) @@ -984,6 +1121,7 @@ boolean sdl_create_window_renderer(struct graphics_data *graphics, goto err_free; } render_data->flat_format = render_data->pixel_format; +#endif } SDL_SetRenderDrawColor(render_data->renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); @@ -1016,12 +1154,11 @@ void sdl_set_texture_scale_mode(struct graphics_data *graphics, { SDL_ScaleMode mode; if(!allow_non_integer || window->is_integer_scaled) - mode = SDL_ScaleModeNearest; + mode = SDL_SCALEMODE_NEAREST; else - mode = SDL_ScaleModeLinear; + mode = SDL_SCALEMODE_LINEAR; - if(SDL_SetTextureScaleMode(render_data->texture[texture_id], mode)) - warn("Failed to set texture %d scale mode: %s\n", texture_id, SDL_GetError()); + SDL_SetTextureScaleMode(render_data->texture[texture_id], mode); } else warn("Texture %d is null!\n", texture_id); @@ -1080,7 +1217,6 @@ boolean gl_create_window(struct graphics_data *graphics, #endif render_data->window = SDL_CreateWindow("MegaZeux", - SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window->width_px, window->height_px, GL_STRIP_FLAGS(sdl_flags(window))); if(!render_data->window) @@ -1089,20 +1225,14 @@ boolean gl_create_window(struct graphics_data *graphics, goto err_free; } + /* This automatically makes the context current. */ render_data->context = SDL_GL_CreateContext(render_data->window); - if(!render_data->context) { warn("Failed to create context: %s\n", SDL_GetError()); goto err_free; } - if(SDL_GL_MakeCurrent(render_data->window, render_data->context)) - { - warn("Failed to make context current: %s\n", SDL_GetError()); - goto err_free; - } - window->platform_id = SDL_GetWindowID(render_data->window); sdl_set_screensaver_enabled(graphics->disable_screensaver == SCREENSAVER_ENABLE); @@ -1168,4 +1298,3 @@ boolean gl_swap_buffers(struct graphics_data *graphics) } #endif // CONFIG_RENDER_GL_FIXED || CONFIG_RENDER_GL_PROGRAM - diff --git a/src/render_sdl.h b/src/render_sdl.h index 02ceb4dac..3caa75558 100644 --- a/src/render_sdl.h +++ b/src/render_sdl.h @@ -36,14 +36,14 @@ struct sdl_render_data SDL_Palette *palette; SDL_Window *window; SDL_GLContext context; - SDL_PixelFormat *pixel_format; + SDL_PixelFormatDetails *pixel_format; #else SDL_Overlay *overlay; #endif SDL_Surface *screen; SDL_Surface *shadow; SDL_Color *palette_colors; - const SDL_PixelFormat *flat_format; // format used by sdl_update_colors. + const SDL_PixelFormatDetails *flat_format; // format used by sdl_update_colors. // SDL Renderer and overlay renderer texture format configuration. uint32_t (*rgb_to_yuv)(uint8_t r, uint8_t g, uint8_t b); @@ -84,7 +84,7 @@ boolean sdl_check_video_mode(struct graphics_data *graphics, #if SDL_VERSION_ATLEAST(2,0,0) boolean sdl_create_window_renderer(struct graphics_data *graphics, - struct video_window *window, uint32_t sdl_rendererflags); + struct video_window *window, boolean requires_blend_ops); void sdl_set_texture_scale_mode(struct graphics_data *graphics, struct video_window *window, int texture_id, boolean allow_non_integer); #endif @@ -93,10 +93,10 @@ void sdl_set_texture_scale_mode(struct graphics_data *graphics, #include "render_gl.h" -#if SDL_VERSION_ATLEAST(2,0,0) +#if SDL_VERSION_ATLEAST(2,0,0) && !SDL_VERSION_ATLEAST(3,0,0) +/* SDL_WINDOW_FULLSCREEN_DESKTOP removed in SDL3. */ #define GL_ALLOW_FLAGS \ - (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP | \ - SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE) + (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_RESIZABLE) #else #define GL_ALLOW_FLAGS (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_RESIZABLE) #endif @@ -117,13 +117,19 @@ static inline void gl_cleanup(struct graphics_data *graphics) static inline boolean GL_LoadLibrary(enum gl_lib_type type) { - if(!SDL_GL_LoadLibrary(NULL)) return true; +#if SDL_VERSION_ATLEAST(3,0,0) + return SDL_GL_LoadLibrary(NULL); +#else + if(SDL_GL_LoadLibrary(NULL) == 0) + return true; + #if !SDL_VERSION_ATLEAST(2,0,0) // If the context already exists, don't reload the library // This is for SDL 1.2 which doesn't let us unload OpenGL if(strcmp(SDL_GetError(), "OpenGL context already created") == 0) return true; #endif return false; +#endif } static inline dso_fn_ptr GL_GetProcAddress(const char *proc) diff --git a/src/render_sdlaccel.c b/src/render_sdlaccel.c index 0094e7707..7c18d1ae5 100644 --- a/src/render_sdlaccel.c +++ b/src/render_sdlaccel.c @@ -31,12 +31,13 @@ #include "SDLmzx.h" #include "graphics.h" -#include "platform.h" #include "render.h" #include "renderers.h" #include "render_sdl.h" #include "util.h" +#include + // 6 versions of each char, 16*256 chars -> 24576 total "chars" // -> 49152 8x8s -> sqrt ~= 221 > 32 * 6 @@ -294,7 +295,7 @@ static boolean sdlaccel_create_window(struct graphics_data *graphics, int tex_chars_h; // This requires that the underlying driver supports framebuffer objects. - if(!sdl_create_window_renderer(graphics, window, SDL_RENDERER_TARGETTEXTURE)) + if(!sdl_create_window_renderer(graphics, window, true)) return false; texture[TEX_SCREEN] = @@ -343,10 +344,8 @@ static boolean sdlaccel_create_window(struct graphics_data *graphics, goto err_free; } - if(SDL_SetTextureBlendMode(texture[TEX_CHARS], SDL_BLENDMODE_BLEND)) - warn("Failed to set char texture blend mode: %s\n", SDL_GetError()); - if(SDL_SetTextureBlendMode(texture[TEX_BACKGROUND], SDL_BLENDMODE_BLEND)) - warn("Failed to set bg texture blend mode: %s\n", SDL_GetError()); + SDL_SetTextureBlendMode(texture[TEX_CHARS], SDL_BLENDMODE_BLEND); + SDL_SetTextureBlendMode(texture[TEX_BACKGROUND], SDL_BLENDMODE_BLEND); sdl_set_texture_scale_mode(graphics, window, TEX_SCREEN, true); sdl_set_texture_scale_mode(graphics, window, TEX_CHARS, false); @@ -495,8 +494,19 @@ static void sdlaccel_do_remap_chars(struct graphics_data *graphics, #ifdef RENDER_GEOMETRY static void vertex_char(struct SDL_Vertex *vertex, float topleft_x, - float topleft_y, float tex_x, float tex_y, SDL_Color sdl_color) + float topleft_y, float tex_x, float tex_y, SDL_Color _sdl_color) { +#if SDL_VERSION_ATLEAST(3,0,0) + SDL_FColor sdl_color = + { + _sdl_color.r / 255.0, + _sdl_color.g / 255.0, + _sdl_color.b / 255.0, + _sdl_color.a / 255.0, + }; +#else + SDL_Color sdl_color = _sdl_color; +#endif vertex[0].position.x = topleft_x; vertex[0].position.y = topleft_y; vertex[0].tex_coord.x = tex_x; @@ -556,8 +566,9 @@ static void sdlaccel_render_layer(struct graphics_data *graphics, SDL_Texture *chars_tex = render_data->sdl.texture[TEX_CHARS]; SDL_Texture *bg_tex = render_data->sdl.texture[TEX_BACKGROUND]; - SDL_Rect dest_bg = { offx, offy, w * CHAR_W, h * CHAR_H }; - SDL_Rect src_bg = { 0, 0, w, h }; + SDL_Rect_mzx dest_bg = sdl_render_rect(offx, offy, w * CHAR_W, h * CHAR_H); + SDL_Rect_mzx src_bg = sdl_render_rect(0, 0, w, h); + void *_bg; int bg_pitch; uint32_t *bg; @@ -642,7 +653,7 @@ static void sdlaccel_render_layer(struct graphics_data *graphics, } } SDL_UnlockTexture(bg_tex); - SDL_RenderCopy(renderer, bg_tex, &src_bg, &dest_bg); + SDL_RenderTexture(renderer, bg_tex, &src_bg, &dest_bg); #ifdef RENDER_GEOMETRY @@ -700,7 +711,8 @@ static void sdlaccel_render_cursor(struct graphics_data *graphics, unsigned x, uint8_t *palette = render_data->palette; // Input coordinates are on the character grid. - SDL_Rect dest = { x * CHAR_W, y * CHAR_H + offset, CHAR_W, lines }; + SDL_Rect_mzx dest = + sdl_render_rect(x * CHAR_W, y * CHAR_H + offset, CHAR_W, lines); SDL_SetRenderDrawBlendMode(render_data->sdl.renderer, SDL_BLENDMODE_NONE); SDL_SetRenderDrawColor(render_data->sdl.renderer, @@ -716,7 +728,7 @@ static void sdlaccel_render_mouse(struct graphics_data *graphics, unsigned x, struct sdlaccel_render_data *render_data = graphics->render_data; // Input coordinates are pixel values. - SDL_Rect dest = { x, y, w, h }; + SDL_Rect_mzx dest = sdl_render_rect(x, y, w, h); /* There is no preset inversion blend mode, so make a custom blend mode. * Lower SDL versions should simply fall back to drawing a white rectangle. @@ -744,13 +756,10 @@ static void sdlaccel_sync_screen(struct graphics_data *graphics, struct sdlaccel_render_data *render_data = graphics->render_data; SDL_Renderer *renderer = render_data->sdl.renderer; SDL_Texture *screen_tex = render_data->sdl.texture[TEX_SCREEN]; - SDL_Rect src; - SDL_Rect dest; + SDL_Rect_mzx src; + SDL_Rect_mzx dest; - src.x = 0; - src.y = 0; - src.w = SCREEN_PIX_W; - src.h = SCREEN_PIX_H; + src = sdl_render_rect(0, 0, SCREEN_PIX_W, SCREEN_PIX_H); dest.x = window->viewport_x; dest.y = window->viewport_y; @@ -758,7 +767,7 @@ static void sdlaccel_sync_screen(struct graphics_data *graphics, dest.h = window->viewport_height; SDL_SetRenderTarget(renderer, NULL); - SDL_RenderCopy(renderer, screen_tex, &src, &dest); + SDL_RenderTexture(renderer, screen_tex, &src, &dest); SDL_RenderPresent(renderer); diff --git a/src/render_soft.c b/src/render_soft.c index 8c985e0f2..0282d5f3f 100644 --- a/src/render_soft.c +++ b/src/render_soft.c @@ -54,17 +54,22 @@ static SDL_Surface *soft_get_screen_surface(struct soft_render_data *_render_dat static void soft_lock_buffer(struct soft_render_data *render_data, uint32_t **pixels, unsigned *pitch, unsigned *bpp, uint32_t *amask) { + const SDL_PixelFormatDetails *format = render_data->sdl.flat_format; SDL_Surface *screen = soft_get_screen_surface(render_data); *pixels = (uint32_t *)screen->pixels; *pitch = screen->pitch; - *bpp = screen->format->BytesPerPixel * 8; +#if SDL_VERSION_ATLEAST(3,0,0) + *bpp = format->bytes_per_pixel * 8; +#else + *bpp = format->BytesPerPixel * 8; +#endif *pixels += *pitch * ((screen->h - 350) / 8); *pixels += (screen->w - 640) * *bpp / 64; if(amask) - *amask = screen->format->Amask; + *amask = format->Amask; SDL_LockSurface(screen); } @@ -279,8 +284,10 @@ static void soft_sync_screen(struct graphics_data *graphics, if(render_data->shadow) { - SDL_Rect src_rect = render_data->shadow->clip_rect; - SDL_Rect dest_rect = render_data->screen->clip_rect; + SDL_Rect src_rect; + SDL_Rect dest_rect; + SDL_GetSurfaceClipRect(render_data->shadow, &src_rect); + SDL_GetSurfaceClipRect(render_data->screen, &dest_rect); SDL_BlitSurface(render_data->shadow, &src_rect, render_data->screen, &dest_rect); } diff --git a/src/render_softscale.c b/src/render_softscale.c index 7d50bba1c..59bbada12 100644 --- a/src/render_softscale.c +++ b/src/render_softscale.c @@ -32,7 +32,6 @@ #include "render_sdl.h" #include "renderers.h" #include "util.h" -#include "yuv.h" struct softscale_render_data { @@ -88,8 +87,9 @@ static boolean softscale_create_window(struct graphics_data *graphics, { struct softscale_render_data *render_data = (struct softscale_render_data *)graphics->render_data; + SDL_Texture *tex; - if(!sdl_create_window_renderer(graphics, window, 0)) + if(!sdl_create_window_renderer(graphics, window, false)) return false; // YUV texture modes are effectively 16-bit to SDL, but MegaZeux treats them @@ -102,15 +102,15 @@ static boolean softscale_create_window(struct graphics_data *graphics, render_data->texture_pixels = NULL; // Initialize the screen texture. - render_data->sdl.texture[0] = - SDL_CreateTexture(render_data->sdl.renderer, render_data->sdl.texture_format, - SDL_TEXTUREACCESS_STREAMING, render_data->texture_width, SCREEN_PIX_H); - - if(!render_data->sdl.texture[0]) + tex = SDL_CreateTexture(render_data->sdl.renderer, render_data->sdl.texture_format, + SDL_TEXTUREACCESS_STREAMING, render_data->texture_width, SCREEN_PIX_H); + if(!tex) { warn("Failed to create texture: %s\n", SDL_GetError()); goto err_free; } + render_data->sdl.texture[0] = tex; + sdl_set_texture_scale_mode(graphics, window, 0, true); return true; @@ -265,8 +265,12 @@ static void softscale_sync_screen(struct graphics_data *graphics, struct softscale_render_data *render_data = graphics->render_data; SDL_Renderer *renderer = render_data->sdl.renderer; SDL_Texture *texture = render_data->sdl.texture[0]; - SDL_Rect *src_rect = &(render_data->texture_rect); - SDL_Rect dest_rect; + SDL_Rect *texture_rect = &(render_data->texture_rect); + SDL_Rect_mzx src_rect; + SDL_Rect_mzx dest_rect; + + src_rect = sdl_render_rect(texture_rect->x, texture_rect->y, + texture_rect->w, texture_rect->h); dest_rect.x = window->viewport_x; dest_rect.y = window->viewport_y; @@ -278,7 +282,7 @@ static void softscale_sync_screen(struct graphics_data *graphics, SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); SDL_RenderClear(renderer); - SDL_RenderCopy(renderer, texture, src_rect, &dest_rect); + SDL_RenderTexture(renderer, texture, &src_rect, &dest_rect); SDL_RenderPresent(renderer); } diff --git a/src/thread_sdl.h b/src/thread_sdl.h index c03182bfc..c01c021a6 100644 --- a/src/thread_sdl.h +++ b/src/thread_sdl.h @@ -29,13 +29,19 @@ __M_BEGIN_DECLS #define THREAD_RES int #define THREAD_RETURN do { return 0; } while(0) -typedef SDL_cond *platform_cond; -typedef SDL_mutex *platform_mutex; -typedef SDL_sem *platform_sem; +typedef SDL_Condition *platform_cond; +typedef SDL_Mutex *platform_mutex; +typedef SDL_Semaphore *platform_sem; typedef SDL_Thread *platform_thread; -typedef SDL_threadID platform_thread_id; typedef SDL_ThreadFunction platform_thread_fn; +// Can't fix this with typedefs--SDL_ThreadID meant something else in SDL 2. +#if SDL_VERSION_ATLEAST(3,0,0) +typedef SDL_ThreadID platform_thread_id; +#else +typedef SDL_threadID platform_thread_id; +#endif + static inline boolean platform_mutex_init(platform_mutex *mutex) { platform_mutex m = SDL_CreateMutex(); @@ -55,21 +61,21 @@ static inline boolean platform_mutex_destroy(platform_mutex *mutex) static inline boolean platform_mutex_lock(platform_mutex *mutex) { - if(SDL_LockMutex(*mutex)) - return false; + // Returns void as of SDL 3. + SDL_LockMutex(*mutex); return true; } static inline boolean platform_mutex_unlock(platform_mutex *mutex) { - if(SDL_UnlockMutex(*mutex)) - return false; + // Returns void as of SDL 3. + SDL_UnlockMutex(*mutex); return true; } static inline boolean platform_cond_init(platform_cond *cond) { - platform_cond c = SDL_CreateCond(); + platform_cond c = SDL_CreateCondition(); if(c) { *cond = c; @@ -80,43 +86,43 @@ static inline boolean platform_cond_init(platform_cond *cond) static inline boolean platform_cond_destroy(platform_cond *cond) { - SDL_DestroyCond(*cond); + SDL_DestroyCondition(*cond); return true; } static inline boolean platform_cond_wait(platform_cond *cond, platform_mutex *mutex) { - if(SDL_CondWait(*cond, *mutex)) - return false; + // Returns void as of SDL 3. + SDL_WaitCondition(*cond, *mutex); return true; } static inline boolean platform_cond_timedwait(platform_cond *cond, platform_mutex *mutex, unsigned int timeout_ms) { - if(SDL_CondWaitTimeout(*cond, *mutex, (Uint32)timeout_ms)) - return false; + // Returns void as of SDL 3. + SDL_WaitConditionTimeout(*cond, *mutex, (Uint32)timeout_ms); return true; } static inline boolean platform_cond_signal(platform_cond *cond) { - if(SDL_CondSignal(*cond)) - return false; + // Returns void as of SDL 3. + SDL_SignalCondition(*cond); return true; } static inline boolean platform_cond_broadcast(platform_cond *cond) { - if(SDL_CondBroadcast(*cond)) - return false; + // Returns void as of SDL 3. + SDL_BroadcastCondition(*cond); return true; } static inline boolean platform_sem_init(platform_sem *sem, unsigned init_value) { - SDL_sem *ret = SDL_CreateSemaphore(init_value); + platform_sem ret = SDL_CreateSemaphore(init_value); if(ret) { *sem = ret; @@ -133,15 +139,15 @@ static inline boolean platform_sem_destroy(platform_sem *sem) static inline boolean platform_sem_wait(platform_sem *sem) { - if(SDL_SemWait(*sem)) - return false; + // Returns void as of SDL 3. + SDL_WaitSemaphore(*sem); return true; } static inline boolean platform_sem_post(platform_sem *sem) { - if(SDL_SemPost(*sem)) - return false; + // Returns void as of SDL 3. + SDL_SignalSemaphore(*sem); return true; } @@ -170,7 +176,7 @@ static inline boolean platform_thread_join(platform_thread *thread) static inline platform_thread_id platform_get_thread_id(void) { - return SDL_ThreadID(); + return SDL_GetCurrentThreadID(); } static inline boolean platform_is_same_thread(platform_thread_id a, diff --git a/testworlds/run.sh b/testworlds/run.sh index 578ea51c1..3fd61a825 100755 --- a/testworlds/run.sh +++ b/testworlds/run.sh @@ -82,8 +82,12 @@ fi # Coupled with the software renderer, this will disable video in MZX, speeding things up # and allowing for automated testing. Disabling the SDL audio driver will prevent annoying # noises from occuring during tests, but shouldn't affect audio-related tests. +# SDL 1.2 and SDL2 export SDL_VIDEODRIVER=dummy export SDL_AUDIODRIVER=dummy +# SDL3 +export SDL_VIDEO_DRIVER=dummy +export SDL_AUDIO_DRIVER=dummy # Standalone mode will allow tests.mzx to terminate MZX and no_titlescreen mode # simplifies things. Disable auto update checking to save time. Some platforms diff --git a/unit/configure.cpp b/unit/configure.cpp index 0f9560bf9..ba259eda7 100644 --- a/unit/configure.cpp +++ b/unit/configure.cpp @@ -31,7 +31,8 @@ #include "../src/io/vio.h" #ifdef CONFIG_SDL -#include +#include "../src/SDLmzx.h" +#undef IGNORE /* Windows defines this for some reason... */ #endif #ifdef CONFIG_EDITOR