yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
sdl_compat.h
Go to the documentation of this file.
1#ifndef YAZE_APP_PLATFORM_SDL_COMPAT_H_
2#define YAZE_APP_PLATFORM_SDL_COMPAT_H_
3
13#ifdef YAZE_USE_SDL3
14#include <SDL3/SDL.h>
15#include <SDL3/SDL_gamepad.h>
16#else
17#include <SDL.h>
18#endif
19
20namespace yaze {
21namespace platform {
22
23// ============================================================================
24// Type Aliases
25// ============================================================================
26
27#ifdef YAZE_USE_SDL3
28// SDL3 uses bool* for keyboard state
29using KeyboardState = const bool*;
30#else
31// SDL2 uses Uint8* for keyboard state
32using KeyboardState = const Uint8*;
33#endif
34
35// ============================================================================
36// Event Type Constants
37// ============================================================================
38
39#ifdef YAZE_USE_SDL3
40constexpr auto kEventKeyDown = SDL_EVENT_KEY_DOWN;
41constexpr auto kEventKeyUp = SDL_EVENT_KEY_UP;
42constexpr auto kEventMouseMotion = SDL_EVENT_MOUSE_MOTION;
43constexpr auto kEventMouseButtonDown = SDL_EVENT_MOUSE_BUTTON_DOWN;
44constexpr auto kEventMouseButtonUp = SDL_EVENT_MOUSE_BUTTON_UP;
45constexpr auto kEventMouseWheel = SDL_EVENT_MOUSE_WHEEL;
46constexpr auto kEventQuit = SDL_EVENT_QUIT;
47constexpr auto kEventDropFile = SDL_EVENT_DROP_FILE;
48constexpr auto kEventWindowCloseRequested = SDL_EVENT_WINDOW_CLOSE_REQUESTED;
49constexpr auto kEventWindowResized = SDL_EVENT_WINDOW_RESIZED;
50constexpr auto kEventGamepadAdded = SDL_EVENT_GAMEPAD_ADDED;
51constexpr auto kEventGamepadRemoved = SDL_EVENT_GAMEPAD_REMOVED;
52#else
53constexpr auto kEventKeyDown = SDL_KEYDOWN;
54constexpr auto kEventKeyUp = SDL_KEYUP;
55constexpr auto kEventMouseMotion = SDL_MOUSEMOTION;
56constexpr auto kEventMouseButtonDown = SDL_MOUSEBUTTONDOWN;
57constexpr auto kEventMouseButtonUp = SDL_MOUSEBUTTONUP;
58constexpr auto kEventMouseWheel = SDL_MOUSEWHEEL;
59constexpr auto kEventQuit = SDL_QUIT;
60constexpr auto kEventDropFile = SDL_DROPFILE;
61// SDL2 uses SDL_WINDOWEVENT with sub-types, not individual events
62// These are handled specially in window code
63constexpr auto kEventWindowEvent = SDL_WINDOWEVENT;
64constexpr auto kEventControllerDeviceAdded = SDL_CONTROLLERDEVICEADDED;
65constexpr auto kEventControllerDeviceRemoved = SDL_CONTROLLERDEVICEREMOVED;
66#endif
67
68// ============================================================================
69// Key Constants
70// ============================================================================
71
72#ifdef YAZE_USE_SDL3
73#include <SDL3/SDL_keycode.h>
74
75constexpr auto kKeyA = 'a';
76constexpr auto kKeyB = 'b';
77constexpr auto kKeyC = 'c';
78constexpr auto kKeyD = 'd';
79constexpr auto kKeyS = 's';
80constexpr auto kKeyX = 'x';
81constexpr auto kKeyY = 'y';
82constexpr auto kKeyZ = 'z';
83constexpr auto kKeyReturn = SDLK_RETURN;
84constexpr auto kKeyRShift = SDLK_RSHIFT;
85constexpr auto kKeyUp = SDLK_UP;
86constexpr auto kKeyDown = SDLK_DOWN;
87constexpr auto kKeyLeft = SDLK_LEFT;
88constexpr auto kKeyRight = SDLK_RIGHT;
89#else
90constexpr auto kKeyA = SDLK_a;
91constexpr auto kKeyB = SDLK_b;
92constexpr auto kKeyC = SDLK_c;
93constexpr auto kKeyD = SDLK_d;
94constexpr auto kKeyS = SDLK_s;
95constexpr auto kKeyX = SDLK_x;
96constexpr auto kKeyY = SDLK_y;
97constexpr auto kKeyZ = SDLK_z;
98constexpr auto kKeyReturn = SDLK_RETURN;
99constexpr auto kKeyRShift = SDLK_RSHIFT;
100constexpr auto kKeyUp = SDLK_UP;
101constexpr auto kKeyDown = SDLK_DOWN;
102constexpr auto kKeyLeft = SDLK_LEFT;
103constexpr auto kKeyRight = SDLK_RIGHT;
104#endif
105
106// ============================================================================
107// Keyboard Helpers
108// ============================================================================
109
115inline SDL_Keycode GetKeyFromEvent(const SDL_Event& event) {
116#ifdef YAZE_USE_SDL3
117 return event.key.key;
118#else
119 return event.key.keysym.sym;
120#endif
121}
122
128inline SDL_Scancode GetScancodeFromKey(SDL_Keycode key) {
129#ifdef YAZE_USE_SDL3
130 return SDL_GetScancodeFromKey(key, nullptr);
131#else
132 return SDL_GetScancodeFromKey(key);
133#endif
134}
135
142inline bool IsKeyPressed(KeyboardState state, SDL_Scancode scancode) {
143#ifdef YAZE_USE_SDL3
144 // SDL3 returns bool*
145 return state[scancode];
146#else
147 // SDL2 returns Uint8*, non-zero means pressed
148 return state[scancode] != 0;
149#endif
150}
151
152// ============================================================================
153// Gamepad/Controller Helpers
154// ============================================================================
155
156#ifdef YAZE_USE_SDL3
157// SDL3 uses SDL_Gamepad instead of SDL_GameController
158using GamepadHandle = SDL_Gamepad*;
159
160inline GamepadHandle OpenGamepad(int index) {
161 SDL_JoystickID* joysticks = SDL_GetGamepads(nullptr);
162 if (joysticks && index < 4) {
163 SDL_JoystickID id = joysticks[index];
164 SDL_free(joysticks);
165 return SDL_OpenGamepad(id);
166 }
167 if (joysticks)
168 SDL_free(joysticks);
169 return nullptr;
170}
171
172inline void CloseGamepad(GamepadHandle gamepad) {
173 if (gamepad)
174 SDL_CloseGamepad(gamepad);
175}
176
177inline bool GetGamepadButton(GamepadHandle gamepad, SDL_GamepadButton button) {
178 return SDL_GetGamepadButton(gamepad, button);
179}
180
181inline int16_t GetGamepadAxis(GamepadHandle gamepad, SDL_GamepadAxis axis) {
182 return SDL_GetGamepadAxis(gamepad, axis);
183}
184
185inline bool IsGamepadConnected(int index) {
186 int count = 0;
187 SDL_JoystickID* joysticks = SDL_GetGamepads(&count);
188 if (joysticks) {
189 SDL_free(joysticks);
190 }
191 return index < count;
192}
193#else
194// SDL2 uses SDL_GameController
195using GamepadHandle = SDL_GameController*;
196
197inline GamepadHandle OpenGamepad(int index) {
198 if (SDL_IsGameController(index)) {
199 return SDL_GameControllerOpen(index);
200 }
201 return nullptr;
202}
203
204inline void CloseGamepad(GamepadHandle gamepad) {
205 if (gamepad)
206 SDL_GameControllerClose(gamepad);
207}
208
209inline bool GetGamepadButton(GamepadHandle gamepad,
210 SDL_GameControllerButton button) {
211 return SDL_GameControllerGetButton(gamepad, button) != 0;
212}
213
214inline int16_t GetGamepadAxis(GamepadHandle gamepad,
215 SDL_GameControllerAxis axis) {
216 return SDL_GameControllerGetAxis(gamepad, axis);
217}
218
219inline bool IsGamepadConnected(int index) {
220 return SDL_IsGameController(index);
221}
222#endif
223
224// ============================================================================
225// Button/Axis Type Aliases
226// ============================================================================
227
228#ifdef YAZE_USE_SDL3
229using GamepadButton = SDL_GamepadButton;
230using GamepadAxis = SDL_GamepadAxis;
231
232constexpr auto kGamepadButtonA = SDL_GAMEPAD_BUTTON_SOUTH;
233constexpr auto kGamepadButtonB = SDL_GAMEPAD_BUTTON_EAST;
234constexpr auto kGamepadButtonX = SDL_GAMEPAD_BUTTON_WEST;
235constexpr auto kGamepadButtonY = SDL_GAMEPAD_BUTTON_NORTH;
236constexpr auto kGamepadButtonBack = SDL_GAMEPAD_BUTTON_BACK;
237constexpr auto kGamepadButtonStart = SDL_GAMEPAD_BUTTON_START;
238constexpr auto kGamepadButtonLeftShoulder = SDL_GAMEPAD_BUTTON_LEFT_SHOULDER;
239constexpr auto kGamepadButtonRightShoulder = SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER;
240constexpr auto kGamepadButtonDpadUp = SDL_GAMEPAD_BUTTON_DPAD_UP;
241constexpr auto kGamepadButtonDpadDown = SDL_GAMEPAD_BUTTON_DPAD_DOWN;
242constexpr auto kGamepadButtonDpadLeft = SDL_GAMEPAD_BUTTON_DPAD_LEFT;
243constexpr auto kGamepadButtonDpadRight = SDL_GAMEPAD_BUTTON_DPAD_RIGHT;
244
245constexpr auto kGamepadAxisLeftX = SDL_GAMEPAD_AXIS_LEFTX;
246constexpr auto kGamepadAxisLeftY = SDL_GAMEPAD_AXIS_LEFTY;
247#else
248using GamepadButton = SDL_GameControllerButton;
249using GamepadAxis = SDL_GameControllerAxis;
250
251constexpr auto kGamepadButtonA = SDL_CONTROLLER_BUTTON_A;
252constexpr auto kGamepadButtonB = SDL_CONTROLLER_BUTTON_B;
253constexpr auto kGamepadButtonX = SDL_CONTROLLER_BUTTON_X;
254constexpr auto kGamepadButtonY = SDL_CONTROLLER_BUTTON_Y;
255constexpr auto kGamepadButtonBack = SDL_CONTROLLER_BUTTON_BACK;
256constexpr auto kGamepadButtonStart = SDL_CONTROLLER_BUTTON_START;
257constexpr auto kGamepadButtonLeftShoulder = SDL_CONTROLLER_BUTTON_LEFTSHOULDER;
259 SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
260constexpr auto kGamepadButtonDpadUp = SDL_CONTROLLER_BUTTON_DPAD_UP;
261constexpr auto kGamepadButtonDpadDown = SDL_CONTROLLER_BUTTON_DPAD_DOWN;
262constexpr auto kGamepadButtonDpadLeft = SDL_CONTROLLER_BUTTON_DPAD_LEFT;
263constexpr auto kGamepadButtonDpadRight = SDL_CONTROLLER_BUTTON_DPAD_RIGHT;
264
265constexpr auto kGamepadAxisLeftX = SDL_CONTROLLER_AXIS_LEFTX;
266constexpr auto kGamepadAxisLeftY = SDL_CONTROLLER_AXIS_LEFTY;
267#endif
268
269// ============================================================================
270// Renderer Helpers
271// ============================================================================
272
279inline SDL_Renderer* CreateRenderer(SDL_Window* window) {
280#ifdef YAZE_USE_SDL3
281 return SDL_CreateRenderer(window, nullptr);
282#else
283 SDL_Renderer* renderer =
284 SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
285 if (renderer == nullptr) {
286 // No working GL acceleration (VM, remote/forwarded X, broken Mesa).
287 // Fall back to software rendering so the app can still start.
288 SDL_LogWarn(SDL_LOG_CATEGORY_RENDER,
289 "Accelerated renderer unavailable (%s); "
290 "falling back to software rendering",
291 SDL_GetError());
292 renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_SOFTWARE);
293 }
294 return renderer;
295#endif
296}
297
307inline void SetRenderVSync(SDL_Renderer* renderer, int interval) {
308#ifdef YAZE_USE_SDL3
309 SDL_SetRenderVSync(renderer, interval);
310#elif SDL_VERSION_ATLEAST(2, 0, 18)
311 if (renderer != nullptr) {
312 SDL_RenderSetVSync(renderer, interval);
313 }
314#else
315 (void)renderer;
316 (void)interval;
317#endif
318}
319
328inline bool RenderTexture(SDL_Renderer* renderer, SDL_Texture* texture,
329 const SDL_Rect* srcrect, const SDL_Rect* dstrect) {
330#ifdef YAZE_USE_SDL3
331 SDL_FRect src_frect, dst_frect;
332 SDL_FRect* src_ptr = nullptr;
333 SDL_FRect* dst_ptr = nullptr;
334
335 if (srcrect) {
336 src_frect.x = static_cast<float>(srcrect->x);
337 src_frect.y = static_cast<float>(srcrect->y);
338 src_frect.w = static_cast<float>(srcrect->w);
339 src_frect.h = static_cast<float>(srcrect->h);
340 src_ptr = &src_frect;
341 }
342
343 if (dstrect) {
344 dst_frect.x = static_cast<float>(dstrect->x);
345 dst_frect.y = static_cast<float>(dstrect->y);
346 dst_frect.w = static_cast<float>(dstrect->w);
347 dst_frect.h = static_cast<float>(dstrect->h);
348 dst_ptr = &dst_frect;
349 }
350
351 return SDL_RenderTexture(renderer, texture, src_ptr, dst_ptr);
352#else
353 return SDL_RenderCopy(renderer, texture, srcrect, dstrect) == 0;
354#endif
355}
356
357// ============================================================================
358// Surface Helpers
359// ============================================================================
360
367inline void FreeSurface(SDL_Surface* surface) {
368 if (!surface)
369 return;
370#ifdef YAZE_USE_SDL3
371 SDL_DestroySurface(surface);
372#else
373 SDL_FreeSurface(surface);
374#endif
375}
376
383inline SDL_Surface* ConvertSurfaceFormat(SDL_Surface* surface, uint32_t format,
384 uint32_t flags = 0) {
385 if (!surface)
386 return nullptr;
387#ifdef YAZE_USE_SDL3
388 (void)flags; // SDL3 removed flags parameter
389 return SDL_ConvertSurface(surface, static_cast<SDL_PixelFormat>(format));
390#else
391 return SDL_ConvertSurfaceFormat(surface, format, flags);
392#endif
393}
394
398inline SDL_Palette* GetSurfacePalette(SDL_Surface* surface) {
399 if (!surface)
400 return nullptr;
401#ifdef YAZE_USE_SDL3
402 return SDL_GetSurfacePalette(surface);
403#else
404 return surface->format ? surface->format->palette : nullptr;
405#endif
406}
407
414inline Uint32 GetSurfaceFormat(SDL_Surface* surface) {
415#ifdef YAZE_USE_SDL3
416 return surface ? static_cast<Uint32>(surface->format)
417 : SDL_PIXELFORMAT_UNKNOWN;
418#else
419 return (surface && surface->format) ? surface->format->format
420 : SDL_PIXELFORMAT_UNKNOWN;
421#endif
422}
423
427inline Uint32 MapRGB(SDL_Surface* surface, Uint8 r, Uint8 g, Uint8 b) {
428 if (!surface)
429 return 0;
430#ifdef YAZE_USE_SDL3
431 const SDL_PixelFormatDetails* details =
432 SDL_GetPixelFormatDetails(surface->format);
433 if (!details)
434 return 0;
435 SDL_Palette* palette = SDL_GetSurfacePalette(surface);
436 return SDL_MapRGB(details, palette, r, g, b);
437#else
438 return SDL_MapRGB(surface->format, r, g, b);
439#endif
440}
441
445inline SDL_Surface* CreateSurface(int width, int height, int depth,
446 uint32_t format) {
447#ifdef YAZE_USE_SDL3
448 (void)depth; // SDL3 infers depth from format
449 return SDL_CreateSurface(width, height, static_cast<SDL_PixelFormat>(format));
450#else
451 return SDL_CreateRGBSurfaceWithFormat(0, width, height, depth, format);
452#endif
453}
454
461inline int GetSurfaceBitsPerPixel(SDL_Surface* surface) {
462 if (!surface)
463 return 0;
464#ifdef YAZE_USE_SDL3
465 const SDL_PixelFormatDetails* details =
466 SDL_GetPixelFormatDetails(surface->format);
467 return details ? details->bits_per_pixel : 0;
468#else
469 return surface->format ? surface->format->BitsPerPixel : 0;
470#endif
471}
472
482inline bool EnsureSurfacePalette256(SDL_Surface* surface) {
483 if (!surface)
484 return false;
485
486 SDL_Palette* existing = GetSurfacePalette(surface);
487 if (existing && existing->ncolors >= 256) {
488 return true; // Already has proper palette
489 }
490
491 // Check if this is an indexed format that needs a palette
492 int bpp = GetSurfaceBitsPerPixel(surface);
493 if (bpp != 8) {
494 return true; // Not an indexed format, no palette needed
495 }
496
497 // Create a new 256-color palette (SDL2: SDL_AllocPalette, SDL3: SDL_CreatePalette)
498#ifdef YAZE_USE_SDL3
499 SDL_Palette* new_palette = SDL_CreatePalette(256);
500#else
501 SDL_Palette* new_palette = SDL_AllocPalette(256);
502#endif
503 if (!new_palette) {
504 SDL_Log("Warning: Failed to create 256-color palette: %s", SDL_GetError());
505 return false;
506 }
507
508 // Initialize with grayscale as a safe default
509 SDL_Color colors[256];
510 for (int i = 0; i < 256; i++) {
511 colors[i].r = colors[i].g = colors[i].b = static_cast<Uint8>(i);
512 colors[i].a = 255;
513 }
514 SDL_SetPaletteColors(new_palette, colors, 0, 256);
515
516 // Attach to surface
517 if (SDL_SetSurfacePalette(surface, new_palette) != 0) {
518 SDL_Log("Warning: Failed to set surface palette: %s", SDL_GetError());
519#ifdef YAZE_USE_SDL3
520 SDL_DestroyPalette(new_palette);
521#else
522 SDL_FreePalette(new_palette);
523#endif
524 return false;
525 }
526
527 return true;
528}
529
536inline int GetSurfaceBytesPerPixel(SDL_Surface* surface) {
537 if (!surface)
538 return 0;
539#ifdef YAZE_USE_SDL3
540 const SDL_PixelFormatDetails* details =
541 SDL_GetPixelFormatDetails(surface->format);
542 return details ? details->bytes_per_pixel : 0;
543#else
544 return surface->format ? surface->format->BytesPerPixel : 0;
545#endif
546}
547
548// ============================================================================
549// Window Event Compatibility Macros
550// These macros allow code to handle window events consistently across SDL2/SDL3
551// ============================================================================
552
553#ifdef YAZE_USE_SDL3
554
555// SDL3 has individual window events at the top level
556#define YAZE_SDL_QUIT SDL_EVENT_QUIT
557#define YAZE_SDL_WINDOWEVENT 0 // Placeholder - SDL3 has no combined event
558
559// SDL3 window events are individual event types
560#define YAZE_SDL_WINDOW_CLOSE SDL_EVENT_WINDOW_CLOSE_REQUESTED
561#define YAZE_SDL_WINDOW_RESIZED SDL_EVENT_WINDOW_RESIZED
562#define YAZE_SDL_WINDOW_SIZE_CHANGED SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED
563#define YAZE_SDL_WINDOW_MINIMIZED SDL_EVENT_WINDOW_MINIMIZED
564#define YAZE_SDL_WINDOW_MAXIMIZED SDL_EVENT_WINDOW_MAXIMIZED
565#define YAZE_SDL_WINDOW_RESTORED SDL_EVENT_WINDOW_RESTORED
566#define YAZE_SDL_WINDOW_SHOWN SDL_EVENT_WINDOW_SHOWN
567#define YAZE_SDL_WINDOW_HIDDEN SDL_EVENT_WINDOW_HIDDEN
568#define YAZE_SDL_WINDOW_EXPOSED SDL_EVENT_WINDOW_EXPOSED
569#define YAZE_SDL_WINDOW_FOCUS_GAINED SDL_EVENT_WINDOW_FOCUS_GAINED
570#define YAZE_SDL_WINDOW_FOCUS_LOST SDL_EVENT_WINDOW_FOCUS_LOST
571
572// SDL3 has no nested window events
573#define YAZE_SDL_HAS_INDIVIDUAL_WINDOW_EVENTS 1
574
575#else // SDL2
576
577// SDL2 event types
578#define YAZE_SDL_QUIT SDL_QUIT
579#define YAZE_SDL_WINDOWEVENT SDL_WINDOWEVENT
580
581// SDL2 window events are nested under SDL_WINDOWEVENT
582#define YAZE_SDL_WINDOW_CLOSE SDL_WINDOWEVENT_CLOSE
583#define YAZE_SDL_WINDOW_RESIZED SDL_WINDOWEVENT_RESIZED
584#define YAZE_SDL_WINDOW_SIZE_CHANGED SDL_WINDOWEVENT_SIZE_CHANGED
585#define YAZE_SDL_WINDOW_MINIMIZED SDL_WINDOWEVENT_MINIMIZED
586#define YAZE_SDL_WINDOW_MAXIMIZED SDL_WINDOWEVENT_MAXIMIZED
587#define YAZE_SDL_WINDOW_RESTORED SDL_WINDOWEVENT_RESTORED
588#define YAZE_SDL_WINDOW_SHOWN SDL_WINDOWEVENT_SHOWN
589#define YAZE_SDL_WINDOW_HIDDEN SDL_WINDOWEVENT_HIDDEN
590#define YAZE_SDL_WINDOW_EXPOSED SDL_WINDOWEVENT_EXPOSED
591#define YAZE_SDL_WINDOW_FOCUS_GAINED SDL_WINDOWEVENT_FOCUS_GAINED
592#define YAZE_SDL_WINDOW_FOCUS_LOST SDL_WINDOWEVENT_FOCUS_LOST
593
594// SDL2 uses nested window events
595#define YAZE_SDL_HAS_INDIVIDUAL_WINDOW_EVENTS 0
596
597#endif // YAZE_USE_SDL3
598
599// ============================================================================
600// Window Event Helper Functions
601// ============================================================================
602
607inline bool IsWindowCloseEvent(const SDL_Event& event) {
608#ifdef YAZE_USE_SDL3
609 return event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED;
610#else
611 return event.type == SDL_WINDOWEVENT &&
612 event.window.event == SDL_WINDOWEVENT_CLOSE;
613#endif
614}
615
619inline bool IsWindowResizeEvent(const SDL_Event& event) {
620#ifdef YAZE_USE_SDL3
621 return event.type == SDL_EVENT_WINDOW_RESIZED ||
622 event.type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED;
623#else
624 return event.type == SDL_WINDOWEVENT &&
625 (event.window.event == SDL_WINDOWEVENT_RESIZED ||
626 event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED);
627#endif
628}
629
633inline bool IsWindowMinimizedEvent(const SDL_Event& event) {
634#ifdef YAZE_USE_SDL3
635 return event.type == SDL_EVENT_WINDOW_MINIMIZED;
636#else
637 return event.type == SDL_WINDOWEVENT &&
638 event.window.event == SDL_WINDOWEVENT_MINIMIZED;
639#endif
640}
641
645inline bool IsWindowRestoredEvent(const SDL_Event& event) {
646#ifdef YAZE_USE_SDL3
647 return event.type == SDL_EVENT_WINDOW_RESTORED;
648#else
649 return event.type == SDL_WINDOWEVENT &&
650 event.window.event == SDL_WINDOWEVENT_RESTORED;
651#endif
652}
653
657inline int GetWindowEventWidth(const SDL_Event& event) {
658 return event.window.data1;
659}
660
664inline int GetWindowEventHeight(const SDL_Event& event) {
665 return event.window.data2;
666}
667
668// ============================================================================
669// Initialization Helpers
670// ============================================================================
671
678inline bool InitSucceeded(int result) {
679#ifdef YAZE_USE_SDL3
680 // SDL3 returns bool (non-zero for success)
681 return result != 0;
682#else
683 // SDL2 returns 0 for success
684 return result == 0;
685#endif
686}
687
693inline uint32_t GetDefaultInitFlags() {
694#ifdef YAZE_USE_SDL3
695 return SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_EVENTS;
696#else
697 return SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_EVENTS;
698#endif
699}
700
701// ============================================================================
702// Surface Helpers
703// ============================================================================
704
708inline SDL_Surface* CreateRGBSurface(Uint32 flags, int width, int height,
709 int depth, Uint32 Rmask, Uint32 Gmask,
710 Uint32 Bmask, Uint32 Amask) {
711#ifdef YAZE_USE_SDL3
712 // SDL3 uses SDL_CreateSurface with pixel format
713 return SDL_CreateSurface(
714 width, height,
715 SDL_GetPixelFormatForMasks(depth, Rmask, Gmask, Bmask, Amask));
716#else
717 return SDL_CreateRGBSurface(flags, width, height, depth, Rmask, Gmask, Bmask,
718 Amask);
719#endif
720}
721
725inline void DestroySurface(SDL_Surface* surface) {
726#ifdef YAZE_USE_SDL3
727 SDL_DestroySurface(surface);
728#else
729 SDL_FreeSurface(surface);
730#endif
731}
732
733// ============================================================================
734// Renderer Helpers
735// ============================================================================
736
740inline int GetRendererOutputSize(SDL_Renderer* renderer, int* w, int* h) {
741#ifdef YAZE_USE_SDL3
742 return SDL_GetCurrentRenderOutputSize(renderer, w, h);
743#else
744 return SDL_GetRendererOutputSize(renderer, w, h);
745#endif
746}
747
754inline SDL_Surface* ReadPixelsToSurface(SDL_Renderer* renderer, int width,
755 int height, const SDL_Rect* rect) {
756#ifdef YAZE_USE_SDL3
757 return SDL_RenderReadPixels(renderer, rect);
758#else
759 // Create surface to read into (ARGB8888 to match typical screenshot needs)
760 SDL_Surface* surface = SDL_CreateRGBSurface(
761 0, width, height, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
762 if (!surface)
763 return nullptr;
764
765 if (SDL_RenderReadPixels(renderer, rect, SDL_PIXELFORMAT_ARGB8888,
766 surface->pixels, surface->pitch) != 0) {
767 SDL_FreeSurface(surface);
768 return nullptr;
769 }
770 return surface;
771#endif
772}
773
777inline SDL_Surface* LoadBMP(const char* file) {
778#ifdef YAZE_USE_SDL3
779 return SDL_LoadBMP(file);
780#else
781 return SDL_LoadBMP(file);
782#endif
783}
784
785} // namespace platform
786} // namespace yaze
787
788#endif // YAZE_APP_PLATFORM_SDL_COMPAT_H_
constexpr auto kKeyB
Definition sdl_compat.h:91
constexpr auto kGamepadButtonA
Definition sdl_compat.h:251
constexpr auto kEventKeyDown
Definition sdl_compat.h:53
constexpr auto kEventMouseButtonUp
Definition sdl_compat.h:57
constexpr auto kEventDropFile
Definition sdl_compat.h:60
SDL_Scancode GetScancodeFromKey(SDL_Keycode key)
Get scancode from keycode.
Definition sdl_compat.h:128
void DestroySurface(SDL_Surface *surface)
Destroy a surface.
Definition sdl_compat.h:725
int GetWindowEventWidth(const SDL_Event &event)
Get window width from resize event data.
Definition sdl_compat.h:657
constexpr auto kEventControllerDeviceAdded
Definition sdl_compat.h:64
SDL_Surface * ConvertSurfaceFormat(SDL_Surface *surface, uint32_t format, uint32_t flags=0)
Convert a surface to a specific pixel format.
Definition sdl_compat.h:383
constexpr auto kGamepadButtonLeftShoulder
Definition sdl_compat.h:257
constexpr auto kKeyX
Definition sdl_compat.h:95
int GetRendererOutputSize(SDL_Renderer *renderer, int *w, int *h)
Get renderer output size.
Definition sdl_compat.h:740
Uint32 GetSurfaceFormat(SDL_Surface *surface)
Get the pixel format of a surface as Uint32.
Definition sdl_compat.h:414
constexpr auto kKeyC
Definition sdl_compat.h:92
bool IsWindowRestoredEvent(const SDL_Event &event)
Check if an event is a window restore event.
Definition sdl_compat.h:645
int GetSurfaceBitsPerPixel(SDL_Surface *surface)
Get bits per pixel from a surface.
Definition sdl_compat.h:461
int GetSurfaceBytesPerPixel(SDL_Surface *surface)
Get bytes per pixel from a surface.
Definition sdl_compat.h:536
constexpr auto kKeyRShift
Definition sdl_compat.h:99
constexpr auto kEventMouseMotion
Definition sdl_compat.h:55
constexpr auto kEventQuit
Definition sdl_compat.h:59
int16_t GetGamepadAxis(GamepadHandle gamepad, SDL_GameControllerAxis axis)
Definition sdl_compat.h:214
constexpr auto kGamepadAxisLeftY
Definition sdl_compat.h:266
constexpr auto kEventMouseWheel
Definition sdl_compat.h:58
constexpr auto kEventWindowEvent
Definition sdl_compat.h:63
bool IsWindowMinimizedEvent(const SDL_Event &event)
Check if an event is a window minimize event.
Definition sdl_compat.h:633
constexpr auto kGamepadButtonDpadDown
Definition sdl_compat.h:261
SDL_Surface * CreateRGBSurface(Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
Create an RGB surface.
Definition sdl_compat.h:708
bool InitSucceeded(int result)
Check if SDL initialization succeeded.
Definition sdl_compat.h:678
bool IsWindowCloseEvent(const SDL_Event &event)
Check if an event is a window close event Works correctly for both SDL2 (nested) and SDL3 (individual...
Definition sdl_compat.h:607
SDL_Renderer * CreateRenderer(SDL_Window *window)
Create a renderer with default settings.
Definition sdl_compat.h:279
constexpr auto kEventMouseButtonDown
Definition sdl_compat.h:56
SDL_Surface * LoadBMP(const char *file)
Load a BMP file.
Definition sdl_compat.h:777
constexpr auto kGamepadAxisLeftX
Definition sdl_compat.h:265
SDL_GameController * GamepadHandle
Definition sdl_compat.h:195
constexpr auto kGamepadButtonDpadRight
Definition sdl_compat.h:263
bool IsWindowResizeEvent(const SDL_Event &event)
Check if an event is a window resize event.
Definition sdl_compat.h:619
SDL_GameControllerButton GamepadButton
Definition sdl_compat.h:248
constexpr auto kKeyRight
Definition sdl_compat.h:103
Uint32 MapRGB(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b)
Map an RGB color to the surface's pixel format.
Definition sdl_compat.h:427
constexpr auto kKeyA
Definition sdl_compat.h:90
constexpr auto kEventKeyUp
Definition sdl_compat.h:54
SDL_Surface * CreateSurface(int width, int height, int depth, uint32_t format)
Create a surface using the appropriate API.
Definition sdl_compat.h:445
constexpr auto kKeyLeft
Definition sdl_compat.h:102
constexpr auto kKeyY
Definition sdl_compat.h:96
constexpr auto kKeyZ
Definition sdl_compat.h:97
SDL_Surface * ReadPixelsToSurface(SDL_Renderer *renderer, int width, int height, const SDL_Rect *rect)
Read pixels from renderer to a surface.
Definition sdl_compat.h:754
constexpr auto kKeyUp
Definition sdl_compat.h:100
GamepadHandle OpenGamepad(int index)
Definition sdl_compat.h:197
constexpr auto kGamepadButtonX
Definition sdl_compat.h:253
SDL_Keycode GetKeyFromEvent(const SDL_Event &event)
Get keyboard state from SDL event.
Definition sdl_compat.h:115
bool IsGamepadConnected(int index)
Definition sdl_compat.h:219
constexpr auto kGamepadButtonDpadUp
Definition sdl_compat.h:260
bool IsKeyPressed(KeyboardState state, SDL_Scancode scancode)
Check if a key is pressed using the keyboard state.
Definition sdl_compat.h:142
constexpr auto kEventControllerDeviceRemoved
Definition sdl_compat.h:65
bool GetGamepadButton(GamepadHandle gamepad, SDL_GameControllerButton button)
Definition sdl_compat.h:209
void SetRenderVSync(SDL_Renderer *renderer, int interval)
Set vertical sync for the renderer.
Definition sdl_compat.h:307
constexpr auto kGamepadButtonB
Definition sdl_compat.h:252
constexpr auto kKeyDown
Definition sdl_compat.h:101
SDL_Palette * GetSurfacePalette(SDL_Surface *surface)
Get the palette attached to a surface.
Definition sdl_compat.h:398
constexpr auto kKeyD
Definition sdl_compat.h:93
constexpr auto kKeyReturn
Definition sdl_compat.h:98
bool EnsureSurfacePalette256(SDL_Surface *surface)
Ensure the surface has a proper 256-color palette for indexed formats.
Definition sdl_compat.h:482
constexpr auto kKeyS
Definition sdl_compat.h:94
bool RenderTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_Rect *dstrect)
Render a texture to the current render target.
Definition sdl_compat.h:328
SDL_GameControllerAxis GamepadAxis
Definition sdl_compat.h:249
constexpr auto kGamepadButtonRightShoulder
Definition sdl_compat.h:258
constexpr auto kGamepadButtonStart
Definition sdl_compat.h:256
const Uint8 * KeyboardState
Definition sdl_compat.h:32
void CloseGamepad(GamepadHandle gamepad)
Definition sdl_compat.h:204
constexpr auto kGamepadButtonDpadLeft
Definition sdl_compat.h:262
uint32_t GetDefaultInitFlags()
Get recommended init flags.
Definition sdl_compat.h:693
int GetWindowEventHeight(const SDL_Event &event)
Get window height from resize event data.
Definition sdl_compat.h:664
constexpr auto kGamepadButtonBack
Definition sdl_compat.h:255
constexpr auto kGamepadButtonY
Definition sdl_compat.h:254
void FreeSurface(SDL_Surface *surface)
Free/destroy a surface.
Definition sdl_compat.h:367