symbian-qemu-0.9.1-12/libsdl-trunk/src/video/riscos/SDL_riscosFullScreenVideo.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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      File added by Alan Buckley (alan_baa@hotmail.com) for RISC OS compatability
       
    26 	 27 March 2003
       
    27 
       
    28      Implements RISC OS full screen display.
       
    29 */
       
    30 
       
    31 #include "SDL_video.h"
       
    32 #include "SDL_mouse.h"
       
    33 #include "../SDL_sysvideo.h"
       
    34 #include "../SDL_pixels_c.h"
       
    35 #include "../../events/SDL_events_c.h"
       
    36 
       
    37 #include "SDL_riscostask.h"
       
    38 #include "SDL_riscosvideo.h"
       
    39 #include "SDL_riscosevents_c.h"
       
    40 #include "SDL_riscosmouse_c.h"
       
    41 
       
    42 #include "kernel.h"
       
    43 #include "swis.h"
       
    44 #include "unixlib/os.h"
       
    45 #include "unixlib/local.h"
       
    46 
       
    47 /* Private structures */
       
    48 typedef struct tagScreenModeBlock
       
    49 {
       
    50    int flags;  // mode selector flags, bit 0 = 1, bit 1-7 format specifier, 8-31 reserved
       
    51    int x_pixels;
       
    52    int y_pixels;
       
    53    int pixel_depth;  // 2^pixel_depth = bpp,i.e. 0 = 1, 1 = 2, 4 = 16, 5 = 32
       
    54    int frame_rate;   // -1 use first match
       
    55    int mode_vars[5]; // array of index, value pairs terminated by -1
       
    56 } SCREENMODEBLOCK;
       
    57 
       
    58 
       
    59 /* Helper functions */
       
    60 void FULLSCREEN_SetDeviceMode(_THIS);
       
    61 int FULLSCREEN_SetMode(int width, int height, int bpp);
       
    62 void FULLSCREEN_SetupBanks(_THIS);
       
    63 
       
    64 /* SDL video device functions for fullscreen mode */
       
    65 static int FULLSCREEN_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
       
    66 static int FULLSCREEN_FlipHWSurface(_THIS, SDL_Surface *surface);
       
    67 void FULLSCREEN_SetWMCaption(_THIS, const char *title, const char *icon);
       
    68 extern int RISCOS_GetWmInfo(_THIS, SDL_SysWMinfo *info);
       
    69 
       
    70 /* UpdateRects variants */
       
    71 static void FULLSCREEN_UpdateRects(_THIS, int numrects, SDL_Rect *rects);
       
    72 static void FULLSCREEN_UpdateRectsMemCpy(_THIS, int numrects, SDL_Rect *rects);
       
    73 static void FULLSCREEN_UpdateRects8bpp(_THIS, int numrects, SDL_Rect *rects);
       
    74 static void FULLSCREEN_UpdateRects16bpp(_THIS, int numrects, SDL_Rect *rects);
       
    75 static void FULLSCREEN_UpdateRects32bpp(_THIS, int numrects, SDL_Rect *rects);
       
    76 static void FULLSCREEN_UpdateRectsOS(_THIS, int numrects, SDL_Rect *rects);
       
    77 
       
    78 /* Local helper functions */
       
    79 static int cmpmodes(const void *va, const void *vb);
       
    80 static int FULLSCREEN_AddMode(_THIS, int bpp, int w, int h);
       
    81 void FULLSCREEN_SetWriteBank(int bank);
       
    82 void FULLSCREEN_SetDisplayBank(int bank);
       
    83 static void FULLSCREEN_DisableEscape();
       
    84 static void FULLSCREEN_EnableEscape();
       
    85 void FULLSCREEN_BuildModeList(_THIS);
       
    86 
       
    87 /* Following variable is set up in riskosTask.c */
       
    88 extern int riscos_backbuffer; /* Create a back buffer in system memory for full screen mode */
       
    89 
       
    90 /* Following is used to create a sprite back buffer */
       
    91 extern unsigned char *WIMP_CreateBuffer(int width, int height, int bpp);
       
    92 
       
    93 /* Fast assembler copy */
       
    94 extern void RISCOS_Put32(void *to, int pixels, int pitch, int rows, void *from, int src_skip_bytes);
       
    95 
       
    96 SDL_Surface *FULLSCREEN_SetVideoMode(_THIS, SDL_Surface *current,
       
    97 				int width, int height, int bpp, Uint32 flags)
       
    98 {
       
    99    _kernel_swi_regs regs;
       
   100    Uint32 Rmask = 0;
       
   101    Uint32 Gmask = 0;
       
   102    Uint32 Bmask = 0;
       
   103    int create_back_buffer = riscos_backbuffer;
       
   104 
       
   105    switch(bpp)
       
   106    {
       
   107 	case 8:
       
   108 		flags |= SDL_HWPALETTE;
       
   109 		break;
       
   110 
       
   111 	case 15:
       
   112 	case 16:
       
   113 		Bmask = 0x00007c00;
       
   114 		Gmask = 0x000003e0;
       
   115 		Rmask = 0x0000001f;
       
   116 		break;
       
   117 
       
   118 	case 32:
       
   119 		Bmask = 0x00ff0000;
       
   120 		Gmask = 0x0000ff00;
       
   121 		Rmask = 0x000000ff;
       
   122 		break;
       
   123 
       
   124 	default:
       
   125 		SDL_SetError("Pixel depth not supported");
       
   126 		return NULL;
       
   127 		break;
       
   128    }
       
   129 
       
   130    if (FULLSCREEN_SetMode(width, height, bpp) == 0)
       
   131    {
       
   132 	   SDL_SetError("Couldn't set requested mode");
       
   133 	   return (NULL);
       
   134    }
       
   135 
       
   136 /* 	printf("Setting mode %dx%d\n", width, height); */
       
   137 
       
   138 	/* Allocate the new pixel format for the screen */
       
   139 	if ( ! SDL_ReallocFormat(current, bpp, Rmask, Gmask, Bmask, 0) ) {
       
   140 	    RISCOS_RestoreWimpMode();
       
   141 		SDL_SetError("Couldn't allocate new pixel format for requested mode");
       
   142 		return(NULL);
       
   143 	}
       
   144 
       
   145 	/* Set up the new mode framebuffer */
       
   146 	current->w = width;
       
   147 	this->hidden->height = current->h = height;
       
   148 
       
   149    regs.r[0] = -1; /* -1 for current screen mode */
       
   150 
       
   151    /* Get screen width in bytes */
       
   152    regs.r[1] = 6; // Screen Width in bytes
       
   153    _kernel_swi(OS_ReadModeVariable, &regs, &regs);
       
   154 
       
   155    current->pitch = regs.r[2];
       
   156 
       
   157    if (flags & SDL_DOUBLEBUF)
       
   158    {
       
   159 	   regs.r[0] = 2; /* Screen area */
       
   160 	   _kernel_swi(OS_ReadDynamicArea, &regs, &regs);
       
   161 	   
       
   162 	   /* Reg 1 has amount of memory currently used for display */
       
   163 	   regs.r[0] = 2; /* Screen area */
       
   164 	   regs.r[1] = (current->pitch * height * 2) - regs.r[1];
       
   165 	   if (_kernel_swi(OS_ChangeDynamicArea, &regs, &regs) != NULL)
       
   166 	   {
       
   167 		   /* Can't allocate enough screen memory for double buffer */
       
   168 		   flags &= ~SDL_DOUBLEBUF;
       
   169 	   }
       
   170    }
       
   171    
       
   172   	current->flags = flags | SDL_FULLSCREEN | SDL_HWSURFACE | SDL_PREALLOC;
       
   173 	
       
   174 
       
   175 	/* Need to set display banks here for double buffering */
       
   176 	if (flags & SDL_DOUBLEBUF)
       
   177 	{
       
   178 	   FULLSCREEN_SetWriteBank(0);
       
   179 	   FULLSCREEN_SetDisplayBank(1);
       
   180 
       
   181          create_back_buffer = 0; /* Don't need a back buffer for a double buffered display */
       
   182     }
       
   183 
       
   184     FULLSCREEN_SetupBanks(this);
       
   185 
       
   186     if (create_back_buffer)
       
   187     {
       
   188        /* If not double buffered we may need to create a memory
       
   189          ** back buffer to simulate processing on other OSes.
       
   190          ** This is turned on by setting the enviromental variable
       
   191          ** SDL$<name>$BackBuffer >= 1
       
   192          */
       
   193        if (riscos_backbuffer == 3)
       
   194           this->hidden->bank[0] = WIMP_CreateBuffer(width, height, bpp);
       
   195        else
       
   196           this->hidden->bank[0] = SDL_malloc(height * current->pitch);
       
   197        if (this->hidden->bank[0] == 0)
       
   198        {
       
   199  	       RISCOS_RestoreWimpMode();
       
   200            SDL_SetError("Couldnt allocate memory for back buffer");
       
   201            return (NULL);
       
   202        }
       
   203        /* Surface updated in programs is now a software surface */
       
   204        current->flags &= ~SDL_HWSURFACE;
       
   205     }
       
   206 
       
   207     /* Store address of allocated screen bank to be freed later */
       
   208     if (this->hidden->alloc_bank) SDL_free(this->hidden->alloc_bank);
       
   209     if (create_back_buffer)
       
   210     {
       
   211         this->hidden->alloc_bank = this->hidden->bank[0];
       
   212         if (riscos_backbuffer == 3)
       
   213         {
       
   214            this->hidden->bank[0] += 60; /* Start of sprite data */
       
   215            if (bpp == 8) this->hidden->bank[0] += 2048; /* 8bpp sprite have palette first */
       
   216         }
       
   217     } else
       
   218 	  this->hidden->alloc_bank = 0;
       
   219 
       
   220     // Clear both banks to black
       
   221     SDL_memset(this->hidden->bank[0], 0, height * current->pitch);
       
   222     SDL_memset(this->hidden->bank[1], 0, height * current->pitch);
       
   223 
       
   224  	   this->hidden->current_bank = 0;
       
   225 	   current->pixels = this->hidden->bank[0];
       
   226 
       
   227     /* Have to set the screen here, so SetDeviceMode will pick it up */
       
   228     this->screen = current;
       
   229 
       
   230 	/* Reset device functions for the wimp */
       
   231 	FULLSCREEN_SetDeviceMode(this);
       
   232 
       
   233 /*	FULLSCREEN_DisableEscape(); */
       
   234 
       
   235 	/* We're done */
       
   236 	return(current);
       
   237 }
       
   238 
       
   239 /* Reset any device functions that have been changed because we have run in WIMP mode */
       
   240 void FULLSCREEN_SetDeviceMode(_THIS)
       
   241 {
       
   242 	/* Update rects is different if we have a backbuffer */
       
   243 
       
   244 	if (riscos_backbuffer && (this->screen->flags & SDL_DOUBLEBUF) == 0)
       
   245       {
       
   246 	   switch(riscos_backbuffer)
       
   247          {
       
   248             case 2: /* ARM code full word copy */
       
   249                switch(this->screen->format->BytesPerPixel)
       
   250                {
       
   251                   case 1: /* 8bpp modes */
       
   252                	   this->UpdateRects = FULLSCREEN_UpdateRects8bpp;
       
   253                      break;
       
   254                   case 2: /* 15/16bpp modes */
       
   255                	   this->UpdateRects = FULLSCREEN_UpdateRects16bpp;
       
   256                      break;
       
   257                   case 4: /* 32 bpp modes */
       
   258                	   this->UpdateRects = FULLSCREEN_UpdateRects32bpp;
       
   259                      break;
       
   260 
       
   261                   default: /* Just default to the memcpy routine */
       
   262                	   this->UpdateRects = FULLSCREEN_UpdateRectsMemCpy;
       
   263                      break;
       
   264                 }
       
   265                break;
       
   266 
       
   267             case 3: /* Use OS sprite plot routine */
       
   268                this->UpdateRects = FULLSCREEN_UpdateRectsOS;
       
   269                break;
       
   270 
       
   271             default: /* Old but safe memcpy */
       
   272                this->UpdateRects = FULLSCREEN_UpdateRectsMemCpy;
       
   273                break;
       
   274          }
       
   275       } else
       
   276 	   this->UpdateRects = FULLSCREEN_UpdateRects; /* Default do nothing implementation */
       
   277 
       
   278 	this->SetColors   = FULLSCREEN_SetColors;
       
   279 
       
   280 	this->FlipHWSurface = FULLSCREEN_FlipHWSurface;
       
   281 
       
   282 	this->SetCaption = FULLSCREEN_SetWMCaption;
       
   283 	this->SetIcon = NULL;
       
   284 	this->IconifyWindow = NULL;
       
   285 	
       
   286 	this->ShowWMCursor = RISCOS_ShowWMCursor;
       
   287 	this->WarpWMCursor = FULLSCREEN_WarpWMCursor;
       
   288 
       
   289 	this->PumpEvents = FULLSCREEN_PumpEvents;	
       
   290 }
       
   291 
       
   292 /* Query for the list of available video modes */
       
   293 void FULLSCREEN_BuildModeList(_THIS)
       
   294 {
       
   295 	_kernel_swi_regs regs;
       
   296 	char *enumInfo = NULL;
       
   297 	char *enum_ptr;
       
   298 	int *blockInfo;
       
   299 	int j;
       
   300 	int num_modes;
       
   301 
       
   302 	/* Find out how much space we need */
       
   303 	regs.r[0] = 2; /* Reason code */
       
   304 	regs.r[2] = 0; /* Number of modes to skip */
       
   305 	regs.r[6] = 0; /* pointer to block or 0 for count */
       
   306 	regs.r[7] = 0; /* Size of block in bytes */
       
   307 	_kernel_swi(OS_ScreenMode, &regs, &regs);
       
   308 
       
   309     num_modes = -regs.r[2];
       
   310 
       
   311 	/* Video memory should be in r[5] */
       
   312 	this->info.video_mem = regs.r[5]/1024;
       
   313 
       
   314 	enumInfo = (unsigned char *)SDL_malloc(-regs.r[7]);
       
   315 	if (enumInfo == NULL)
       
   316 	{
       
   317 		SDL_OutOfMemory();
       
   318 		return;
       
   319 	}
       
   320 	/* Read mode information into block */
       
   321 	regs.r[2] = 0;
       
   322 	regs.r[6] = (int)enumInfo;
       
   323 	regs.r[7] = -regs.r[7];
       
   324 	_kernel_swi(OS_ScreenMode, &regs, &regs);
       
   325 
       
   326 	enum_ptr = enumInfo;
       
   327 
       
   328 	for (j =0; j < num_modes;j++)
       
   329 	{
       
   330 		blockInfo = (int *)enum_ptr;
       
   331 		if ((blockInfo[1] & 255) == 1) /* We understand this format */
       
   332 		{
       
   333 			switch(blockInfo[4])
       
   334 			{
       
   335 			case 3: /* 8 bits per pixel */
       
   336 				FULLSCREEN_AddMode(this, 8, blockInfo[2], blockInfo[3]);
       
   337 				break;
       
   338 			case 4: /* 15 bits per pixel */
       
   339 				FULLSCREEN_AddMode(this, 15, blockInfo[2], blockInfo[3]);
       
   340 				break;
       
   341 			case 5: /* 32 bits per pixel */
       
   342 				FULLSCREEN_AddMode(this, 32, blockInfo[2], blockInfo[3]);
       
   343 				break;
       
   344 			}
       
   345 		}
       
   346 
       
   347 		enum_ptr += blockInfo[0];
       
   348 	}
       
   349 
       
   350 	SDL_free(enumInfo);
       
   351 		
       
   352 	/* Sort the mode lists */
       
   353 	for ( j=0; j<NUM_MODELISTS; ++j ) {
       
   354 		if ( SDL_nummodes[j] > 0 ) {
       
   355 			SDL_qsort(SDL_modelist[j], SDL_nummodes[j], sizeof *SDL_modelist[j], cmpmodes);
       
   356 		}
       
   357 	}
       
   358 }
       
   359 
       
   360 static int FULLSCREEN_FlipHWSurface(_THIS, SDL_Surface *surface)
       
   361 {
       
   362    _kernel_swi_regs regs;
       
   363    regs.r[0] = 19;
       
   364 
       
   365    FULLSCREEN_SetDisplayBank(this->hidden->current_bank);
       
   366    this->hidden->current_bank ^= 1;
       
   367    FULLSCREEN_SetWriteBank(this->hidden->current_bank);
       
   368    surface->pixels = this->hidden->bank[this->hidden->current_bank];
       
   369 
       
   370    /* Wait for Vsync */
       
   371    _kernel_swi(OS_Byte, &regs, &regs);
       
   372 
       
   373 	return(0);
       
   374 }
       
   375 
       
   376 /* Nothing to do if we are writing direct to hardware */
       
   377 static void FULLSCREEN_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
       
   378 {
       
   379 }
       
   380 
       
   381 /* Safe but slower Memory copy from our allocated back buffer */
       
   382 static void FULLSCREEN_UpdateRectsMemCpy(_THIS, int numrects, SDL_Rect *rects)
       
   383 {
       
   384       int j;
       
   385       char *to, *from;
       
   386       int pitch = this->screen->pitch;
       
   387       int row;
       
   388       int xmult = this->screen->format->BytesPerPixel;
       
   389       for (j = 0; j < numrects; j++)
       
   390       {
       
   391          from = this->hidden->bank[0] + rects->x * xmult + rects->y * pitch;
       
   392          to  = this->hidden->bank[1] + rects->x * xmult + rects->y * pitch;
       
   393          for (row = 0; row < rects->h; row++)
       
   394          {
       
   395              SDL_memcpy(to, from, rects->w * xmult);
       
   396              from += pitch;
       
   397              to += pitch;
       
   398          }
       
   399          rects++;
       
   400       }
       
   401 }
       
   402 
       
   403 /* Use optimized assembler memory copy. Deliberately copies extra columns if
       
   404    necessary to ensure the rectangle is word aligned. */
       
   405 static void FULLSCREEN_UpdateRects8bpp(_THIS, int numrects, SDL_Rect *rects)
       
   406 {
       
   407    int j;
       
   408    char *to, *from;
       
   409    int pitch = this->screen->pitch;
       
   410    int width_bytes;
       
   411    int src_skip_bytes;
       
   412 
       
   413    for (j = 0; j < numrects; j++)
       
   414    {
       
   415       from = this->hidden->bank[0] + rects->x + rects->y * pitch;
       
   416       to  = this->hidden->bank[1] + rects->x + rects->y * pitch;
       
   417       width_bytes = rects->w;
       
   418       if ((int)from & 3)
       
   419       {
       
   420          int extra = ((int)from & 3);
       
   421          from -= extra;
       
   422          to -= extra;
       
   423          width_bytes += extra;
       
   424       }
       
   425       if (width_bytes & 3) width_bytes += 4 - (width_bytes & 3);
       
   426       src_skip_bytes = pitch - width_bytes;
       
   427                
       
   428       RISCOS_Put32(to, (width_bytes >> 2), pitch, (int)rects->h, from, src_skip_bytes);
       
   429       rects++;
       
   430    }
       
   431 }
       
   432 
       
   433 /* Use optimized assembler memory copy. Deliberately copies extra columns if
       
   434    necessary to ensure the rectangle is word aligned. */
       
   435 static void FULLSCREEN_UpdateRects16bpp(_THIS, int numrects, SDL_Rect *rects)
       
   436 {
       
   437    int j;
       
   438    char *to, *from;
       
   439    int pitch = this->screen->pitch;
       
   440    int width_bytes;
       
   441    int src_skip_bytes;
       
   442 
       
   443    for (j = 0; j < numrects; j++)
       
   444    {
       
   445       from = this->hidden->bank[0] + (rects->x << 1) + rects->y * pitch;
       
   446       to  = this->hidden->bank[1] + (rects->x << 1) + rects->y * pitch;
       
   447       width_bytes = (((int)rects->w) << 1);
       
   448       if ((int)from & 3)
       
   449       {
       
   450          from -= 2;
       
   451          to -= 2;
       
   452          width_bytes += 2;
       
   453       }
       
   454       if (width_bytes & 3) width_bytes += 2;
       
   455       src_skip_bytes = pitch - width_bytes;
       
   456                
       
   457       RISCOS_Put32(to, (width_bytes >> 2), pitch, (int)rects->h, from, src_skip_bytes);
       
   458       rects++;
       
   459    }
       
   460 }
       
   461 
       
   462 /* Use optimized assembler memory copy. 32 bpp modes are always word aligned */
       
   463 static void FULLSCREEN_UpdateRects32bpp(_THIS, int numrects, SDL_Rect *rects)
       
   464 {
       
   465    int j;
       
   466    char *to, *from;
       
   467    int pitch = this->screen->pitch;
       
   468    int width;
       
   469 
       
   470    for (j = 0; j < numrects; j++)
       
   471    {
       
   472       from = this->hidden->bank[0] + (rects->x << 2) + rects->y * pitch;
       
   473       to  = this->hidden->bank[1] + (rects->x << 2) + rects->y * pitch;
       
   474       width = (int)rects->w ;
       
   475                
       
   476       RISCOS_Put32(to, width, pitch, (int)rects->h, from, pitch - (width << 2));
       
   477       rects++;
       
   478    }
       
   479 }
       
   480 
       
   481 /* Use operating system sprite plots. Currently this is much slower than the
       
   482    other variants however accelerated sprite plotting can be seen on the horizon
       
   483    so this prepares for it. */
       
   484 static void FULLSCREEN_UpdateRectsOS(_THIS, int numrects, SDL_Rect *rects)
       
   485 {
       
   486    _kernel_swi_regs regs;
       
   487    _kernel_oserror *err;
       
   488    int j;
       
   489    int y;
       
   490 
       
   491    regs.r[0] = 28 + 512;
       
   492    regs.r[1] = (unsigned int)this->hidden->alloc_bank;
       
   493    regs.r[2] = (unsigned int)this->hidden->alloc_bank+16;
       
   494    regs.r[5] = 0;
       
   495 
       
   496    for (j = 0; j < numrects; j++)
       
   497    {
       
   498       y = this->screen->h - rects->y; /* top of clipping region */
       
   499       _kernel_oswrch(24); /* Set graphics clip region */
       
   500       _kernel_oswrch((rects->x << this->hidden->xeig) & 0xFF); /* left */
       
   501       _kernel_oswrch(((rects->x << this->hidden->xeig) >> 8) & 0xFF);
       
   502       _kernel_oswrch(((y - rects->h) << this->hidden->yeig) & 0xFF); /* bottom */
       
   503       _kernel_oswrch((((y - rects->h) << this->hidden->yeig)>> 8) & 0xFF);
       
   504       _kernel_oswrch(((rects->x + rects->w - 1) << this->hidden->xeig) & 0xFF); /* right */
       
   505       _kernel_oswrch((((rects->x + rects->w - 1)<< this->hidden->xeig) >> 8) & 0xFF);
       
   506       _kernel_oswrch(((y-1) << this->hidden->yeig) & 0xFF); /* top */
       
   507       _kernel_oswrch((((y-1) << this->hidden->yeig) >> 8) & 0xFF);
       
   508 
       
   509       regs.r[3] = 0;
       
   510       regs.r[4] = 0;
       
   511 
       
   512       if ((err = _kernel_swi(OS_SpriteOp, &regs, &regs)) != 0)
       
   513       {
       
   514          printf("OS_SpriteOp failed \n%s\n",err->errmess);
       
   515       }
       
   516 
       
   517       rects++;
       
   518 
       
   519       /* Reset to full screen clipping */
       
   520       _kernel_oswrch(24); /* Set graphics clip region */
       
   521       _kernel_oswrch(0); /* left */
       
   522       _kernel_oswrch(0);
       
   523       _kernel_oswrch(0); /* bottom */
       
   524       _kernel_oswrch(0);
       
   525       _kernel_oswrch(((this->screen->w-1) << this->hidden->xeig) & 0xFF); /* right */
       
   526       _kernel_oswrch((((this->screen->w-1) << this->hidden->xeig) >> 8) & 0xFF);
       
   527       _kernel_oswrch(((this->screen->h-1) << this->hidden->yeig) & 0xFF); /* top */
       
   528       _kernel_oswrch((((this->screen->h-1) << this->hidden->yeig) >> 8) & 0xFF);
       
   529    }
       
   530 }
       
   531 
       
   532 
       
   533 int FULLSCREEN_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
       
   534 {
       
   535 	_kernel_swi_regs regs;
       
   536 	int palette[256];
       
   537 
       
   538 	regs.r[0] = -1;
       
   539 	regs.r[1] = -1;
       
   540 	regs.r[2] = (int)palette;
       
   541 	regs.r[3] = 1024;
       
   542 	regs.r[4] = 0;
       
   543 	_kernel_swi(ColourTrans_ReadPalette, &regs, &regs);
       
   544 
       
   545 	while(ncolors--)
       
   546 	{
       
   547 		palette[firstcolor] = ((colors->b) << 24) | ((colors->g) << 16) | ((colors->r) << 8);
       
   548 		firstcolor++;
       
   549 		colors++;
       
   550 	}
       
   551 
       
   552 	regs.r[0] = -1;
       
   553 	regs.r[1] = -1;
       
   554 	regs.r[2] = (int)palette;
       
   555 	regs.r[3] = 0;
       
   556 	regs.r[4] = 0;
       
   557 	_kernel_swi(ColourTrans_WritePalette, &regs, &regs);
       
   558 
       
   559 	return(1);
       
   560 }
       
   561 
       
   562 
       
   563 static int cmpmodes(const void *va, const void *vb)
       
   564 {
       
   565     SDL_Rect *a = *(SDL_Rect **)va;
       
   566     SDL_Rect *b = *(SDL_Rect **)vb;
       
   567     if(a->w == b->w)
       
   568         return b->h - a->h;
       
   569     else
       
   570         return b->w - a->w;
       
   571 }
       
   572 
       
   573 static int FULLSCREEN_AddMode(_THIS, int bpp, int w, int h)
       
   574 {
       
   575 	SDL_Rect *mode;
       
   576 	int i, index;
       
   577 	int next_mode;
       
   578 
       
   579 	/* Check to see if we already have this mode */
       
   580 	if ( bpp < 8 ) {  /* Not supported */
       
   581 		return(0);
       
   582 	}
       
   583 	index = ((bpp+7)/8)-1;
       
   584 	for ( i=0; i<SDL_nummodes[index]; ++i ) {
       
   585 		mode = SDL_modelist[index][i];
       
   586 		if ( (mode->w == w) && (mode->h == h) ) {
       
   587 			return(0);
       
   588 		}
       
   589 	}
       
   590 
       
   591 	/* Set up the new video mode rectangle */
       
   592 	mode = (SDL_Rect *)SDL_malloc(sizeof *mode);
       
   593 	if ( mode == NULL ) {
       
   594 		SDL_OutOfMemory();
       
   595 		return(-1);
       
   596 	}
       
   597 	mode->x = 0;
       
   598 	mode->y = 0;
       
   599 	mode->w = w;
       
   600 	mode->h = h;
       
   601 
       
   602 	/* Allocate the new list of modes, and fill in the new mode */
       
   603 	next_mode = SDL_nummodes[index];
       
   604 	SDL_modelist[index] = (SDL_Rect **)
       
   605 	       SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *));
       
   606 	if ( SDL_modelist[index] == NULL ) {
       
   607 		SDL_OutOfMemory();
       
   608 		SDL_nummodes[index] = 0;
       
   609 		SDL_free(mode);
       
   610 		return(-1);
       
   611 	}
       
   612 	SDL_modelist[index][next_mode] = mode;
       
   613 	SDL_modelist[index][next_mode+1] = NULL;
       
   614 	SDL_nummodes[index]++;
       
   615 
       
   616 	return(0);
       
   617 }
       
   618 
       
   619 void FULLSCREEN_SetWriteBank(int bank)
       
   620 {
       
   621    _kernel_swi_regs regs;
       
   622    regs.r[0] = 112;
       
   623    regs.r[1] = bank+1;
       
   624    _kernel_swi(OS_Byte, &regs, &regs);
       
   625 }
       
   626 
       
   627 void FULLSCREEN_SetDisplayBank(int bank)
       
   628 {
       
   629    _kernel_swi_regs regs;
       
   630    regs.r[0] = 113;
       
   631    regs.r[1] = bank+1;
       
   632    _kernel_swi(OS_Byte, &regs, &regs);
       
   633 }
       
   634 
       
   635 
       
   636 /** Disable special escape key processing */
       
   637 static void FULLSCREEN_DisableEscape()
       
   638 {
       
   639    _kernel_swi_regs regs;
       
   640    regs.r[0] = 229;
       
   641    regs.r[1] = 1;
       
   642    regs.r[2] = 0;
       
   643    _kernel_swi(OS_Byte, &regs, &regs);
       
   644   
       
   645 }
       
   646 
       
   647 /** Enable special escape key processing */
       
   648 static void FULLSCREEN_EnableEscape()
       
   649 {
       
   650    _kernel_swi_regs regs;
       
   651    regs.r[0] = 229;
       
   652    regs.r[1] = 0;
       
   653    regs.r[2] = 0;
       
   654    _kernel_swi(OS_Byte, &regs, &regs);
       
   655   
       
   656 }
       
   657 
       
   658 /** Store caption in case this is called before we create a window */
       
   659 void FULLSCREEN_SetWMCaption(_THIS, const char *title, const char *icon)
       
   660 {
       
   661 	SDL_strlcpy(this->hidden->title, title, SDL_arraysize(this->hidden->title));
       
   662 }
       
   663 
       
   664 /* Set screen mode
       
   665 *
       
   666 *  Returns 1 if mode is set ok, otherwise 0
       
   667 */
       
   668 
       
   669 int FULLSCREEN_SetMode(int width, int height, int bpp)
       
   670 {
       
   671    SCREENMODEBLOCK smb;
       
   672    _kernel_swi_regs regs;
       
   673 
       
   674    smb.flags = 1;
       
   675    smb.x_pixels = width;
       
   676    smb.y_pixels = height;
       
   677    smb.mode_vars[0] = -1;
       
   678 
       
   679    switch(bpp)
       
   680    {
       
   681 	case 8:
       
   682 		smb.pixel_depth = 3;
       
   683 		/* Note: Need to set ModeFlags to 128 and NColour variables to 255 get full 8 bit palette */
       
   684 		smb.mode_vars[0] = 0; smb.mode_vars[1] = 128; /* Mode flags */
       
   685 		smb.mode_vars[2] = 3; smb.mode_vars[3] = 255; /* NColour (number of colours -1) */
       
   686 		smb.mode_vars[4] = -1; /* End of list */
       
   687 		break;
       
   688 
       
   689 	case 15:
       
   690 	case 16:
       
   691 		smb.pixel_depth = 4;
       
   692 		break;
       
   693 
       
   694 	case 32:
       
   695 		smb.pixel_depth = 5;
       
   696 		break;
       
   697 
       
   698 	default:
       
   699 		SDL_SetError("Pixel depth not supported");
       
   700 		return 0;
       
   701 		break;
       
   702    }
       
   703    
       
   704    smb.frame_rate = -1;
       
   705 
       
   706    regs.r[0] = 0;
       
   707    regs.r[1] = (int)&smb;
       
   708 
       
   709    if (_kernel_swi(OS_ScreenMode, &regs, &regs) != 0)
       
   710    {
       
   711 	   SDL_SetError("Couldn't set requested mode");
       
   712 	   return 0;
       
   713    }
       
   714 
       
   715     /* Turn cursor off*/
       
   716     _kernel_oswrch(23);_kernel_oswrch(1);_kernel_oswrch(0);
       
   717     _kernel_oswrch(0);_kernel_oswrch(0);_kernel_oswrch(0);
       
   718     _kernel_oswrch(0);_kernel_oswrch(0);_kernel_oswrch(0);
       
   719     _kernel_oswrch(0);_kernel_oswrch(0);
       
   720 
       
   721    return 1;
       
   722 }
       
   723 
       
   724 /* Get Start addresses for the screen banks */
       
   725 void FULLSCREEN_SetupBanks(_THIS)
       
   726 {
       
   727    _kernel_swi_regs regs;
       
   728    int block[5];
       
   729    block[0] = 148; /* Write screen start */
       
   730    block[1] = 149; /* Display screen start */
       
   731    block[2] = 4;  /* X eig factor */
       
   732    block[3] = 5;  /* Y eig factor */
       
   733    block[4] = -1;  /* End of list of variables to request */
       
   734 
       
   735    regs.r[0] = (int)block;
       
   736    regs.r[1] = (int)block;
       
   737    _kernel_swi(OS_ReadVduVariables, &regs, &regs);
       
   738 
       
   739    this->hidden->bank[0] = (void *)block[0];
       
   740    this->hidden->bank[1] = (void *)block[1];
       
   741    this->hidden->xeig = block[2];
       
   742    this->hidden->yeig = block[3];
       
   743 }
       
   744 
       
   745 /* Toggle to full screen mode from the WIMP */
       
   746 
       
   747 int FULLSCREEN_ToggleFromWimp(_THIS)
       
   748 {
       
   749    int width = this->screen->w;
       
   750    int height = this->screen->h;
       
   751    int bpp = this->screen->format->BitsPerPixel;
       
   752 
       
   753    RISCOS_StoreWimpMode();
       
   754    if (FULLSCREEN_SetMode(width, height, bpp))
       
   755    {
       
   756        char *buffer = this->hidden->alloc_bank; /* This is start of sprite data */
       
   757        /* Support back buffer mode only */
       
   758        if (riscos_backbuffer == 0) riscos_backbuffer = 1;
       
   759 
       
   760        FULLSCREEN_SetupBanks(this);
       
   761 
       
   762        this->hidden->bank[0] = buffer + 60; /* Start of sprite data */
       
   763        if (bpp == 8) this->hidden->bank[0] += 2048; /* 8bpp sprite have palette first */
       
   764 
       
   765 	   this->hidden->current_bank = 0;
       
   766 	   this->screen->pixels = this->hidden->bank[0];
       
   767 
       
   768        /* Copy back buffer to screen memory */
       
   769        SDL_memcpy(this->hidden->bank[1], this->hidden->bank[0], width * height * this->screen->format->BytesPerPixel);
       
   770 
       
   771        FULLSCREEN_SetDeviceMode(this);
       
   772        return 1;
       
   773    } else
       
   774       RISCOS_RestoreWimpMode();
       
   775 
       
   776    return 0;
       
   777 }