1 /* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2012 Sam Lantinga 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Library General Public 7 License as published by the Free Software Foundation; either 8 version 2 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Library General Public License for more details. 14 15 You should have received a copy of the GNU Library General Public 16 License along with this library; if not, write to the Free 17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 19 Sam Lantinga 20 slouken (at) libsdl.org 21 */ 22 #include "SDL_config.h" 23 24 /* 25 File added by Alan Buckley (alan_baa (at) 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, ®s, ®s); 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, ®s, ®s); 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, ®s, ®s) != 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, ®s, ®s); 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, ®s, ®s); 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, ®s, ®s); 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, ®s, ®s)) != 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, ®s, ®s); 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, ®s, ®s); 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, ®s, ®s); 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, ®s, ®s); 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, ®s, ®s); 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, ®s, ®s); 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, ®s, ®s) != 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, ®s, ®s); 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 } 778