src/video/riscos/SDL_riscostask.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 29 May 2003 04:44:13 +0000
changeset 630 550bccdf04bd
child 769 b8d311d90021
permissions -rw-r--r--
Added initial support for RISC OS (thanks Peter Naulls!)
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997, 1998, 1999, 2000, 2001  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@devolution.com
    21 */
    22 
    23 /*
    24     This file added by Alan Buckley (alan_baa@hotmail.com) to support RISCOS 
    25 	26 March 2003
    26 
    27 	File includes routines for:
    28 	  Setting up as a WIMP Task
    29 	  Reading information about the current desktop
    30 	  Storing information before a switch to full screen
    31 	  Restoring desktop after switching to full screen
    32 */
    33 
    34 #include <stdlib.h>
    35 #include <string.h>
    36 
    37 #include "kernel.h"
    38 #include "swis.h"
    39 
    40 #include "SDL_riscostask.h"
    41 
    42 /* RISCOS variables */
    43 
    44 static int task_handle = 0;
    45 static int wimp_version = 0;
    46 
    47 /* RISC OS variables to help compatability with certain programs */
    48 int riscos_backbuffer = 0; /* Create a back buffer in system memory for full screen mode */
    49 int riscos_closeaction = 1; /* Close icon action */
    50 int riscos_audiobuffer = 0; /* Audio buffer size */
    51 
    52 static int stored_mode = -1; /* -1 when in desktop, mode number or pointer when full screen */
    53 
    54 extern int mouseInWindow; /* Mouse is in WIMP window */
    55 
    56 /* Local function */
    57 
    58 static int RISCOS_GetTaskName(char *task_name);
    59 
    60 /* Uncomment next line to copy mode changes/restores to stderr */
    61 /* #define DUMP_MODE */
    62 #ifdef DUMP_MODE
    63 #include "stdio.h"
    64 static void dump_mode()
    65 {
    66     fprintf(stderr, "mode %d\n", stored_mode);
    67     if (stored_mode < -1 || stored_mode >= 256)
    68     {
    69         int blockSize = 0;
    70 		int *storeBlock = (int *)stored_mode;
    71 
    72         while(blockSize < 5 || storeBlock[blockSize] != -1)
    73         {
    74            fprintf(stderr, "   %d\n", storeBlock[blockSize++]);
    75         }
    76     }
    77 }
    78 #endif
    79 
    80 /******************************************************************
    81 
    82  Initialise as RISCOS Wimp task
    83 
    84 *******************************************************************/
    85 
    86 int RISCOS_InitTask()
    87 {
    88    char task_name[32];
    89    _kernel_swi_regs regs;
    90    int messages[4];
    91 
    92    if (RISCOS_GetTaskName(task_name) == 0) return 0;
    93 
    94    messages[0] = 9;       /* Palette changed */
    95    messages[1] = 0x400c1; /* Mode changed */
    96    messages[2] = 8;       /* Pre quit */
    97    messages[2] = 0;
    98    
    99 	regs.r[0] = (unsigned int)360; /* Minimum version 3.6 */
   100 	regs.r[1] = (unsigned int)0x4b534154;
   101 	regs.r[2] = (unsigned int)task_name;
   102 	regs.r[3] = (unsigned int)messages;
   103 
   104    if (_kernel_swi(Wimp_Initialise, &regs, &regs) == 0)
   105    {
   106 	   wimp_version = regs.r[0];
   107 	   task_handle = regs.r[1];
   108 	   return 1;
   109    }
   110 
   111    return 0;
   112 }
   113 
   114 /*********************************************************************
   115 
   116   Close down application on exit.
   117 
   118 **********************************************************************/
   119 
   120 void RISCOS_ExitTask()
   121 {
   122 	_kernel_swi_regs regs;
   123 
   124     if (stored_mode == -1)
   125     {
   126        /* Ensure cursor is put back to standard pointer shape if
   127           we have been running in a window */
   128        _kernel_osbyte(106,1,0);
   129     }
   130 
   131 	/* Ensure we end up back in the wimp */
   132 	RISCOS_RestoreWimpMode();
   133 
   134 	/* Neatly exit the task */
   135    	regs.r[0] = task_handle;
   136    	regs.r[1] = (unsigned int)0x4b534154;
   137    	_kernel_swi(Wimp_CloseDown, &regs, &regs);
   138 	task_handle = 0;
   139 }
   140 
   141 /**************************************************************************
   142 
   143   Get the name of the task for the desktop.
   144 
   145   Param:   task_name - name of task 32 characters.
   146 
   147   Returns: 1 is successful, otherwise 0
   148 
   149   Notes:   Works by getting using OS_GetEnv to get the command line
   150 		   used to run the program and then parsing a name from it
   151 		   as follows.
   152 
   153 		   1. Use name after final period if not !RunImage
   154 		   2. If name is !RunImage then process item before the period
   155 		      in front of !RunImage.
   156 		   3. If directory name use that
   157 		   4. if in form <XXX$Dir> use the XXX.
   158 
   159 		   Finally once this value has been retrieved use it unless
   160 		   there is a variable set up in the form SDL$<name>$TaskName
   161 		   in which case the value of this variable will be used.
   162 
   163 		   Now also gets other riscos configuration varibles
   164                 SDL$<name>$BackBuffer - set to 1 to use a system memory backbuffer in fullscreen mode
   165 						    so updates wait until a call to SDL_UpdateRects. (default 0)
   166 						    This is required for programmes where they have assumed this is
   167 						    always the case which is contrary to the documentation.
   168                SDL$<name>$CloseAction
   169                     0 Don't show close icon
   170                     1 Show close icon
   171 
   172                SDL$<name>$AudioBuffer - set to number of samples to buffer
   173                     in advance. Will default to a minimum of 1024 or twice
   174                     amount requested by program whichever is largest.
   175                     If not specified default is amount for 10 csecs.
   176                     Time that will be pre-buffered can be calculated as
   177                     sample to buffer * 1000 / freq milliseconds.
   178                     
   179 ***************************************************************************/
   180 
   181 int RISCOS_GetTaskName(char *task_name)
   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, &regs, &regs) == 0)
   189    {
   190 	   char *command_line = (char *)regs.r[0];
   191 	   char *buffer = malloc(strlen(command_line)+1);
   192 	   char *env_var;
   193 	   char *p;
   194 
   195 	   strcpy(buffer, command_line);
   196 	   p = strchr(buffer, ' ');
   197 	   if (p) *p = 0;
   198 	   p = strrchr(buffer, '.');
   199 	   if (p == 0) p = buffer;
   200 	   if (stricmp(p+1,"!RunImage") == 0)
   201 	   {
   202 		   *p = 0;
   203 	   	   p = strrchr(buffer, '.');
   204 		   if (p == 0) p = buffer;
   205 	   }
   206 	   if (*p == '.') p++;
   207 	   if (*p == '!') p++; /* Skip "!" at beginning of application directories */
   208 
   209        if (*p == '<')
   210        {
   211           // Probably in the form <appname$Dir>
   212           char *q = strchr(p, '$');
   213           if (q == 0) q = strchr(p,'>'); /* Use variable name if not */
   214           if (q) *q = 0;
   215           p++; /* Move over the < */
   216        }
   217 
   218 	   if (*p)
   219 	   {
   220 		   /* Read variables that effect the RISCOS SDL engine for this task */
   221 		   env_var = malloc(strlen(p) + 18); /* 18 is larger than the biggest variable name */
   222 		   if (env_var)
   223 		   {
   224 			   char *env_val;
   225 
   226 			   /* See if a variable of form SDL$<dirname>$TaskName exists */
   227 
   228 			   strcpy(env_var, "SDL$");
   229 			   strcat(env_var, p);
   230 			   strcat(env_var, "$TaskName");
   231 
   232 			   env_val = getenv(env_var);
   233 			   if (env_val) strncpy(task_name, env_val, 31);
   234 
   235 			   strcpy(env_var, "SDL$");
   236 			   strcat(env_var, p);
   237 			   strcat(env_var, "$BackBuffer");
   238 
   239 			   env_val = getenv(env_var);
   240 			   if (env_val && strcmp(env_val,"1") == 0) riscos_backbuffer = 1;
   241 
   242 			   strcpy(env_var, "SDL$");
   243 			   strcat(env_var, p);
   244 			   strcat(env_var, "$CloseAction");
   245 
   246 			   env_val = getenv(env_var);
   247 			   if (env_val && strcmp(env_val,"0") == 0) riscos_closeaction = 0;
   248 
   249 			   strcpy(env_var, "SDL$");
   250 			   strcat(env_var, p);
   251 			   strcat(env_var, "$AudioBuffer");
   252 
   253 			   env_val = getenv(env_var);
   254 			   riscos_audiobuffer = atoi(env_val);
   255 
   256 			   free(env_var);
   257 		   }
   258 		   
   259 		   if (task_name[0] == 0) strncpy(task_name, p, 31);
   260 		   task_name[31] = 0;
   261 	   }
   262 
   263 	   free(buffer);
   264    }
   265 
   266    if (task_name[0] == 0) strcpy(task_name, "SDL Task");
   267 
   268    return 1;
   269 }
   270 
   271 /*****************************************************************
   272 
   273   Store the current desktop screen mode if we are in the desktop.
   274 
   275 ******************************************************************/
   276 
   277 void RISCOS_StoreWimpMode()
   278 {
   279      _kernel_swi_regs regs;
   280 
   281 	/* Don't store if in full screen mode */
   282 	if (stored_mode != -1) return;
   283 
   284     regs.r[0] = 1;
   285     _kernel_swi(OS_ScreenMode, &regs, &regs);
   286     if (regs.r[1] >= 0 && regs.r[1] < 256) stored_mode = regs.r[1];
   287     else
   288     {
   289         int blockSize = 0;
   290         int *retBlock = (int *)regs.r[1];
   291 		int *storeBlock;
   292         int j;
   293 
   294         while(blockSize < 5 || retBlock[blockSize] != -1) blockSize++;
   295         blockSize++;
   296         storeBlock = (int *)malloc(blockSize * sizeof(int));
   297         retBlock = (int *)regs.r[1];
   298         for ( j = 0; j < blockSize; j++)
   299            storeBlock[j] = retBlock[j];
   300 
   301 		stored_mode = (int)storeBlock;
   302      }
   303 #if DUMP_MODE
   304     fprintf(stderr, "Stored "); dump_mode();
   305 #endif
   306 }
   307 
   308 /*****************************************************************
   309 
   310   Restore desktop screen mode if we are in full screen mode.
   311 
   312 *****************************************************************/
   313 
   314 void RISCOS_RestoreWimpMode()
   315 {
   316     _kernel_swi_regs regs;
   317 
   318 	/* Only need to restore if we are in full screen mode */
   319 	if (stored_mode == -1) return;
   320 
   321 #if DUMP_MODE
   322    fprintf(stderr, "Restored"); dump_mode();
   323 #endif
   324 
   325     regs.r[0] = stored_mode;
   326     _kernel_swi(Wimp_SetMode, &regs, &regs);
   327     if (stored_mode < 0 || stored_mode > 256)
   328     {
   329        free((int *)stored_mode);
   330     }
   331     stored_mode = -1;
   332 
   333     /* Flush keyboard buffer to dump the keystrokes we've already polled */
   334     regs.r[0] = 21;
   335     regs.r[1] = 0; /* Keyboard buffer number */
   336     _kernel_swi(OS_Byte, &regs, &regs);
   337 
   338     mouseInWindow = 0;
   339 
   340 }
   341 
   342 /*********************************************************************
   343 
   344   Get version of Wimp running when task was initialised.
   345 
   346 *********************************************************************/
   347 
   348 int RISCOS_GetWimpVersion()
   349 {
   350 	return wimp_version;
   351 }
   352 
   353 int RISCOS_GetTaskHandle()
   354 {
   355 	return task_handle;
   356 }