1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2004 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 /*
25 This file added by Alan Buckley (alan_baa@hotmail.com) to support RISC OS
26 26 March 2003
27
28 File includes routines for:
29 Setting up as a WIMP Task
30 Reading information about the current desktop
31 Storing information before a switch to full screen
32 Restoring desktop after switching to full screen
33 */
34
35 #include "kernel.h"
36 #include "swis.h"
37
38 #include "SDL_stdinc.h"
39 #include "SDL_riscostask.h"
40
41 #if !SDL_THREADS_DISABLED
42 #include <pthread.h>
43 pthread_t main_thread;
44 #endif
45
46 /* RISC OS variables */
47
48 static int task_handle = 0;
49 static int wimp_version = 0;
50
51 /* RISC OS variables to help compatability with certain programs */
52 int riscos_backbuffer = 0; /* Create a back buffer in system memory for full screen mode */
53 int riscos_closeaction = 1; /* Close icon action */
54
55 static int stored_mode = -1; /* -1 when in desktop, mode number or pointer when full screen */
56
57 extern int mouseInWindow; /* Mouse is in WIMP window */
58
59 /* Local function */
60
61 static int RISCOS_GetTaskName(char *task_name, size_t maxlen);
62
63 /* Uncomment next line to copy mode changes/restores to stderr */
64 /* #define DUMP_MODE */
65 #ifdef DUMP_MODE
66 #include "stdio.h"
dump_mode()67 static void dump_mode()
68 {
69 fprintf(stderr, "mode %d\n", stored_mode);
70 if (stored_mode < -1 || stored_mode >= 256)
71 {
72 int blockSize = 0;
73 int *storeBlock = (int *)stored_mode;
74
75 while(blockSize < 5 || storeBlock[blockSize] != -1)
76 {
77 fprintf(stderr, " %d\n", storeBlock[blockSize++]);
78 }
79 }
80 }
81 #endif
82
83 /******************************************************************
84
85 Initialise as RISC OS Wimp task
86
87 *******************************************************************/
88
RISCOS_InitTask()89 int RISCOS_InitTask()
90 {
91 char task_name[32];
92 _kernel_swi_regs regs;
93 int messages[4];
94
95 if (RISCOS_GetTaskName(task_name, SDL_arraysize(task_name)) == 0) return 0;
96
97 messages[0] = 9; /* Palette changed */
98 messages[1] = 0x400c1; /* Mode changed */
99 messages[2] = 8; /* Pre quit */
100 messages[2] = 0;
101
102 regs.r[0] = (unsigned int)360; /* Minimum version 3.6 */
103 regs.r[1] = (unsigned int)0x4b534154;
104 regs.r[2] = (unsigned int)task_name;
105 regs.r[3] = (unsigned int)messages;
106
107 if (_kernel_swi(Wimp_Initialise, ®s, ®s) == 0)
108 {
109 wimp_version = regs.r[0];
110 task_handle = regs.r[1];
111 return 1;
112 }
113
114 #if !SDL_THREADS_DISABLED
115 main_thread = pthread_self();
116 #endif
117
118 return 0;
119 }
120
121 /*********************************************************************
122
123 Close down application on exit.
124
125 **********************************************************************/
126
RISCOS_ExitTask()127 void RISCOS_ExitTask()
128 {
129 _kernel_swi_regs regs;
130
131 if (stored_mode == -1)
132 {
133 /* Ensure cursor is put back to standard pointer shape if
134 we have been running in a window */
135 _kernel_osbyte(106,1,0);
136 }
137
138 /* Ensure we end up back in the wimp */
139 RISCOS_RestoreWimpMode();
140
141 /* Neatly exit the task */
142 regs.r[0] = task_handle;
143 regs.r[1] = (unsigned int)0x4b534154;
144 _kernel_swi(Wimp_CloseDown, ®s, ®s);
145 task_handle = 0;
146 }
147
148 /**************************************************************************
149
150 Get the name of the task for the desktop.
151
152 Param: task_name - name of task 32 characters.
153
154 Returns: 1 is successful, otherwise 0
155
156 Notes: Works by getting using OS_GetEnv to get the command line
157 used to run the program and then parsing a name from it
158 as follows.
159
160 1. Use name after final period if not !RunImage
161 2. If name is !RunImage then process item before the period
162 in front of !RunImage.
163 3. If directory name use that
164 4. if in form <XXX$Dir> use the XXX.
165
166 Finally once this value has been retrieved use it unless
167 there is a variable set up in the form SDL$<name>$TaskName
168 in which case the value of this variable will be used.
169
170 Now also gets other RISC OS configuration varibles
171 SDL$<name>$BackBuffer - set to 1 to use a system memory backbuffer in fullscreen mode
172 so updates wait until a call to SDL_UpdateRects. (default 0)
173 This is required for programmes where they have assumed this is
174 always the case which is contrary to the documentation.
175 SDL$<name>$CloseAction
176 0 Don't show close icon
177 1 Show close icon
178
179 ***************************************************************************/
180
RISCOS_GetTaskName(char * task_name,size_t maxlen)181 int RISCOS_GetTaskName(char *task_name, size_t maxlen)
182 {
183 _kernel_swi_regs regs;
184
185 task_name[0] = 0;
186
187 /* Figure out a sensible task name */
188 if (_kernel_swi(OS_GetEnv, ®s, ®s) == 0)
189 {
190 char *command_line = (char *)regs.r[0];
191 size_t len = SDL_strlen(command_line)+1;
192 char *buffer = SDL_stack_alloc(char, len);
193 char *env_var;
194 char *p;
195
196 SDL_strlcpy(buffer, command_line, len);
197 p = SDL_strchr(buffer, ' ');
198 if (p) *p = 0;
199 p = SDL_strrchr(buffer, '.');
200 if (p == 0) p = buffer;
201 if (stricmp(p+1,"!RunImage") == 0)
202 {
203 *p = 0;
204 p = SDL_strrchr(buffer, '.');
205 if (p == 0) p = buffer;
206 }
207 if (*p == '.') p++;
208 if (*p == '!') p++; /* Skip "!" at beginning of application directories */
209
210 if (*p == '<')
211 {
212 // Probably in the form <appname$Dir>
213 char *q = SDL_strchr(p, '$');
214 if (q == 0) q = SDL_strchr(p,'>'); /* Use variable name if not */
215 if (q) *q = 0;
216 p++; /* Move over the < */
217 }
218
219 if (*p)
220 {
221 /* Read variables that effect the RISC OS SDL engine for this task */
222 len = SDL_strlen(p) + 18; /* 18 is larger than the biggest variable name */
223 env_var = SDL_stack_alloc(char, len);
224 if (env_var)
225 {
226 char *env_val;
227
228 /* See if a variable of form SDL$<dirname>$TaskName exists */
229
230 SDL_strlcpy(env_var, "SDL$", len);
231 SDL_strlcat(env_var, p, len);
232 SDL_strlcat(env_var, "$TaskName", len);
233
234 env_val = SDL_getenv(env_var);
235 if (env_val) SDL_strlcpy(task_name, env_val, maxlen);
236
237 SDL_strlcpy(env_var, "SDL$", len);
238 SDL_strlcat(env_var, p, len);
239 SDL_strlcat(env_var, "$BackBuffer", len);
240
241 env_val = SDL_getenv(env_var);
242 if (env_val) riscos_backbuffer = atoi(env_val);
243
244 SDL_strlcpy(env_var, "SDL$", len);
245 SDL_strlcat(env_var, p, len);
246 SDL_strlcat(env_var, "$CloseAction", len);
247
248 env_val = SDL_getenv(env_var);
249 if (env_val && SDL_strcmp(env_val,"0") == 0) riscos_closeaction = 0;
250
251 SDL_stack_free(env_var);
252 }
253
254 if (!*task_name) SDL_strlcpy(task_name, p, maxlen);
255 }
256
257 SDL_stack_free(buffer);
258 }
259
260 if (task_name[0] == 0) SDL_strlcpy(task_name, "SDL Task", maxlen);
261
262 return 1;
263 }
264
265 /*****************************************************************
266
267 Store the current desktop screen mode if we are in the desktop.
268
269 ******************************************************************/
270
RISCOS_StoreWimpMode()271 void RISCOS_StoreWimpMode()
272 {
273 _kernel_swi_regs regs;
274
275 /* Don't store if in full screen mode */
276 if (stored_mode != -1) return;
277
278 regs.r[0] = 1;
279 _kernel_swi(OS_ScreenMode, ®s, ®s);
280 if (regs.r[1] >= 0 && regs.r[1] < 256) stored_mode = regs.r[1];
281 else
282 {
283 int blockSize = 0;
284 int *retBlock = (int *)regs.r[1];
285 int *storeBlock;
286 int j;
287
288 while(blockSize < 5 || retBlock[blockSize] != -1) blockSize++;
289 blockSize++;
290 storeBlock = (int *)SDL_malloc(blockSize * sizeof(int));
291 retBlock = (int *)regs.r[1];
292 for ( j = 0; j < blockSize; j++)
293 storeBlock[j] = retBlock[j];
294
295 stored_mode = (int)storeBlock;
296 }
297 #if DUMP_MODE
298 fprintf(stderr, "Stored "); dump_mode();
299 #endif
300 }
301
302 /*****************************************************************
303
304 Restore desktop screen mode if we are in full screen mode.
305
306 *****************************************************************/
307
RISCOS_RestoreWimpMode()308 void RISCOS_RestoreWimpMode()
309 {
310 _kernel_swi_regs regs;
311
312 /* Only need to restore if we are in full screen mode */
313 if (stored_mode == -1) return;
314
315 #if DUMP_MODE
316 fprintf(stderr, "Restored"); dump_mode();
317 #endif
318
319 regs.r[0] = stored_mode;
320 _kernel_swi(Wimp_SetMode, ®s, ®s);
321 if (stored_mode < 0 || stored_mode > 256)
322 {
323 SDL_free((int *)stored_mode);
324 }
325 stored_mode = -1;
326
327 /* Flush keyboard buffer to dump the keystrokes we've already polled */
328 regs.r[0] = 21;
329 regs.r[1] = 0; /* Keyboard buffer number */
330 _kernel_swi(OS_Byte, ®s, ®s);
331
332 mouseInWindow = 0;
333
334 }
335
336 /*********************************************************************
337
338 Get version of Wimp running when task was initialised.
339
340 *********************************************************************/
341
RISCOS_GetWimpVersion()342 int RISCOS_GetWimpVersion()
343 {
344 return wimp_version;
345 }
346
RISCOS_GetTaskHandle()347 int RISCOS_GetTaskHandle()
348 {
349 return task_handle;
350 }
351