src/video/riscos/SDL_riscostask.c
author Cameron Cawley <ccawley2011@gmail.com>
Fri, 17 Aug 2018 22:37:16 +0100
branchSDL-1.2
changeset 12502 2560bdcf3130
parent 6137 4720145f848b
permissions -rw-r--r--
riscos: Fix returning from full-screen to 16M colour modes
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2012 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"
    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)
    76         {
    77            fprintf(stderr, "   %d\n", storeBlock[blockSize++]);
    78         }
    79         while(storeBlock[blockSize] != -1)
    80         {
    81            fprintf(stderr, "   %d   %d\n", storeBlock[blockSize++], storeBlock[blockSize++]);
    82         }
    83     }
    84 }
    85 #endif
    86 
    87 /******************************************************************
    88 
    89  Initialise as RISC OS Wimp task
    90 
    91 *******************************************************************/
    92 
    93 int RISCOS_InitTask()
    94 {
    95    char task_name[32];
    96    _kernel_swi_regs regs;
    97    int messages[4];
    98 
    99    if (RISCOS_GetTaskName(task_name, SDL_arraysize(task_name)) == 0) return 0;
   100 
   101    messages[0] = 9;       /* Palette changed */
   102    messages[1] = 0x400c1; /* Mode changed */
   103    messages[2] = 8;       /* Pre quit */
   104    messages[2] = 0;
   105    
   106 	regs.r[0] = (unsigned int)360; /* Minimum version 3.6 */
   107 	regs.r[1] = (unsigned int)0x4b534154;
   108 	regs.r[2] = (unsigned int)task_name;
   109 	regs.r[3] = (unsigned int)messages;
   110 
   111    if (_kernel_swi(Wimp_Initialise, &regs, &regs) == 0)
   112    {
   113 	   wimp_version = regs.r[0];
   114 	   task_handle = regs.r[1];
   115 	   return 1;
   116    }
   117 
   118 #if !SDL_THREADS_DISABLED
   119    main_thread = pthread_self();
   120 #endif
   121 
   122    return 0;
   123 }
   124 
   125 /*********************************************************************
   126 
   127   Close down application on exit.
   128 
   129 **********************************************************************/
   130 
   131 void RISCOS_ExitTask()
   132 {
   133 	_kernel_swi_regs regs;
   134 
   135     if (stored_mode == -1)
   136     {
   137        /* Ensure cursor is put back to standard pointer shape if
   138           we have been running in a window */
   139        _kernel_osbyte(106,1,0);
   140     }
   141 
   142 	/* Ensure we end up back in the wimp */
   143 	RISCOS_RestoreWimpMode();
   144 
   145 	/* Neatly exit the task */
   146    	regs.r[0] = task_handle;
   147    	regs.r[1] = (unsigned int)0x4b534154;
   148    	_kernel_swi(Wimp_CloseDown, &regs, &regs);
   149 	task_handle = 0;
   150 }
   151 
   152 /**************************************************************************
   153 
   154   Get the name of the task for the desktop.
   155 
   156   Param:   task_name - name of task 32 characters.
   157 
   158   Returns: 1 is successful, otherwise 0
   159 
   160   Notes:   Works by getting using OS_GetEnv to get the command line
   161 		   used to run the program and then parsing a name from it
   162 		   as follows.
   163 
   164 		   1. Use name after final period if not !RunImage
   165 		   2. If name is !RunImage then process item before the period
   166 		      in front of !RunImage.
   167 		   3. If directory name use that
   168 		   4. if in form <XXX$Dir> use the XXX.
   169 
   170 		   Finally once this value has been retrieved use it unless
   171 		   there is a variable set up in the form SDL$<name>$TaskName
   172 		   in which case the value of this variable will be used.
   173 
   174 		   Now also gets other RISC OS configuration varibles
   175                 SDL$<name>$BackBuffer - set to 1 to use a system memory backbuffer in fullscreen mode
   176 						    so updates wait until a call to SDL_UpdateRects. (default 0)
   177 						    This is required for programmes where they have assumed this is
   178 						    always the case which is contrary to the documentation.
   179                SDL$<name>$CloseAction
   180                     0 Don't show close icon
   181                     1 Show close icon
   182 
   183 ***************************************************************************/
   184 
   185 int RISCOS_GetTaskName(char *task_name, size_t maxlen)
   186 {
   187 	_kernel_swi_regs regs;
   188 
   189    task_name[0] = 0;
   190 
   191    /* Figure out a sensible task name */
   192    if (_kernel_swi(OS_GetEnv, &regs, &regs) == 0)
   193    {
   194 	   char *command_line = (char *)regs.r[0];
   195 	   size_t len = SDL_strlen(command_line)+1;
   196 	   char *buffer = SDL_stack_alloc(char, len);
   197 	   char *env_var;
   198 	   char *p;
   199 
   200 	   SDL_strlcpy(buffer, command_line, len);
   201 	   p = SDL_strchr(buffer, ' ');
   202 	   if (p) *p = 0;
   203 	   p = SDL_strrchr(buffer, '.');
   204 	   if (p == 0) p = buffer;
   205 	   if (stricmp(p+1,"!RunImage") == 0)
   206 	   {
   207 		   *p = 0;
   208 	   	   p = SDL_strrchr(buffer, '.');
   209 		   if (p == 0) p = buffer;
   210 	   }
   211 	   if (*p == '.') p++;
   212 	   if (*p == '!') p++; /* Skip "!" at beginning of application directories */
   213 
   214        if (*p == '<')
   215        {
   216           // Probably in the form <appname$Dir>
   217           char *q = SDL_strchr(p, '$');
   218           if (q == 0) q = SDL_strchr(p,'>'); /* Use variable name if not */
   219           if (q) *q = 0;
   220           p++; /* Move over the < */
   221        }
   222 
   223 	   if (*p)
   224 	   {
   225 		   /* Read variables that effect the RISC OS SDL engine for this task */
   226 		   len = SDL_strlen(p) + 18; /* 18 is larger than the biggest variable name */
   227 		   env_var = SDL_stack_alloc(char, len);
   228 		   if (env_var)
   229 		   {
   230 			   char *env_val;
   231 
   232 			   /* See if a variable of form SDL$<dirname>$TaskName exists */
   233 
   234 			   SDL_strlcpy(env_var, "SDL$", len);
   235 			   SDL_strlcat(env_var, p, len);
   236 			   SDL_strlcat(env_var, "$TaskName", len);
   237 
   238 			   env_val = SDL_getenv(env_var);
   239 			   if (env_val) SDL_strlcpy(task_name, env_val, maxlen);
   240 
   241 			   SDL_strlcpy(env_var, "SDL$", len);
   242 			   SDL_strlcat(env_var, p, len);
   243 			   SDL_strlcat(env_var, "$BackBuffer", len);
   244 
   245 			   env_val = SDL_getenv(env_var);
   246 			   if (env_val) riscos_backbuffer = atoi(env_val);
   247 
   248 			   SDL_strlcpy(env_var, "SDL$", len);
   249 			   SDL_strlcat(env_var, p, len);
   250 			   SDL_strlcat(env_var, "$CloseAction", len);
   251 
   252 			   env_val = SDL_getenv(env_var);
   253 			   if (env_val && SDL_strcmp(env_val,"0") == 0) riscos_closeaction = 0;
   254 
   255 			   SDL_stack_free(env_var);
   256 		   }
   257 		   
   258 		   if (!*task_name) SDL_strlcpy(task_name, p, maxlen);
   259 	   }
   260 
   261 	   SDL_stack_free(buffer);
   262    }
   263 
   264    if (task_name[0] == 0) SDL_strlcpy(task_name, "SDL Task", maxlen);
   265 
   266    return 1;
   267 }
   268 
   269 /*****************************************************************
   270 
   271   Store the current desktop screen mode if we are in the desktop.
   272 
   273 ******************************************************************/
   274 
   275 void RISCOS_StoreWimpMode()
   276 {
   277      _kernel_swi_regs regs;
   278 
   279 	/* Don't store if in full screen mode */
   280 	if (stored_mode != -1) return;
   281 
   282     regs.r[0] = 1;
   283     _kernel_swi(OS_ScreenMode, &regs, &regs);
   284     if (regs.r[1] >= 0 && regs.r[1] < 256) stored_mode = regs.r[1];
   285     else
   286     {
   287         int blockSize = 0;
   288         int *retBlock = (int *)regs.r[1];
   289 		int *storeBlock;
   290         int j;
   291 
   292         while(blockSize < 5) blockSize++;
   293         while(retBlock[blockSize] != -1) blockSize+=2;
   294         blockSize++;
   295         storeBlock = (int *)SDL_malloc(blockSize * sizeof(int));
   296         retBlock = (int *)regs.r[1];
   297         for ( j = 0; j < blockSize; j++)
   298            storeBlock[j] = retBlock[j];
   299 
   300 		stored_mode = (int)storeBlock;
   301      }
   302 #ifdef DUMP_MODE
   303     fprintf(stderr, "Stored "); dump_mode();
   304 #endif
   305 }
   306 
   307 /*****************************************************************
   308 
   309   Restore desktop screen mode if we are in full screen mode.
   310 
   311 *****************************************************************/
   312 
   313 void RISCOS_RestoreWimpMode()
   314 {
   315     _kernel_swi_regs regs;
   316 
   317 	/* Only need to restore if we are in full screen mode */
   318 	if (stored_mode == -1) return;
   319 
   320 #ifdef DUMP_MODE
   321    fprintf(stderr, "Restored"); dump_mode();
   322 #endif
   323 
   324     regs.r[0] = stored_mode;
   325     _kernel_swi(Wimp_SetMode, &regs, &regs);
   326     if (stored_mode < 0 || stored_mode > 256)
   327     {
   328        SDL_free((int *)stored_mode);
   329     }
   330     stored_mode = -1;
   331 
   332     /* Flush keyboard buffer to dump the keystrokes we've already polled */
   333     regs.r[0] = 21;
   334     regs.r[1] = 0; /* Keyboard buffer number */
   335     _kernel_swi(OS_Byte, &regs, &regs);
   336 
   337     mouseInWindow = 0;
   338 
   339 }
   340 
   341 /*********************************************************************
   342 
   343   Get version of Wimp running when task was initialised.
   344 
   345 *********************************************************************/
   346 
   347 int RISCOS_GetWimpVersion()
   348 {
   349 	return wimp_version;
   350 }
   351 
   352 int RISCOS_GetTaskHandle()
   353 {
   354 	return task_handle;
   355 }