summaryrefslogtreecommitdiff
path: root/contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsvideo.c
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2025-12-27 12:03:39 -0800
committer3gg <3gg@shellblade.net>2025-12-27 12:03:39 -0800
commit5a079a2d114f96d4847d1ee305d5b7c16eeec50e (patch)
tree8926ab44f168acf787d8e19608857b3af0f82758 /contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsvideo.c
Initial commit
Diffstat (limited to 'contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsvideo.c')
-rw-r--r--contrib/SDL-3.2.8/src/video/n3ds/SDL_n3dsvideo.c259
1 files changed, 259 insertions, 0 deletions
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 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifdef SDL_VIDEO_DRIVER_N3DS
24
25#include "../SDL_sysvideo.h"
26#include "SDL_n3dsevents_c.h"
27#include "SDL_n3dsframebuffer_c.h"
28#include "SDL_n3dsswkb.h"
29#include "SDL_n3dstouch.h"
30#include "SDL_n3dsvideo.h"
31
32#define N3DSVID_DRIVER_NAME "n3ds"
33
34static bool AddN3DSDisplay(gfxScreen_t screen);
35
36static bool N3DS_VideoInit(SDL_VideoDevice *_this);
37static void N3DS_VideoQuit(SDL_VideoDevice *_this);
38static bool N3DS_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display);
39static bool N3DS_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode);
40static bool N3DS_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect);
41static bool N3DS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props);
42static void N3DS_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
43
44struct SDL_DisplayData
45{
46 gfxScreen_t screen;
47};
48
49struct SDL_DisplayModeData
50{
51 GSPGPU_FramebufferFormat fmt;
52};
53
54static const struct
55{
56 SDL_PixelFormat pixfmt;
57 GSPGPU_FramebufferFormat gspfmt;
58} format_map[] = {
59 { SDL_PIXELFORMAT_RGBA8888, GSP_RGBA8_OES },
60 { SDL_PIXELFORMAT_BGR24, GSP_BGR8_OES },
61 { SDL_PIXELFORMAT_RGB565, GSP_RGB565_OES },
62 { SDL_PIXELFORMAT_RGBA5551, GSP_RGB5_A1_OES },
63 { SDL_PIXELFORMAT_RGBA4444, GSP_RGBA4_OES }
64};
65
66// N3DS driver bootstrap functions
67
68static void N3DS_DeleteDevice(SDL_VideoDevice *device)
69{
70 SDL_free(device->internal);
71 SDL_free(device);
72}
73
74static SDL_VideoDevice *N3DS_CreateDevice(void)
75{
76 SDL_VideoDevice *device;
77 SDL_VideoData *phdata;
78
79 // Initialize all variables that we clean on shutdown
80 device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice));
81 if (!device) {
82 return NULL;
83 }
84
85 // Initialize internal data
86 phdata = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData));
87 if (!phdata) {
88 SDL_free(device);
89 return NULL;
90 }
91
92 device->internal = phdata;
93
94 device->VideoInit = N3DS_VideoInit;
95 device->VideoQuit = N3DS_VideoQuit;
96
97 device->GetDisplayModes = N3DS_GetDisplayModes;
98 device->SetDisplayMode = N3DS_SetDisplayMode;
99 device->GetDisplayBounds = N3DS_GetDisplayBounds;
100
101 device->CreateSDLWindow = N3DS_CreateWindow;
102 device->DestroyWindow = N3DS_DestroyWindow;
103
104 device->HasScreenKeyboardSupport = N3DS_HasScreenKeyboardSupport;
105 device->StartTextInput = N3DS_StartTextInput;
106 device->StopTextInput = N3DS_StopTextInput;
107
108 device->PumpEvents = N3DS_PumpEvents;
109
110 device->CreateWindowFramebuffer = SDL_N3DS_CreateWindowFramebuffer;
111 device->UpdateWindowFramebuffer = SDL_N3DS_UpdateWindowFramebuffer;
112 device->DestroyWindowFramebuffer = SDL_N3DS_DestroyWindowFramebuffer;
113
114 device->free = N3DS_DeleteDevice;
115
116 device->device_caps = VIDEO_DEVICE_CAPS_FULLSCREEN_ONLY;
117
118 return device;
119}
120
121VideoBootStrap N3DS_bootstrap = { N3DSVID_DRIVER_NAME, "N3DS Video Driver", N3DS_CreateDevice, NULL, /* no ShowMessageBox implementation */ false };
122
123static bool N3DS_VideoInit(SDL_VideoDevice *_this)
124{
125 SDL_VideoData *internal = (SDL_VideoData *)_this->internal;
126
127 gfxInit(GSP_RGBA8_OES, GSP_RGBA8_OES, false);
128 hidInit();
129
130 internal->top_display = AddN3DSDisplay(GFX_TOP);
131 internal->touch_display = AddN3DSDisplay(GFX_BOTTOM);
132
133 N3DS_InitTouch();
134 N3DS_SwkbInit();
135
136 return true;
137}
138
139static bool AddN3DSDisplay(gfxScreen_t screen)
140{
141 SDL_DisplayMode mode;
142 SDL_DisplayModeData *modedata;
143 SDL_VideoDisplay display;
144 SDL_DisplayData *display_driver_data = SDL_calloc(1, sizeof(SDL_DisplayData));
145 if (!display_driver_data) {
146 return false;
147 }
148
149 SDL_zero(mode);
150 SDL_zero(display);
151
152 display_driver_data->screen = screen;
153
154 modedata = SDL_malloc(sizeof(SDL_DisplayModeData));
155 if (!modedata) {
156 return false;
157 }
158
159 mode.w = (screen == GFX_TOP) ? GSP_SCREEN_HEIGHT_TOP : GSP_SCREEN_HEIGHT_BOTTOM;
160 mode.h = GSP_SCREEN_WIDTH;
161 mode.refresh_rate = 60.0f;
162 mode.format = SDL_PIXELFORMAT_RGBA8888;
163 mode.internal = modedata;
164 modedata->fmt = GSP_RGBA8_OES;
165
166 display.name = (screen == GFX_TOP) ? "N3DS top screen" : "N3DS bottom screen";
167 display.desktop_mode = mode;
168 display.internal = display_driver_data;
169
170 if (SDL_AddVideoDisplay(&display, false) == 0) {
171 return false;
172 }
173 return true;
174}
175
176static void N3DS_VideoQuit(SDL_VideoDevice *_this)
177{
178 N3DS_SwkbQuit();
179 N3DS_QuitTouch();
180
181 hidExit();
182 gfxExit();
183}
184
185static bool N3DS_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display)
186{
187 SDL_DisplayData *displaydata = display->internal;
188 SDL_DisplayModeData *modedata;
189 SDL_DisplayMode mode;
190 int i;
191
192 for (i = 0; i < SDL_arraysize(format_map); i++) {
193 modedata = SDL_malloc(sizeof(SDL_DisplayModeData));
194 if (!modedata)
195 continue;
196
197 SDL_zero(mode);
198 mode.w = (displaydata->screen == GFX_TOP) ? GSP_SCREEN_HEIGHT_TOP : GSP_SCREEN_HEIGHT_BOTTOM;
199 mode.h = GSP_SCREEN_WIDTH;
200 mode.refresh_rate = 60.0f;
201 mode.format = format_map[i].pixfmt;
202 mode.internal = modedata;
203 modedata->fmt = format_map[i].gspfmt;
204
205 if (!SDL_AddFullscreenDisplayMode(display, &mode)) {
206 SDL_free(modedata);
207 }
208 }
209
210 return true;
211}
212
213static bool N3DS_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
214{
215 SDL_DisplayData *displaydata = display->internal;
216 SDL_DisplayModeData *modedata = mode->internal;
217
218 gfxSetScreenFormat(displaydata->screen, modedata->fmt);
219 return true;
220}
221
222static bool N3DS_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect)
223{
224 SDL_DisplayData *driver_data = display->internal;
225
226 if (!driver_data) {
227 return false;
228 }
229
230 rect->x = 0;
231 rect->y = (driver_data->screen == GFX_TOP) ? 0 : GSP_SCREEN_WIDTH;
232 rect->w = display->current_mode->w;
233 rect->h = display->current_mode->h;
234 return true;
235}
236
237static bool N3DS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props)
238{
239 SDL_DisplayData *display_data;
240 SDL_WindowData *window_data = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData));
241 if (!window_data) {
242 return false;
243 }
244 display_data = SDL_GetDisplayDriverDataForWindow(window);
245 window_data->screen = display_data->screen;
246 window->internal = window_data;
247 SDL_SetKeyboardFocus(window);
248 return true;
249}
250
251static void N3DS_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
252{
253 if (!window) {
254 return;
255 }
256 SDL_free(window->internal);
257}
258
259#endif // SDL_VIDEO_DRIVER_N3DS