src/video/xbios/SDL_xbios.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 27 Feb 2002 16:15:34 +0000
changeset 287 e4bd0cf95506
parent 281 c5010ab8ba35
child 297 f6ffac90895c
permissions -rw-r--r--
From: Patrice Mandin <pmandin@caramail.com>
Subject: [SDL] [PATCH] Little cleanups for Atari port
slouken@281
     1
/*
slouken@281
     2
    SDL - Simple DirectMedia Layer
slouken@281
     3
    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
slouken@281
     4
slouken@281
     5
    This library is free software; you can redistribute it and/or
slouken@281
     6
    modify it under the terms of the GNU Library General Public
slouken@281
     7
    License as published by the Free Software Foundation; either
slouken@281
     8
    version 2 of the License, or (at your option) any later version.
slouken@281
     9
slouken@281
    10
    This library is distributed in the hope that it will be useful,
slouken@281
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@281
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@281
    13
    Library General Public License for more details.
slouken@281
    14
slouken@281
    15
    You should have received a copy of the GNU Library General Public
slouken@281
    16
    License along with this library; if not, write to the Free
slouken@281
    17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
slouken@281
    18
slouken@281
    19
    Sam Lantinga
slouken@281
    20
    slouken@libsdl.org
slouken@281
    21
*/
slouken@281
    22
slouken@281
    23
#ifdef SAVE_RCSID
slouken@281
    24
static char rcsid =
slouken@281
    25
 "@(#) $Id$";
slouken@281
    26
#endif
slouken@281
    27
slouken@281
    28
/*
slouken@281
    29
 * Xbios SDL video driver
slouken@281
    30
 * 
slouken@281
    31
 * Patrice Mandin
slouken@281
    32
 */
slouken@281
    33
slouken@281
    34
#include <stdio.h>
slouken@281
    35
#include <stdlib.h>
slouken@281
    36
#include <string.h>
slouken@281
    37
#include <sys/stat.h>
slouken@281
    38
#include <unistd.h>
slouken@281
    39
slouken@281
    40
/* Mint includes */
slouken@281
    41
#include <sys/cookie.h>
slouken@281
    42
#include <mint/osbind.h>
slouken@281
    43
#include <mint/falcon.h>
slouken@281
    44
slouken@281
    45
#include "SDL.h"
slouken@281
    46
#include "SDL_error.h"
slouken@281
    47
#include "SDL_video.h"
slouken@281
    48
#include "SDL_mouse.h"
slouken@281
    49
#include "SDL_sysvideo.h"
slouken@281
    50
#include "SDL_pixels_c.h"
slouken@281
    51
#include "SDL_events_c.h"
slouken@281
    52
slouken@281
    53
#include "SDL_ataric2p_s.h"
slouken@281
    54
#include "SDL_ataric2p060_c.h"
slouken@281
    55
#include "SDL_atarievents_c.h"
slouken@281
    56
#include "SDL_atarimxalloc_c.h"
slouken@281
    57
#include "SDL_xbios.h"
slouken@281
    58
slouken@281
    59
#define XBIOS_VID_DRIVER_NAME "xbios"
slouken@281
    60
slouken@281
    61
/* Initialization/Query functions */
slouken@281
    62
static int XBIOS_VideoInit(_THIS, SDL_PixelFormat *vformat);
slouken@281
    63
static SDL_Rect **XBIOS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
slouken@281
    64
static SDL_Surface *XBIOS_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
slouken@281
    65
static int XBIOS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
slouken@281
    66
static void XBIOS_VideoQuit(_THIS);
slouken@281
    67
slouken@281
    68
/* Hardware surface functions */
slouken@281
    69
static int XBIOS_AllocHWSurface(_THIS, SDL_Surface *surface);
slouken@281
    70
static int XBIOS_LockHWSurface(_THIS, SDL_Surface *surface);
slouken@281
    71
static int XBIOS_FlipHWSurface(_THIS, SDL_Surface *surface);
slouken@281
    72
static void XBIOS_UnlockHWSurface(_THIS, SDL_Surface *surface);
slouken@281
    73
static void XBIOS_FreeHWSurface(_THIS, SDL_Surface *surface);
slouken@281
    74
static void XBIOS_UpdateRects(_THIS, int numrects, SDL_Rect *rects);
slouken@281
    75
slouken@281
    76
/* List of video modes */
slouken@281
    77
slouken@281
    78
/* ST modes */
slouken@281
    79
static int xbiosnummodes_st=1;
slouken@281
    80
static xbiosmode_t xbiosmodelist_st[]={
slouken@281
    81
	{ST_LOW>>8,320,200,4,SDL_FALSE}
slouken@281
    82
};
slouken@281
    83
slouken@281
    84
/* TT modes */
slouken@281
    85
static int xbiosnummodes_tt=2;
slouken@281
    86
static xbiosmode_t xbiosmodelist_tt[]={
slouken@281
    87
	{TT_LOW,320,480,8,SDL_FALSE},
slouken@281
    88
	{TT_LOW,320,240,8,SDL_TRUE}	/* Software double-lined mode */
slouken@281
    89
};
slouken@281
    90
slouken@281
    91
/* Falcon RVB modes */
slouken@281
    92
static int xbiosnummodes_f30rvb=16;
slouken@281
    93
static xbiosmode_t xbiosmodelist_f30rvb[]={
slouken@281
    94
	{BPS16|COL80|OVERSCAN|VERTFLAG,768,480,16,SDL_FALSE},
slouken@281
    95
	{BPS16|COL80|OVERSCAN,768,240,16,SDL_FALSE},
slouken@281
    96
	{BPS16|COL80|VERTFLAG,640,400,16,SDL_FALSE},
slouken@281
    97
	{BPS16|COL80,640,200,16,SDL_FALSE},
slouken@281
    98
	{BPS16|OVERSCAN|VERTFLAG,384,480,16,SDL_FALSE},
slouken@281
    99
	{BPS16|OVERSCAN,384,240,16,SDL_FALSE},
slouken@281
   100
	{BPS16|VERTFLAG,320,400,16,SDL_FALSE},
slouken@281
   101
	{BPS16,320,200,16,SDL_FALSE},
slouken@281
   102
slouken@281
   103
	{BPS8|COL80|OVERSCAN|VERTFLAG,768,480,8,SDL_FALSE},
slouken@281
   104
	{BPS8|COL80|OVERSCAN,768,240,8,SDL_FALSE},
slouken@281
   105
	{BPS8|COL80|VERTFLAG,640,400,8,SDL_FALSE},
slouken@281
   106
	{BPS8|COL80,640,200,8,SDL_FALSE},
slouken@281
   107
	{BPS8|OVERSCAN|VERTFLAG,384,480,8,SDL_FALSE},
slouken@281
   108
	{BPS8|OVERSCAN,384,240,8,SDL_FALSE},
slouken@281
   109
	{BPS8|VERTFLAG,320,400,8,SDL_FALSE},
slouken@281
   110
	{BPS8,320,200,8,SDL_FALSE}
slouken@281
   111
};
slouken@281
   112
slouken@281
   113
/* Falcon VGA modes */
slouken@281
   114
static int xbiosnummodes_f30vga=6;
slouken@281
   115
static xbiosmode_t xbiosmodelist_f30vga[]={
slouken@281
   116
	{BPS16,320,480,16,SDL_FALSE},
slouken@281
   117
	{BPS16|VERTFLAG,320,240,16,SDL_FALSE},
slouken@281
   118
slouken@281
   119
	{BPS8|COL80,640,480,8,SDL_FALSE},	
slouken@281
   120
	{BPS8|COL80|VERTFLAG,640,240,8,SDL_FALSE},
slouken@281
   121
	{BPS8,320,480,8,SDL_FALSE},
slouken@281
   122
	{BPS8|VERTFLAG,320,240,8,SDL_FALSE}
slouken@281
   123
};
slouken@281
   124
slouken@281
   125
/* To setup palette */
slouken@281
   126
slouken@281
   127
static unsigned short	TT_palette[256];
slouken@281
   128
static unsigned long	F30_palette[256];
slouken@281
   129
slouken@281
   130
/* Xbios driver bootstrap functions */
slouken@281
   131
slouken@281
   132
static int XBIOS_Available(void)
slouken@281
   133
{
slouken@281
   134
	const char *envr = getenv("SDL_VIDEODRIVER");
slouken@281
   135
	unsigned long cookie_vdo;
slouken@281
   136
slouken@281
   137
	/* Check if user asked a different video driver */
slouken@281
   138
	if ((envr) && (strcmp(envr, XBIOS_VID_DRIVER_NAME)!=0)) {
slouken@281
   139
		return 0;
slouken@281
   140
	}
slouken@281
   141
slouken@281
   142
	/* Cookie _VDO present ? if not, assume ST machine */
slouken@281
   143
	if (Getcookie(C__VDO, &cookie_vdo) != C_FOUND) {
slouken@281
   144
		cookie_vdo = VDO_ST << 16;
slouken@281
   145
	}
slouken@281
   146
slouken@281
   147
	/* Test if we have a monochrome monitor plugged in */
slouken@281
   148
	switch( cookie_vdo >>16) {
slouken@281
   149
		case VDO_ST:
slouken@281
   150
		case VDO_STE:
slouken@281
   151
			if ( Getrez() == (ST_HIGH>>8) )
slouken@281
   152
				return 0;
slouken@281
   153
			break;
slouken@281
   154
		case VDO_TT:
slouken@281
   155
			if ( (EgetShift() & ES_MODE) == TT_HIGH)
slouken@281
   156
				return 0;
slouken@281
   157
			break;
slouken@281
   158
		case VDO_F30:
slouken@281
   159
			if ( Montype() == MONITOR_MONO)
slouken@281
   160
				return 0;
slouken@281
   161
			break;
slouken@281
   162
		default:
slouken@281
   163
			return 0;
slouken@281
   164
	}
slouken@281
   165
slouken@281
   166
	return 1;
slouken@281
   167
}
slouken@281
   168
slouken@281
   169
static void XBIOS_DeleteDevice(SDL_VideoDevice *device)
slouken@281
   170
{
slouken@281
   171
	free(device->hidden);
slouken@281
   172
	free(device);
slouken@281
   173
}
slouken@281
   174
slouken@281
   175
static SDL_VideoDevice *XBIOS_CreateDevice(int devindex)
slouken@281
   176
{
slouken@281
   177
	SDL_VideoDevice *device;
slouken@281
   178
slouken@281
   179
	/* Initialize all variables that we clean on shutdown */
slouken@281
   180
	device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
slouken@281
   181
	if ( device ) {
slouken@281
   182
		memset(device, 0, (sizeof *device));
slouken@281
   183
		device->hidden = (struct SDL_PrivateVideoData *)
slouken@281
   184
				malloc((sizeof *device->hidden));
slouken@281
   185
	}
slouken@281
   186
	if ( (device == NULL) || (device->hidden == NULL) ) {
slouken@281
   187
		SDL_OutOfMemory();
slouken@281
   188
		if ( device ) {
slouken@281
   189
			free(device);
slouken@281
   190
		}
slouken@281
   191
		return(0);
slouken@281
   192
	}
slouken@281
   193
	memset(device->hidden, 0, (sizeof *device->hidden));
slouken@281
   194
slouken@281
   195
	atari_test_cpu060_present();
slouken@281
   196
slouken@281
   197
	/* Video functions */
slouken@281
   198
	device->VideoInit = XBIOS_VideoInit;
slouken@281
   199
	device->ListModes = XBIOS_ListModes;
slouken@281
   200
	device->SetVideoMode = XBIOS_SetVideoMode;
slouken@281
   201
	device->SetColors = XBIOS_SetColors;
slouken@281
   202
	device->UpdateRects = NULL;
slouken@281
   203
	device->VideoQuit = XBIOS_VideoQuit;
slouken@281
   204
	device->AllocHWSurface = XBIOS_AllocHWSurface;
slouken@281
   205
	device->LockHWSurface = XBIOS_LockHWSurface;
slouken@281
   206
	device->UnlockHWSurface = XBIOS_UnlockHWSurface;
slouken@281
   207
	device->FlipHWSurface = XBIOS_FlipHWSurface;
slouken@281
   208
	device->FreeHWSurface = XBIOS_FreeHWSurface;
slouken@281
   209
slouken@281
   210
	/* Events */
slouken@281
   211
	device->InitOSKeymap = Atari_InitOSKeymap;
slouken@281
   212
	device->PumpEvents = Atari_PumpEvents;
slouken@281
   213
slouken@281
   214
	device->free = XBIOS_DeleteDevice;
slouken@281
   215
slouken@281
   216
	return device;
slouken@281
   217
}
slouken@281
   218
slouken@281
   219
VideoBootStrap XBIOS_bootstrap = {
slouken@281
   220
	XBIOS_VID_DRIVER_NAME, "Atari Xbios driver",
slouken@281
   221
	XBIOS_Available, XBIOS_CreateDevice
slouken@281
   222
};
slouken@281
   223
slouken@281
   224
static int XBIOS_VideoInit(_THIS, SDL_PixelFormat *vformat)
slouken@281
   225
{
slouken@281
   226
	int i,j8,j16;
slouken@281
   227
	xbiosmode_t *current_mode;
slouken@281
   228
slouken@281
   229
	/* Initialize all variables that we clean on shutdown */
slouken@281
   230
	memset (SDL_modelist, 0, sizeof(SDL_modelist));
slouken@281
   231
slouken@281
   232
	/* Cookie _VDO present ? if not, assume ST machine */
slouken@281
   233
	if (Getcookie(C__VDO, &XBIOS_cvdo) != C_FOUND) {
slouken@281
   234
		XBIOS_cvdo = VDO_ST << 16;
slouken@281
   235
	}
slouken@281
   236
slouken@281
   237
	/* Allocate memory for old palette */
slouken@281
   238
	XBIOS_oldpalette = (void *)malloc(256*sizeof(long));
slouken@281
   239
	if ( !XBIOS_oldpalette ) {
slouken@281
   240
		SDL_SetError("Unable to allocate memory for old palette\n");
slouken@281
   241
		return(-1);
slouken@281
   242
	}
slouken@281
   243
slouken@281
   244
	/* Initialize video mode list */
slouken@281
   245
	/* and save current screen status (palette, screen address, video mode) */
slouken@281
   246
slouken@281
   247
	switch (XBIOS_cvdo >>16) {
slouken@281
   248
		case VDO_ST:
slouken@281
   249
		case VDO_STE:
slouken@281
   250
			{
slouken@281
   251
				short *oldpalette;
slouken@281
   252
slouken@281
   253
				XBIOS_nummodes=xbiosnummodes_st;
slouken@281
   254
				XBIOS_modelist=xbiosmodelist_st;
slouken@281
   255
			
slouken@281
   256
				XBIOS_oldvbase=Physbase();
slouken@281
   257
				XBIOS_oldvmode=Getrez();
slouken@281
   258
				switch(XBIOS_oldvmode << 8) {
slouken@281
   259
					case ST_LOW:
slouken@281
   260
						XBIOS_oldnumcol=16;
slouken@281
   261
						break;
slouken@281
   262
					case ST_MED:
slouken@281
   263
						XBIOS_oldnumcol=4;
slouken@281
   264
						break;
slouken@281
   265
					case ST_HIGH:
slouken@281
   266
						XBIOS_oldnumcol=2;
slouken@281
   267
						break;
slouken@281
   268
					default:
slouken@281
   269
						XBIOS_oldnumcol=0;
slouken@281
   270
						break;
slouken@281
   271
				}
slouken@281
   272
slouken@281
   273
				oldpalette= (short *) XBIOS_oldpalette;
slouken@281
   274
				for (i=0;i<XBIOS_oldnumcol;i++) {
slouken@281
   275
					*oldpalette++=Setcolor(i,-1);
slouken@281
   276
				}
slouken@281
   277
slouken@281
   278
				vformat->BitsPerPixel = 8;
slouken@281
   279
			}
slouken@281
   280
			break;
slouken@281
   281
		case VDO_TT:
slouken@281
   282
			XBIOS_nummodes=xbiosnummodes_tt;
slouken@281
   283
			XBIOS_modelist=xbiosmodelist_tt;
slouken@281
   284
slouken@281
   285
			XBIOS_oldvbase=Logbase();
slouken@281
   286
			XBIOS_oldvmode=EgetShift();
slouken@281
   287
slouken@281
   288
			switch(XBIOS_oldvmode & ES_MODE) {
slouken@281
   289
				case TT_LOW:
slouken@281
   290
					XBIOS_oldnumcol=256;
slouken@281
   291
					break;
slouken@281
   292
				case ST_LOW:
slouken@281
   293
				case TT_MED:
slouken@281
   294
					XBIOS_oldnumcol=16;
slouken@281
   295
					break;
slouken@281
   296
				case ST_MED:
slouken@281
   297
					XBIOS_oldnumcol=4;
slouken@281
   298
					break;
slouken@281
   299
				case ST_HIGH:
slouken@281
   300
				case TT_HIGH:
slouken@281
   301
					XBIOS_oldnumcol=2;
slouken@281
   302
					break;
slouken@281
   303
				default:
slouken@281
   304
					XBIOS_oldnumcol=0;
slouken@281
   305
					break;
slouken@281
   306
			}
slouken@281
   307
			if (XBIOS_oldnumcol) {
slouken@281
   308
				EgetPalette(0, XBIOS_oldnumcol, XBIOS_oldpalette);
slouken@281
   309
			}
slouken@281
   310
slouken@281
   311
			vformat->BitsPerPixel = 8;
slouken@281
   312
			break;
slouken@281
   313
		case VDO_F30:
slouken@281
   314
			switch (Montype())
slouken@281
   315
			{
slouken@281
   316
				case MONITOR_MONO:
slouken@281
   317
					/* Not usable */
slouken@281
   318
					break;
slouken@281
   319
				case MONITOR_RGB:
slouken@281
   320
				case MONITOR_TV:
slouken@281
   321
					XBIOS_nummodes = xbiosnummodes_f30rvb;
slouken@281
   322
					XBIOS_modelist = xbiosmodelist_f30rvb;
slouken@281
   323
					break;
slouken@281
   324
				case MONITOR_VGA:
slouken@281
   325
					XBIOS_nummodes = xbiosnummodes_f30vga;
slouken@281
   326
					XBIOS_modelist = xbiosmodelist_f30vga;
slouken@281
   327
					break;
slouken@281
   328
			}
slouken@281
   329
			XBIOS_oldvbase=Logbase();
slouken@281
   330
			XBIOS_oldvmode=Vsetmode(-1);
slouken@281
   331
slouken@281
   332
			XBIOS_oldnumcol= 1<< (1 << (XBIOS_oldvmode & NUMCOLS));
slouken@281
   333
			if (XBIOS_oldnumcol > 256) {
slouken@281
   334
				XBIOS_oldnumcol = 0;
slouken@281
   335
			}
slouken@281
   336
			if (XBIOS_oldnumcol) {
slouken@281
   337
				VgetRGB(0, XBIOS_oldnumcol, XBIOS_oldpalette);
slouken@281
   338
			}
slouken@281
   339
slouken@281
   340
			vformat->BitsPerPixel = 16;
slouken@281
   341
slouken@281
   342
			/* Keep vga/rvb, and pal/ntsc bits */
slouken@281
   343
			current_mode = XBIOS_modelist;
slouken@281
   344
			for (i=0;i<XBIOS_nummodes;i++) {
slouken@281
   345
				Uint16 newvmode;			
slouken@281
   346
slouken@281
   347
				newvmode = current_mode->number;
slouken@281
   348
				newvmode &= ~(VGA|PAL);
slouken@281
   349
				newvmode |= XBIOS_oldvmode & (VGA|PAL);
slouken@281
   350
				current_mode->number = newvmode;
slouken@281
   351
				
slouken@281
   352
				current_mode++;
slouken@281
   353
			}
slouken@281
   354
slouken@281
   355
			break;
slouken@281
   356
	}
slouken@281
   357
	
slouken@281
   358
	current_mode = XBIOS_modelist;
slouken@281
   359
	j8 = j16 = 0;
slouken@281
   360
	for (i=0;i<XBIOS_nummodes;i++) {
slouken@281
   361
		switch (current_mode->depth) {
slouken@281
   362
			case 4:
slouken@281
   363
			case 8:
slouken@281
   364
				SDL_modelist[0][j8] = malloc(sizeof(SDL_Rect));
slouken@281
   365
				SDL_modelist[0][j8]->x = SDL_modelist[0][j8]->y = 0;
slouken@281
   366
				SDL_modelist[0][j8]->w = current_mode->width;
slouken@281
   367
				SDL_modelist[0][j8]->h = current_mode->height;
slouken@281
   368
				XBIOS_videomodes[0][j8]=current_mode;
slouken@281
   369
				current_mode++;
slouken@281
   370
				j8++;
slouken@281
   371
				break;
slouken@281
   372
			case 16:
slouken@281
   373
				SDL_modelist[1][j16] = malloc(sizeof(SDL_Rect));
slouken@281
   374
				SDL_modelist[1][j16]->x = SDL_modelist[1][j16]->y = 0;
slouken@281
   375
				SDL_modelist[1][j16]->w = current_mode->width;
slouken@281
   376
				SDL_modelist[1][j16]->h = current_mode->height;
slouken@281
   377
				XBIOS_videomodes[1][j16]=current_mode;
slouken@281
   378
				current_mode++;
slouken@281
   379
				j16++;
slouken@281
   380
				break;
slouken@281
   381
		}		
slouken@281
   382
	}
slouken@281
   383
	SDL_modelist[0][j8] = NULL;
slouken@281
   384
	SDL_modelist[1][j16] = NULL;
slouken@281
   385
slouken@281
   386
	XBIOS_screens[0]=NULL;
slouken@281
   387
	XBIOS_screens[1]=NULL;
slouken@281
   388
	XBIOS_shadowscreen=NULL;
slouken@281
   389
slouken@281
   390
	/* Update hardware info */
slouken@281
   391
	this->info.hw_available = 1;
slouken@281
   392
	this->info.video_mem = (Uint32) Atari_SysMalloc(-1L, MX_STRAM);
slouken@281
   393
slouken@281
   394
	/* Init chunky to planar routine */
slouken@281
   395
	Atari_C2pInit = Atari_C2pInit8;
slouken@281
   396
	if (atari_cpu060_avail) {
slouken@281
   397
		Atari_C2pConvert = Atari_C2pConvert8_060;
slouken@281
   398
	} else {
slouken@281
   399
		Atari_C2pConvert = Atari_C2pConvert8;
slouken@281
   400
	}
slouken@281
   401
	Atari_C2pInit();
slouken@281
   402
slouken@281
   403
	/* We're done! */
slouken@281
   404
	return(0);
slouken@281
   405
}
slouken@281
   406
slouken@281
   407
static SDL_Rect **XBIOS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
slouken@281
   408
{
slouken@281
   409
	/* 8 bits -> list 0 */
slouken@281
   410
	/* 16 bits -> list 1 */
slouken@281
   411
	return(SDL_modelist[(format->BitsPerPixel)>>4]);
slouken@281
   412
}
slouken@281
   413
slouken@281
   414
static void XBIOS_FreeBuffers(_THIS)
slouken@281
   415
{
slouken@281
   416
	int i;
slouken@281
   417
slouken@281
   418
	for (i=0;i<2;i++) {
slouken@281
   419
		if (XBIOS_screensmem[i]!=NULL) {
slouken@281
   420
			Mfree(XBIOS_screensmem[i]);
slouken@281
   421
			XBIOS_screensmem[i]=NULL;
slouken@281
   422
		}
slouken@281
   423
	}
slouken@281
   424
slouken@281
   425
	if (XBIOS_shadowscreen!=NULL) {
slouken@281
   426
		Mfree(XBIOS_shadowscreen);
slouken@281
   427
		XBIOS_shadowscreen=NULL;
slouken@281
   428
	}
slouken@281
   429
}
slouken@281
   430
slouken@281
   431
static SDL_Surface *XBIOS_SetVideoMode(_THIS, SDL_Surface *current,
slouken@281
   432
				int width, int height, int bpp, Uint32 flags)
slouken@281
   433
{
slouken@281
   434
	int mode, new_depth;
slouken@281
   435
	int i;
slouken@281
   436
	xbiosmode_t *new_video_mode;
slouken@281
   437
	Uint32 new_screen_size;
slouken@281
   438
	Uint32 modeflags;
slouken@281
   439
slouken@281
   440
	/* Free current buffers */
slouken@281
   441
	XBIOS_FreeBuffers(this);
slouken@281
   442
slouken@281
   443
	/* Search if the mode exists (width, height, bpp) */
slouken@281
   444
	bpp >>= 4;
slouken@281
   445
	for ( mode=0; SDL_modelist[bpp][mode]; ++mode ) {
slouken@281
   446
		if ( (SDL_modelist[bpp][mode]->w == width) &&
slouken@281
   447
		     (SDL_modelist[bpp][mode]->h == height) ) {
slouken@281
   448
slouken@281
   449
			break;
slouken@281
   450
		}
slouken@281
   451
	}
slouken@281
   452
	if ( SDL_modelist[bpp][mode] == NULL ) {
slouken@281
   453
		SDL_SetError("Couldn't find requested mode in list");
slouken@281
   454
		return(NULL);
slouken@281
   455
	}
slouken@281
   456
slouken@281
   457
	modeflags = (SDL_FULLSCREEN|SDL_HWPALETTE);
slouken@281
   458
slouken@281
   459
	/* Allocate needed buffers: simple/double buffer and shadow surface */
slouken@281
   460
	new_video_mode = XBIOS_videomodes[bpp][mode];
slouken@281
   461
	new_depth = new_video_mode->depth;
slouken@281
   462
	if (new_depth == 4) {
slouken@281
   463
		Atari_C2pInit = Atari_C2pInit4;
slouken@281
   464
		if (atari_cpu060_avail) {
slouken@281
   465
			Atari_C2pConvert = Atari_C2pConvert4_060;
slouken@281
   466
		} else {
slouken@281
   467
			Atari_C2pConvert = Atari_C2pConvert4;
slouken@281
   468
		}
slouken@281
   469
		new_depth=8;
slouken@281
   470
		modeflags |= SDL_SWSURFACE;
slouken@281
   471
	} else if (new_depth == 8) {
slouken@281
   472
		Atari_C2pInit = Atari_C2pInit8;
slouken@281
   473
		if (atari_cpu060_avail) {
slouken@281
   474
			Atari_C2pConvert = Atari_C2pConvert8_060;
slouken@281
   475
		} else {
slouken@281
   476
			Atari_C2pConvert = Atari_C2pConvert8;
slouken@281
   477
		}
slouken@281
   478
		modeflags |= SDL_SWSURFACE;
slouken@281
   479
	} else {
slouken@281
   480
		modeflags |= SDL_HWSURFACE;
slouken@281
   481
	}
slouken@281
   482
slouken@281
   483
	new_screen_size = width * height * ((new_depth)>>3);
slouken@281
   484
	new_screen_size += 256; /* To align on a 256 byte adress */	
slouken@281
   485
slouken@281
   486
	if (new_depth == 8) {
slouken@281
   487
		XBIOS_shadowscreen = Atari_SysMalloc(new_screen_size, MX_PREFTTRAM);
slouken@281
   488
slouken@281
   489
		if (XBIOS_shadowscreen == NULL) {
slouken@281
   490
			SDL_SetError("XBIOS_SetVideoMode: Not enough memory for shadow surface");
slouken@281
   491
			return (NULL);
slouken@281
   492
		}
slouken@287
   493
		memset(XBIOS_shadowscreen, 0, new_screen_size);
slouken@281
   494
	}
slouken@281
   495
slouken@281
   496
	/* Output buffer needs to be twice in size for the software double-line mode */
slouken@281
   497
	XBIOS_doubleline = SDL_FALSE;
slouken@281
   498
	if (new_video_mode->doubleline) {
slouken@281
   499
		new_screen_size <<= 1;
slouken@281
   500
		XBIOS_doubleline = SDL_TRUE;
slouken@281
   501
	}
slouken@281
   502
slouken@281
   503
	XBIOS_screensmem[0] = Atari_SysMalloc(new_screen_size, MX_STRAM);
slouken@281
   504
slouken@281
   505
	if (XBIOS_screensmem[0]==NULL) {
slouken@281
   506
		XBIOS_FreeBuffers(this);
slouken@281
   507
		SDL_SetError("XBIOS_SetVideoMode: Not enough memory for video buffer");
slouken@281
   508
		return (NULL);
slouken@281
   509
	}
slouken@287
   510
	memset(XBIOS_screensmem[0], 0, new_screen_size);
slouken@281
   511
slouken@281
   512
	XBIOS_screens[0]=(void *) (( (long) XBIOS_screensmem[0]+256) & 0xFFFFFF00UL);
slouken@281
   513
slouken@281
   514
	/* Double buffer ? */
slouken@281
   515
	if (flags & SDL_DOUBLEBUF) {
slouken@281
   516
		XBIOS_screensmem[1] = Atari_SysMalloc(new_screen_size, MX_STRAM);
slouken@281
   517
slouken@281
   518
		if (XBIOS_screensmem[1]==NULL) {
slouken@281
   519
			XBIOS_FreeBuffers(this);
slouken@281
   520
			SDL_SetError("XBIOS_SetVideoMode: Not enough memory for double buffer");
slouken@281
   521
			return (NULL);
slouken@281
   522
		}
slouken@287
   523
		memset(XBIOS_screensmem[1], 0, new_screen_size);
slouken@281
   524
slouken@281
   525
		XBIOS_screens[1]=(void *) (( (long) XBIOS_screensmem[1]+256) & 0xFFFFFF00UL);
slouken@281
   526
		modeflags |= SDL_DOUBLEBUF;
slouken@281
   527
	}
slouken@281
   528
	
slouken@281
   529
	/* Allocate the new pixel format for the screen */
slouken@281
   530
	if ( ! SDL_ReallocFormat(current, new_depth, 0, 0, 0, 0) ) {
slouken@281
   531
		XBIOS_FreeBuffers(this);
slouken@281
   532
		SDL_SetError("Couldn't allocate new pixel format for requested mode");
slouken@281
   533
		return(NULL);
slouken@281
   534
	}
slouken@281
   535
slouken@281
   536
	current->flags = modeflags;
slouken@281
   537
	current->w = XBIOS_width = width;
slouken@281
   538
	current->h = XBIOS_height = height;
slouken@281
   539
	current->pitch = (width * new_depth)>>3;
slouken@281
   540
slouken@281
   541
	/* this is for C2P conversion */
slouken@281
   542
	XBIOS_pitch = (new_video_mode->width * new_video_mode->depth)>>3;
slouken@281
   543
slouken@281
   544
	if (new_depth == 8)
slouken@281
   545
		current->pixels = XBIOS_shadowscreen;
slouken@281
   546
	else
slouken@281
   547
		current->pixels = XBIOS_screens[0];
slouken@281
   548
slouken@281
   549
	XBIOS_fbnum = 0;
slouken@281
   550
slouken@281
   551
	/* Now set the video mode */
slouken@281
   552
	Setscreen(-1,XBIOS_screens[0],-1);
slouken@281
   553
slouken@281
   554
	switch(XBIOS_cvdo >> 16) {
slouken@281
   555
		case VDO_ST:
slouken@281
   556
			Setscreen(-1,-1,new_video_mode->number);
slouken@281
   557
			/* Reset palette */
slouken@281
   558
			for (i=0;i<16;i++) {
slouken@281
   559
				int c;
slouken@281
   560
slouken@281
   561
				c = ((i>>1)<<8) | ((i>>1)<<4) | (i>>1);
slouken@281
   562
				if ((i & 1) && (i<15))
slouken@281
   563
					c += (1<<4);
slouken@281
   564
				if (i==14)
slouken@281
   565
					c -= 1<<8;
slouken@281
   566
slouken@281
   567
				TT_palette[i]= c;
slouken@281
   568
			}
slouken@281
   569
			Setpalette(TT_palette);
slouken@281
   570
			break;
slouken@281
   571
		case VDO_STE:
slouken@281
   572
			Setscreen(-1,-1,new_video_mode->number);
slouken@281
   573
			/* Reset palette */
slouken@281
   574
			for (i=0;i<16;i++)
slouken@281
   575
			{
slouken@281
   576
				int c;
slouken@281
   577
slouken@281
   578
				c=((i&1)<<3)|((i>>1)&7);
slouken@281
   579
				TT_palette[i]=(c<<8)|(c<<4)|c;
slouken@281
   580
			}
slouken@281
   581
			Setpalette(TT_palette);
slouken@281
   582
			break;
slouken@281
   583
		case VDO_TT:
slouken@281
   584
			EsetShift(new_video_mode->number);
slouken@281
   585
			break;
slouken@281
   586
		case VDO_F30:
slouken@281
   587
			Vsetmode(new_video_mode->number);
slouken@281
   588
			break;
slouken@281
   589
	}
slouken@281
   590
slouken@281
   591
	Vsync();
slouken@281
   592
slouken@281
   593
	this->UpdateRects = XBIOS_UpdateRects;
slouken@281
   594
slouken@281
   595
	return (current);
slouken@281
   596
}
slouken@281
   597
slouken@281
   598
/* We don't actually allow hardware surfaces other than the main one */
slouken@281
   599
static int XBIOS_AllocHWSurface(_THIS, SDL_Surface *surface)
slouken@281
   600
{
slouken@281
   601
	return(-1);
slouken@281
   602
}
slouken@281
   603
slouken@281
   604
static void XBIOS_FreeHWSurface(_THIS, SDL_Surface *surface)
slouken@281
   605
{
slouken@281
   606
	return;
slouken@281
   607
}
slouken@281
   608
slouken@281
   609
static int XBIOS_LockHWSurface(_THIS, SDL_Surface *surface)
slouken@281
   610
{
slouken@281
   611
	return(0);
slouken@281
   612
}
slouken@281
   613
slouken@281
   614
static void XBIOS_UnlockHWSurface(_THIS, SDL_Surface *surface)
slouken@281
   615
{
slouken@281
   616
	return;
slouken@281
   617
}
slouken@281
   618
slouken@281
   619
static void XBIOS_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
slouken@281
   620
{
slouken@281
   621
	SDL_Surface *surface;
slouken@281
   622
	
slouken@281
   623
	surface = this->screen;
slouken@281
   624
slouken@281
   625
	XBIOS_FlipHWSurface(this, surface);
slouken@281
   626
}
slouken@281
   627
slouken@281
   628
static int XBIOS_FlipHWSurface(_THIS, SDL_Surface *surface)
slouken@281
   629
{
slouken@281
   630
	if ((surface->format->BitsPerPixel) == 8) {
slouken@281
   631
		void *destscr;
slouken@281
   632
		int destx;
slouken@281
   633
			
slouken@281
   634
		/* Center on destination screen */
slouken@281
   635
		destscr = XBIOS_screens[XBIOS_fbnum];
slouken@281
   636
		destscr += XBIOS_pitch * ((XBIOS_height - surface->h) >> 1);
slouken@281
   637
		destx = (XBIOS_width - surface->w) >> 1;
slouken@281
   638
		destx &= ~15;
slouken@281
   639
		destscr += destx;
slouken@281
   640
slouken@281
   641
		/* Convert chunky to planar screen */
slouken@281
   642
		Atari_C2pConvert(
slouken@281
   643
			surface->pixels,
slouken@281
   644
			destscr,
slouken@281
   645
			surface->w,
slouken@281
   646
			surface->h,
slouken@281
   647
			XBIOS_doubleline,
slouken@281
   648
			surface->pitch,
slouken@281
   649
			XBIOS_pitch
slouken@281
   650
		);
slouken@281
   651
	}
slouken@281
   652
slouken@281
   653
	Setscreen(-1,XBIOS_screens[XBIOS_fbnum],-1);
slouken@281
   654
	Vsync();
slouken@281
   655
slouken@281
   656
	if ((surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) {
slouken@281
   657
		XBIOS_fbnum ^= 1;				
slouken@281
   658
	}
slouken@281
   659
slouken@281
   660
	return(0);
slouken@281
   661
}
slouken@281
   662
slouken@281
   663
static int XBIOS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
slouken@281
   664
{
slouken@281
   665
	int		i;
slouken@281
   666
	int		r,v,b;
slouken@281
   667
slouken@281
   668
	switch( XBIOS_cvdo >> 16) {
slouken@281
   669
		case VDO_ST:
slouken@281
   670
		case VDO_STE:
slouken@281
   671
		 	for (i=0;i<ncolors;i++)
slouken@281
   672
			{
slouken@281
   673
				r = colors[i].r;	
slouken@281
   674
				v = colors[i].g;
slouken@281
   675
				b = colors[i].b;
slouken@281
   676
slouken@281
   677
				TT_palette[firstcolor+i]=((r*30)+(v*59)+(b*11))/100;
slouken@281
   678
			}
slouken@281
   679
			Atari_C2pConvert4_pal(TT_palette); /* convert the lighting */
slouken@281
   680
			break;
slouken@281
   681
		case VDO_TT:
slouken@281
   682
			for(i = 0; i < ncolors; i++)
slouken@281
   683
			{
slouken@281
   684
				r = colors[i].r;	
slouken@281
   685
				v = colors[i].g;
slouken@281
   686
				b = colors[i].b;
slouken@281
   687
					
slouken@281
   688
				TT_palette[i]=((r>>4)<<8)|((v>>4)<<4)|(b>>4);
slouken@281
   689
			}
slouken@281
   690
			EsetPalette(firstcolor,ncolors,TT_palette);
slouken@281
   691
			break;
slouken@281
   692
		case VDO_F30:
slouken@281
   693
			for(i = 0; i < ncolors; i++)
slouken@281
   694
			{
slouken@281
   695
				r = colors[i].r;	
slouken@281
   696
				v = colors[i].g;
slouken@281
   697
				b = colors[i].b;
slouken@281
   698
slouken@281
   699
				F30_palette[i]=(r<<16)|(v<<8)|b;
slouken@281
   700
			}
slouken@281
   701
			VsetRGB(firstcolor,ncolors,F30_palette);
slouken@281
   702
			break;
slouken@281
   703
	}
slouken@281
   704
slouken@281
   705
	return(1);
slouken@281
   706
}
slouken@281
   707
slouken@281
   708
/* Note:  If we are terminated, this could be called in the middle of
slouken@281
   709
   another SDL video routine -- notably UpdateRects.
slouken@281
   710
*/
slouken@281
   711
static void XBIOS_VideoQuit(_THIS)
slouken@281
   712
{
slouken@281
   713
	int i,j;
slouken@281
   714
slouken@281
   715
	Atari_ShutdownEvents();
slouken@281
   716
slouken@281
   717
	/* Restore video mode and palette */
slouken@281
   718
	switch(XBIOS_cvdo >> 16) {
slouken@281
   719
		case VDO_ST:
slouken@281
   720
		case VDO_STE:
slouken@281
   721
			Setscreen(-1,XBIOS_oldvbase,XBIOS_oldvmode);
slouken@281
   722
			if (XBIOS_oldnumcol) {
slouken@281
   723
				Setpalette(XBIOS_oldpalette);
slouken@281
   724
			}
slouken@281
   725
			break;
slouken@281
   726
		case VDO_TT:
slouken@281
   727
			Setscreen(-1,XBIOS_oldvbase,-1);
slouken@281
   728
			EsetShift(XBIOS_oldvmode);
slouken@281
   729
			if (XBIOS_oldnumcol) {
slouken@281
   730
				EsetPalette(0, XBIOS_oldnumcol, XBIOS_oldpalette);
slouken@281
   731
			}
slouken@281
   732
			break;
slouken@281
   733
		case VDO_F30:
slouken@281
   734
			Setscreen(-1, XBIOS_oldvbase, -1);
slouken@281
   735
			Vsetmode(XBIOS_oldvmode);
slouken@281
   736
			if (XBIOS_oldnumcol) {
slouken@281
   737
				VsetRGB(0, XBIOS_oldnumcol, XBIOS_oldpalette);
slouken@281
   738
			}
slouken@281
   739
			break;
slouken@281
   740
	}
slouken@281
   741
	Vsync();
slouken@281
   742
slouken@281
   743
	if (XBIOS_oldpalette) {
slouken@281
   744
		free(XBIOS_oldpalette);
slouken@281
   745
		XBIOS_oldpalette=NULL;
slouken@281
   746
	}
slouken@281
   747
	XBIOS_FreeBuffers(this);
slouken@281
   748
slouken@281
   749
	/* Free mode list */
slouken@281
   750
	for (j=0;j<NUM_MODELISTS;j++) {
slouken@281
   751
		for (i=0;i<SDL_NUMMODES;i++) {
slouken@281
   752
			if (SDL_modelist[j][i]!=NULL) {
slouken@281
   753
				free(SDL_modelist[j][i]);
slouken@281
   754
				SDL_modelist[j][i]=NULL;
slouken@281
   755
			}
slouken@281
   756
		}
slouken@281
   757
	}
slouken@281
   758
slouken@281
   759
	this->screen->pixels = NULL;	
slouken@281
   760
}