Home | History | Annotate | Download | only in xbios
      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