src/video/riscos/SDL_riscosFullScreenVideo.c
changeset 630 550bccdf04bd
child 769 b8d311d90021
equal deleted inserted replaced
629:3fa401bb4bb5 630:550bccdf04bd
       
     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      File added by Alan Buckley (alan_baa@hotmail.com) for RISCOS compatability
       
    25 	 27 March 2003
       
    26 
       
    27      Implements RISCOS full screen display.
       
    28 */
       
    29 
       
    30 #include <stdio.h>
       
    31 #include <stdlib.h>
       
    32 #include <string.h>
       
    33 
       
    34 #include "SDL.h"
       
    35 #include "SDL_error.h"
       
    36 #include "SDL_video.h"
       
    37 #include "SDL_mouse.h"
       
    38 #include "SDL_sysvideo.h"
       
    39 #include "SDL_pixels_c.h"
       
    40 #include "SDL_events_c.h"
       
    41 
       
    42 #include "SDL_riscostask.h"
       
    43 #include "SDL_riscosvideo.h"
       
    44 #include "SDL_riscosevents_c.h"
       
    45 #include "SDL_riscosmouse_c.h"
       
    46 
       
    47 #include "kernel.h"
       
    48 #include "swis.h"
       
    49 #include "unixlib/os.h"
       
    50 #include "unixlib/local.h"
       
    51 
       
    52 /* Private structures */
       
    53 typedef struct tagScreenModeBlock
       
    54 {
       
    55    int flags;  // mode selector flags, bit 0 = 1, bit 1-7 format specifier, 8-31 reserved
       
    56    int x_pixels;
       
    57    int y_pixels;
       
    58    int pixel_depth;  // 2^pixel_depth = bpp,i.e. 0 = 1, 1 = 2, 4 = 16, 5 = 32
       
    59    int frame_rate;   // -1 use first match
       
    60    int mode_vars[5]; // array of index, value pairs terminated by -1
       
    61 } SCREENMODEBLOCK;
       
    62 
       
    63 
       
    64 /* Helper functions */
       
    65 void FULLSCREEN_SetDeviceMode(_THIS);
       
    66 int FULLSCREEN_SetMode(int width, int height, int bpp);
       
    67 void FULLSCREEN_SetupBanks(_THIS);
       
    68 
       
    69 /* SDL video device functions for fullscreen mode */
       
    70 static int FULLSCREEN_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
       
    71 static int FULLSCREEN_FlipHWSurface(_THIS, SDL_Surface *surface);
       
    72 static void FULLSCREEN_UpdateRects(_THIS, int numrects, SDL_Rect *rects);
       
    73 void FULLSCREEN_SetWMCaption(_THIS, const char *title, const char *icon);
       
    74 extern int RISCOS_GetWmInfo(_THIS, SDL_SysWMinfo *info);
       
    75 
       
    76 /* Local helper functions */
       
    77 static int cmpmodes(const void *va, const void *vb);
       
    78 static int FULLSCREEN_AddMode(_THIS, int bpp, int w, int h);
       
    79 void FULLSCREEN_SetWriteBank(int bank);
       
    80 void FULLSCREEN_SetDisplayBank(int bank);
       
    81 static void FULLSCREEN_DisableEscape();
       
    82 static void FULLSCREEN_EnableEscape();
       
    83 void FULLSCREEN_BuildModeList(_THIS);
       
    84 
       
    85 /* Following variable is set up in riskosTask.c */
       
    86 extern int riscos_backbuffer; /* Create a back buffer in system memory for full screen mode */
       
    87 
       
    88 
       
    89 
       
    90 SDL_Surface *FULLSCREEN_SetVideoMode(_THIS, SDL_Surface *current,
       
    91 				int width, int height, int bpp, Uint32 flags)
       
    92 {
       
    93    _kernel_swi_regs regs;
       
    94    Uint32 Rmask = 0;
       
    95    Uint32 Gmask = 0;
       
    96    Uint32 Bmask = 0;
       
    97    int create_back_buffer = riscos_backbuffer;
       
    98 
       
    99    switch(bpp)
       
   100    {
       
   101 	case 8:
       
   102 		flags |= SDL_HWPALETTE;
       
   103 		break;
       
   104 
       
   105 	case 15:
       
   106 	case 16:
       
   107 		Bmask = 0x00007c00;
       
   108 		Gmask = 0x000003e0;
       
   109 		Rmask = 0x0000001f;
       
   110 		break;
       
   111 
       
   112 	case 32:
       
   113 		Bmask = 0x00ff0000;
       
   114 		Gmask = 0x0000ff00;
       
   115 		Rmask = 0x000000ff;
       
   116 		break;
       
   117 
       
   118 	default:
       
   119 		SDL_SetError("Pixel depth not supported");
       
   120 		return NULL;
       
   121 		break;
       
   122    }
       
   123 
       
   124    if (FULLSCREEN_SetMode(width, height, bpp) == 0)
       
   125    {
       
   126 	   SDL_SetError("Couldn't set requested mode");
       
   127 	   return (NULL);
       
   128    }
       
   129 
       
   130 /* 	printf("Setting mode %dx%d\n", width, height); */
       
   131 
       
   132 	/* Allocate the new pixel format for the screen */
       
   133 	if ( ! SDL_ReallocFormat(current, bpp, Rmask, Gmask, Bmask, 0) ) {
       
   134 	    RISCOS_RestoreWimpMode();
       
   135 		SDL_SetError("Couldn't allocate new pixel format for requested mode");
       
   136 		return(NULL);
       
   137 	}
       
   138 
       
   139 	/* Set up the new mode framebuffer */
       
   140 	current->w = width;
       
   141 	this->hidden->height = current->h = height;
       
   142 
       
   143    regs.r[0] = -1; /* -1 for current screen mode */
       
   144 
       
   145    /* Get screen width in bytes */
       
   146    regs.r[1] = 6; // Screen Width in bytes
       
   147    _kernel_swi(OS_ReadModeVariable, &regs, &regs);
       
   148 
       
   149    current->pitch = regs.r[2];
       
   150 
       
   151    if (flags & SDL_DOUBLEBUF)
       
   152    {
       
   153 	   regs.r[0] = 2; /* Screen area */
       
   154 	   _kernel_swi(OS_ReadDynamicArea, &regs, &regs);
       
   155 	   
       
   156 	   /* Reg 1 has amount of memory currently used for display */
       
   157 	   regs.r[0] = 2; /* Screen area */
       
   158 	   regs.r[1] = (current->pitch * height * 2) - regs.r[1];
       
   159 	   if (_kernel_swi(OS_ChangeDynamicArea, &regs, &regs) != NULL)
       
   160 	   {
       
   161 		   /* Can't allocate enough screen memory for double buffer */
       
   162 		   flags &= ~SDL_DOUBLEBUF;
       
   163 	   }
       
   164    }
       
   165    
       
   166   	current->flags = flags | SDL_FULLSCREEN | SDL_HWSURFACE | SDL_PREALLOC;
       
   167 	
       
   168 
       
   169 	/* Need to set display banks here for double buffering */
       
   170 	if (flags & SDL_DOUBLEBUF)
       
   171 	{
       
   172 	   FULLSCREEN_SetWriteBank(0);
       
   173 	   FULLSCREEN_SetDisplayBank(1);
       
   174 
       
   175          create_back_buffer = 0; /* Don't need a back buffer for a double buffered display */
       
   176     }
       
   177 
       
   178     FULLSCREEN_SetupBanks(this);
       
   179 
       
   180     if (create_back_buffer)
       
   181     {
       
   182        /* If not double buffered we may need to create a memory
       
   183        ** back buffer to simulate processing on other OS's. 
       
   184          ** This is turned on by setting the enviromental variable
       
   185          ** SDL$<name>$BackBuffer to 1
       
   186          */    
       
   187        this->hidden->bank[0] = malloc(height * current->pitch);
       
   188        if (this->hidden->bank[0] == 0)
       
   189        {
       
   190  	       RISCOS_RestoreWimpMode();
       
   191            SDL_SetError("Couldnt allocate memory for back buffer");
       
   192            return (NULL);
       
   193        }
       
   194        /* Surface updated in programs is now a software surface */
       
   195        current->flags &= ~SDL_HWSURFACE;
       
   196     }
       
   197 
       
   198 	   /* Store address of allocated screen bank to be freed later */
       
   199 	   if (this->hidden->alloc_bank) free(this->hidden->alloc_bank);
       
   200 	   if (create_back_buffer)
       
   201 	   {
       
   202 		   this->hidden->alloc_bank = this->hidden->bank[0];
       
   203 	   } else
       
   204 		   this->hidden->alloc_bank = 0;
       
   205 
       
   206        // Clear both banks to black
       
   207        memset(this->hidden->bank[0], 0, height * current->pitch);
       
   208 	   memset(this->hidden->bank[1], 0, height * current->pitch);
       
   209 
       
   210  	   this->hidden->current_bank = 0;
       
   211 	   current->pixels = this->hidden->bank[0];
       
   212 
       
   213 	/* Reset device functions for the wimp */
       
   214 	FULLSCREEN_SetDeviceMode(this);
       
   215 
       
   216 /*	FULLSCREEN_DisableEscape(); */
       
   217 
       
   218 	/* We're done */
       
   219 	return(current);
       
   220 }
       
   221 
       
   222 /* Reset any device functions that have been changed because we have run in WIMP mode */
       
   223 void FULLSCREEN_SetDeviceMode(_THIS)
       
   224 {
       
   225 	if (this->SetColors == FULLSCREEN_SetColors) return; /* Already set up */
       
   226 
       
   227 	this->SetColors   = FULLSCREEN_SetColors;
       
   228 	this->UpdateRects = FULLSCREEN_UpdateRects;
       
   229 
       
   230 	this->FlipHWSurface = FULLSCREEN_FlipHWSurface;
       
   231 
       
   232 	this->SetCaption = FULLSCREEN_SetWMCaption;
       
   233 	this->SetIcon = NULL;
       
   234 	this->IconifyWindow = NULL;
       
   235 	
       
   236 	this->ShowWMCursor = RISCOS_ShowWMCursor;
       
   237 	this->WarpWMCursor = FULLSCREEN_WarpWMCursor;
       
   238 
       
   239 	this->PumpEvents = FULLSCREEN_PumpEvents;	
       
   240 }
       
   241 
       
   242 /* Query for the list of available video modes */
       
   243 void FULLSCREEN_BuildModeList(_THIS)
       
   244 {
       
   245 	_kernel_swi_regs regs;
       
   246 	char *enumInfo = NULL;
       
   247 	char *enum_ptr;
       
   248 	int *blockInfo;
       
   249 	int j;
       
   250 	int num_modes;
       
   251 
       
   252 	/* Find out how much space we need */
       
   253 	regs.r[0] = 2; /* Reason code */
       
   254 	regs.r[2] = 0; /* Number of modes to skip */
       
   255 	regs.r[6] = 0; /* pointer to block or 0 for count */
       
   256 	regs.r[7] = 0; /* Size of block in bytes */
       
   257 	_kernel_swi(OS_ScreenMode, &regs, &regs);
       
   258 
       
   259     num_modes = -regs.r[2];
       
   260 
       
   261 	/* Video memory should be in r[5] */
       
   262 	this->info.video_mem = regs.r[5]/1024;
       
   263 
       
   264 	enumInfo = (unsigned char *)malloc(-regs.r[7]);
       
   265 	if (enumInfo == NULL)
       
   266 	{
       
   267 		SDL_OutOfMemory();
       
   268 		return;
       
   269 	}
       
   270 	/* Read mode information into block */
       
   271 	regs.r[2] = 0;
       
   272 	regs.r[6] = (int)enumInfo;
       
   273 	regs.r[7] = -regs.r[7];
       
   274 	_kernel_swi(OS_ScreenMode, &regs, &regs);
       
   275 
       
   276 	enum_ptr = enumInfo;
       
   277 
       
   278 	for (j =0; j < num_modes;j++)
       
   279 	{
       
   280 		blockInfo = (int *)enum_ptr;
       
   281 		if ((blockInfo[1] & 255) == 1) /* We understand this format */
       
   282 		{
       
   283 			switch(blockInfo[4])
       
   284 			{
       
   285 			case 3: /* 8 bits per pixel */
       
   286 				FULLSCREEN_AddMode(this, 8, blockInfo[2], blockInfo[3]);
       
   287 				break;
       
   288 			case 4: /* 15 bits per pixel */
       
   289 				FULLSCREEN_AddMode(this, 15, blockInfo[2], blockInfo[3]);
       
   290 				break;
       
   291 			case 5: /* 32 bits per pixel */
       
   292 				FULLSCREEN_AddMode(this, 32, blockInfo[2], blockInfo[3]);
       
   293 				break;
       
   294 			}
       
   295 		}
       
   296 
       
   297 		enum_ptr += blockInfo[0];
       
   298 	}
       
   299 
       
   300 	free(enumInfo);
       
   301 		
       
   302 	/* Sort the mode lists */
       
   303 	for ( j=0; j<NUM_MODELISTS; ++j ) {
       
   304 		if ( SDL_nummodes[j] > 0 ) {
       
   305 			qsort(SDL_modelist[j], SDL_nummodes[j], sizeof *SDL_modelist[j], cmpmodes);
       
   306 		}
       
   307 	}
       
   308 }
       
   309 
       
   310 static int FULLSCREEN_FlipHWSurface(_THIS, SDL_Surface *surface)
       
   311 {
       
   312    _kernel_swi_regs regs;
       
   313    regs.r[0] = 19;
       
   314    /* Wait for Vsync */
       
   315    _kernel_swi(OS_Byte, &regs, &regs);
       
   316 
       
   317    FULLSCREEN_SetDisplayBank(this->hidden->current_bank);
       
   318    this->hidden->current_bank ^= 1;
       
   319    FULLSCREEN_SetWriteBank(this->hidden->current_bank);
       
   320    surface->pixels = this->hidden->bank[this->hidden->current_bank];
       
   321 
       
   322 	return(0);
       
   323 }
       
   324 
       
   325 static void FULLSCREEN_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
       
   326 {
       
   327    if (riscos_backbuffer && (this->screen->flags & SDL_DOUBLEBUF) == 0)
       
   328    {
       
   329       /* If not double buffered copy rectangles to main screen now */
       
   330       int j;
       
   331       char *to, *from;
       
   332       int pitch = this->screen->pitch;
       
   333       int row;
       
   334       int xmult = this->screen->format->BytesPerPixel;
       
   335       for (j = 0; j < numrects; j++)
       
   336       {
       
   337          from = this->hidden->bank[0] + rects->x * xmult + rects->y * pitch;
       
   338          to  = this->hidden->bank[1] + rects->x * xmult + rects->y * pitch;
       
   339          for (row = 0; row < rects->h; row++)
       
   340          {
       
   341              memcpy(to, from, rects->w * xmult);
       
   342              from += pitch;
       
   343              to += pitch;
       
   344          }
       
   345          rects++;
       
   346       }
       
   347    }
       
   348 }
       
   349 
       
   350 int FULLSCREEN_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
       
   351 {
       
   352 	_kernel_swi_regs regs;
       
   353 	int palette[256];
       
   354 
       
   355 	regs.r[0] = -1;
       
   356 	regs.r[1] = -1;
       
   357 	regs.r[2] = (int)palette;
       
   358 	regs.r[3] = 1024;
       
   359 	regs.r[4] = 0;
       
   360 	_kernel_swi(ColourTrans_ReadPalette, &regs, &regs);
       
   361 
       
   362 	while(ncolors--)
       
   363 	{
       
   364 		palette[firstcolor] = ((colors->b) << 24) | ((colors->g) << 16) | ((colors->r) << 8);
       
   365 		firstcolor++;
       
   366 		colors++;
       
   367 	}
       
   368 
       
   369 	regs.r[0] = -1;
       
   370 	regs.r[1] = -1;
       
   371 	regs.r[2] = (int)palette;
       
   372 	regs.r[3] = 0;
       
   373 	regs.r[4] = 0;
       
   374 	_kernel_swi(ColourTrans_WritePalette, &regs, &regs);
       
   375 
       
   376 	return(1);
       
   377 }
       
   378 
       
   379 
       
   380 static int cmpmodes(const void *va, const void *vb)
       
   381 {
       
   382     SDL_Rect *a = *(SDL_Rect **)va;
       
   383     SDL_Rect *b = *(SDL_Rect **)vb;
       
   384     if(a->w > b->w)
       
   385         return -1;
       
   386     return b->h - a->h;
       
   387 }
       
   388 
       
   389 static int FULLSCREEN_AddMode(_THIS, int bpp, int w, int h)
       
   390 {
       
   391 	SDL_Rect *mode;
       
   392 	int i, index;
       
   393 	int next_mode;
       
   394 
       
   395 	/* Check to see if we already have this mode */
       
   396 	if ( bpp < 8 ) {  /* Not supported */
       
   397 		return(0);
       
   398 	}
       
   399 	index = ((bpp+7)/8)-1;
       
   400 	for ( i=0; i<SDL_nummodes[index]; ++i ) {
       
   401 		mode = SDL_modelist[index][i];
       
   402 		if ( (mode->w == w) && (mode->h == h) ) {
       
   403 			return(0);
       
   404 		}
       
   405 	}
       
   406 
       
   407 	/* Set up the new video mode rectangle */
       
   408 	mode = (SDL_Rect *)malloc(sizeof *mode);
       
   409 	if ( mode == NULL ) {
       
   410 		SDL_OutOfMemory();
       
   411 		return(-1);
       
   412 	}
       
   413 	mode->x = 0;
       
   414 	mode->y = 0;
       
   415 	mode->w = w;
       
   416 	mode->h = h;
       
   417 
       
   418 	/* Allocate the new list of modes, and fill in the new mode */
       
   419 	next_mode = SDL_nummodes[index];
       
   420 	SDL_modelist[index] = (SDL_Rect **)
       
   421 	       realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *));
       
   422 	if ( SDL_modelist[index] == NULL ) {
       
   423 		SDL_OutOfMemory();
       
   424 		SDL_nummodes[index] = 0;
       
   425 		free(mode);
       
   426 		return(-1);
       
   427 	}
       
   428 	SDL_modelist[index][next_mode] = mode;
       
   429 	SDL_modelist[index][next_mode+1] = NULL;
       
   430 	SDL_nummodes[index]++;
       
   431 
       
   432 	return(0);
       
   433 }
       
   434 
       
   435 void FULLSCREEN_SetWriteBank(int bank)
       
   436 {
       
   437    _kernel_swi_regs regs;
       
   438    regs.r[0] = 112;
       
   439    regs.r[1] = bank+1;
       
   440    _kernel_swi(OS_Byte, &regs, &regs);
       
   441 }
       
   442 
       
   443 void FULLSCREEN_SetDisplayBank(int bank)
       
   444 {
       
   445    _kernel_swi_regs regs;
       
   446    regs.r[0] = 113;
       
   447    regs.r[1] = bank+1;
       
   448    _kernel_swi(OS_Byte, &regs, &regs);
       
   449 }
       
   450 
       
   451 
       
   452 /** Disable special escape key processing */
       
   453 static void FULLSCREEN_DisableEscape()
       
   454 {
       
   455    _kernel_swi_regs regs;
       
   456    regs.r[0] = 229;
       
   457    regs.r[1] = 1;
       
   458    regs.r[2] = 0;
       
   459    _kernel_swi(OS_Byte, &regs, &regs);
       
   460   
       
   461 }
       
   462 
       
   463 /** Enable special escape key processing */
       
   464 static void FULLSCREEN_EnableEscape()
       
   465 {
       
   466    _kernel_swi_regs regs;
       
   467    regs.r[0] = 229;
       
   468    regs.r[1] = 0;
       
   469    regs.r[2] = 0;
       
   470    _kernel_swi(OS_Byte, &regs, &regs);
       
   471   
       
   472 }
       
   473 
       
   474 /** Store caption in case this is called before we create a window */
       
   475 void FULLSCREEN_SetWMCaption(_THIS, const char *title, const char *icon)
       
   476 {
       
   477 	strncpy(this->hidden->title, title, 255);
       
   478 	this->hidden->title[255] = 0;
       
   479 }
       
   480 
       
   481 /* Set screen mode
       
   482 *
       
   483 *  Returns 1 if mode is set ok, otherwise 0
       
   484 */
       
   485 
       
   486 int FULLSCREEN_SetMode(int width, int height, int bpp)
       
   487 {
       
   488    SCREENMODEBLOCK smb;
       
   489    _kernel_swi_regs regs;
       
   490 
       
   491    smb.flags = 1;
       
   492    smb.x_pixels = width;
       
   493    smb.y_pixels = height;
       
   494    smb.mode_vars[0] = -1;
       
   495 
       
   496    switch(bpp)
       
   497    {
       
   498 	case 8:
       
   499 		smb.pixel_depth = 3;
       
   500 		/* Note: Need to set ModeFlags to 128 and NColour variables to 255 get full 8 bit palette */
       
   501 		smb.mode_vars[0] = 0; smb.mode_vars[1] = 128; /* Mode flags */
       
   502 		smb.mode_vars[2] = 3; smb.mode_vars[3] = 255; /* NColour (number of colours -1) */
       
   503 		smb.mode_vars[4] = -1; /* End of list */
       
   504 		break;
       
   505 
       
   506 	case 15:
       
   507 	case 16:
       
   508 		smb.pixel_depth = 4;
       
   509 		break;
       
   510 
       
   511 	case 32:
       
   512 		smb.pixel_depth = 5;
       
   513 		break;
       
   514 
       
   515 	default:
       
   516 		SDL_SetError("Pixel depth not supported");
       
   517 		return 0;
       
   518 		break;
       
   519    }
       
   520    
       
   521    smb.frame_rate = -1;
       
   522 
       
   523    regs.r[0] = 0;
       
   524    regs.r[1] = (int)&smb;
       
   525 
       
   526    if (_kernel_swi(OS_ScreenMode, &regs, &regs) != 0)
       
   527    {
       
   528 	   SDL_SetError("Couldn't set requested mode");
       
   529 	   return 0;
       
   530    }
       
   531 
       
   532     /* Turn cursor off*/
       
   533     _kernel_oswrch(23);_kernel_oswrch(1);_kernel_oswrch(0);
       
   534     _kernel_oswrch(0);_kernel_oswrch(0);_kernel_oswrch(0);
       
   535     _kernel_oswrch(0);_kernel_oswrch(0);_kernel_oswrch(0);
       
   536     _kernel_oswrch(0);_kernel_oswrch(0);
       
   537 
       
   538    return 1;
       
   539 }
       
   540 
       
   541 /* Get Start addresses for the screen banks */
       
   542 void FULLSCREEN_SetupBanks(_THIS)
       
   543 {
       
   544    _kernel_swi_regs regs;
       
   545    int block[5];
       
   546    block[0] = 148; /* Write screen start */
       
   547    block[1] = 149; /* Display screen start */
       
   548    block[2] = 4;  /* X eig factor */
       
   549    block[3] = 5;  /* Y eig factor */
       
   550    block[4] = -1;  /* End of list of variables to request */
       
   551 
       
   552    regs.r[0] = (int)block;
       
   553    regs.r[1] = (int)block;
       
   554    _kernel_swi(OS_ReadVduVariables, &regs, &regs);
       
   555 
       
   556    this->hidden->bank[0] = (void *)block[0];
       
   557    this->hidden->bank[1] = (void *)block[1];
       
   558    this->hidden->xeig = block[2];
       
   559    this->hidden->yeig = block[3];
       
   560 }
       
   561 
       
   562 /* Toggle to full screen mode from the WIMP */
       
   563 
       
   564 int FULLSCREEN_ToggleFromWimp(_THIS)
       
   565 {
       
   566    int width = this->screen->w;
       
   567    int height = this->screen->h;
       
   568    int bpp = this->screen->format->BitsPerPixel;
       
   569 
       
   570    RISCOS_StoreWimpMode();
       
   571    if (FULLSCREEN_SetMode(width, height, bpp))
       
   572    {
       
   573        char *buffer = this->hidden->alloc_bank; /* This is start of sprite data */
       
   574        /* Support back buffer mode only */
       
   575        riscos_backbuffer = 1;
       
   576 
       
   577        FULLSCREEN_SetupBanks(this);
       
   578 
       
   579        this->hidden->bank[0] = buffer + 60; /* Start of sprite data */
       
   580        if (bpp == 8) this->hidden->bank[0] += 2048; /* 8bpp sprite have palette first */
       
   581 
       
   582 	   this->hidden->current_bank = 0;
       
   583 	   this->screen->pixels = this->hidden->bank[0];
       
   584 
       
   585        /* Copy back buffer to screen memory */
       
   586        memcpy(this->hidden->bank[1], this->hidden->bank[0], width * height * this->screen->format->BytesPerPixel);
       
   587 
       
   588        FULLSCREEN_SetDeviceMode(this);
       
   589        return 1;
       
   590    } else
       
   591       RISCOS_RestoreWimpMode();
       
   592 
       
   593    return 0;
       
   594 }