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 Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 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 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 19 Sam Lantinga 20 slouken (at) libsdl.org 21 */ 22 #include "SDL_config.h" 23 24 /* 25 * Xbios SDL video driver 26 * 27 * Patrice Mandin 28 */ 29 30 #include <sys/stat.h> 31 #include <unistd.h> 32 33 /* Mint includes */ 34 #include <mint/cookie.h> 35 #include <mint/osbind.h> 36 #include <mint/falcon.h> 37 38 #include "SDL_video.h" 39 #include "SDL_mouse.h" 40 #include "../SDL_sysvideo.h" 41 #include "../SDL_pixels_c.h" 42 #include "../../events/SDL_events_c.h" 43 44 #include "../ataricommon/SDL_ataric2p_s.h" 45 #include "../ataricommon/SDL_atarievents_c.h" 46 #include "../ataricommon/SDL_atarimxalloc_c.h" 47 #include "../ataricommon/SDL_atarigl_c.h" 48 #include "SDL_xbios.h" 49 #include "SDL_xbios_blowup.h" 50 #include "SDL_xbios_centscreen.h" 51 #include "SDL_xbios_sb3.h" 52 #include "SDL_xbios_tveille.h" 53 #include "SDL_xbios_milan.h" 54 55 #define XBIOS_VID_DRIVER_NAME "xbios" 56 57 #ifndef C_fVDI 58 #define C_fVDI 0x66564449L 59 #endif 60 61 /* Debug print info */ 62 #if 0 63 #define DEBUG_PRINT(what) \ 64 { \ 65 printf what; \ 66 } 67 #define DEBUG_VIDEO_XBIOS 1 68 #else 69 #define DEBUG_PRINT(what) 70 #undef DEBUG_VIDEO_XBIOS 71 #endif 72 73 /* Initialization/Query functions */ 74 static int XBIOS_VideoInit(_THIS, SDL_PixelFormat *vformat); 75 static SDL_Rect **XBIOS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); 76 static SDL_Surface *XBIOS_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); 77 static int XBIOS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); 78 static void XBIOS_VideoQuit(_THIS); 79 80 /* Hardware surface functions */ 81 static int XBIOS_AllocHWSurface(_THIS, SDL_Surface *surface); 82 static int XBIOS_LockHWSurface(_THIS, SDL_Surface *surface); 83 static int XBIOS_FlipHWSurface(_THIS, SDL_Surface *surface); 84 static void XBIOS_UnlockHWSurface(_THIS, SDL_Surface *surface); 85 static void XBIOS_FreeHWSurface(_THIS, SDL_Surface *surface); 86 static void XBIOS_UpdateRects(_THIS, int numrects, SDL_Rect *rects); 87 88 #if SDL_VIDEO_OPENGL 89 /* OpenGL functions */ 90 static void XBIOS_GL_SwapBuffers(_THIS); 91 #endif 92 93 /* To setup palette */ 94 95 static unsigned short TT_palette[256]; 96 static unsigned long F30_palette[256]; 97 98 /* Default list of video modes */ 99 100 static const xbiosmode_t stmodes[1]={ 101 {ST_LOW>>8,320,200,4, XBIOSMODE_C2P} 102 }; 103 104 static const xbiosmode_t ttmodes[2]={ 105 {TT_LOW,320,480,8, XBIOSMODE_C2P}, 106 {TT_LOW,320,240,8, XBIOSMODE_C2P|XBIOSMODE_DOUBLELINE} 107 }; 108 109 static const xbiosmode_t falconrgbmodes[16]={ 110 {BPS16|COL80|OVERSCAN|VERTFLAG,768,480,16,0}, 111 {BPS16|COL80|OVERSCAN,768,240,16,0}, 112 {BPS16|COL80|VERTFLAG,640,400,16,0}, 113 {BPS16|COL80,640,200,16,0}, 114 {BPS16|OVERSCAN|VERTFLAG,384,480,16,0}, 115 {BPS16|OVERSCAN,384,240,16,0}, 116 {BPS16|VERTFLAG,320,400,16,0}, 117 {BPS16,320,200,16,0}, 118 {BPS8|COL80|OVERSCAN|VERTFLAG,768,480,8,XBIOSMODE_C2P}, 119 {BPS8|COL80|OVERSCAN,768,240,8,XBIOSMODE_C2P}, 120 {BPS8|COL80|VERTFLAG,640,400,8,XBIOSMODE_C2P}, 121 {BPS8|COL80,640,200,8,XBIOSMODE_C2P}, 122 {BPS8|OVERSCAN|VERTFLAG,384,480,8,XBIOSMODE_C2P}, 123 {BPS8|OVERSCAN,384,240,8,XBIOSMODE_C2P}, 124 {BPS8|VERTFLAG,320,400,8,XBIOSMODE_C2P}, 125 {BPS8,320,200,8,XBIOSMODE_C2P} 126 }; 127 128 static const xbiosmode_t falconvgamodes[6]={ 129 {BPS16,320,480,16,0}, 130 {BPS16|VERTFLAG,320,240,16,0}, 131 {BPS8|COL80,640,480,8,XBIOSMODE_C2P}, 132 {BPS8|COL80|VERTFLAG,640,240,8,XBIOSMODE_C2P}, 133 {BPS8,320,480,8,XBIOSMODE_C2P}, 134 {BPS8|VERTFLAG,320,240,8,XBIOSMODE_C2P} 135 }; 136 137 /* Xbios driver bootstrap functions */ 138 139 static int XBIOS_Available(void) 140 { 141 long cookie_vdo, /*cookie_mil,*/ cookie_hade, cookie_scpn; 142 long cookie_fvdi; 143 const char *envr = SDL_getenv("SDL_VIDEODRIVER"); 144 145 /* Milan/Hades Atari clones do not have an Atari video chip */ 146 if ( /*(Getcookie(C__MIL, &cookie_mil) == C_FOUND) ||*/ 147 (Getcookie(C_hade, &cookie_hade) == C_FOUND) ) { 148 return 0; 149 } 150 151 /* fVDI means graphic card, so no Xbios with it */ 152 if (Getcookie(C_fVDI, &cookie_fvdi) == C_FOUND) { 153 if (!envr) { 154 return 0; 155 } 156 if (SDL_strcmp(envr, XBIOS_VID_DRIVER_NAME)!=0) { 157 return 0; 158 } 159 /* Except if we force Xbios usage, through env var */ 160 } 161 162 /* Cookie _VDO present ? if not, assume ST machine */ 163 if (Getcookie(C__VDO, &cookie_vdo) != C_FOUND) { 164 cookie_vdo = VDO_ST << 16; 165 } 166 167 /* Test if we have a monochrome monitor plugged in */ 168 switch( cookie_vdo >>16) { 169 case VDO_ST: 170 case VDO_STE: 171 if ( Getrez() == (ST_HIGH>>8) ) 172 return 0; 173 break; 174 case VDO_TT: 175 if ( (EgetShift() & ES_MODE) == TT_HIGH) 176 return 0; 177 break; 178 case VDO_F30: 179 if ( VgetMonitor() == MONITOR_MONO) 180 return 0; 181 if (Getcookie(C_SCPN, &cookie_scpn) == C_FOUND) { 182 if (!SDL_XBIOS_SB3Usable((scpn_cookie_t *)cookie_scpn)) { 183 return 0; 184 } 185 } 186 break; 187 case VDO_MILAN: 188 break; 189 default: 190 return 0; 191 } 192 193 return 1; 194 } 195 196 static void XBIOS_DeleteDevice(SDL_VideoDevice *device) 197 { 198 SDL_free(device->hidden); 199 SDL_free(device); 200 } 201 202 static SDL_VideoDevice *XBIOS_CreateDevice(int devindex) 203 { 204 SDL_VideoDevice *device; 205 206 /* Initialize all variables that we clean on shutdown */ 207 device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); 208 if ( device ) { 209 SDL_memset(device, 0, (sizeof *device)); 210 device->hidden = (struct SDL_PrivateVideoData *) 211 SDL_malloc((sizeof *device->hidden)); 212 device->gl_data = (struct SDL_PrivateGLData *) 213 SDL_malloc((sizeof *device->gl_data)); 214 } 215 if ( (device == NULL) || (device->hidden == NULL) ) { 216 SDL_OutOfMemory(); 217 if ( device ) { 218 SDL_free(device); 219 } 220 return(0); 221 } 222 SDL_memset(device->hidden, 0, (sizeof *device->hidden)); 223 SDL_memset(device->gl_data, 0, sizeof(*device->gl_data)); 224 225 /* Video functions */ 226 device->VideoInit = XBIOS_VideoInit; 227 device->ListModes = XBIOS_ListModes; 228 device->SetVideoMode = XBIOS_SetVideoMode; 229 device->SetColors = XBIOS_SetColors; 230 device->UpdateRects = NULL; 231 device->VideoQuit = XBIOS_VideoQuit; 232 device->AllocHWSurface = XBIOS_AllocHWSurface; 233 device->LockHWSurface = XBIOS_LockHWSurface; 234 device->UnlockHWSurface = XBIOS_UnlockHWSurface; 235 device->FlipHWSurface = XBIOS_FlipHWSurface; 236 device->FreeHWSurface = XBIOS_FreeHWSurface; 237 238 #if SDL_VIDEO_OPENGL 239 /* OpenGL functions */ 240 device->GL_LoadLibrary = SDL_AtariGL_LoadLibrary; 241 device->GL_GetProcAddress = SDL_AtariGL_GetProcAddress; 242 device->GL_GetAttribute = SDL_AtariGL_GetAttribute; 243 device->GL_MakeCurrent = SDL_AtariGL_MakeCurrent; 244 device->GL_SwapBuffers = XBIOS_GL_SwapBuffers; 245 #endif 246 247 /* Events */ 248 device->InitOSKeymap = Atari_InitOSKeymap; 249 device->PumpEvents = Atari_PumpEvents; 250 251 device->free = XBIOS_DeleteDevice; 252 253 return device; 254 } 255 256 VideoBootStrap XBIOS_bootstrap = { 257 XBIOS_VID_DRIVER_NAME, "Atari Xbios driver", 258 XBIOS_Available, XBIOS_CreateDevice 259 }; 260 261 void SDL_XBIOS_AddMode(_THIS, int actually_add, const xbiosmode_t *modeinfo) 262 { 263 int i = 0; 264 265 switch(modeinfo->depth) { 266 case 15: 267 case 16: 268 i = 1; 269 break; 270 case 24: 271 i = 2; 272 break; 273 case 32: 274 i = 3; 275 break; 276 } 277 278 if ( actually_add ) { 279 SDL_Rect saved_rect[2]; 280 xbiosmode_t saved_mode[2]; 281 int b, j; 282 283 /* Add the mode, sorted largest to smallest */ 284 b = 0; 285 j = 0; 286 while ( (SDL_modelist[i][j]->w > modeinfo->width) || 287 (SDL_modelist[i][j]->h > modeinfo->height) ) { 288 ++j; 289 } 290 /* Skip modes that are already in our list */ 291 if ( (SDL_modelist[i][j]->w == modeinfo->width) && 292 (SDL_modelist[i][j]->h == modeinfo->height) ) { 293 return; 294 } 295 /* Insert the new mode */ 296 saved_rect[b] = *SDL_modelist[i][j]; 297 SDL_memcpy(&saved_mode[b], SDL_xbiosmode[i][j], sizeof(xbiosmode_t)); 298 SDL_modelist[i][j]->w = modeinfo->width; 299 SDL_modelist[i][j]->h = modeinfo->height; 300 SDL_memcpy(SDL_xbiosmode[i][j], modeinfo, sizeof(xbiosmode_t)); 301 /* Everybody scoot down! */ 302 if ( saved_rect[b].w && saved_rect[b].h ) { 303 for ( ++j; SDL_modelist[i][j]->w; ++j ) { 304 saved_rect[!b] = *SDL_modelist[i][j]; 305 memcpy(&saved_mode[!b], SDL_xbiosmode[i][j], sizeof(xbiosmode_t)); 306 *SDL_modelist[i][j] = saved_rect[b]; 307 SDL_memcpy(SDL_xbiosmode[i][j], &saved_mode[b], sizeof(xbiosmode_t)); 308 b = !b; 309 } 310 *SDL_modelist[i][j] = saved_rect[b]; 311 SDL_memcpy(SDL_xbiosmode[i][j], &saved_mode[b], sizeof(xbiosmode_t)); 312 } 313 } else { 314 ++SDL_nummodes[i]; 315 } 316 } 317 318 static void XBIOS_ListSTModes(_THIS, int actually_add) 319 { 320 SDL_XBIOS_AddMode(this, actually_add, &stmodes[0]); 321 } 322 323 static void XBIOS_ListTTModes(_THIS, int actually_add) 324 { 325 int i; 326 327 for (i=0; i<2; i++) { 328 SDL_XBIOS_AddMode(this, actually_add, &ttmodes[i]); 329 } 330 } 331 332 static void XBIOS_ListFalconRgbModes(_THIS, int actually_add) 333 { 334 int i; 335 336 for (i=0; i<16; i++) { 337 xbiosmode_t modeinfo; 338 339 SDL_memcpy(&modeinfo, &falconrgbmodes[i], sizeof(xbiosmode_t)); 340 modeinfo.number &= ~(VGA|PAL); 341 modeinfo.number |= XBIOS_oldvmode & (VGA|PAL); 342 343 SDL_XBIOS_AddMode(this, actually_add, &modeinfo); 344 } 345 } 346 347 static void XBIOS_ListFalconVgaModes(_THIS, int actually_add) 348 { 349 int i; 350 351 for (i=0; i<6; i++) { 352 xbiosmode_t modeinfo; 353 354 SDL_memcpy(&modeinfo, &falconvgamodes[i], sizeof(xbiosmode_t)); 355 modeinfo.number &= ~(VGA|PAL); 356 modeinfo.number |= XBIOS_oldvmode & (VGA|PAL); 357 358 SDL_XBIOS_AddMode(this, actually_add, &modeinfo); 359 } 360 } 361 362 static int XBIOS_VideoInit(_THIS, SDL_PixelFormat *vformat) 363 { 364 int i; 365 long cookie_blow, cookie_scpn, cookie_cnts; 366 367 /* Initialize all variables that we clean on shutdown */ 368 for ( i=0; i<NUM_MODELISTS; ++i ) { 369 SDL_nummodes[i] = 0; 370 SDL_modelist[i] = NULL; 371 SDL_xbiosmode[i] = NULL; 372 } 373 374 /* Cookie _VDO present ? if not, assume ST machine */ 375 if (Getcookie(C__VDO, &XBIOS_cvdo) != C_FOUND) { 376 XBIOS_cvdo = VDO_ST << 16; 377 } 378 379 /* Allocate memory for old palette */ 380 XBIOS_oldpalette = (void *)SDL_malloc(256*sizeof(long)); 381 if ( !XBIOS_oldpalette ) { 382 SDL_SetError("Unable to allocate memory for old palette\n"); 383 return(-1); 384 } 385 386 /* Initialize video mode list */ 387 /* and save current screen status (palette, screen address, video mode) */ 388 XBIOS_centscreen = SDL_FALSE; 389 XBIOS_oldvbase = Physbase(); 390 391 /* Determine the current screen size */ 392 this->info.current_w = 0; 393 this->info.current_h = 0; 394 395 /* Determine the screen depth (use default 8-bit depth) */ 396 vformat->BitsPerPixel = 8; 397 398 /* First allocate room for needed video modes */ 399 switch (XBIOS_cvdo >>16) { 400 case VDO_ST: 401 case VDO_STE: 402 { 403 short *oldpalette; 404 405 XBIOS_oldvmode=Getrez(); 406 switch(XBIOS_oldvmode << 8) { 407 case ST_LOW: 408 XBIOS_oldnumcol=16; 409 break; 410 case ST_MED: 411 XBIOS_oldnumcol=4; 412 break; 413 case ST_HIGH: 414 XBIOS_oldnumcol=2; 415 break; 416 } 417 418 oldpalette= (short *) XBIOS_oldpalette; 419 for (i=0;i<XBIOS_oldnumcol;i++) { 420 *oldpalette++=Setcolor(i,-1); 421 } 422 423 XBIOS_ListSTModes(this, 0); 424 } 425 break; 426 case VDO_TT: 427 XBIOS_oldvmode=EgetShift(); 428 429 switch(XBIOS_oldvmode & ES_MODE) { 430 case TT_LOW: 431 XBIOS_oldnumcol=256; 432 break; 433 case ST_LOW: 434 case TT_MED: 435 XBIOS_oldnumcol=16; 436 break; 437 case ST_MED: 438 XBIOS_oldnumcol=4; 439 break; 440 case ST_HIGH: 441 case TT_HIGH: 442 XBIOS_oldnumcol=2; 443 break; 444 } 445 if (XBIOS_oldnumcol) { 446 EgetPalette(0, XBIOS_oldnumcol, XBIOS_oldpalette); 447 } 448 449 XBIOS_ListTTModes(this, 0); 450 break; 451 case VDO_F30: 452 XBIOS_oldvmode=VsetMode(-1); 453 454 XBIOS_oldnumcol= 1<< (1 << (XBIOS_oldvmode & NUMCOLS)); 455 if (XBIOS_oldnumcol > 256) { 456 XBIOS_oldnumcol = 0; 457 } 458 if (XBIOS_oldnumcol) { 459 VgetRGB(0, XBIOS_oldnumcol, XBIOS_oldpalette); 460 } 461 462 vformat->BitsPerPixel = 16; 463 464 /* ScreenBlaster 3 ? */ 465 if (Getcookie(C_SCPN, &cookie_scpn) == C_FOUND) { 466 SDL_XBIOS_ListSB3Modes(this, 0, (scpn_cookie_t *)cookie_scpn); 467 } else 468 /* Centscreen ? */ 469 if (Getcookie(C_CNTS, &cookie_cnts) == C_FOUND) { 470 XBIOS_oldvmode = SDL_XBIOS_ListCentscreenModes(this, 0); 471 XBIOS_centscreen = SDL_TRUE; 472 } else 473 /* Standard, with or without Blowup */ 474 { 475 switch (VgetMonitor()) 476 { 477 case MONITOR_RGB: 478 case MONITOR_TV: 479 XBIOS_ListFalconRgbModes(this, 0); 480 break; 481 case MONITOR_VGA: 482 XBIOS_ListFalconVgaModes(this, 0); 483 break; 484 } 485 486 if (Getcookie(C_BLOW, &cookie_blow) == C_FOUND) { 487 SDL_XBIOS_ListBlowupModes(this, 0, (blow_cookie_t *)cookie_blow); 488 } 489 } 490 break; 491 case VDO_MILAN: 492 { 493 SCREENINFO si; 494 495 /* Read infos about current mode */ 496 VsetScreen(-1, &XBIOS_oldvmode, MI_MAGIC, CMD_GETMODE); 497 498 si.size = sizeof(SCREENINFO); 499 si.devID = XBIOS_oldvmode; 500 si.scrFlags = 0; 501 VsetScreen(-1, &si, MI_MAGIC, CMD_GETINFO); 502 503 this->info.current_w = si.scrWidth; 504 this->info.current_h = si.scrHeight; 505 506 XBIOS_oldnumcol = 0; 507 if (si.scrFlags & SCRINFO_OK) { 508 if (si.scrPlanes <= 8) { 509 XBIOS_oldnumcol = 1<<si.scrPlanes; 510 } 511 } 512 if (XBIOS_oldnumcol) { 513 VgetRGB(0, XBIOS_oldnumcol, XBIOS_oldpalette); 514 } 515 516 SDL_XBIOS_ListMilanModes(this, 0); 517 } 518 break; 519 } 520 521 for ( i=0; i<NUM_MODELISTS; ++i ) { 522 int j; 523 524 SDL_xbiosmode[i] = (xbiosmode_t **) 525 SDL_malloc((SDL_nummodes[i]+1)*sizeof(xbiosmode_t *)); 526 if ( SDL_xbiosmode[i] == NULL ) { 527 SDL_OutOfMemory(); 528 return(-1); 529 } 530 for ( j=0; j<SDL_nummodes[i]; ++j ) { 531 SDL_xbiosmode[i][j]=(xbiosmode_t *)SDL_malloc(sizeof(xbiosmode_t)); 532 if ( SDL_xbiosmode[i][j] == NULL ) { 533 SDL_OutOfMemory(); 534 return(-1); 535 } 536 SDL_memset(SDL_xbiosmode[i][j], 0, sizeof(xbiosmode_t)); 537 } 538 SDL_xbiosmode[i][j] = NULL; 539 540 SDL_modelist[i] = (SDL_Rect **) 541 SDL_malloc((SDL_nummodes[i]+1)*sizeof(SDL_Rect *)); 542 if ( SDL_modelist[i] == NULL ) { 543 SDL_OutOfMemory(); 544 return(-1); 545 } 546 for ( j=0; j<SDL_nummodes[i]; ++j ) { 547 SDL_modelist[i][j]=(SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); 548 if ( SDL_modelist[i][j] == NULL ) { 549 SDL_OutOfMemory(); 550 return(-1); 551 } 552 SDL_memset(SDL_modelist[i][j], 0, sizeof(SDL_Rect)); 553 } 554 SDL_modelist[i][j] = NULL; 555 } 556 557 /* Now fill the mode list */ 558 switch (XBIOS_cvdo >>16) { 559 case VDO_ST: 560 case VDO_STE: 561 XBIOS_ListSTModes(this, 1); 562 break; 563 case VDO_TT: 564 XBIOS_ListTTModes(this, 1); 565 break; 566 case VDO_F30: 567 /* ScreenBlaster 3 ? */ 568 if (Getcookie(C_SCPN, &cookie_scpn) == C_FOUND) { 569 SDL_XBIOS_ListSB3Modes(this, 1, (scpn_cookie_t *)cookie_scpn); 570 } else 571 /* Centscreen ? */ 572 if (Getcookie(C_CNTS, &cookie_cnts) == C_FOUND) { 573 XBIOS_oldvmode = SDL_XBIOS_ListCentscreenModes(this, 1); 574 XBIOS_centscreen = SDL_TRUE; 575 } else 576 /* Standard, with or without Blowup */ 577 { 578 switch (VgetMonitor()) 579 { 580 case MONITOR_RGB: 581 case MONITOR_TV: 582 XBIOS_ListFalconRgbModes(this, 1); 583 break; 584 case MONITOR_VGA: 585 XBIOS_ListFalconVgaModes(this, 1); 586 break; 587 } 588 589 if (Getcookie(C_BLOW, &cookie_blow) == C_FOUND) { 590 SDL_XBIOS_ListBlowupModes(this, 1, (blow_cookie_t *)cookie_blow); 591 } 592 } 593 break; 594 case VDO_MILAN: 595 SDL_XBIOS_ListMilanModes(this, 1); 596 break; 597 } 598 599 XBIOS_screens[0]=NULL; 600 XBIOS_screens[1]=NULL; 601 XBIOS_shadowscreen=NULL; 602 603 /* Update hardware info */ 604 this->info.hw_available = 1; 605 this->info.video_mem = (Uint32) Atari_SysMalloc(-1L, MX_STRAM); 606 607 /* Init chunky to planar routine */ 608 SDL_Atari_C2pConvert = SDL_Atari_C2pConvert8; 609 610 #if SDL_VIDEO_OPENGL 611 SDL_AtariGL_InitPointers(this); 612 #endif 613 614 /* Disable screensavers */ 615 if (SDL_XBIOS_TveillePresent(this)) { 616 SDL_XBIOS_TveilleDisable(this); 617 } 618 619 /* We're done! */ 620 return(0); 621 } 622 623 static SDL_Rect **XBIOS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) 624 { 625 return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]); 626 } 627 628 static void XBIOS_FreeBuffers(_THIS) 629 { 630 int i; 631 632 for (i=0;i<2;i++) { 633 if (XBIOS_screensmem[i]!=NULL) { 634 if ((XBIOS_cvdo>>16) == VDO_MILAN) { 635 if (i==1) { 636 VsetScreen(-1, -1, MI_MAGIC, CMD_FREEPAGE); 637 } 638 } else { 639 Mfree(XBIOS_screensmem[i]); 640 } 641 XBIOS_screensmem[i]=NULL; 642 } 643 } 644 645 if (XBIOS_shadowscreen!=NULL) { 646 Mfree(XBIOS_shadowscreen); 647 XBIOS_shadowscreen=NULL; 648 } 649 } 650 651 static SDL_Surface *XBIOS_SetVideoMode(_THIS, SDL_Surface *current, 652 int width, int height, int bpp, Uint32 flags) 653 { 654 int mode, new_depth; 655 int i, num_buffers; 656 xbiosmode_t *new_video_mode; 657 Uint32 new_screen_size; 658 Uint32 modeflags; 659 660 /* Free current buffers */ 661 XBIOS_FreeBuffers(this); 662 663 /* Try to set the requested linear video mode */ 664 bpp = (bpp+7)/8-1; 665 for ( mode=0; SDL_modelist[bpp][mode]; ++mode ) { 666 if ( (SDL_modelist[bpp][mode]->w == width) && 667 (SDL_modelist[bpp][mode]->h == height) ) { 668 break; 669 } 670 } 671 if ( SDL_modelist[bpp][mode] == NULL ) { 672 SDL_SetError("Couldn't find requested mode in list"); 673 return(NULL); 674 } 675 new_video_mode = SDL_xbiosmode[bpp][mode]; 676 677 modeflags = SDL_FULLSCREEN | SDL_PREALLOC; 678 679 /* Allocate needed buffers: simple/double buffer and shadow surface */ 680 new_depth = new_video_mode->depth; 681 if (new_depth == 4) { 682 SDL_Atari_C2pConvert = SDL_Atari_C2pConvert4; 683 new_depth=8; 684 modeflags |= SDL_SWSURFACE|SDL_HWPALETTE; 685 } else if (new_depth == 8) { 686 SDL_Atari_C2pConvert = SDL_Atari_C2pConvert8; 687 modeflags |= SDL_SWSURFACE|SDL_HWPALETTE; 688 } else { 689 modeflags |= SDL_HWSURFACE; 690 } 691 692 new_screen_size = width * height * ((new_depth)>>3); 693 new_screen_size += 256; /* To align on a 256 byte adress */ 694 695 if (new_video_mode->flags & XBIOSMODE_C2P) { 696 XBIOS_shadowscreen = Atari_SysMalloc(new_screen_size, MX_PREFTTRAM); 697 698 if (XBIOS_shadowscreen == NULL) { 699 SDL_SetError("Can not allocate %d KB for shadow buffer", new_screen_size>>10); 700 return (NULL); 701 } 702 SDL_memset(XBIOS_shadowscreen, 0, new_screen_size); 703 } 704 705 /* Output buffer needs to be twice in size for the software double-line mode */ 706 if (new_video_mode->flags & XBIOSMODE_DOUBLELINE) { 707 new_screen_size <<= 1; 708 } 709 710 /* Double buffer ? */ 711 num_buffers = 1; 712 713 #if SDL_VIDEO_OPENGL 714 if (flags & SDL_OPENGL) { 715 if (this->gl_config.double_buffer) { 716 flags |= SDL_DOUBLEBUF; 717 } 718 } 719 #endif 720 if ((flags & SDL_DOUBLEBUF) && ((XBIOS_cvdo>>16) != VDO_MILAN)) { 721 num_buffers = 2; 722 modeflags |= SDL_DOUBLEBUF; 723 } 724 725 /* Allocate buffers */ 726 for (i=0; i<num_buffers; i++) { 727 if ((XBIOS_cvdo>>16) == VDO_MILAN) { 728 if (i==0) { 729 XBIOS_screensmem[i] = XBIOS_oldvbase; 730 } else { 731 VsetScreen(-1, &XBIOS_screensmem[i], MI_MAGIC, CMD_ALLOCPAGE); 732 } 733 } else { 734 XBIOS_screensmem[i] = Atari_SysMalloc(new_screen_size, MX_STRAM); 735 } 736 737 if (XBIOS_screensmem[i]==NULL) { 738 XBIOS_FreeBuffers(this); 739 SDL_SetError("Can not allocate %d KB for buffer %d", new_screen_size>>10, i); 740 return (NULL); 741 } 742 SDL_memset(XBIOS_screensmem[i], 0, new_screen_size); 743 744 XBIOS_screens[i]=(void *) (( (long) XBIOS_screensmem[i]+256) & 0xFFFFFF00UL); 745 } 746 747 /* Allocate the new pixel format for the screen */ 748 if ( ! SDL_ReallocFormat(current, new_depth, 0, 0, 0, 0) ) { 749 XBIOS_FreeBuffers(this); 750 SDL_SetError("Couldn't allocate new pixel format for requested mode"); 751 return(NULL); 752 } 753 754 XBIOS_current = new_video_mode; 755 current->w = width; 756 current->h = height; 757 current->pitch = (width * new_depth)>>3; 758 759 /* this is for C2P conversion */ 760 XBIOS_pitch = (new_video_mode->width * new_video_mode->depth)>>3; 761 762 if (new_video_mode->flags & XBIOSMODE_C2P) 763 current->pixels = XBIOS_shadowscreen; 764 else 765 current->pixels = XBIOS_screens[0]; 766 767 XBIOS_fbnum = 0; 768 769 #if SDL_VIDEO_OPENGL 770 if (flags & SDL_OPENGL) { 771 if (!SDL_AtariGL_Init(this, current)) { 772 XBIOS_FreeBuffers(this); 773 SDL_SetError("Can not create OpenGL context"); 774 return NULL; 775 } 776 777 modeflags |= SDL_OPENGL; 778 } 779 #endif 780 781 current->flags = modeflags; 782 783 #ifndef DEBUG_VIDEO_XBIOS 784 /* Now set the video mode */ 785 if ((XBIOS_cvdo>>16) == VDO_MILAN) { 786 VsetScreen(-1, XBIOS_screens[0], MI_MAGIC, CMD_SETADR); 787 } else { 788 Setscreen(-1,XBIOS_screens[0],-1); 789 } 790 791 switch(XBIOS_cvdo >> 16) { 792 case VDO_ST: 793 Setscreen(-1,-1,new_video_mode->number); 794 795 /* Reset palette */ 796 for (i=0;i<16;i++) { 797 TT_palette[i]= ((i>>1)<<8) | (((i*8)/17)<<4) | (i>>1); 798 } 799 Setpalette(TT_palette); 800 break; 801 case VDO_STE: 802 Setscreen(-1,-1,new_video_mode->number); 803 804 /* Reset palette */ 805 for (i=0;i<16;i++) 806 { 807 int c; 808 809 c=((i&1)<<3)|((i>>1)&7); 810 TT_palette[i]=(c<<8)|(c<<4)|c; 811 } 812 Setpalette(TT_palette); 813 break; 814 case VDO_TT: 815 EsetShift(new_video_mode->number); 816 break; 817 case VDO_F30: 818 if (XBIOS_centscreen) { 819 SDL_XBIOS_CentscreenSetmode(this, width, height, new_depth); 820 } else { 821 VsetMode(new_video_mode->number); 822 } 823 824 /* Set hardware palette to black in True Colour */ 825 if (new_depth > 8) { 826 SDL_memset(F30_palette, 0, sizeof(F30_palette)); 827 VsetRGB(0,256,F30_palette); 828 } 829 break; 830 case VDO_MILAN: 831 VsetScreen(-1, new_video_mode->number, MI_MAGIC, CMD_SETMODE); 832 833 /* Set hardware palette to black in True Colour */ 834 if (new_depth > 8) { 835 SDL_memset(F30_palette, 0, sizeof(F30_palette)); 836 VsetRGB(0,256,F30_palette); 837 } 838 break; 839 } 840 841 Vsync(); 842 #endif 843 844 this->UpdateRects = XBIOS_UpdateRects; 845 846 return (current); 847 } 848 849 /* We don't actually allow hardware surfaces other than the main one */ 850 static int XBIOS_AllocHWSurface(_THIS, SDL_Surface *surface) 851 { 852 return(-1); 853 } 854 855 static void XBIOS_FreeHWSurface(_THIS, SDL_Surface *surface) 856 { 857 return; 858 } 859 860 static int XBIOS_LockHWSurface(_THIS, SDL_Surface *surface) 861 { 862 return(0); 863 } 864 865 static void XBIOS_UnlockHWSurface(_THIS, SDL_Surface *surface) 866 { 867 return; 868 } 869 870 static void XBIOS_UpdateRects(_THIS, int numrects, SDL_Rect *rects) 871 { 872 SDL_Surface *surface; 873 874 surface = this->screen; 875 876 if (XBIOS_current->flags & XBIOSMODE_C2P) { 877 int i; 878 int doubleline = (XBIOS_current->flags & XBIOSMODE_DOUBLELINE ? 1 : 0); 879 880 for (i=0;i<numrects;i++) { 881 void *source,*destination; 882 int x1,x2; 883 884 x1 = rects[i].x & ~15; 885 x2 = rects[i].x+rects[i].w; 886 if (x2 & 15) { 887 x2 = (x2 | 15) +1; 888 } 889 890 source = surface->pixels; 891 source += surface->pitch * rects[i].y; 892 source += x1; 893 894 destination = XBIOS_screens[XBIOS_fbnum]; 895 destination += XBIOS_pitch * rects[i].y; 896 destination += x1; 897 898 /* Convert chunky to planar screen */ 899 SDL_Atari_C2pConvert( 900 source, 901 destination, 902 x2-x1, 903 rects[i].h, 904 doubleline, 905 surface->pitch, 906 XBIOS_pitch 907 ); 908 } 909 } 910 911 #ifndef DEBUG_VIDEO_XBIOS 912 if ((XBIOS_cvdo>>16) == VDO_MILAN) { 913 VsetScreen(-1, XBIOS_screens[XBIOS_fbnum], MI_MAGIC, CMD_SETADR); 914 } else { 915 Setscreen(-1,XBIOS_screens[XBIOS_fbnum],-1); 916 } 917 918 Vsync(); 919 #endif 920 921 if ((surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) { 922 XBIOS_fbnum ^= 1; 923 if ((XBIOS_current->flags & XBIOSMODE_C2P) == 0) { 924 surface->pixels=XBIOS_screens[XBIOS_fbnum]; 925 } 926 } 927 } 928 929 static int XBIOS_FlipHWSurface(_THIS, SDL_Surface *surface) 930 { 931 if (XBIOS_current->flags & XBIOSMODE_C2P) { 932 void *destscr; 933 int destx; 934 int doubleline = (XBIOS_current->flags & XBIOSMODE_DOUBLELINE ? 1 : 0); 935 936 /* Center on destination screen */ 937 destscr = XBIOS_screens[XBIOS_fbnum]; 938 destscr += XBIOS_pitch * ((XBIOS_current->height - surface->h) >> 1); 939 destx = (XBIOS_current->width - surface->w) >> 1; 940 destx &= ~15; 941 destscr += destx; 942 943 /* Convert chunky to planar screen */ 944 SDL_Atari_C2pConvert( 945 surface->pixels, 946 destscr, 947 surface->w, 948 surface->h, 949 doubleline, 950 surface->pitch, 951 XBIOS_pitch 952 ); 953 } 954 955 #ifndef DEBUG_VIDEO_XBIOS 956 if ((XBIOS_cvdo>>16) == VDO_MILAN) { 957 VsetScreen(-1, XBIOS_screens[XBIOS_fbnum], MI_MAGIC, CMD_SETADR); 958 } else { 959 Setscreen(-1,XBIOS_screens[XBIOS_fbnum],-1); 960 } 961 962 Vsync(); 963 #endif 964 965 if ((surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) { 966 XBIOS_fbnum ^= 1; 967 if ((XBIOS_current->flags & XBIOSMODE_C2P) == 0) { 968 surface->pixels=XBIOS_screens[XBIOS_fbnum]; 969 } 970 } 971 972 return(0); 973 } 974 975 static int XBIOS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) 976 { 977 #ifndef DEBUG_VIDEO_XBIOS 978 int i; 979 int r,v,b; 980 981 switch( XBIOS_cvdo >> 16) { 982 case VDO_ST: 983 case VDO_STE: 984 for (i=0;i<ncolors;i++) 985 { 986 r = colors[i].r; 987 v = colors[i].g; 988 b = colors[i].b; 989 990 TT_palette[firstcolor+i]=((r*30)+(v*59)+(b*11))/100; 991 } 992 SDL_Atari_C2pConvert4_pal(TT_palette); /* convert the lighting */ 993 break; 994 case VDO_TT: 995 for(i = 0; i < ncolors; i++) 996 { 997 r = colors[i].r; 998 v = colors[i].g; 999 b = colors[i].b; 1000 1001 TT_palette[i]=((r>>4)<<8)|((v>>4)<<4)|(b>>4); 1002 } 1003 EsetPalette(firstcolor,ncolors,TT_palette); 1004 break; 1005 case VDO_F30: 1006 case VDO_MILAN: 1007 for(i = 0; i < ncolors; i++) 1008 { 1009 r = colors[i].r; 1010 v = colors[i].g; 1011 b = colors[i].b; 1012 1013 F30_palette[i]=(r<<16)|(v<<8)|b; 1014 } 1015 VsetRGB(firstcolor,ncolors,F30_palette); 1016 break; 1017 } 1018 #endif 1019 1020 return(1); 1021 } 1022 1023 /* Note: If we are terminated, this could be called in the middle of 1024 another SDL video routine -- notably UpdateRects. 1025 */ 1026 static void XBIOS_VideoQuit(_THIS) 1027 { 1028 int i,j; 1029 1030 Atari_ShutdownEvents(); 1031 1032 /* Restore video mode and palette */ 1033 #ifndef DEBUG_VIDEO_XBIOS 1034 switch(XBIOS_cvdo >> 16) { 1035 case VDO_ST: 1036 case VDO_STE: 1037 Setscreen(-1,XBIOS_oldvbase,XBIOS_oldvmode); 1038 if (XBIOS_oldnumcol) { 1039 Setpalette(XBIOS_oldpalette); 1040 } 1041 break; 1042 case VDO_TT: 1043 Setscreen(-1,XBIOS_oldvbase,-1); 1044 EsetShift(XBIOS_oldvmode); 1045 if (XBIOS_oldnumcol) { 1046 EsetPalette(0, XBIOS_oldnumcol, XBIOS_oldpalette); 1047 } 1048 break; 1049 case VDO_F30: 1050 Setscreen(-1, XBIOS_oldvbase, -1); 1051 if (XBIOS_centscreen) { 1052 SDL_XBIOS_CentscreenRestore(this, XBIOS_oldvmode); 1053 } else { 1054 VsetMode(XBIOS_oldvmode); 1055 } 1056 if (XBIOS_oldnumcol) { 1057 VsetRGB(0, XBIOS_oldnumcol, XBIOS_oldpalette); 1058 } 1059 break; 1060 case VDO_MILAN: 1061 VsetScreen(-1, &XBIOS_oldvbase, MI_MAGIC, CMD_SETADR); 1062 VsetScreen(-1, &XBIOS_oldvmode, MI_MAGIC, CMD_SETMODE); 1063 if (XBIOS_oldnumcol) { 1064 VsetRGB(0, XBIOS_oldnumcol, XBIOS_oldpalette); 1065 } 1066 break; 1067 } 1068 Vsync(); 1069 #endif 1070 1071 #if SDL_VIDEO_OPENGL 1072 if (gl_active) { 1073 SDL_AtariGL_Quit(this, SDL_TRUE); 1074 } 1075 #endif 1076 1077 if (XBIOS_oldpalette) { 1078 SDL_free(XBIOS_oldpalette); 1079 XBIOS_oldpalette=NULL; 1080 } 1081 XBIOS_FreeBuffers(this); 1082 1083 /* Free mode list */ 1084 for ( i=0; i<NUM_MODELISTS; ++i ) { 1085 if ( SDL_modelist[i] != NULL ) { 1086 for ( j=0; SDL_modelist[i][j]; ++j ) 1087 SDL_free(SDL_modelist[i][j]); 1088 SDL_free(SDL_modelist[i]); 1089 SDL_modelist[i] = NULL; 1090 } 1091 if ( SDL_xbiosmode[i] != NULL ) { 1092 for ( j=0; SDL_xbiosmode[i][j]; ++j ) 1093 SDL_free(SDL_xbiosmode[i][j]); 1094 SDL_free(SDL_xbiosmode[i]); 1095 SDL_xbiosmode[i] = NULL; 1096 } 1097 } 1098 1099 this->screen->pixels = NULL; 1100 1101 /* Restore screensavers */ 1102 if (SDL_XBIOS_TveillePresent(this)) { 1103 SDL_XBIOS_TveilleEnable(this); 1104 } 1105 } 1106 1107 #if SDL_VIDEO_OPENGL 1108 1109 static void XBIOS_GL_SwapBuffers(_THIS) 1110 { 1111 SDL_AtariGL_SwapBuffers(this); 1112 XBIOS_FlipHWSurface(this, this->screen); 1113 SDL_AtariGL_MakeCurrent(this); 1114 } 1115 1116 #endif 1117