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