Home | History | Annotate | Download | only in xbios
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2006 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 
     54 #define XBIOS_VID_DRIVER_NAME "xbios"
     55 
     56 /* Debug print info */
     57 #if 0
     58 #define DEBUG_PRINT(what) \
     59 	{ \
     60 		printf what; \
     61 	}
     62 #define DEBUG_VIDEO_XBIOS 1
     63 #else
     64 #define DEBUG_PRINT(what)
     65 #undef DEBUG_VIDEO_XBIOS
     66 #endif
     67 
     68 /* Initialization/Query functions */
     69 static int XBIOS_VideoInit(_THIS, SDL_PixelFormat *vformat);
     70 static SDL_Rect **XBIOS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
     71 static SDL_Surface *XBIOS_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
     72 static int XBIOS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
     73 static void XBIOS_VideoQuit(_THIS);
     74 
     75 /* Hardware surface functions */
     76 static int XBIOS_AllocHWSurface(_THIS, SDL_Surface *surface);
     77 static int XBIOS_LockHWSurface(_THIS, SDL_Surface *surface);
     78 static int XBIOS_FlipHWSurface(_THIS, SDL_Surface *surface);
     79 static void XBIOS_UnlockHWSurface(_THIS, SDL_Surface *surface);
     80 static void XBIOS_FreeHWSurface(_THIS, SDL_Surface *surface);
     81 static void XBIOS_UpdateRects(_THIS, int numrects, SDL_Rect *rects);
     82 
     83 #if SDL_VIDEO_OPENGL
     84 /* OpenGL functions */
     85 static void XBIOS_GL_SwapBuffers(_THIS);
     86 #endif
     87 
     88 /* To setup palette */
     89 
     90 static unsigned short	TT_palette[256];
     91 static unsigned long	F30_palette[256];
     92 
     93 /* Xbios driver bootstrap functions */
     94 
     95 static int XBIOS_Available(void)
     96 {
     97 	unsigned long cookie_vdo, cookie_mil, cookie_hade, cookie_scpn;
     98 
     99 	/* Milan/Hades Atari clones do not have an Atari video chip */
    100 	if ( (Getcookie(C__MIL, &cookie_mil) == C_FOUND) ||
    101 		(Getcookie(C_hade, &cookie_hade) == C_FOUND) ) {
    102 		return 0;
    103 	}
    104 
    105 	/* Cookie _VDO present ? if not, assume ST machine */
    106 	if (Getcookie(C__VDO, &cookie_vdo) != C_FOUND) {
    107 		cookie_vdo = VDO_ST << 16;
    108 	}
    109 
    110 	/* Test if we have a monochrome monitor plugged in */
    111 	switch( cookie_vdo >>16) {
    112 		case VDO_ST:
    113 		case VDO_STE:
    114 			if ( Getrez() == (ST_HIGH>>8) )
    115 				return 0;
    116 			break;
    117 		case VDO_TT:
    118 			if ( (EgetShift() & ES_MODE) == TT_HIGH)
    119 				return 0;
    120 			break;
    121 		case VDO_F30:
    122 			if ( VgetMonitor() == MONITOR_MONO)
    123 				return 0;
    124 			if (Getcookie(C_SCPN, &cookie_scpn) == C_FOUND) {
    125 				if (!SDL_XBIOS_SB3Usable((scpn_cookie_t *)cookie_scpn)) {
    126 					return 0;
    127 				}
    128 			}
    129 			break;
    130 		default:
    131 			return 0;
    132 	}
    133 
    134 	return 1;
    135 }
    136 
    137 static void XBIOS_DeleteDevice(SDL_VideoDevice *device)
    138 {
    139 	SDL_free(device->hidden);
    140 	SDL_free(device);
    141 }
    142 
    143 static SDL_VideoDevice *XBIOS_CreateDevice(int devindex)
    144 {
    145 	SDL_VideoDevice *device;
    146 
    147 	/* Initialize all variables that we clean on shutdown */
    148 	device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
    149 	if ( device ) {
    150 		SDL_memset(device, 0, (sizeof *device));
    151 		device->hidden = (struct SDL_PrivateVideoData *)
    152 				SDL_malloc((sizeof *device->hidden));
    153 		device->gl_data = (struct SDL_PrivateGLData *)
    154 				SDL_malloc((sizeof *device->gl_data));
    155 	}
    156 	if ( (device == NULL) || (device->hidden == NULL) ) {
    157 		SDL_OutOfMemory();
    158 		if ( device ) {
    159 			SDL_free(device);
    160 		}
    161 		return(0);
    162 	}
    163 	SDL_memset(device->hidden, 0, (sizeof *device->hidden));
    164 	SDL_memset(device->gl_data, 0, sizeof(*device->gl_data));
    165 
    166 	/* Video functions */
    167 	device->VideoInit = XBIOS_VideoInit;
    168 	device->ListModes = XBIOS_ListModes;
    169 	device->SetVideoMode = XBIOS_SetVideoMode;
    170 	device->SetColors = XBIOS_SetColors;
    171 	device->UpdateRects = NULL;
    172 	device->VideoQuit = XBIOS_VideoQuit;
    173 	device->AllocHWSurface = XBIOS_AllocHWSurface;
    174 	device->LockHWSurface = XBIOS_LockHWSurface;
    175 	device->UnlockHWSurface = XBIOS_UnlockHWSurface;
    176 	device->FlipHWSurface = XBIOS_FlipHWSurface;
    177 	device->FreeHWSurface = XBIOS_FreeHWSurface;
    178 
    179 #if SDL_VIDEO_OPENGL
    180 	/* OpenGL functions */
    181 	device->GL_LoadLibrary = SDL_AtariGL_LoadLibrary;
    182 	device->GL_GetProcAddress = SDL_AtariGL_GetProcAddress;
    183 	device->GL_GetAttribute = SDL_AtariGL_GetAttribute;
    184 	device->GL_MakeCurrent = SDL_AtariGL_MakeCurrent;
    185 	device->GL_SwapBuffers = XBIOS_GL_SwapBuffers;
    186 #endif
    187 
    188 	/* Events */
    189 	device->InitOSKeymap = Atari_InitOSKeymap;
    190 	device->PumpEvents = Atari_PumpEvents;
    191 
    192 	device->free = XBIOS_DeleteDevice;
    193 
    194 	return device;
    195 }
    196 
    197 VideoBootStrap XBIOS_bootstrap = {
    198 	XBIOS_VID_DRIVER_NAME, "Atari Xbios driver",
    199 	XBIOS_Available, XBIOS_CreateDevice
    200 };
    201 
    202 void SDL_XBIOS_AddMode(_THIS, Uint16 modecode, Uint16 width, Uint16 height,
    203 	Uint16 depth, SDL_bool flags)
    204 {
    205 	int i, curpos;
    206 	xbiosmode_t *current_mode;
    207 
    208 	/* Check if mode already exists */
    209 	if (XBIOS_modelist) {
    210 		current_mode = XBIOS_modelist;
    211 		for (i=0;i<XBIOS_nummodes; i++, current_mode++) {
    212 			if (current_mode->width != width)
    213 				continue;
    214 			if (current_mode->height != height)
    215 				continue;
    216 			if (current_mode->depth != depth)
    217 				continue;
    218 			return;
    219 		}
    220 	}
    221 
    222 	++XBIOS_nummodes;
    223 	XBIOS_modelist = (xbiosmode_t *) SDL_realloc(XBIOS_modelist, XBIOS_nummodes * sizeof(xbiosmode_t));
    224 
    225 	/* Keep the list sorted: bpp, width, height */
    226 	curpos=0;
    227 
    228 	for(i=0; i<XBIOS_nummodes-1; i++) {
    229 		if (XBIOS_modelist[i].depth <= depth) {
    230 			if (XBIOS_modelist[i].width < width) {
    231 				break;
    232 			} else if (XBIOS_modelist[i].width == width) {
    233 				if (XBIOS_modelist[i].height <= height) {
    234 					break;
    235 				}
    236 			}
    237 		}
    238 		curpos++;
    239 	}
    240 
    241 	/* Push remaining modes further */
    242 	for(i=XBIOS_nummodes-1; i>curpos; i--) {
    243 		SDL_memcpy(&XBIOS_modelist[i], &XBIOS_modelist[i-1], sizeof(xbiosmode_t));
    244 	}
    245 
    246 	XBIOS_modelist[curpos].number = modecode;
    247 	XBIOS_modelist[curpos].width = width;
    248 	XBIOS_modelist[curpos].height = height;
    249 	XBIOS_modelist[curpos].depth = depth;
    250 	XBIOS_modelist[curpos].doubleline = flags;
    251 }
    252 
    253 static int XBIOS_VideoInit(_THIS, SDL_PixelFormat *vformat)
    254 {
    255 	int i,j8,j16;
    256 	xbiosmode_t *current_mode;
    257 	unsigned long cookie_blow, cookie_scpn, cookie_cnts;
    258 
    259 	/* Initialize all variables that we clean on shutdown */
    260 	memset (SDL_modelist, 0, sizeof(SDL_modelist));
    261 
    262 	/* Cookie _VDO present ? if not, assume ST machine */
    263 	if (Getcookie(C__VDO, &XBIOS_cvdo) != C_FOUND) {
    264 		XBIOS_cvdo = VDO_ST << 16;
    265 	}
    266 
    267 	/* Allocate memory for old palette */
    268 	XBIOS_oldpalette = (void *)SDL_malloc(256*sizeof(long));
    269 	if ( !XBIOS_oldpalette ) {
    270 		SDL_SetError("Unable to allocate memory for old palette\n");
    271 		return(-1);
    272 	}
    273 
    274 	/* Initialize video mode list */
    275 	/* and save current screen status (palette, screen address, video mode) */
    276 	XBIOS_nummodes = 0;
    277 	XBIOS_modelist = NULL;
    278 	XBIOS_centscreen = SDL_FALSE;
    279 
    280 	switch (XBIOS_cvdo >>16) {
    281 		case VDO_ST:
    282 		case VDO_STE:
    283 			{
    284 				short *oldpalette;
    285 
    286 				SDL_XBIOS_AddMode(this, ST_LOW>>8,320,200,4,SDL_FALSE);
    287 
    288 				XBIOS_oldvbase=Physbase();
    289 				XBIOS_oldvmode=Getrez();
    290 				switch(XBIOS_oldvmode << 8) {
    291 					case ST_LOW:
    292 						XBIOS_oldnumcol=16;
    293 						break;
    294 					case ST_MED:
    295 						XBIOS_oldnumcol=4;
    296 						break;
    297 					case ST_HIGH:
    298 						XBIOS_oldnumcol=2;
    299 						break;
    300 					default:
    301 						XBIOS_oldnumcol=0;
    302 						break;
    303 				}
    304 
    305 				oldpalette= (short *) XBIOS_oldpalette;
    306 				for (i=0;i<XBIOS_oldnumcol;i++) {
    307 					*oldpalette++=Setcolor(i,-1);
    308 				}
    309 
    310 				vformat->BitsPerPixel = 8;
    311 			}
    312 			break;
    313 		case VDO_TT:
    314 
    315 			SDL_XBIOS_AddMode(this, TT_LOW,320,480,8,SDL_FALSE);
    316 			/* Software double-lined mode */
    317 			SDL_XBIOS_AddMode(this, TT_LOW,320,240,8,SDL_TRUE);
    318 
    319 			XBIOS_oldvbase=Logbase();
    320 			XBIOS_oldvmode=EgetShift();
    321 
    322 			switch(XBIOS_oldvmode & ES_MODE) {
    323 				case TT_LOW:
    324 					XBIOS_oldnumcol=256;
    325 					break;
    326 				case ST_LOW:
    327 				case TT_MED:
    328 					XBIOS_oldnumcol=16;
    329 					break;
    330 				case ST_MED:
    331 					XBIOS_oldnumcol=4;
    332 					break;
    333 				case ST_HIGH:
    334 				case TT_HIGH:
    335 					XBIOS_oldnumcol=2;
    336 					break;
    337 				default:
    338 					XBIOS_oldnumcol=0;
    339 					break;
    340 			}
    341 			if (XBIOS_oldnumcol) {
    342 				EgetPalette(0, XBIOS_oldnumcol, XBIOS_oldpalette);
    343 			}
    344 
    345 			vformat->BitsPerPixel = 8;
    346 			break;
    347 		case VDO_F30:
    348 			switch (VgetMonitor())
    349 			{
    350 				case MONITOR_MONO:
    351 					/* Not usable */
    352 					break;
    353 				case MONITOR_RGB:
    354 				case MONITOR_TV:
    355 					SDL_XBIOS_AddMode(this, BPS16|COL80|OVERSCAN|VERTFLAG,768,480,16,SDL_FALSE);
    356 					SDL_XBIOS_AddMode(this, BPS16|COL80|OVERSCAN,768,240,16,SDL_FALSE);
    357 					SDL_XBIOS_AddMode(this, BPS16|COL80|VERTFLAG,640,400,16,SDL_FALSE);
    358 					SDL_XBIOS_AddMode(this, BPS16|COL80,640,200,16,SDL_FALSE);
    359 					SDL_XBIOS_AddMode(this, BPS16|OVERSCAN|VERTFLAG,384,480,16,SDL_FALSE);
    360 					SDL_XBIOS_AddMode(this, BPS16|OVERSCAN,384,240,16,SDL_FALSE);
    361 					SDL_XBIOS_AddMode(this, BPS16|VERTFLAG,320,400,16,SDL_FALSE);
    362 					SDL_XBIOS_AddMode(this, BPS16,320,200,16,SDL_FALSE);
    363 					SDL_XBIOS_AddMode(this, BPS8|COL80|OVERSCAN|VERTFLAG,768,480,8,SDL_FALSE);
    364 					SDL_XBIOS_AddMode(this, BPS8|COL80|OVERSCAN,768,240,8,SDL_FALSE);
    365 					SDL_XBIOS_AddMode(this, BPS8|COL80|VERTFLAG,640,400,8,SDL_FALSE);
    366 					SDL_XBIOS_AddMode(this, BPS8|COL80,640,200,8,SDL_FALSE);
    367 					SDL_XBIOS_AddMode(this, BPS8|OVERSCAN|VERTFLAG,384,480,8,SDL_FALSE);
    368 					SDL_XBIOS_AddMode(this, BPS8|OVERSCAN,384,240,8,SDL_FALSE);
    369 					SDL_XBIOS_AddMode(this, BPS8|VERTFLAG,320,400,8,SDL_FALSE);
    370 					SDL_XBIOS_AddMode(this, BPS8,320,200,8,SDL_FALSE);
    371 					break;
    372 				case MONITOR_VGA:
    373 					SDL_XBIOS_AddMode(this, BPS16,320,480,16,SDL_FALSE);
    374 					SDL_XBIOS_AddMode(this, BPS16|VERTFLAG,320,240,16,SDL_FALSE);
    375 					SDL_XBIOS_AddMode(this, BPS8|COL80,640,480,8,SDL_FALSE);
    376 					SDL_XBIOS_AddMode(this, BPS8|COL80|VERTFLAG,640,240,8,SDL_FALSE);
    377 					SDL_XBIOS_AddMode(this, BPS8,320,480,8,SDL_FALSE);
    378 					SDL_XBIOS_AddMode(this, BPS8|VERTFLAG,320,240,8,SDL_FALSE);
    379 					break;
    380 			}
    381 			XBIOS_oldvbase=Logbase();
    382 			XBIOS_oldvmode=VsetMode(-1);
    383 
    384 			XBIOS_oldnumcol= 1<< (1 << (XBIOS_oldvmode & NUMCOLS));
    385 			if (XBIOS_oldnumcol > 256) {
    386 				XBIOS_oldnumcol = 0;
    387 			}
    388 			if (XBIOS_oldnumcol) {
    389 				VgetRGB(0, XBIOS_oldnumcol, XBIOS_oldpalette);
    390 			}
    391 
    392 			vformat->BitsPerPixel = 16;
    393 
    394 			/* Keep vga/rvb, and pal/ntsc bits */
    395 			current_mode = XBIOS_modelist;
    396 			for (i=0;i<XBIOS_nummodes;i++) {
    397 				Uint16 newvmode;
    398 
    399 				newvmode = current_mode->number;
    400 				newvmode &= ~(VGA|PAL);
    401 				newvmode |= XBIOS_oldvmode & (VGA|PAL);
    402 				current_mode->number = newvmode;
    403 
    404 				current_mode++;
    405 			}
    406 
    407 			/* Initialize BlowUp/SB3/Centscreen stuff if present */
    408 			if (Getcookie(C_BLOW, &cookie_blow) == C_FOUND) {
    409 				SDL_XBIOS_BlowupInit(this, (blow_cookie_t *)cookie_blow);
    410 			} else if (Getcookie(C_SCPN, &cookie_scpn) == C_FOUND) {
    411 				SDL_XBIOS_SB3Init(this, (scpn_cookie_t *)cookie_scpn);
    412 			} else if (Getcookie(C_CNTS, &cookie_cnts) == C_FOUND) {
    413 				XBIOS_oldvmode = SDL_XBIOS_CentscreenInit(this);
    414 				XBIOS_centscreen = SDL_TRUE;
    415 			}
    416 
    417 			break;
    418 	}
    419 
    420 	/* Determine the current screen size */
    421 	if ( XBIOS_nummodes > 0 ) {
    422 		/* FIXME: parse video mode list to search for current mode */
    423 		this->info.current_w = XBIOS_modelist[0].width;
    424 		this->info.current_h = XBIOS_modelist[0].height;
    425 	}
    426 
    427 	current_mode = XBIOS_modelist;
    428 	j8 = j16 = 0;
    429 	for (i=0; i<XBIOS_nummodes; i++, current_mode++) {
    430 		switch (current_mode->depth) {
    431 			case 4:
    432 			case 8:
    433 				SDL_modelist[0][j8] = SDL_malloc(sizeof(SDL_Rect));
    434 				SDL_modelist[0][j8]->x = SDL_modelist[0][j8]->y = 0;
    435 				SDL_modelist[0][j8]->w = current_mode->width;
    436 				SDL_modelist[0][j8]->h = current_mode->height;
    437 				XBIOS_videomodes[0][j8]=current_mode;
    438 				j8++;
    439 				break;
    440 			case 16:
    441 				SDL_modelist[1][j16] = SDL_malloc(sizeof(SDL_Rect));
    442 				SDL_modelist[1][j16]->x = SDL_modelist[1][j16]->y = 0;
    443 				SDL_modelist[1][j16]->w = current_mode->width;
    444 				SDL_modelist[1][j16]->h = current_mode->height;
    445 				XBIOS_videomodes[1][j16]=current_mode;
    446 				j16++;
    447 				break;
    448 		}
    449 	}
    450 	SDL_modelist[0][j8] = NULL;
    451 	SDL_modelist[1][j16] = NULL;
    452 
    453 	XBIOS_screens[0]=NULL;
    454 	XBIOS_screens[1]=NULL;
    455 	XBIOS_shadowscreen=NULL;
    456 
    457 	/* Update hardware info */
    458 	this->info.hw_available = 1;
    459 	this->info.video_mem = (Uint32) Atari_SysMalloc(-1L, MX_STRAM);
    460 
    461 	/* Init chunky to planar routine */
    462 	SDL_Atari_C2pConvert = SDL_Atari_C2pConvert8;
    463 
    464 #if SDL_VIDEO_OPENGL
    465 	SDL_AtariGL_InitPointers(this);
    466 #endif
    467 
    468 	/* Disable screensavers */
    469 	if (SDL_XBIOS_TveillePresent(this)) {
    470 		SDL_XBIOS_TveilleDisable(this);
    471 	}
    472 
    473 	/* We're done! */
    474 	return(0);
    475 }
    476 
    477 static SDL_Rect **XBIOS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
    478 {
    479 	/* 8 bits -> list 0 */
    480 	/* 16 bits -> list 1 */
    481 	if ((format->BitsPerPixel != 8) && (format->BitsPerPixel !=16)) {
    482 		return NULL;
    483 	}
    484 
    485 	return(SDL_modelist[(format->BitsPerPixel)>>4]);
    486 }
    487 
    488 static void XBIOS_FreeBuffers(_THIS)
    489 {
    490 	int i;
    491 
    492 	for (i=0;i<2;i++) {
    493 		if (XBIOS_screensmem[i]!=NULL) {
    494 			Mfree(XBIOS_screensmem[i]);
    495 			XBIOS_screensmem[i]=NULL;
    496 		}
    497 	}
    498 
    499 	if (XBIOS_shadowscreen!=NULL) {
    500 		Mfree(XBIOS_shadowscreen);
    501 		XBIOS_shadowscreen=NULL;
    502 	}
    503 }
    504 
    505 static SDL_Surface *XBIOS_SetVideoMode(_THIS, SDL_Surface *current,
    506 				int width, int height, int bpp, Uint32 flags)
    507 {
    508 	int mode, new_depth;
    509 	int i;
    510 	xbiosmode_t *new_video_mode;
    511 	Uint32 new_screen_size;
    512 	Uint32 modeflags;
    513 
    514 	/* Free current buffers */
    515 	XBIOS_FreeBuffers(this);
    516 
    517 	/* Limit bpp */
    518 	if (bpp>16) {
    519 		bpp = 16;
    520 	}
    521 	bpp >>= 4;
    522 
    523 	/* Search if the mode exists (width, height, bpp) */
    524 	for ( mode=0; SDL_modelist[bpp][mode]; ++mode ) {
    525 		if ( (SDL_modelist[bpp][mode]->w == width) &&
    526 		     (SDL_modelist[bpp][mode]->h == height) ) {
    527 
    528 			break;
    529 		}
    530 	}
    531 	if ( SDL_modelist[bpp][mode] == NULL ) {
    532 		SDL_SetError("Couldn't find requested mode in list");
    533 		return(NULL);
    534 	}
    535 
    536 	modeflags = SDL_FULLSCREEN | SDL_PREALLOC;
    537 
    538 	/* Allocate needed buffers: simple/double buffer and shadow surface */
    539 	new_video_mode = XBIOS_videomodes[bpp][mode];
    540 	new_depth = new_video_mode->depth;
    541 	if (new_depth == 4) {
    542 		SDL_Atari_C2pConvert = SDL_Atari_C2pConvert4;
    543 		new_depth=8;
    544 		modeflags |= SDL_SWSURFACE|SDL_HWPALETTE;
    545 	} else if (new_depth == 8) {
    546 		SDL_Atari_C2pConvert = SDL_Atari_C2pConvert8;
    547 		modeflags |= SDL_SWSURFACE|SDL_HWPALETTE;
    548 	} else {
    549 		modeflags |= SDL_HWSURFACE;
    550 	}
    551 
    552 	new_screen_size = width * height * ((new_depth)>>3);
    553 	new_screen_size += 256; /* To align on a 256 byte adress */
    554 
    555 	if (new_depth == 8) {
    556 		XBIOS_shadowscreen = Atari_SysMalloc(new_screen_size, MX_PREFTTRAM);
    557 
    558 		if (XBIOS_shadowscreen == NULL) {
    559 			SDL_SetError("Can not allocate %d KB for shadow buffer", new_screen_size>>10);
    560 			return (NULL);
    561 		}
    562 		SDL_memset(XBIOS_shadowscreen, 0, new_screen_size);
    563 	}
    564 
    565 	/* Output buffer needs to be twice in size for the software double-line mode */
    566 	XBIOS_doubleline = SDL_FALSE;
    567 	if (new_video_mode->doubleline) {
    568 		new_screen_size <<= 1;
    569 		XBIOS_doubleline = SDL_TRUE;
    570 	}
    571 
    572 	XBIOS_screensmem[0] = Atari_SysMalloc(new_screen_size, MX_STRAM);
    573 
    574 	if (XBIOS_screensmem[0]==NULL) {
    575 		XBIOS_FreeBuffers(this);
    576 		SDL_SetError("Can not allocate %d KB for frame buffer", new_screen_size>>10);
    577 		return (NULL);
    578 	}
    579 	SDL_memset(XBIOS_screensmem[0], 0, new_screen_size);
    580 
    581 	XBIOS_screens[0]=(void *) (( (long) XBIOS_screensmem[0]+256) & 0xFFFFFF00UL);
    582 
    583 #if SDL_VIDEO_OPENGL
    584 	if (flags & SDL_OPENGL) {
    585 		if (this->gl_config.double_buffer) {
    586 			flags |= SDL_DOUBLEBUF;
    587 		}
    588 	}
    589 #endif
    590 
    591 	/* Double buffer ? */
    592 	if (flags & SDL_DOUBLEBUF) {
    593 		XBIOS_screensmem[1] = Atari_SysMalloc(new_screen_size, MX_STRAM);
    594 
    595 		if (XBIOS_screensmem[1]==NULL) {
    596 			XBIOS_FreeBuffers(this);
    597 			SDL_SetError("Can not allocate %d KB for double buffer", new_screen_size>>10);
    598 			return (NULL);
    599 		}
    600 		SDL_memset(XBIOS_screensmem[1], 0, new_screen_size);
    601 
    602 		XBIOS_screens[1]=(void *) (( (long) XBIOS_screensmem[1]+256) & 0xFFFFFF00UL);
    603 		modeflags |= SDL_DOUBLEBUF;
    604 	}
    605 
    606 	/* Allocate the new pixel format for the screen */
    607 	if ( ! SDL_ReallocFormat(current, new_depth, 0, 0, 0, 0) ) {
    608 		XBIOS_FreeBuffers(this);
    609 		SDL_SetError("Couldn't allocate new pixel format for requested mode");
    610 		return(NULL);
    611 	}
    612 
    613 	current->w = XBIOS_width = width;
    614 	current->h = XBIOS_height = height;
    615 	current->pitch = (width * new_depth)>>3;
    616 
    617 	/* this is for C2P conversion */
    618 	XBIOS_pitch = (new_video_mode->width * new_video_mode->depth)>>3;
    619 
    620 	if (new_depth == 8)
    621 		current->pixels = XBIOS_shadowscreen;
    622 	else
    623 		current->pixels = XBIOS_screens[0];
    624 
    625 	XBIOS_fbnum = 0;
    626 
    627 #if SDL_VIDEO_OPENGL
    628 	if (flags & SDL_OPENGL) {
    629 		if (!SDL_AtariGL_Init(this, current)) {
    630 			XBIOS_FreeBuffers(this);
    631 			SDL_SetError("Can not create OpenGL context");
    632 			return NULL;
    633 		}
    634 
    635 		modeflags |= SDL_OPENGL;
    636 	}
    637 #endif
    638 
    639 	current->flags = modeflags;
    640 
    641 	/* Now set the video mode */
    642 #ifndef DEBUG_VIDEO_XBIOS
    643 	Setscreen(-1,XBIOS_screens[0],-1);
    644 #endif
    645 
    646 	switch(XBIOS_cvdo >> 16) {
    647 		case VDO_ST:
    648 #ifndef DEBUG_VIDEO_XBIOS
    649 			Setscreen(-1,-1,new_video_mode->number);
    650 #endif
    651 			/* Reset palette */
    652 			for (i=0;i<16;i++) {
    653 				TT_palette[i]= ((i>>1)<<8) | (((i*8)/17)<<4) | (i>>1);
    654 			}
    655 #ifndef DEBUG_VIDEO_XBIOS
    656 			Setpalette(TT_palette);
    657 #endif
    658 			break;
    659 		case VDO_STE:
    660 #ifndef DEBUG_VIDEO_XBIOS
    661 			Setscreen(-1,-1,new_video_mode->number);
    662 #endif
    663 			/* Reset palette */
    664 			for (i=0;i<16;i++)
    665 			{
    666 				int c;
    667 
    668 				c=((i&1)<<3)|((i>>1)&7);
    669 				TT_palette[i]=(c<<8)|(c<<4)|c;
    670 			}
    671 #ifndef DEBUG_VIDEO_XBIOS
    672 			Setpalette(TT_palette);
    673 #endif
    674 			break;
    675 		case VDO_TT:
    676 #ifndef DEBUG_VIDEO_XBIOS
    677 			EsetShift(new_video_mode->number);
    678 #endif
    679 			break;
    680 		case VDO_F30:
    681 #ifndef DEBUG_VIDEO_XBIOS
    682 			if (XBIOS_centscreen) {
    683 				SDL_XBIOS_CentscreenSetmode(this, width, height, new_depth);
    684 			} else {
    685 				VsetMode(new_video_mode->number);
    686 			}
    687 #endif
    688 			/* Set hardware palette to black in True Colour */
    689 			if (new_depth == 16) {
    690 				SDL_memset(F30_palette, 0, sizeof(F30_palette));
    691 				VsetRGB(0,256,F30_palette);
    692 			}
    693 			break;
    694 	}
    695 
    696 	Vsync();
    697 
    698 	this->UpdateRects = XBIOS_UpdateRects;
    699 
    700 	return (current);
    701 }
    702 
    703 /* We don't actually allow hardware surfaces other than the main one */
    704 static int XBIOS_AllocHWSurface(_THIS, SDL_Surface *surface)
    705 {
    706 	return(-1);
    707 }
    708 
    709 static void XBIOS_FreeHWSurface(_THIS, SDL_Surface *surface)
    710 {
    711 	return;
    712 }
    713 
    714 static int XBIOS_LockHWSurface(_THIS, SDL_Surface *surface)
    715 {
    716 	return(0);
    717 }
    718 
    719 static void XBIOS_UnlockHWSurface(_THIS, SDL_Surface *surface)
    720 {
    721 	return;
    722 }
    723 
    724 static void XBIOS_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
    725 {
    726 	SDL_Surface *surface;
    727 
    728 	surface = this->screen;
    729 
    730 	if ((surface->format->BitsPerPixel) == 8) {
    731 		int i;
    732 
    733 		for (i=0;i<numrects;i++) {
    734 			void *source,*destination;
    735 			int x1,x2;
    736 
    737 			x1 = rects[i].x & ~15;
    738 			x2 = rects[i].x+rects[i].w;
    739 			if (x2 & 15) {
    740 				x2 = (x2 | 15) +1;
    741 			}
    742 
    743 			source = surface->pixels;
    744 			source += surface->pitch * rects[i].y;
    745 			source += x1;
    746 
    747 			destination = XBIOS_screens[XBIOS_fbnum];
    748 			destination += XBIOS_pitch * rects[i].y;
    749 			destination += x1;
    750 
    751 			/* Convert chunky to planar screen */
    752 			SDL_Atari_C2pConvert(
    753 				source,
    754 				destination,
    755 				x2-x1,
    756 				rects[i].h,
    757 				XBIOS_doubleline,
    758 				surface->pitch,
    759 				XBIOS_pitch
    760 			);
    761 		}
    762 	}
    763 
    764 #ifndef DEBUG_VIDEO_XBIOS
    765 	Setscreen(-1,XBIOS_screens[XBIOS_fbnum],-1);
    766 #endif
    767 	Vsync();
    768 
    769 	if ((surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) {
    770 		XBIOS_fbnum ^= 1;
    771 		if ((surface->format->BitsPerPixel) > 8) {
    772 			surface->pixels=XBIOS_screens[XBIOS_fbnum];
    773 		}
    774 	}
    775 }
    776 
    777 static int XBIOS_FlipHWSurface(_THIS, SDL_Surface *surface)
    778 {
    779 	if ((surface->format->BitsPerPixel) == 8) {
    780 		void *destscr;
    781 		int destx;
    782 
    783 		/* Center on destination screen */
    784 		destscr = XBIOS_screens[XBIOS_fbnum];
    785 		destscr += XBIOS_pitch * ((XBIOS_height - surface->h) >> 1);
    786 		destx = (XBIOS_width - surface->w) >> 1;
    787 		destx &= ~15;
    788 		destscr += destx;
    789 
    790 		/* Convert chunky to planar screen */
    791 		SDL_Atari_C2pConvert(
    792 			surface->pixels,
    793 			destscr,
    794 			surface->w,
    795 			surface->h,
    796 			XBIOS_doubleline,
    797 			surface->pitch,
    798 			XBIOS_pitch
    799 		);
    800 	}
    801 
    802 #ifndef DEBUG_VIDEO_XBIOS
    803 	Setscreen(-1,XBIOS_screens[XBIOS_fbnum],-1);
    804 #endif
    805 	Vsync();
    806 
    807 	if ((surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) {
    808 		XBIOS_fbnum ^= 1;
    809 		if ((surface->format->BitsPerPixel) > 8) {
    810 			surface->pixels=XBIOS_screens[XBIOS_fbnum];
    811 		}
    812 	}
    813 
    814 	return(0);
    815 }
    816 
    817 static int XBIOS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
    818 {
    819 	int		i;
    820 	int		r,v,b;
    821 
    822 	switch( XBIOS_cvdo >> 16) {
    823 		case VDO_ST:
    824 		case VDO_STE:
    825 		 	for (i=0;i<ncolors;i++)
    826 			{
    827 				r = colors[i].r;
    828 				v = colors[i].g;
    829 				b = colors[i].b;
    830 
    831 				TT_palette[firstcolor+i]=((r*30)+(v*59)+(b*11))/100;
    832 			}
    833 			SDL_Atari_C2pConvert4_pal(TT_palette); /* convert the lighting */
    834 			break;
    835 		case VDO_TT:
    836 			for(i = 0; i < ncolors; i++)
    837 			{
    838 				r = colors[i].r;
    839 				v = colors[i].g;
    840 				b = colors[i].b;
    841 
    842 				TT_palette[i]=((r>>4)<<8)|((v>>4)<<4)|(b>>4);
    843 			}
    844 #ifndef DEBUG_VIDEO_XBIOS
    845 			EsetPalette(firstcolor,ncolors,TT_palette);
    846 #endif
    847 			break;
    848 		case VDO_F30:
    849 			for(i = 0; i < ncolors; i++)
    850 			{
    851 				r = colors[i].r;
    852 				v = colors[i].g;
    853 				b = colors[i].b;
    854 
    855 				F30_palette[i]=(r<<16)|(v<<8)|b;
    856 			}
    857 #ifndef DEBUG_VIDEO_XBIOS
    858 			VsetRGB(firstcolor,ncolors,F30_palette);
    859 #endif
    860 			break;
    861 	}
    862 
    863 	return(1);
    864 }
    865 
    866 /* Note:  If we are terminated, this could be called in the middle of
    867    another SDL video routine -- notably UpdateRects.
    868 */
    869 static void XBIOS_VideoQuit(_THIS)
    870 {
    871 	int i,j;
    872 
    873 	Atari_ShutdownEvents();
    874 
    875 	/* Restore video mode and palette */
    876 #ifndef DEBUG_VIDEO_XBIOS
    877 	switch(XBIOS_cvdo >> 16) {
    878 		case VDO_ST:
    879 		case VDO_STE:
    880 			Setscreen(-1,XBIOS_oldvbase,XBIOS_oldvmode);
    881 			if (XBIOS_oldnumcol) {
    882 				Setpalette(XBIOS_oldpalette);
    883 			}
    884 			break;
    885 		case VDO_TT:
    886 			Setscreen(-1,XBIOS_oldvbase,-1);
    887 			EsetShift(XBIOS_oldvmode);
    888 			if (XBIOS_oldnumcol) {
    889 				EsetPalette(0, XBIOS_oldnumcol, XBIOS_oldpalette);
    890 			}
    891 			break;
    892 		case VDO_F30:
    893 			Setscreen(-1, XBIOS_oldvbase, -1);
    894 			if (XBIOS_centscreen) {
    895 				SDL_XBIOS_CentscreenRestore(this, XBIOS_oldvmode);
    896 			} else {
    897 				VsetMode(XBIOS_oldvmode);
    898 			}
    899 			if (XBIOS_oldnumcol) {
    900 				VsetRGB(0, XBIOS_oldnumcol, XBIOS_oldpalette);
    901 			}
    902 			break;
    903 	}
    904 	Vsync();
    905 #endif
    906 
    907 
    908 #if SDL_VIDEO_OPENGL
    909 	if (gl_active) {
    910 		SDL_AtariGL_Quit(this, SDL_TRUE);
    911 	}
    912 #endif
    913 
    914 	if (XBIOS_oldpalette) {
    915 		SDL_free(XBIOS_oldpalette);
    916 		XBIOS_oldpalette=NULL;
    917 	}
    918 	XBIOS_FreeBuffers(this);
    919 
    920 	/* Free mode list */
    921 	for (j=0;j<NUM_MODELISTS;j++) {
    922 		for (i=0;i<SDL_NUMMODES;i++) {
    923 			if (SDL_modelist[j][i]!=NULL) {
    924 				SDL_free(SDL_modelist[j][i]);
    925 				SDL_modelist[j][i]=NULL;
    926 			}
    927 		}
    928 	}
    929 
    930 	if (XBIOS_modelist) {
    931 		SDL_free(XBIOS_modelist);
    932 		XBIOS_nummodes=0;
    933 		XBIOS_modelist=NULL;
    934 	}
    935 
    936 	this->screen->pixels = NULL;
    937 
    938 	/* Restore screensavers */
    939 	if (SDL_XBIOS_TveillePresent(this)) {
    940 		SDL_XBIOS_TveilleRestore(this);
    941 	}
    942 }
    943 
    944 #if SDL_VIDEO_OPENGL
    945 
    946 static void XBIOS_GL_SwapBuffers(_THIS)
    947 {
    948 	SDL_AtariGL_SwapBuffers(this);
    949 	XBIOS_FlipHWSurface(this, this->screen);
    950 	SDL_AtariGL_MakeCurrent(this);
    951 }
    952 
    953 #endif
    954