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
304inline void SetRenderVSync(SDL_Renderer* renderer, int interval) {
305#ifdef YAZE_USE_SDL3
306 SDL_SetRenderVSync(renderer, interval);
307#else
308 // SDL2 sets vsync at creation time, this is a no-op
309 (void)renderer;
310 (void)interval;
311#endif
312}
313
322inline bool RenderTexture(SDL_Renderer* renderer, SDL_Texture* texture,
323 const SDL_Rect* srcrect, const SDL_Rect* dstrect) {
324#ifdef YAZE_USE_SDL3
325 SDL_FRect src_frect, dst_frect;
326 SDL_FRect* src_ptr = nullptr;
327 SDL_FRect* dst_ptr = nullptr;
328
329 if (srcrect) {
330 src_frect.x = static_cast<float>(srcrect->x);
331 src_frect.y = static_cast<float>(srcrect->y);
332 src_frect.w = static_cast<float>(srcrect->w);
333 src_frect.h = static_cast<float>(srcrect->h);
334 src_ptr = &src_frect;
335 }
336
337 if (dstrect) {
338 dst_frect.x = static_cast<float>(dstrect->x);
339 dst_frect.y = static_cast<float>(dstrect->y);
340 dst_frect.w = static_cast<float>(dstrect->w);
341 dst_frect.h = static_cast<float>(dstrect->h);
342 dst_ptr = &dst_frect;
343 }
344
345 return SDL_RenderTexture(renderer, texture, src_ptr, dst_ptr);
346#else
347 return SDL_RenderCopy(renderer, texture, srcrect, dstrect) == 0;
348#endif
349}
350
351// ============================================================================
352// Surface Helpers
353// ============================================================================
354
361inline void FreeSurface(SDL_Surface* surface) {
362 if (!surface)
363 return;
364#ifdef YAZE_USE_SDL3
365 SDL_DestroySurface(surface);
366#else
367 SDL_FreeSurface(surface);
368#endif
369}
370
377inline SDL_Surface* ConvertSurfaceFormat(SDL_Surface* surface, uint32_t format,
378 uint32_t flags = 0) {
379 if (!surface)
380 return nullptr;
381#ifdef YAZE_USE_SDL3
382 (void)flags; // SDL3 removed flags parameter
383 return SDL_ConvertSurface(surface, static_cast<SDL_PixelFormat>(format));
384#else
385 return SDL_ConvertSurfaceFormat(surface, format, flags);
386#endif
387}
388
392inline SDL_Palette* GetSurfacePalette(SDL_Surface* surface) {
393 if (!surface)
394 return nullptr;
395#ifdef YAZE_USE_SDL3
396 return SDL_GetSurfacePalette(surface);
397#else
398 return surface->format ? surface->format->palette : nullptr;
399#endif
400}
401
408inline Uint32 GetSurfaceFormat(SDL_Surface* surface) {
409#ifdef YAZE_USE_SDL3
410 return surface ? static_cast<Uint32>(surface->format)
411 : SDL_PIXELFORMAT_UNKNOWN;
412#else
413 return (surface && surface->format) ? surface->format->format
414 : SDL_PIXELFORMAT_UNKNOWN;
415#endif
416}
417
421inline Uint32 MapRGB(SDL_Surface* surface, Uint8 r, Uint8 g, Uint8 b) {
422 if (!surface)
423 return 0;
424#ifdef YAZE_USE_SDL3
425 const SDL_PixelFormatDetails* details =
426 SDL_GetPixelFormatDetails(surface->format);
427 if (!details)
428 return 0;
429 SDL_Palette* palette = SDL_GetSurfacePalette(surface);
430 return SDL_MapRGB(details, palette, r, g, b);
431#else
432 return SDL_MapRGB(surface->format, r, g, b);
433#endif
434}
435
439inline SDL_Surface* CreateSurface(int width, int height, int depth,
440 uint32_t format) {
441#ifdef YAZE_USE_SDL3
442 (void)depth; // SDL3 infers depth from format
443 return SDL_CreateSurface(width, height, static_cast<SDL_PixelFormat>(format));
444#else
445 return SDL_CreateRGBSurfaceWithFormat(0, width, height, depth, format);
446#endif
447}
448
455inline int GetSurfaceBitsPerPixel(SDL_Surface* surface) {
456 if (!surface)
457 return 0;
458#ifdef YAZE_USE_SDL3
459 const SDL_PixelFormatDetails* details =
460 SDL_GetPixelFormatDetails(surface->format);
461 return details ? details->bits_per_pixel : 0;
462#else
463 return surface->format ? surface->format->BitsPerPixel : 0;
464#endif
465}
466
476inline bool EnsureSurfacePalette256(SDL_Surface* surface) {
477 if (!surface)
478 return false;
479
480 SDL_Palette* existing = GetSurfacePalette(surface);
481 if (existing && existing->ncolors >= 256) {
482 return true; // Already has proper palette
483 }
484
485 // Check if this is an indexed format that needs a palette
486 int bpp = GetSurfaceBitsPerPixel(surface);
487 if (bpp != 8) {
488 return true; // Not an indexed format, no palette needed
489 }
490
491 // Create a new 256-color palette (SDL2: SDL_AllocPalette, SDL3: SDL_CreatePalette)
492#ifdef YAZE_USE_SDL3
493 SDL_Palette* new_palette = SDL_CreatePalette(256);
494#else
495 SDL_Palette* new_palette = SDL_AllocPalette(256);
496#endif
497 if (!new_palette) {
498 SDL_Log("Warning: Failed to create 256-color palette: %s", SDL_GetError());
499 return false;
500 }
501
502 // Initialize with grayscale as a safe default
503 SDL_Color colors[256];
504 for (int i = 0; i < 256; i++) {
505 colors[i].r = colors[i].g = colors[i].b = static_cast<Uint8>(i);
506 colors[i].a = 255;
507 }
508 SDL_SetPaletteColors(new_palette, colors, 0, 256);
509
510 // Attach to surface
511 if (SDL_SetSurfacePalette(surface, new_palette) != 0) {
512 SDL_Log("Warning: Failed to set surface palette: %s", SDL_GetError());
513#ifdef YAZE_USE_SDL3
514 SDL_DestroyPalette(new_palette);
515#else
516 SDL_FreePalette(new_palette);
517#endif
518 return false;
519 }
520
521 return true;
522}
523
530inline int GetSurfaceBytesPerPixel(SDL_Surface* surface) {
531 if (!surface)
532 return 0;
533#ifdef YAZE_USE_SDL3
534 const SDL_PixelFormatDetails* details =
535 SDL_GetPixelFormatDetails(surface->format);
536 return details ? details->bytes_per_pixel : 0;
537#else
538 return surface->format ? surface->format->BytesPerPixel : 0;
539#endif
540}
541
542// ============================================================================
543// Window Event Compatibility Macros
544// These macros allow code to handle window events consistently across SDL2/SDL3
545// ============================================================================
546
547#ifdef YAZE_USE_SDL3
548
549// SDL3 has individual window events at the top level
550#define YAZE_SDL_QUIT SDL_EVENT_QUIT
551#define YAZE_SDL_WINDOWEVENT 0 // Placeholder - SDL3 has no combined event
552
553// SDL3 window events are individual event types
554#define YAZE_SDL_WINDOW_CLOSE SDL_EVENT_WINDOW_CLOSE_REQUESTED
555#define YAZE_SDL_WINDOW_RESIZED SDL_EVENT_WINDOW_RESIZED
556#define YAZE_SDL_WINDOW_SIZE_CHANGED SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED
557#define YAZE_SDL_WINDOW_MINIMIZED SDL_EVENT_WINDOW_MINIMIZED
558#define YAZE_SDL_WINDOW_MAXIMIZED SDL_EVENT_WINDOW_MAXIMIZED
559#define YAZE_SDL_WINDOW_RESTORED SDL_EVENT_WINDOW_RESTORED
560#define YAZE_SDL_WINDOW_SHOWN SDL_EVENT_WINDOW_SHOWN
561#define YAZE_SDL_WINDOW_HIDDEN SDL_EVENT_WINDOW_HIDDEN
562#define YAZE_SDL_WINDOW_EXPOSED SDL_EVENT_WINDOW_EXPOSED
563#define YAZE_SDL_WINDOW_FOCUS_GAINED SDL_EVENT_WINDOW_FOCUS_GAINED
564#define YAZE_SDL_WINDOW_FOCUS_LOST SDL_EVENT_WINDOW_FOCUS_LOST
565
566// SDL3 has no nested window events
567#define YAZE_SDL_HAS_INDIVIDUAL_WINDOW_EVENTS 1
568
569#else // SDL2
570
571// SDL2 event types
572#define YAZE_SDL_QUIT SDL_QUIT
573#define YAZE_SDL_WINDOWEVENT SDL_WINDOWEVENT
574
575// SDL2 window events are nested under SDL_WINDOWEVENT
576#define YAZE_SDL_WINDOW_CLOSE SDL_WINDOWEVENT_CLOSE
577#define YAZE_SDL_WINDOW_RESIZED SDL_WINDOWEVENT_RESIZED
578#define YAZE_SDL_WINDOW_SIZE_CHANGED SDL_WINDOWEVENT_SIZE_CHANGED
579#define YAZE_SDL_WINDOW_MINIMIZED SDL_WINDOWEVENT_MINIMIZED
580#define YAZE_SDL_WINDOW_MAXIMIZED SDL_WINDOWEVENT_MAXIMIZED
581#define YAZE_SDL_WINDOW_RESTORED SDL_WINDOWEVENT_RESTORED
582#define YAZE_SDL_WINDOW_SHOWN SDL_WINDOWEVENT_SHOWN
583#define YAZE_SDL_WINDOW_HIDDEN SDL_WINDOWEVENT_HIDDEN
584#define YAZE_SDL_WINDOW_EXPOSED SDL_WINDOWEVENT_EXPOSED
585#define YAZE_SDL_WINDOW_FOCUS_GAINED SDL_WINDOWEVENT_FOCUS_GAINED
586#define YAZE_SDL_WINDOW_FOCUS_LOST SDL_WINDOWEVENT_FOCUS_LOST
587
588// SDL2 uses nested window events
589#define YAZE_SDL_HAS_INDIVIDUAL_WINDOW_EVENTS 0
590
591#endif // YAZE_USE_SDL3
592
593// ============================================================================
594// Window Event Helper Functions
595// ============================================================================
596
601inline bool IsWindowCloseEvent(const SDL_Event& event) {
602#ifdef YAZE_USE_SDL3
603 return event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED;
604#else
605 return event.type == SDL_WINDOWEVENT &&
606 event.window.event == SDL_WINDOWEVENT_CLOSE;
607#endif
608}
609
613inline bool IsWindowResizeEvent(const SDL_Event& event) {
614#ifdef YAZE_USE_SDL3
615 return event.type == SDL_EVENT_WINDOW_RESIZED ||
616 event.type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED;
617#else
618 return event.type == SDL_WINDOWEVENT &&
619 (event.window.event == SDL_WINDOWEVENT_RESIZED ||
620 event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED);
621#endif
622}
623
627inline bool IsWindowMinimizedEvent(const SDL_Event& event) {
628#ifdef YAZE_USE_SDL3
629 return event.type == SDL_EVENT_WINDOW_MINIMIZED;
630#else
631 return event.type == SDL_WINDOWEVENT &&
632 event.window.event == SDL_WINDOWEVENT_MINIMIZED;
633#endif
634}
635
639inline bool IsWindowRestoredEvent(const SDL_Event& event) {
640#ifdef YAZE_USE_SDL3
641 return event.type == SDL_EVENT_WINDOW_RESTORED;
642#else
643 return event.type == SDL_WINDOWEVENT &&
644 event.window.event == SDL_WINDOWEVENT_RESTORED;
645#endif
646}
647
651inline int GetWindowEventWidth(const SDL_Event& event) {
652 return event.window.data1;
653}
654
658inline int GetWindowEventHeight(const SDL_Event& event) {
659 return event.window.data2;
660}
661
662// ============================================================================
663// Initialization Helpers
664// ============================================================================
665
672inline bool InitSucceeded(int result) {
673#ifdef YAZE_USE_SDL3
674 // SDL3 returns bool (non-zero for success)
675 return result != 0;
676#else
677 // SDL2 returns 0 for success
678 return result == 0;
679#endif
680}
681
687inline uint32_t GetDefaultInitFlags() {
688#ifdef YAZE_USE_SDL3
689 return SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_EVENTS;
690#else
691 return SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_EVENTS;
692#endif
693}
694
695// ============================================================================
696// Surface Helpers
697// ============================================================================
698
702inline SDL_Surface* CreateRGBSurface(Uint32 flags, int width, int height,
703 int depth, Uint32 Rmask, Uint32 Gmask,
704 Uint32 Bmask, Uint32 Amask) {
705#ifdef YAZE_USE_SDL3
706 // SDL3 uses SDL_CreateSurface with pixel format
707 return SDL_CreateSurface(
708 width, height,
709 SDL_GetPixelFormatForMasks(depth, Rmask, Gmask, Bmask, Amask));
710#else
711 return SDL_CreateRGBSurface(flags, width, height, depth, Rmask, Gmask, Bmask,
712 Amask);
713#endif
714}
715
719inline void DestroySurface(SDL_Surface* surface) {
720#ifdef YAZE_USE_SDL3
721 SDL_DestroySurface(surface);
722#else
723 SDL_FreeSurface(surface);
724#endif
725}
726
727// ============================================================================
728// Renderer Helpers
729// ============================================================================
730
734inline int GetRendererOutputSize(SDL_Renderer* renderer, int* w, int* h) {
735#ifdef YAZE_USE_SDL3
736 return SDL_GetCurrentRenderOutputSize(renderer, w, h);
737#else
738 return SDL_GetRendererOutputSize(renderer, w, h);
739#endif
740}
741
748inline SDL_Surface* ReadPixelsToSurface(SDL_Renderer* renderer, int width,
749 int height, const SDL_Rect* rect) {
750#ifdef YAZE_USE_SDL3
751 return SDL_RenderReadPixels(renderer, rect);
752#else
753 // Create surface to read into (ARGB8888 to match typical screenshot needs)
754 SDL_Surface* surface = SDL_CreateRGBSurface(
755 0, width, height, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
756 if (!surface)
757 return nullptr;
758
759 if (SDL_RenderReadPixels(renderer, rect, SDL_PIXELFORMAT_ARGB8888,
760 surface->pixels, surface->pitch) != 0) {
761 SDL_FreeSurface(surface);
762 return nullptr;
763 }
764 return surface;
765#endif
766}
767
771inline SDL_Surface* LoadBMP(const char* file) {
772#ifdef YAZE_USE_SDL3
773 return SDL_LoadBMP(file);
774#else
775 return SDL_LoadBMP(file);
776#endif
777}
778
779} // namespace platform
780} // namespace yaze
781
782#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:719
int GetWindowEventWidth(const SDL_Event &event)
Get window width from resize event data.
Definition sdl_compat.h:651
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:377
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:734
Uint32 GetSurfaceFormat(SDL_Surface *surface)
Get the pixel format of a surface as Uint32.
Definition sdl_compat.h:408
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:639
int GetSurfaceBitsPerPixel(SDL_Surface *surface)
Get bits per pixel from a surface.
Definition sdl_compat.h:455
int GetSurfaceBytesPerPixel(SDL_Surface *surface)
Get bytes per pixel from a surface.
Definition sdl_compat.h:530
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:627
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:702
bool InitSucceeded(int result)
Check if SDL initialization succeeded.
Definition sdl_compat.h:672
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:601
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:771
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:613
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:421
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:439
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:748
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:304
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:392
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:476
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:322
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:687
int GetWindowEventHeight(const SDL_Event &event)
Get window height from resize event data.
Definition sdl_compat.h:658
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:361