summaryrefslogtreecommitdiff
path: root/contrib/SDL-3.2.8/src/video/riscos/SDL_riscosmodes.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/SDL-3.2.8/src/video/riscos/SDL_riscosmodes.c')
-rw-r--r--contrib/SDL-3.2.8/src/video/riscos/SDL_riscosmodes.c310
1 files changed, 310 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/video/riscos/SDL_riscosmodes.c b/contrib/SDL-3.2.8/src/video/riscos/SDL_riscosmodes.c
new file mode 100644
index 0000000..d4e9a53
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/video/riscos/SDL_riscosmodes.c
@@ -0,0 +1,310 @@
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_RISCOS
24
25#include "../SDL_sysvideo.h"
26#include "../../events/SDL_mouse_c.h"
27
28#include "SDL_riscosvideo.h"
29#include "SDL_riscosmodes.h"
30
31#include <kernel.h>
32#include <swis.h>
33
34enum
35{
36 MODE_FLAG_565 = 1 << 7,
37
38 MODE_FLAG_COLOUR_SPACE = 0xF << 12,
39
40 MODE_FLAG_TBGR = 0,
41 MODE_FLAG_TRGB = 1 << 14,
42 MODE_FLAG_ABGR = 1 << 15,
43 MODE_FLAG_ARGB = MODE_FLAG_TRGB | MODE_FLAG_ABGR
44};
45
46static const struct
47{
48 SDL_PixelFormat pixel_format;
49 int modeflags, ncolour, log2bpp;
50} mode_to_pixelformat[] = {
51 // { SDL_PIXELFORMAT_INDEX1LSB, 0, 1, 0 },
52 // { SDL_PIXELFORMAT_INDEX2LSB, 0, 3, 1 },
53 // { SDL_PIXELFORMAT_INDEX4LSB, 0, 15, 2 },
54 // { SDL_PIXELFORMAT_INDEX8, MODE_FLAG_565, 255, 3 },
55 { SDL_PIXELFORMAT_XBGR1555, MODE_FLAG_TBGR, 65535, 4 },
56 { SDL_PIXELFORMAT_XRGB1555, MODE_FLAG_TRGB, 65535, 4 },
57 { SDL_PIXELFORMAT_ABGR1555, MODE_FLAG_ABGR, 65535, 4 },
58 { SDL_PIXELFORMAT_ARGB1555, MODE_FLAG_ARGB, 65535, 4 },
59 { SDL_PIXELFORMAT_XBGR4444, MODE_FLAG_TBGR, 4095, 4 },
60 { SDL_PIXELFORMAT_XRGB4444, MODE_FLAG_TRGB, 4095, 4 },
61 { SDL_PIXELFORMAT_ABGR4444, MODE_FLAG_ABGR, 4095, 4 },
62 { SDL_PIXELFORMAT_ARGB4444, MODE_FLAG_ARGB, 4095, 4 },
63 { SDL_PIXELFORMAT_BGR565, MODE_FLAG_TBGR | MODE_FLAG_565, 65535, 4 },
64 { SDL_PIXELFORMAT_RGB565, MODE_FLAG_TRGB | MODE_FLAG_565, 65535, 4 },
65 { SDL_PIXELFORMAT_BGR24, MODE_FLAG_TBGR, 16777215, 6 },
66 { SDL_PIXELFORMAT_RGB24, MODE_FLAG_TRGB, 16777215, 6 },
67 { SDL_PIXELFORMAT_XBGR8888, MODE_FLAG_TBGR, -1, 5 },
68 { SDL_PIXELFORMAT_XRGB8888, MODE_FLAG_TRGB, -1, 5 },
69 { SDL_PIXELFORMAT_ABGR8888, MODE_FLAG_ABGR, -1, 5 },
70 { SDL_PIXELFORMAT_ARGB8888, MODE_FLAG_ARGB, -1, 5 }
71};
72
73static SDL_PixelFormat RISCOS_ModeToPixelFormat(int ncolour, int modeflags, int log2bpp)
74{
75 int i;
76
77 for (i = 0; i < SDL_arraysize(mode_to_pixelformat); i++) {
78 if (log2bpp == mode_to_pixelformat[i].log2bpp &&
79 (ncolour == mode_to_pixelformat[i].ncolour || ncolour == 0) &&
80 (modeflags & (MODE_FLAG_565 | MODE_FLAG_COLOUR_SPACE)) == mode_to_pixelformat[i].modeflags) {
81 return mode_to_pixelformat[i].pixel_format;
82 }
83 }
84
85 return SDL_PIXELFORMAT_UNKNOWN;
86}
87
88static size_t measure_mode_block(const int *block)
89{
90 size_t blockSize = ((block[0] & 0xFF) == 3) ? 7 : 5;
91 while (block[blockSize] != -1) {
92 blockSize += 2;
93 }
94 blockSize++;
95
96 return blockSize * 4;
97}
98
99static bool read_mode_variable(int *block, int var)
100{
101 _kernel_swi_regs regs;
102 regs.r[0] = (int)block;
103 regs.r[1] = var;
104 _kernel_swi(OS_ReadModeVariable, &regs, &regs);
105 return regs.r[2];
106}
107
108static bool read_mode_block(int *block, SDL_DisplayMode *mode, bool extended)
109{
110 int xres, yres, ncolour, modeflags, log2bpp, rate;
111
112 if ((block[0] & 0xFF) == 1) {
113 xres = block[1];
114 yres = block[2];
115 log2bpp = block[3];
116 rate = block[4];
117 ncolour = (1 << (1 << log2bpp)) - 1;
118 modeflags = MODE_FLAG_TBGR;
119 } else if ((block[0] & 0xFF) == 3) {
120 xres = block[1];
121 yres = block[2];
122 ncolour = block[3];
123 modeflags = block[4];
124 log2bpp = block[5];
125 rate = block[6];
126 } else {
127 return false;
128 }
129
130 if (extended) {
131 xres = read_mode_variable(block, 11) + 1;
132 yres = read_mode_variable(block, 12) + 1;
133 log2bpp = read_mode_variable(block, 9);
134 ncolour = read_mode_variable(block, 3);
135 modeflags = read_mode_variable(block, 0);
136 }
137
138 SDL_zerop(mode);
139 mode->w = xres;
140 mode->h = yres;
141 mode->format = RISCOS_ModeToPixelFormat(ncolour, modeflags, log2bpp);
142 mode->refresh_rate = (float)rate;
143
144 return true;
145}
146
147static void *convert_mode_block(const int *block)
148{
149 int xres, yres, log2bpp, rate, ncolour = 0, modeflags = 0;
150 size_t pos = 0;
151 int *dst;
152
153 if ((block[0] & 0xFF) == 1) {
154 xres = block[1];
155 yres = block[2];
156 log2bpp = block[3];
157 rate = block[4];
158 } else if ((block[0] & 0xFF) == 3) {
159 xres = block[1];
160 yres = block[2];
161 ncolour = block[3];
162 modeflags = block[4];
163 log2bpp = block[5];
164 rate = block[6];
165 } else {
166 return NULL;
167 }
168
169 dst = SDL_malloc(40);
170 if (!dst) {
171 return NULL;
172 }
173
174 dst[pos++] = 1;
175 dst[pos++] = xres;
176 dst[pos++] = yres;
177 dst[pos++] = log2bpp;
178 dst[pos++] = rate;
179 if (ncolour != 0) {
180 dst[pos++] = 3;
181 dst[pos++] = ncolour;
182 }
183 if (modeflags != 0) {
184 dst[pos++] = 0;
185 dst[pos++] = modeflags;
186 }
187 dst[pos++] = -1;
188
189 return dst;
190}
191
192static void *copy_memory(const void *src, size_t size, size_t alloc)
193{
194 void *dst = SDL_malloc(alloc);
195 if (dst) {
196 SDL_memcpy(dst, src, size);
197 }
198 return dst;
199}
200
201bool RISCOS_InitModes(SDL_VideoDevice *_this)
202{
203 SDL_DisplayMode mode;
204 int *current_mode;
205 _kernel_swi_regs regs;
206 _kernel_oserror *error;
207 size_t size;
208
209 regs.r[0] = 1;
210 error = _kernel_swi(OS_ScreenMode, &regs, &regs);
211 if (error) {
212 return SDL_SetError("Unable to retrieve the current screen mode: %s (%i)", error->errmess, error->errnum);
213 }
214
215 current_mode = (int *)regs.r[1];
216 if (!read_mode_block(current_mode, &mode, true)) {
217 return SDL_SetError("Unsupported mode block format %d", current_mode[0]);
218 }
219
220 size = measure_mode_block(current_mode);
221 mode.internal = copy_memory(current_mode, size, size);
222 if (!mode.internal) {
223 return false;
224 }
225
226 if (SDL_AddBasicVideoDisplay(&mode) == 0) {
227 return false;
228 }
229 return true;
230}
231
232bool RISCOS_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display)
233{
234 SDL_DisplayMode mode;
235 _kernel_swi_regs regs;
236 _kernel_oserror *error;
237 void *block, *pos;
238
239 regs.r[0] = 2;
240 regs.r[2] = 0;
241 regs.r[6] = 0;
242 regs.r[7] = 0;
243 error = _kernel_swi(OS_ScreenMode, &regs, &regs);
244 if (error) {
245 return SDL_SetError("Unable to enumerate screen modes: %s (%i)", error->errmess, error->errnum);
246 }
247
248 block = SDL_malloc(-regs.r[7]);
249 if (!block) {
250 return false;
251 }
252
253 regs.r[6] = (int)block;
254 regs.r[7] = -regs.r[7];
255 error = _kernel_swi(OS_ScreenMode, &regs, &regs);
256 if (error) {
257 SDL_free(block);
258 return SDL_SetError("Unable to enumerate screen modes: %s (%i)", error->errmess, error->errnum);
259 }
260
261 for (pos = block; pos < (void *)regs.r[6]; pos += *((int *)pos)) {
262 if (!read_mode_block(pos + 4, &mode, false)) {
263 continue;
264 }
265
266 if (mode.format == SDL_PIXELFORMAT_UNKNOWN) {
267 continue;
268 }
269
270 mode.internal = convert_mode_block(pos + 4);
271 if (!mode.internal) {
272 SDL_free(block);
273 return false;
274 }
275
276 if (!SDL_AddFullscreenDisplayMode(display, &mode)) {
277 SDL_free(mode.internal);
278 }
279 }
280
281 SDL_free(block);
282 return true;
283}
284
285bool RISCOS_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
286{
287 const char disable_cursor[] = { 23, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
288 _kernel_swi_regs regs;
289 _kernel_oserror *error;
290 int i;
291
292 regs.r[0] = 0;
293 regs.r[1] = (int)mode->internal;
294 error = _kernel_swi(OS_ScreenMode, &regs, &regs);
295 if (error) {
296 return SDL_SetError("Unable to set the current screen mode: %s (%i)", error->errmess, error->errnum);
297 }
298
299 // Turn the text cursor off
300 for (i = 0; i < SDL_arraysize(disable_cursor); i++) {
301 _kernel_oswrch(disable_cursor[i]);
302 }
303
304 // Update cursor visibility, since it may have been disabled by the mode change.
305 SDL_SetCursor(NULL);
306
307 return true;
308}
309
310#endif // SDL_VIDEO_DRIVER_RISCOS