SDL-1.2.14
[sdl_omap.git] / src / video / riscos / SDL_riscosFullScreenVideo.c
CommitLineData
e14743d1 1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 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 */
48typedef 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 */
60void FULLSCREEN_SetDeviceMode(_THIS);
61int FULLSCREEN_SetMode(int width, int height, int bpp);
62void FULLSCREEN_SetupBanks(_THIS);
63
64/* SDL video device functions for fullscreen mode */
65static int FULLSCREEN_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
66static int FULLSCREEN_FlipHWSurface(_THIS, SDL_Surface *surface);
67void FULLSCREEN_SetWMCaption(_THIS, const char *title, const char *icon);
68extern int RISCOS_GetWmInfo(_THIS, SDL_SysWMinfo *info);
69
70/* UpdateRects variants */
71static void FULLSCREEN_UpdateRects(_THIS, int numrects, SDL_Rect *rects);
72static void FULLSCREEN_UpdateRectsMemCpy(_THIS, int numrects, SDL_Rect *rects);
73static void FULLSCREEN_UpdateRects8bpp(_THIS, int numrects, SDL_Rect *rects);
74static void FULLSCREEN_UpdateRects16bpp(_THIS, int numrects, SDL_Rect *rects);
75static void FULLSCREEN_UpdateRects32bpp(_THIS, int numrects, SDL_Rect *rects);
76static void FULLSCREEN_UpdateRectsOS(_THIS, int numrects, SDL_Rect *rects);
77
78/* Local helper functions */
79static int cmpmodes(const void *va, const void *vb);
80static int FULLSCREEN_AddMode(_THIS, int bpp, int w, int h);
81void FULLSCREEN_SetWriteBank(int bank);
82void FULLSCREEN_SetDisplayBank(int bank);
83static void FULLSCREEN_DisableEscape();
84static void FULLSCREEN_EnableEscape();
85void FULLSCREEN_BuildModeList(_THIS);
86
87/* Following variable is set up in riskosTask.c */
88extern 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 */
91extern unsigned char *WIMP_CreateBuffer(int width, int height, int bpp);
92
93/* Fast assembler copy */
94extern void RISCOS_Put32(void *to, int pixels, int pitch, int rows, void *from, int src_skip_bytes);
95
96SDL_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 */
240void 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 */
293void 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
360static 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 */
377static void FULLSCREEN_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
378{
379}
380
381/* Safe but slower Memory copy from our allocated back buffer */
382static 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. */
405static 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. */
435static 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 */
463static 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. */
484static 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
533int 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
563static 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
573static 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
619void 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
627void 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 */
637static 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 */
648static 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 */
659void 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
669int 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 */
725void 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
747int 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}