From 5a079a2d114f96d4847d1ee305d5b7c16eeec50e Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sat, 27 Dec 2025 12:03:39 -0800 Subject: Initial commit --- contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsevents.c | 45 ++++ .../SDL-3.2.8/src/video/n3ds/SDL_n3dsevents_c.h | 29 +++ .../SDL-3.2.8/src/video/n3ds/SDL_n3dsframebuffer.c | 161 +++++++++++++ .../src/video/n3ds/SDL_n3dsframebuffer_c.h | 31 +++ contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsswkb.c | 69 ++++++ contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsswkb.h | 36 +++ contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dstouch.c | 86 +++++++ contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dstouch.h | 29 +++ contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsvideo.c | 259 +++++++++++++++++++++ contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsvideo.h | 41 ++++ 10 files changed, 786 insertions(+) create mode 100644 contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsevents.c create mode 100644 contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsevents_c.h create mode 100644 contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsframebuffer.c create mode 100644 contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsframebuffer_c.h create mode 100644 contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsswkb.c create mode 100644 contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsswkb.h create mode 100644 contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dstouch.c create mode 100644 contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dstouch.h create mode 100644 contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsvideo.c create mode 100644 contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsvideo.h (limited to 'contrib/SDL-3.2.8/src/video/n3ds') diff --git a/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsevents.c b/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsevents.c new file mode 100644 index 0000000..3d5e0e3 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsevents.c @@ -0,0 +1,45 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_DRIVER_N3DS + +#include <3ds.h> + +#include "../../events/SDL_events_c.h" +#include "SDL_n3dsevents_c.h" +#include "SDL_n3dstouch.h" + +void N3DS_PumpEvents(SDL_VideoDevice *_this) +{ + hidScanInput(); + N3DS_PollTouch(_this); + + if (!aptMainLoop()) { + SDL_Event ev; + ev.type = SDL_EVENT_QUIT; + ev.common.timestamp = 0; + SDL_PushEvent(&ev); + return; + } +} + +#endif // SDL_VIDEO_DRIVER_N3DS diff --git a/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsevents_c.h b/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsevents_c.h new file mode 100644 index 0000000..898fbb2 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsevents_c.h @@ -0,0 +1,29 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_n3dsevents_c_h_ +#define SDL_n3dsevents_c_h_ + +#include "SDL_internal.h" + +extern void N3DS_PumpEvents(SDL_VideoDevice *_this); + +#endif // SDL_n3dsevents_c_h_ diff --git a/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsframebuffer.c b/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsframebuffer.c new file mode 100644 index 0000000..d632545 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsframebuffer.c @@ -0,0 +1,161 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_DRIVER_N3DS + +#include "../SDL_sysvideo.h" +#include "../../SDL_properties_c.h" +#include "SDL_n3dsframebuffer_c.h" +#include "SDL_n3dsvideo.h" + +#define N3DS_SURFACE "SDL.internal.window.surface" + +typedef struct +{ + int width, height; +} Dimensions; + +static void CopyFramebuffertoN3DS_16(u16 *dest, const Dimensions dest_dim, const u16 *source, const Dimensions source_dim); +static void CopyFramebuffertoN3DS_24(u8 *dest, const Dimensions dest_dim, const u8 *source, const Dimensions source_dim); +static void CopyFramebuffertoN3DS_32(u32 *dest, const Dimensions dest_dim, const u32 *source, const Dimensions source_dim); +static int GetDestOffset(int x, int y, int dest_width); +static int GetSourceOffset(int x, int y, int source_width); +static void FlushN3DSBuffer(const void *buffer, u32 bufsize, gfxScreen_t screen); + + +bool SDL_N3DS_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, SDL_PixelFormat *format, void **pixels, int *pitch) +{ + SDL_Surface *framebuffer; + const SDL_DisplayMode *mode; + int w, h; + + SDL_N3DS_DestroyWindowFramebuffer(_this, window); + + mode = SDL_GetCurrentDisplayMode(SDL_GetDisplayForWindow(window)); + SDL_GetWindowSizeInPixels(window, &w, &h); + framebuffer = SDL_CreateSurface(w, h, mode->format); + + if (!framebuffer) { + return false; + } + + SDL_SetSurfaceProperty(SDL_GetWindowProperties(window), N3DS_SURFACE, framebuffer); + *format = mode->format; + *pixels = framebuffer->pixels; + *pitch = framebuffer->pitch; + return true; +} + +bool SDL_N3DS_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rects, int numrects) +{ + SDL_WindowData *drv_data = window->internal; + SDL_Surface *surface; + u16 width, height; + void *framebuffer; + u32 bufsize; + + surface = (SDL_Surface *)SDL_GetPointerProperty(SDL_GetWindowProperties(window), N3DS_SURFACE, NULL); + if (!surface) { + return SDL_SetError("%s: Unable to get the window surface.", __func__); + } + + // Get the N3DS internal framebuffer and its size + framebuffer = gfxGetFramebuffer(drv_data->screen, GFX_LEFT, &width, &height); + bufsize = width * height * 4; + + if (SDL_BYTESPERPIXEL(surface->format) == 2) + CopyFramebuffertoN3DS_16(framebuffer, (Dimensions){ width, height }, + surface->pixels, (Dimensions){ surface->w, surface->h }); + else if (SDL_BYTESPERPIXEL(surface->format) == 3) + CopyFramebuffertoN3DS_24(framebuffer, (Dimensions){ width, height }, + surface->pixels, (Dimensions){ surface->w, surface->h }); + else + CopyFramebuffertoN3DS_32(framebuffer, (Dimensions){ width, height }, + surface->pixels, (Dimensions){ surface->w, surface->h }); + FlushN3DSBuffer(framebuffer, bufsize, drv_data->screen); + + return true; +} + +static void CopyFramebuffertoN3DS_16(u16 *dest, const Dimensions dest_dim, const u16 *source, const Dimensions source_dim) +{ + int rows = SDL_min(dest_dim.width, source_dim.height); + int cols = SDL_min(dest_dim.height, source_dim.width); + for (int y = 0; y < rows; ++y) { + for (int x = 0; x < cols; ++x) { + const u16 *s = source + GetSourceOffset(x, y, source_dim.width); + u16 *d = dest + GetDestOffset(x, y, dest_dim.width); + *d = *s; + } + } +} + +static void CopyFramebuffertoN3DS_24(u8 *dest, const Dimensions dest_dim, const u8 *source, const Dimensions source_dim) +{ + int rows = SDL_min(dest_dim.width, source_dim.height); + int cols = SDL_min(dest_dim.height, source_dim.width); + for (int y = 0; y < rows; ++y) { + for (int x = 0; x < cols; ++x) { + const u8 *s = source + GetSourceOffset(x, y, source_dim.width) * 3; + u8 *d = dest + GetDestOffset(x, y, dest_dim.width) * 3; + d[0] = s[0]; + d[1] = s[1]; + d[2] = s[2]; + } + } +} + +static void CopyFramebuffertoN3DS_32(u32 *dest, const Dimensions dest_dim, const u32 *source, const Dimensions source_dim) +{ + int rows = SDL_min(dest_dim.width, source_dim.height); + int cols = SDL_min(dest_dim.height, source_dim.width); + for (int y = 0; y < rows; ++y) { + for (int x = 0; x < cols; ++x) { + const u32 *s = source + GetSourceOffset(x, y, source_dim.width); + u32 *d = dest + GetDestOffset(x, y, dest_dim.width); + *d = *s; + } + } +} + +static int GetDestOffset(int x, int y, int dest_width) +{ + return dest_width - y - 1 + dest_width * x; +} + +static int GetSourceOffset(int x, int y, int source_width) +{ + return x + y * source_width; +} + +static void FlushN3DSBuffer(const void *buffer, u32 bufsize, gfxScreen_t screen) +{ + GSPGPU_FlushDataCache(buffer, bufsize); + gfxScreenSwapBuffers(screen, false); +} + +void SDL_N3DS_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window) +{ + SDL_ClearProperty(SDL_GetWindowProperties(window), N3DS_SURFACE); +} + +#endif // SDL_VIDEO_DRIVER_N3DS diff --git a/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsframebuffer_c.h b/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsframebuffer_c.h new file mode 100644 index 0000000..d442add --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsframebuffer_c.h @@ -0,0 +1,31 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_n3dsframebuffer_c_h_ +#define SDL_n3dsframebuffer_c_h_ + +#include "SDL_internal.h" + +extern bool SDL_N3DS_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, SDL_PixelFormat *format, void **pixels, int *pitch); +extern bool SDL_N3DS_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rects, int numrects); +extern void SDL_N3DS_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window); + +#endif // SDL_n3dsframebuffer_c_h_ diff --git a/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsswkb.c b/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsswkb.c new file mode 100644 index 0000000..95f0466 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsswkb.c @@ -0,0 +1,69 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_DRIVER_N3DS + +#include <3ds.h> + +#include "SDL_n3dsswkb.h" + +static SwkbdState sw_keyboard; +const static size_t BUFFER_SIZE = 256; + +void N3DS_SwkbInit(void) +{ + swkbdInit(&sw_keyboard, SWKBD_TYPE_NORMAL, 2, -1); +} + +void N3DS_SwkbPoll(void) +{ + return; +} + +void N3DS_SwkbQuit(void) +{ + return; +} + +bool N3DS_HasScreenKeyboardSupport(SDL_VideoDevice *_this) +{ + return true; +} + +bool N3DS_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props) +{ + char buffer[BUFFER_SIZE]; + SwkbdButton button_pressed; + button_pressed = swkbdInputText(&sw_keyboard, buffer, BUFFER_SIZE); + if (button_pressed == SWKBD_BUTTON_CONFIRM) { + SDL_SendKeyboardText(buffer); + } + return true; +} + +bool N3DS_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window) +{ + return true; +} + +#endif // SDL_VIDEO_DRIVER_N3DS diff --git a/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsswkb.h b/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsswkb.h new file mode 100644 index 0000000..8857c00 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsswkb.h @@ -0,0 +1,36 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_n3dskeyboard_h_ +#define SDL_n3dskeyboard_h_ + +#include "../../events/SDL_events_c.h" + +void N3DS_SwkbInit(); +void N3DS_SwkbPoll(); +void N3DS_SwkbQuit(); + +bool N3DS_HasScreenKeyboardSupport(SDL_VideoDevice *_this); + +bool N3DS_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props); +bool N3DS_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window); + +#endif // SDL_n3dskeyboard_h_ diff --git a/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dstouch.c b/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dstouch.c new file mode 100644 index 0000000..8116e4a --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dstouch.c @@ -0,0 +1,86 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_DRIVER_N3DS + +#include <3ds.h> + +#include "../../events/SDL_touch_c.h" +#include "../SDL_sysvideo.h" +#include "SDL_n3dstouch.h" +#include "SDL_n3dsvideo.h" + +#define N3DS_TOUCH_ID 1 +#define N3DS_TOUCH_FINGER 1 + +/* + Factors used to convert touchscreen coordinates to + SDL's 0-1 values. Note that the N3DS's screen is + internally in a portrait disposition so the + GSP_SCREEN constants are flipped. +*/ +#define TOUCHSCREEN_SCALE_X 1.0f / (GSP_SCREEN_HEIGHT_BOTTOM - 1) +#define TOUCHSCREEN_SCALE_Y 1.0f / (GSP_SCREEN_WIDTH - 1) + +void N3DS_InitTouch(void) +{ + SDL_AddTouch(N3DS_TOUCH_ID, SDL_TOUCH_DEVICE_DIRECT, "Touchscreen"); +} + +void N3DS_QuitTouch(void) +{ + SDL_DelTouch(N3DS_TOUCH_ID); +} + +void N3DS_PollTouch(SDL_VideoDevice *_this) +{ + SDL_VideoData *internal = (SDL_VideoData *)_this->internal; + touchPosition touch; + SDL_Window *window; + SDL_VideoDisplay *display; + static bool was_pressed = false; + bool pressed; + hidTouchRead(&touch); + pressed = (touch.px != 0 || touch.py != 0); + + display = SDL_GetVideoDisplay(internal->touch_display); + window = display ? display->fullscreen_window : NULL; + + if (pressed != was_pressed) { + was_pressed = pressed; + SDL_SendTouch(0, N3DS_TOUCH_ID, N3DS_TOUCH_FINGER, + window, + pressed ? SDL_EVENT_FINGER_DOWN : SDL_EVENT_FINGER_UP, + touch.px * TOUCHSCREEN_SCALE_X, + touch.py * TOUCHSCREEN_SCALE_Y, + pressed ? 1.0f : 0.0f); + } else if (pressed) { + SDL_SendTouchMotion(0, N3DS_TOUCH_ID, N3DS_TOUCH_FINGER, + window, + touch.px * TOUCHSCREEN_SCALE_X, + touch.py * TOUCHSCREEN_SCALE_Y, + 1.0f); + } +} + +#endif // SDL_VIDEO_DRIVER_N3DS diff --git a/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dstouch.h b/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dstouch.h new file mode 100644 index 0000000..7dac5a8 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dstouch.h @@ -0,0 +1,29 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_n3dstouch_h_ +#define SDL_n3dstouch_h_ + +void N3DS_InitTouch(void); +void N3DS_QuitTouch(void); +void N3DS_PollTouch(SDL_VideoDevice *_this); + +#endif // SDL_n3dstouch_h_ diff --git a/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsvideo.c b/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsvideo.c new file mode 100644 index 0000000..8e925bf --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsvideo.c @@ -0,0 +1,259 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_DRIVER_N3DS + +#include "../SDL_sysvideo.h" +#include "SDL_n3dsevents_c.h" +#include "SDL_n3dsframebuffer_c.h" +#include "SDL_n3dsswkb.h" +#include "SDL_n3dstouch.h" +#include "SDL_n3dsvideo.h" + +#define N3DSVID_DRIVER_NAME "n3ds" + +static bool AddN3DSDisplay(gfxScreen_t screen); + +static bool N3DS_VideoInit(SDL_VideoDevice *_this); +static void N3DS_VideoQuit(SDL_VideoDevice *_this); +static bool N3DS_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display); +static bool N3DS_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode); +static bool N3DS_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect); +static bool N3DS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); +static void N3DS_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); + +struct SDL_DisplayData +{ + gfxScreen_t screen; +}; + +struct SDL_DisplayModeData +{ + GSPGPU_FramebufferFormat fmt; +}; + +static const struct +{ + SDL_PixelFormat pixfmt; + GSPGPU_FramebufferFormat gspfmt; +} format_map[] = { + { SDL_PIXELFORMAT_RGBA8888, GSP_RGBA8_OES }, + { SDL_PIXELFORMAT_BGR24, GSP_BGR8_OES }, + { SDL_PIXELFORMAT_RGB565, GSP_RGB565_OES }, + { SDL_PIXELFORMAT_RGBA5551, GSP_RGB5_A1_OES }, + { SDL_PIXELFORMAT_RGBA4444, GSP_RGBA4_OES } +}; + +// N3DS driver bootstrap functions + +static void N3DS_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->internal); + SDL_free(device); +} + +static SDL_VideoDevice *N3DS_CreateDevice(void) +{ + SDL_VideoDevice *device; + SDL_VideoData *phdata; + + // Initialize all variables that we clean on shutdown + device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); + if (!device) { + return NULL; + } + + // Initialize internal data + phdata = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); + if (!phdata) { + SDL_free(device); + return NULL; + } + + device->internal = phdata; + + device->VideoInit = N3DS_VideoInit; + device->VideoQuit = N3DS_VideoQuit; + + device->GetDisplayModes = N3DS_GetDisplayModes; + device->SetDisplayMode = N3DS_SetDisplayMode; + device->GetDisplayBounds = N3DS_GetDisplayBounds; + + device->CreateSDLWindow = N3DS_CreateWindow; + device->DestroyWindow = N3DS_DestroyWindow; + + device->HasScreenKeyboardSupport = N3DS_HasScreenKeyboardSupport; + device->StartTextInput = N3DS_StartTextInput; + device->StopTextInput = N3DS_StopTextInput; + + device->PumpEvents = N3DS_PumpEvents; + + device->CreateWindowFramebuffer = SDL_N3DS_CreateWindowFramebuffer; + device->UpdateWindowFramebuffer = SDL_N3DS_UpdateWindowFramebuffer; + device->DestroyWindowFramebuffer = SDL_N3DS_DestroyWindowFramebuffer; + + device->free = N3DS_DeleteDevice; + + device->device_caps = VIDEO_DEVICE_CAPS_FULLSCREEN_ONLY; + + return device; +} + +VideoBootStrap N3DS_bootstrap = { N3DSVID_DRIVER_NAME, "N3DS Video Driver", N3DS_CreateDevice, NULL, /* no ShowMessageBox implementation */ false }; + +static bool N3DS_VideoInit(SDL_VideoDevice *_this) +{ + SDL_VideoData *internal = (SDL_VideoData *)_this->internal; + + gfxInit(GSP_RGBA8_OES, GSP_RGBA8_OES, false); + hidInit(); + + internal->top_display = AddN3DSDisplay(GFX_TOP); + internal->touch_display = AddN3DSDisplay(GFX_BOTTOM); + + N3DS_InitTouch(); + N3DS_SwkbInit(); + + return true; +} + +static bool AddN3DSDisplay(gfxScreen_t screen) +{ + SDL_DisplayMode mode; + SDL_DisplayModeData *modedata; + SDL_VideoDisplay display; + SDL_DisplayData *display_driver_data = SDL_calloc(1, sizeof(SDL_DisplayData)); + if (!display_driver_data) { + return false; + } + + SDL_zero(mode); + SDL_zero(display); + + display_driver_data->screen = screen; + + modedata = SDL_malloc(sizeof(SDL_DisplayModeData)); + if (!modedata) { + return false; + } + + mode.w = (screen == GFX_TOP) ? GSP_SCREEN_HEIGHT_TOP : GSP_SCREEN_HEIGHT_BOTTOM; + mode.h = GSP_SCREEN_WIDTH; + mode.refresh_rate = 60.0f; + mode.format = SDL_PIXELFORMAT_RGBA8888; + mode.internal = modedata; + modedata->fmt = GSP_RGBA8_OES; + + display.name = (screen == GFX_TOP) ? "N3DS top screen" : "N3DS bottom screen"; + display.desktop_mode = mode; + display.internal = display_driver_data; + + if (SDL_AddVideoDisplay(&display, false) == 0) { + return false; + } + return true; +} + +static void N3DS_VideoQuit(SDL_VideoDevice *_this) +{ + N3DS_SwkbQuit(); + N3DS_QuitTouch(); + + hidExit(); + gfxExit(); +} + +static bool N3DS_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display) +{ + SDL_DisplayData *displaydata = display->internal; + SDL_DisplayModeData *modedata; + SDL_DisplayMode mode; + int i; + + for (i = 0; i < SDL_arraysize(format_map); i++) { + modedata = SDL_malloc(sizeof(SDL_DisplayModeData)); + if (!modedata) + continue; + + SDL_zero(mode); + mode.w = (displaydata->screen == GFX_TOP) ? GSP_SCREEN_HEIGHT_TOP : GSP_SCREEN_HEIGHT_BOTTOM; + mode.h = GSP_SCREEN_WIDTH; + mode.refresh_rate = 60.0f; + mode.format = format_map[i].pixfmt; + mode.internal = modedata; + modedata->fmt = format_map[i].gspfmt; + + if (!SDL_AddFullscreenDisplayMode(display, &mode)) { + SDL_free(modedata); + } + } + + return true; +} + +static bool N3DS_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode) +{ + SDL_DisplayData *displaydata = display->internal; + SDL_DisplayModeData *modedata = mode->internal; + + gfxSetScreenFormat(displaydata->screen, modedata->fmt); + return true; +} + +static bool N3DS_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect) +{ + SDL_DisplayData *driver_data = display->internal; + + if (!driver_data) { + return false; + } + + rect->x = 0; + rect->y = (driver_data->screen == GFX_TOP) ? 0 : GSP_SCREEN_WIDTH; + rect->w = display->current_mode->w; + rect->h = display->current_mode->h; + return true; +} + +static bool N3DS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) +{ + SDL_DisplayData *display_data; + SDL_WindowData *window_data = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); + if (!window_data) { + return false; + } + display_data = SDL_GetDisplayDriverDataForWindow(window); + window_data->screen = display_data->screen; + window->internal = window_data; + SDL_SetKeyboardFocus(window); + return true; +} + +static void N3DS_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) +{ + if (!window) { + return; + } + SDL_free(window->internal); +} + +#endif // SDL_VIDEO_DRIVER_N3DS diff --git a/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsvideo.h b/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsvideo.h new file mode 100644 index 0000000..14b70e9 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsvideo.h @@ -0,0 +1,41 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifndef SDL_n3dsvideo_h_ +#define SDL_n3dsvideo_h_ + +#include <3ds.h> + +#include "../SDL_sysvideo.h" + +struct SDL_VideoData +{ + int top_display; + int touch_display; +}; + +struct SDL_WindowData +{ + gfxScreen_t screen; /**< Keeps track of which N3DS screen is targeted */ +}; + +#endif // SDL_n3dsvideo_h_ -- cgit v1.2.3