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