Home | History | Annotate | Download | only in gem
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2012 Sam Lantinga
      4 
      5     This library is free software; you can redistribute it and/or
      6     modify it under the terms of the GNU Lesser General Public
      7     License as published by the Free Software Foundation; either
      8     version 2.1 of the License, or (at your option) any later version.
      9 
     10     This library is distributed in the hope that it will be useful,
     11     but WITHOUT ANY WARRANTY; without even the implied warranty of
     12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13     Lesser General Public License for more details.
     14 
     15     You should have received a copy of the GNU Lesser General Public
     16     License along with this library; if not, write to the Free Software
     17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     18 
     19     Sam Lantinga
     20     slouken (at) libsdl.org
     21 */
     22 #include "SDL_config.h"
     23 
     24 /*
     25 	GEM video driver
     26 
     27 	Patrice Mandin
     28 	and work from
     29 	Olivier Landemarre, Johan Klockars, Xavier Joubert, Claude Attard
     30 */
     31 
     32 /* Mint includes */
     33 #include <gem.h>
     34 #include <gemx.h>
     35 #include <mint/osbind.h>
     36 #include <mint/cookie.h>
     37 
     38 #include "SDL_endian.h"
     39 #include "SDL_video.h"
     40 #include "SDL_mouse.h"
     41 #include "../SDL_sysvideo.h"
     42 #include "../SDL_pixels_c.h"
     43 #include "../../events/SDL_events_c.h"
     44 #include "../SDL_cursor_c.h"
     45 
     46 #include "../ataricommon/SDL_ataric2p_s.h"
     47 #include "../ataricommon/SDL_atarieddi_s.h"
     48 #include "../ataricommon/SDL_atarimxalloc_c.h"
     49 #include "../ataricommon/SDL_atarigl_c.h"
     50 
     51 #include "SDL_gemvideo.h"
     52 #include "SDL_gemevents_c.h"
     53 #include "SDL_gemmouse_c.h"
     54 #include "SDL_gemwm_c.h"
     55 #include "../ataricommon/SDL_xbiosevents_c.h"
     56 #include "../ataricommon/SDL_ataridevmouse_c.h"
     57 
     58 /* Defines */
     59 
     60 /*#define DEBUG_VIDEO_GEM	1*/
     61 
     62 #define GEM_VID_DRIVER_NAME "gem"
     63 
     64 #undef MIN
     65 #define MIN(a,b) (((a)<(b)) ? (a) : (b))
     66 #undef MAX
     67 #define MAX(a,b) (((a)>(b)) ? (a) : (b))
     68 
     69 /* Variables */
     70 
     71 static unsigned char vdi_index[256] = {
     72 	0,  2,  3,  6,  4,  7,  5,   8,
     73 	9, 10, 11, 14, 12, 15, 13, 255
     74 };
     75 
     76 static const char empty_name[]="";
     77 
     78 /* Initialization/Query functions */
     79 static int GEM_VideoInit(_THIS, SDL_PixelFormat *vformat);
     80 static SDL_Rect **GEM_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
     81 static SDL_Surface *GEM_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
     82 static int GEM_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
     83 static void GEM_VideoQuit(_THIS);
     84 
     85 /* Hardware surface functions */
     86 static int GEM_AllocHWSurface(_THIS, SDL_Surface *surface);
     87 static int GEM_LockHWSurface(_THIS, SDL_Surface *surface);
     88 static int GEM_FlipHWSurface(_THIS, SDL_Surface *surface);
     89 static void GEM_UnlockHWSurface(_THIS, SDL_Surface *surface);
     90 static void GEM_FreeHWSurface(_THIS, SDL_Surface *surface);
     91 static void GEM_UpdateRects(_THIS, int numrects, SDL_Rect *rects);
     92 #if 0
     93 static int GEM_ToggleFullScreen(_THIS, int on);
     94 #endif
     95 
     96 /* Internal functions */
     97 static void GEM_FreeBuffers(_THIS);
     98 static void GEM_ClearScreen(_THIS);
     99 static void GEM_ClearRect(_THIS, short *rect);
    100 static void GEM_SetNewPalette(_THIS, Uint16 newpal[256][3]);
    101 static void GEM_LockScreen(_THIS);
    102 static void GEM_UnlockScreen(_THIS);
    103 static void refresh_window(_THIS, int winhandle, short *rect);
    104 
    105 #if SDL_VIDEO_OPENGL
    106 /* OpenGL functions */
    107 static void GEM_GL_SwapBuffers(_THIS);
    108 #endif
    109 
    110 /* GEM driver bootstrap functions */
    111 
    112 static int GEM_Available(void)
    113 {
    114 	/* Test if AES available */
    115 	if (appl_init() == -1)
    116 		return 0;
    117 
    118 	appl_exit();
    119 	return 1;
    120 }
    121 
    122 static void GEM_DeleteDevice(SDL_VideoDevice *device)
    123 {
    124 	SDL_free(device->hidden);
    125 	SDL_free(device);
    126 }
    127 
    128 static SDL_VideoDevice *GEM_CreateDevice(int devindex)
    129 {
    130 	SDL_VideoDevice *device;
    131 	int vectors_mask;
    132 /*	unsigned long dummy;*/
    133 
    134 	/* Initialize all variables that we clean on shutdown */
    135 	device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
    136 	if ( device ) {
    137 		SDL_memset(device, 0, (sizeof *device));
    138 		device->hidden = (struct SDL_PrivateVideoData *)
    139 				SDL_malloc((sizeof *device->hidden));
    140 		device->gl_data = (struct SDL_PrivateGLData *)
    141 				SDL_malloc((sizeof *device->gl_data));
    142 	}
    143 	if ( (device == NULL) || (device->hidden == NULL) ) {
    144 		SDL_OutOfMemory();
    145 		if ( device ) {
    146 			SDL_free(device);
    147 		}
    148 		return(0);
    149 	}
    150 	SDL_memset(device->hidden, 0, (sizeof *device->hidden));
    151 	SDL_memset(device->gl_data, 0, sizeof(*device->gl_data));
    152 
    153 	/* Set the function pointers */
    154 	device->VideoInit = GEM_VideoInit;
    155 	device->ListModes = GEM_ListModes;
    156 	device->SetVideoMode = GEM_SetVideoMode;
    157 	device->SetColors = GEM_SetColors;
    158 	device->UpdateRects = NULL /*GEM_UpdateRects*/;
    159 	device->VideoQuit = GEM_VideoQuit;
    160 	device->AllocHWSurface = GEM_AllocHWSurface;
    161 	device->LockHWSurface = GEM_LockHWSurface;
    162 	device->UnlockHWSurface = GEM_UnlockHWSurface;
    163 	device->FlipHWSurface = GEM_FlipHWSurface;
    164 	device->FreeHWSurface = GEM_FreeHWSurface;
    165 	device->ToggleFullScreen = NULL /*GEM_ToggleFullScreen*/;
    166 
    167 	/* Window manager */
    168 	device->SetCaption = GEM_SetCaption;
    169 	device->SetIcon = GEM_SetIcon;
    170 	device->IconifyWindow = GEM_IconifyWindow;
    171 	device->GrabInput = GEM_GrabInput;
    172 
    173 	/* Events */
    174 	device->InitOSKeymap = GEM_InitOSKeymap;
    175 	device->PumpEvents = GEM_PumpEvents;
    176 
    177 	/* Mouse */
    178 	device->FreeWMCursor = GEM_FreeWMCursor;
    179 	device->CreateWMCursor = GEM_CreateWMCursor;
    180 	device->ShowWMCursor = GEM_ShowWMCursor;
    181 	device->WarpWMCursor = NULL /*GEM_WarpWMCursor*/;
    182 	device->CheckMouseMode = GEM_CheckMouseMode;
    183 
    184 #if SDL_VIDEO_OPENGL
    185 	/* OpenGL functions */
    186 	device->GL_LoadLibrary = SDL_AtariGL_LoadLibrary;
    187 	device->GL_GetProcAddress = SDL_AtariGL_GetProcAddress;
    188 	device->GL_GetAttribute = SDL_AtariGL_GetAttribute;
    189 	device->GL_MakeCurrent = SDL_AtariGL_MakeCurrent;
    190 	device->GL_SwapBuffers = GEM_GL_SwapBuffers;
    191 #endif
    192 
    193 	device->hidden->use_dev_mouse =
    194 		(SDL_AtariDevMouse_Open()!=0) ? SDL_TRUE : SDL_FALSE;
    195 
    196 	vectors_mask = ATARI_XBIOS_JOYSTICKEVENTS;	/* XBIOS joystick events */
    197 	if (!(device->hidden->use_dev_mouse)) {
    198 		vectors_mask |= ATARI_XBIOS_MOUSEEVENTS;	/* XBIOS mouse events */
    199 	}
    200 /*	if (Getcookie(C_MiNT, &dummy)==C_FOUND) {
    201 		vectors_mask = 0;
    202 	}*/
    203 
    204 	SDL_AtariXbios_InstallVectors(vectors_mask);
    205 
    206 	device->free = GEM_DeleteDevice;
    207 
    208 	return device;
    209 }
    210 
    211 VideoBootStrap GEM_bootstrap = {
    212 	GEM_VID_DRIVER_NAME, "Atari GEM video driver",
    213 	GEM_Available, GEM_CreateDevice
    214 };
    215 
    216 static void VDI_ReadExtInfo(_THIS, short *work_out)
    217 {
    218 	unsigned long EdDI_version;
    219 	long cookie_EdDI;
    220 	Uint16 clut_type;
    221 
    222 	/* Read EdDI informations */
    223 	if  (Getcookie(C_EdDI, &cookie_EdDI) == C_NOTFOUND) {
    224 		return;
    225 	}
    226 
    227 	EdDI_version = Atari_get_EdDI_version( (void *)cookie_EdDI);
    228 
    229 	vq_scrninfo(VDI_handle, work_out);
    230 
    231 	VDI_format = work_out[0];
    232 	clut_type = work_out[1];
    233 
    234 	/* With EdDI>=1.1, we can have screen pitch, address and format
    235 	 * so we can directly write to screen without using vro_cpyfm
    236 	 */
    237 	if (EdDI_version >= EDDI_11) {
    238 		VDI_pitch = work_out[5];
    239 		VDI_screen = (void *) *((unsigned long *) &work_out[6]);
    240 	}
    241 
    242 	switch(clut_type) {
    243 		case VDI_CLUT_HARDWARE:
    244 			{
    245 				int i;
    246 				Uint16 *tmp_p;
    247 
    248 				tmp_p = (Uint16 *)&work_out[16];
    249 
    250 				for (i=0;i<256;i++) {
    251 					vdi_index[*tmp_p++] = i;
    252 				}
    253 			}
    254 			break;
    255 		case VDI_CLUT_SOFTWARE:
    256 			{
    257 				int component; /* red, green, blue, alpha, overlay */
    258 				int num_bit;
    259 				unsigned short *tmp_p;
    260 
    261 				/* We can build masks with info here */
    262 				tmp_p = (unsigned short *) &work_out[16];
    263 				for (component=0;component<5;component++) {
    264 					for (num_bit=0;num_bit<16;num_bit++) {
    265 						unsigned short valeur;
    266 
    267 						valeur = *tmp_p++;
    268 
    269 						if (valeur == 0xffff) {
    270 							continue;
    271 						}
    272 
    273 						switch(component) {
    274 							case 0:
    275 								VDI_redmask |= 1<< valeur;
    276 								break;
    277 							case 1:
    278 								VDI_greenmask |= 1<< valeur;
    279 								break;
    280 							case 2:
    281 								VDI_bluemask |= 1<< valeur;
    282 								break;
    283 							case 3:
    284 								VDI_alphamask |= 1<< valeur;
    285 								break;
    286 						}
    287 					}
    288 				}
    289 			}
    290 
    291 			/* Remove lower green bits for Intel endian screen */
    292 			if ((VDI_greenmask == ((7<<13)|3)) || (VDI_greenmask == ((7<<13)|7))) {
    293 				VDI_greenmask &= ~(7<<13);
    294 			}
    295 			break;
    296 		case VDI_CLUT_NONE:
    297 			break;
    298 	}
    299 }
    300 
    301 int GEM_VideoInit(_THIS, SDL_PixelFormat *vformat)
    302 {
    303 	int i, menubar_size;
    304 	short work_in[12], work_out[272], dummy;
    305 
    306 	/* Open AES (Application Environment Services) */
    307 	if (appl_init() == -1) {
    308 		fprintf(stderr,"Can not open AES\n");
    309 		return 1;
    310 	}
    311 
    312 	/* Read version and features */
    313 	GEM_version = aes_global[0];
    314 	if (GEM_version >= 0x0410) {
    315 		short ap_gout[4], errorcode;
    316 
    317 		GEM_wfeatures=0;
    318 		errorcode=appl_getinfo(AES_WINDOW, &ap_gout[0], &ap_gout[1], &ap_gout[2], &ap_gout[3]);
    319 
    320 		if (errorcode==0) {
    321 			GEM_wfeatures=ap_gout[0];
    322 		}
    323 	}
    324 
    325 	/* Ask VDI physical workstation handle opened by AES */
    326 	VDI_handle = graf_handle(&dummy, &dummy, &dummy, &dummy);
    327 	if (VDI_handle<1) {
    328 		fprintf(stderr,"Wrong VDI handle %d returned by AES\n",VDI_handle);
    329 		return 1;
    330 	}
    331 
    332 	/* Open virtual VDI workstation */
    333 	work_in[0]=Getrez()+2;
    334 	for(i = 1; i < 10; i++)
    335 		work_in[i] = 1;
    336 	work_in[10] = 2;
    337 
    338 	v_opnvwk(work_in, &VDI_handle, work_out);
    339 	if (VDI_handle == 0) {
    340 		fprintf(stderr,"Can not open VDI virtual workstation\n");
    341 		return 1;
    342 	}
    343 
    344 	/* Read fullscreen size */
    345 	VDI_w = work_out[0] + 1;
    346 	VDI_h = work_out[1] + 1;
    347 
    348 	/* Read desktop size and position */
    349 	if (!wind_get(DESKTOP_HANDLE, WF_WORKXYWH, &GEM_desk_x, &GEM_desk_y, &GEM_desk_w, &GEM_desk_h)) {
    350 		fprintf(stderr,"Can not read desktop properties\n");
    351 		return 1;
    352 	}
    353 
    354 	/* Read bit depth */
    355 	vq_extnd(VDI_handle, 1, work_out);
    356 	VDI_bpp = work_out[4];
    357 	VDI_oldnumcolors=0;
    358 
    359 	switch(VDI_bpp) {
    360 		case 8:
    361 			VDI_pixelsize=1;
    362 			break;
    363 		case 15:
    364 		case 16:
    365 			VDI_pixelsize=2;
    366 			break;
    367 		case 24:
    368 			VDI_pixelsize=3;
    369 			break;
    370 		case 32:
    371 			VDI_pixelsize=4;
    372 			break;
    373 		default:
    374 			fprintf(stderr,"%d bits colour depth not supported\n",VDI_bpp);
    375 			return 1;
    376 	}
    377 
    378 	/* Setup hardware -> VDI palette mapping */
    379 	for(i = 16; i < 255; i++) {
    380 		vdi_index[i] = i;
    381 	}
    382 	vdi_index[255] = 1;
    383 
    384 	/* Save current palette */
    385 	if (VDI_bpp>8) {
    386 		VDI_oldnumcolors=1<<8;
    387 	} else {
    388 		VDI_oldnumcolors=1<<VDI_bpp;
    389 	}
    390 
    391 	for(i = 0; i < VDI_oldnumcolors; i++) {
    392 		short rgb[3];
    393 
    394 		vq_color(VDI_handle, i, 0, rgb);
    395 
    396 		VDI_oldpalette[i][0] = rgb[0];
    397 		VDI_oldpalette[i][1] = rgb[1];
    398 		VDI_oldpalette[i][2] = rgb[2];
    399 	}
    400 	VDI_setpalette = GEM_SetNewPalette;
    401 	SDL_memcpy(VDI_curpalette,VDI_oldpalette,sizeof(VDI_curpalette));
    402 
    403 	/* Setup screen info */
    404 	GEM_title_name = empty_name;
    405 	GEM_icon_name = empty_name;
    406 
    407 	GEM_handle = -1;
    408 	GEM_locked = SDL_FALSE;
    409 	GEM_win_fulled = SDL_FALSE;
    410 	GEM_fullscreen = SDL_FALSE;
    411 	GEM_lock_redraw = SDL_TRUE;	/* Prevent redraw till buffers are setup */
    412 
    413 	VDI_screen = NULL;
    414 	VDI_pitch = VDI_w * VDI_pixelsize;
    415 	VDI_format = ( (VDI_bpp <= 8) ? VDI_FORMAT_INTER : VDI_FORMAT_PACK);
    416 	VDI_redmask = VDI_greenmask = VDI_bluemask = VDI_alphamask = 0;
    417 	VDI_ReadExtInfo(this, work_out);
    418 
    419 #ifdef DEBUG_VIDEO_GEM
    420 	printf("sdl:video:gem: screen: address=0x%08x, pitch=%d\n", VDI_screen, VDI_pitch);
    421 	printf("sdl:video:gem: format=%d\n", VDI_format);
    422 	printf("sdl:video:gem: masks: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
    423 		VDI_alphamask, VDI_redmask, VDI_greenmask, VDI_bluemask
    424 	);
    425 #endif
    426 
    427 	/* Setup destination mfdb */
    428 	VDI_dst_mfdb.fd_addr = NULL;
    429 
    430 	/* Determine the current screen size */
    431 	this->info.current_w = VDI_w;
    432 	this->info.current_h = VDI_h;
    433 
    434 	/* Determine the screen depth */
    435 	/* we change this during the SDL_SetVideoMode implementation... */
    436 	vformat->BitsPerPixel = VDI_bpp;
    437 
    438 	/* Set mouse cursor to arrow */
    439 	graf_mouse(ARROW, NULL);
    440 	GEM_cursor = NULL;
    441 
    442 	/* Init chunky to planar routine */
    443 	SDL_Atari_C2pConvert = SDL_Atari_C2pConvert8;
    444 
    445 	/* Setup VDI fill functions */
    446 	vsf_color(VDI_handle,0);
    447 	vsf_interior(VDI_handle,1);
    448 	vsf_perimeter(VDI_handle,0);
    449 
    450 	/* Menu bar save buffer */
    451 	menubar_size = GEM_desk_w * GEM_desk_y * VDI_pixelsize;
    452 	GEM_menubar=Atari_SysMalloc(menubar_size,MX_PREFTTRAM);
    453 
    454 	/* Fill video modes list */
    455 	SDL_modelist[0] = SDL_malloc(sizeof(SDL_Rect));
    456 	SDL_modelist[0]->x = 0;
    457 	SDL_modelist[0]->y = 0;
    458 	SDL_modelist[0]->w = VDI_w;
    459 	SDL_modelist[0]->h = VDI_h;
    460 
    461 	SDL_modelist[1] = NULL;
    462 
    463 #if SDL_VIDEO_OPENGL
    464 	SDL_AtariGL_InitPointers(this);
    465 #endif
    466 
    467 	this->info.wm_available = 1;
    468 
    469 	/* We're done! */
    470 	return(0);
    471 }
    472 
    473 SDL_Rect **GEM_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
    474 {
    475 	if (format->BitsPerPixel != VDI_bpp) {
    476 		return ((SDL_Rect **)NULL);
    477 	}
    478 
    479 	if (flags & SDL_FULLSCREEN) {
    480 		return (SDL_modelist);
    481 	}
    482 
    483 	return((SDL_Rect **)-1);
    484 }
    485 
    486 static void GEM_FreeBuffers(_THIS)
    487 {
    488 	/* Release buffer */
    489 	if ( GEM_buffer2 ) {
    490 		Mfree( GEM_buffer2 );
    491 		GEM_buffer2=NULL;
    492 	}
    493 
    494 	if ( GEM_buffer1 ) {
    495 		Mfree( GEM_buffer1 );
    496 		GEM_buffer1=NULL;
    497 	}
    498 }
    499 
    500 static void GEM_ClearRect(_THIS, short *rect)
    501 {
    502 	short oldrgb[3], rgb[3]={0,0,0};
    503 
    504 	vq_color(VDI_handle, vdi_index[0], 0, oldrgb);
    505 	vs_color(VDI_handle, vdi_index[0], rgb);
    506 
    507 	vsf_color(VDI_handle,0);
    508 	vsf_interior(VDI_handle,1);
    509 	vsf_perimeter(VDI_handle,0);
    510 	v_bar(VDI_handle, rect);
    511 
    512 	vs_color(VDI_handle, vdi_index[0], oldrgb);
    513 }
    514 
    515 static void GEM_ClearScreen(_THIS)
    516 {
    517 	short pxy[4];
    518 
    519 	v_hide_c(VDI_handle);
    520 
    521 	pxy[0] = pxy[1] = 0;
    522 	pxy[2] = VDI_w - 1;
    523 	pxy[3] = VDI_h - 1;
    524 	GEM_ClearRect(this, pxy);
    525 
    526 	v_show_c(VDI_handle, 1);
    527 }
    528 
    529 static void GEM_SetNewPalette(_THIS, Uint16 newpal[256][3])
    530 {
    531 	int i;
    532 	short rgb[3];
    533 
    534 	if (VDI_oldnumcolors==0)
    535 		return;
    536 
    537 	for(i = 0; i < VDI_oldnumcolors; i++) {
    538 		rgb[0] = newpal[i][0];
    539 		rgb[1] = newpal[i][1];
    540 		rgb[2] = newpal[i][2];
    541 
    542 		vs_color(VDI_handle, i, rgb);
    543 	}
    544 }
    545 
    546 static void GEM_LockScreen(_THIS)
    547 {
    548 	if (!GEM_locked) {
    549 		/* Lock AES */
    550 		wind_update(BEG_UPDATE);
    551 		wind_update(BEG_MCTRL);
    552 		/* Reserve memory space, used to be sure of compatibility */
    553 		form_dial( FMD_START, 0,0,0,0, 0,0,VDI_w,VDI_h);
    554 
    555 		/* Save menu bar */
    556 		if (GEM_menubar) {
    557 			MFDB mfdb_src;
    558 			short blitcoords[8];
    559 
    560 			mfdb_src.fd_addr=GEM_menubar;
    561 			mfdb_src.fd_w=GEM_desk_w;
    562 			mfdb_src.fd_h=GEM_desk_y;
    563 			mfdb_src.fd_wdwidth=GEM_desk_w>>4;
    564 			mfdb_src.fd_nplanes=VDI_bpp;
    565 			mfdb_src.fd_stand=
    566 				mfdb_src.fd_r1=
    567 				mfdb_src.fd_r2=
    568 				mfdb_src.fd_r3= 0;
    569 
    570 			blitcoords[0] = blitcoords[4] = 0;
    571 			blitcoords[1] = blitcoords[5] = 0;
    572 			blitcoords[2] = blitcoords[6] = GEM_desk_w-1;
    573 			blitcoords[3] = blitcoords[7] = GEM_desk_y-1;
    574 
    575 			vro_cpyfm(VDI_handle, S_ONLY, blitcoords, &VDI_dst_mfdb, &mfdb_src);
    576 		}
    577 
    578 		GEM_locked=SDL_TRUE;
    579 	}
    580 }
    581 
    582 static void GEM_UnlockScreen(_THIS)
    583 {
    584 	if (GEM_locked) {
    585 		/* Restore menu bar */
    586 		if (GEM_menubar) {
    587 			MFDB mfdb_src;
    588 			short blitcoords[8];
    589 
    590 			mfdb_src.fd_addr=GEM_menubar;
    591 			mfdb_src.fd_w=GEM_desk_w;
    592 			mfdb_src.fd_h=GEM_desk_y;
    593 			mfdb_src.fd_wdwidth=GEM_desk_w>>4;
    594 			mfdb_src.fd_nplanes=VDI_bpp;
    595 			mfdb_src.fd_stand=
    596 				mfdb_src.fd_r1=
    597 				mfdb_src.fd_r2=
    598 				mfdb_src.fd_r3= 0;
    599 
    600 			blitcoords[0] = blitcoords[4] = 0;
    601 			blitcoords[1] = blitcoords[5] = 0;
    602 			blitcoords[2] = blitcoords[6] = GEM_desk_w-1;
    603 			blitcoords[3] = blitcoords[7] = GEM_desk_y-1;
    604 
    605 			vro_cpyfm(VDI_handle, S_ONLY, blitcoords, &mfdb_src, &VDI_dst_mfdb);
    606 		}
    607 
    608 		/* Restore screen memory, and send REDRAW to all apps */
    609 		form_dial( FMD_FINISH, 0,0,0,0, 0,0,VDI_w,VDI_h);
    610 		/* Unlock AES */
    611 		wind_update(END_MCTRL);
    612 		wind_update(END_UPDATE);
    613 
    614 		GEM_locked=SDL_FALSE;
    615 	}
    616 }
    617 
    618 SDL_Surface *GEM_SetVideoMode(_THIS, SDL_Surface *current,
    619 				int width, int height, int bpp, Uint32 flags)
    620 {
    621 	Uint32 modeflags, screensize;
    622 	SDL_bool use_shadow1, use_shadow2;
    623 
    624 	/* width must be multiple of 16, for vro_cpyfm() and c2p_convert() */
    625 	if ((width & 15) != 0) {
    626 		width = (width | 15) +1;
    627 	}
    628 
    629 	/*--- Verify if asked mode can be used ---*/
    630 	if (VDI_bpp != bpp) {
    631 		SDL_SetError("%d bpp mode not supported", bpp);
    632 		return(NULL);
    633 	}
    634 
    635 	if (flags & SDL_FULLSCREEN) {
    636 		if ((VDI_w < width) || (VDI_h < height)) {
    637 			SDL_SetError("%dx%d mode is too large", width, height);
    638 			return(NULL);
    639 		}
    640 	}
    641 
    642 	/*--- Allocate the new pixel format for the screen ---*/
    643 	if ( ! SDL_ReallocFormat(current, VDI_bpp, VDI_redmask, VDI_greenmask, VDI_bluemask, VDI_alphamask) ) {
    644 		SDL_SetError("Couldn't allocate new pixel format for requested mode");
    645 		return(NULL);
    646 	}
    647 
    648 	screensize = width * height * VDI_pixelsize;
    649 
    650 #ifdef DEBUG_VIDEO_GEM
    651 	printf("sdl:video:gem: setvideomode(): %dx%dx%d = %d\n", width, height, bpp, screensize);
    652 #endif
    653 
    654 	/*--- Allocate shadow buffers if needed, and conversion operations ---*/
    655 	GEM_FreeBuffers(this);
    656 
    657 	GEM_bufops=0;
    658 	use_shadow1=use_shadow2=SDL_FALSE;
    659 	if (VDI_screen && (flags & SDL_FULLSCREEN)) {
    660 		if (VDI_format==VDI_FORMAT_INTER) {
    661 			use_shadow1=SDL_TRUE;
    662 			GEM_bufops = B2S_C2P_1TOS;
    663 		}
    664 	} else {
    665 		use_shadow1=SDL_TRUE;
    666 		if (VDI_format==VDI_FORMAT_PACK) {
    667 			GEM_bufops = B2S_VROCPYFM_1TOS;
    668 		} else {
    669 			use_shadow2=SDL_TRUE;
    670 			GEM_bufops = B2S_C2P_1TO2|B2S_VROCPYFM_2TOS;
    671 		}
    672 	}
    673 
    674 	if (use_shadow1) {
    675 		GEM_buffer1 = Atari_SysMalloc(screensize, MX_PREFTTRAM);
    676 		if (GEM_buffer1==NULL) {
    677 			SDL_SetError("Can not allocate %d KB for frame buffer", screensize>>10);
    678 			return NULL;
    679 		}
    680 		SDL_memset(GEM_buffer1, 0, screensize);
    681 #ifdef DEBUG_VIDEO_GEM
    682 		printf("sdl:video:gem: setvideomode(): allocated buffer 1\n");
    683 #endif
    684 	}
    685 
    686 	if (use_shadow2) {
    687 		GEM_buffer2 = Atari_SysMalloc(screensize, MX_PREFTTRAM);
    688 		if (GEM_buffer2==NULL) {
    689 			SDL_SetError("Can not allocate %d KB for shadow buffer", screensize>>10);
    690 			return NULL;
    691 		}
    692 		SDL_memset(GEM_buffer2, 0, screensize);
    693 #ifdef DEBUG_VIDEO_GEM
    694 		printf("sdl:video:gem: setvideomode(): allocated buffer 2\n");
    695 #endif
    696 	}
    697 
    698 	/*--- Initialize screen ---*/
    699 	modeflags = SDL_PREALLOC;
    700 	if (VDI_bpp == 8) {
    701 		modeflags |= SDL_HWPALETTE;
    702 	}
    703 
    704 	if (flags & SDL_FULLSCREEN) {
    705 		GEM_LockScreen(this);
    706 
    707 		GEM_ClearScreen(this);
    708 
    709 		modeflags |= SDL_FULLSCREEN;
    710 		if (VDI_screen && (VDI_format==VDI_FORMAT_PACK) && !use_shadow1) {
    711 			modeflags |= SDL_HWSURFACE;
    712 		} else {
    713 			modeflags |= SDL_SWSURFACE;
    714 		}
    715 
    716 		GEM_fullscreen = SDL_TRUE;
    717 	} else {
    718 		int old_win_type;
    719 		short x2,y2,w2,h2;
    720 
    721 		GEM_UnlockScreen(this);
    722 
    723 		/* Set window gadgets */
    724 		old_win_type = GEM_win_type;
    725 		if (!(flags & SDL_NOFRAME)) {
    726 			GEM_win_type=NAME|MOVER|CLOSER|SMALLER;
    727 			if (flags & SDL_RESIZABLE) {
    728 				GEM_win_type |= FULLER|SIZER;
    729 				modeflags |= SDL_RESIZABLE;
    730 			}
    731 		} else {
    732 			GEM_win_type=0;
    733 			modeflags |= SDL_NOFRAME;
    734 		}
    735 		modeflags |= SDL_SWSURFACE;
    736 
    737 		/* Recreate window ? only for different widget or non-created window */
    738 		if ((old_win_type != GEM_win_type) || (GEM_handle < 0)) {
    739 			/* Calculate window size */
    740 			if (!wind_calc(WC_BORDER, GEM_win_type, 0,0,width,height, &x2,&y2,&w2,&h2)) {
    741 				GEM_FreeBuffers(this);
    742 				SDL_SetError("Can not calculate window attributes");
    743 				return NULL;
    744 			}
    745 
    746 			/* Center window */
    747 			x2 = (GEM_desk_w-w2)>>1;
    748 			y2 = (GEM_desk_h-h2)>>1;
    749 			if (x2<0) {
    750 				x2 = 0;
    751 			}
    752 			if (y2<0) {
    753 				y2 = 0;
    754 			}
    755 			x2 += GEM_desk_x;
    756 			y2 += GEM_desk_y;
    757 
    758 			/* Destroy existing window */
    759 			if (GEM_handle >= 0) {
    760 				wind_close(GEM_handle);
    761 				wind_delete(GEM_handle);
    762 			}
    763 
    764 			/* Create window */
    765 			GEM_handle=wind_create(GEM_win_type, x2,y2,w2,h2);
    766 			if (GEM_handle<0) {
    767 				GEM_FreeBuffers(this);
    768 				SDL_SetError("Can not create window");
    769 				return NULL;
    770 			}
    771 
    772 #ifdef DEBUG_VIDEO_GEM
    773 			printf("sdl:video:gem: handle=%d\n", GEM_handle);
    774 #endif
    775 
    776 			/* Setup window name */
    777 			wind_set(GEM_handle,WF_NAME,(short)(((unsigned long)GEM_title_name)>>16),(short)(((unsigned long)GEM_title_name) & 0xffff),0,0);
    778 			GEM_refresh_name = SDL_FALSE;
    779 
    780 			/* Open the window */
    781 			wind_open(GEM_handle,x2,y2,w2,h2);
    782 		} else {
    783 			/* Resize window to fit asked video mode */
    784 			wind_get (GEM_handle, WF_WORKXYWH, &x2,&y2,&w2,&h2);
    785 			if (wind_calc(WC_BORDER, GEM_win_type, x2,y2,width,height, &x2,&y2,&w2,&h2)) {
    786 				wind_set (GEM_handle, WF_CURRXYWH, x2,y2,w2,h2);
    787 			}
    788 		}
    789 
    790 		GEM_fullscreen = SDL_FALSE;
    791 	}
    792 
    793 	/* Set up the new mode framebuffer */
    794 	current->w = width;
    795 	current->h = height;
    796 	if (use_shadow1) {
    797 		current->pixels = GEM_buffer1;
    798 		current->pitch = width * VDI_pixelsize;
    799 	} else {
    800 		current->pixels = VDI_screen;
    801 		current->pitch = VDI_pitch;
    802 	}
    803 
    804 #if SDL_VIDEO_OPENGL
    805 	if (flags & SDL_OPENGL) {
    806 		if (!SDL_AtariGL_Init(this, current)) {
    807 			GEM_FreeBuffers(this);
    808 			SDL_SetError("Can not create OpenGL context");
    809 			return NULL;
    810 		}
    811 
    812 		modeflags |= SDL_OPENGL;
    813 	}
    814 #endif
    815 
    816 	current->flags = modeflags;
    817 
    818 #ifdef DEBUG_VIDEO_GEM
    819 	printf("sdl:video:gem: surface: %dx%d\n", current->w, current->h);
    820 #endif
    821 
    822 	this->UpdateRects = GEM_UpdateRects;
    823 	GEM_lock_redraw = SDL_FALSE;	/* Enable redraw */
    824 
    825 	/* We're done */
    826 	return(current);
    827 }
    828 
    829 static int GEM_AllocHWSurface(_THIS, SDL_Surface *surface)
    830 {
    831 	return -1;
    832 }
    833 
    834 static void GEM_FreeHWSurface(_THIS, SDL_Surface *surface)
    835 {
    836 	return;
    837 }
    838 
    839 static int GEM_LockHWSurface(_THIS, SDL_Surface *surface)
    840 {
    841 	return(0);
    842 }
    843 
    844 static void GEM_UnlockHWSurface(_THIS, SDL_Surface *surface)
    845 {
    846 	return;
    847 }
    848 
    849 static void GEM_UpdateRectsFullscreen(_THIS, int numrects, SDL_Rect *rects)
    850 {
    851 	SDL_Surface *surface;
    852 	int i, surf_width;
    853 
    854 	surface = this->screen;
    855 	/* Need to be a multiple of 16 pixels */
    856 	surf_width=surface->w;
    857 	if ((surf_width & 15) != 0) {
    858 		surf_width = (surf_width | 15) + 1;
    859 	}
    860 
    861 	if (GEM_bufops & (B2S_C2P_1TO2|B2S_C2P_1TOS)) {
    862 		void *destscr;
    863 		int destpitch;
    864 
    865 		if (GEM_bufops & B2S_C2P_1TOS) {
    866 			destscr = VDI_screen;
    867 			destpitch = VDI_pitch;
    868 		} else {
    869 			destscr = GEM_buffer2;
    870 			destpitch = surface->pitch;
    871 		}
    872 
    873 		for (i=0;i<numrects;i++) {
    874 			void *source,*destination;
    875 			int x1,x2;
    876 
    877 			x1 = rects[i].x & ~15;
    878 			x2 = rects[i].x+rects[i].w;
    879 			if (x2 & 15) {
    880 				x2 = (x2 | 15) +1;
    881 			}
    882 
    883 			source = surface->pixels;
    884 			source += surface->pitch * rects[i].y;
    885 			source += x1;
    886 
    887 			destination = destscr;
    888 			destination += destpitch * rects[i].y;
    889 			destination += x1;
    890 
    891 			SDL_Atari_C2pConvert(
    892 				source, destination,
    893 				x2-x1, rects[i].h,
    894 				SDL_FALSE,
    895 				surface->pitch, destpitch
    896 			);
    897 		}
    898 	}
    899 
    900 	if (GEM_bufops & (B2S_VROCPYFM_1TOS|B2S_VROCPYFM_2TOS)) {
    901 		MFDB mfdb_src;
    902 		short blitcoords[8];
    903 
    904 		mfdb_src.fd_addr=surface->pixels;
    905 		mfdb_src.fd_w=surf_width;
    906 		mfdb_src.fd_h=surface->h;
    907 		mfdb_src.fd_wdwidth= (surface->pitch/VDI_pixelsize) >> 4;
    908 		mfdb_src.fd_nplanes=surface->format->BitsPerPixel;
    909 		mfdb_src.fd_stand=
    910 			mfdb_src.fd_r1=
    911 			mfdb_src.fd_r2=
    912 			mfdb_src.fd_r3= 0;
    913 		if (GEM_bufops & B2S_VROCPYFM_2TOS) {
    914 			mfdb_src.fd_addr=GEM_buffer2;
    915 		}
    916 
    917 		for ( i=0; i<numrects; ++i ) {
    918 			blitcoords[0] = blitcoords[4] = rects[i].x;
    919 			blitcoords[1] = blitcoords[5] = rects[i].y;
    920 			blitcoords[2] = blitcoords[6] = rects[i].x + rects[i].w - 1;
    921 			blitcoords[3] = blitcoords[7] = rects[i].y + rects[i].h - 1;
    922 
    923 			vro_cpyfm(VDI_handle, S_ONLY, blitcoords, &mfdb_src, &VDI_dst_mfdb);
    924 		}
    925 	}
    926 }
    927 
    928 static void GEM_UpdateRectsWindowed(_THIS, int numrects, SDL_Rect *rects)
    929 {
    930 	short pxy[4], wind_pxy[4];
    931 	int i;
    932 
    933 	if (wind_get(GEM_handle, WF_WORKXYWH, &wind_pxy[0], &wind_pxy[1], &wind_pxy[2], &wind_pxy[3])==0) {
    934 		return;
    935 	}
    936 
    937 	for ( i=0; i<numrects; ++i ) {
    938 		pxy[0] = wind_pxy[0] + rects[i].x;
    939 		pxy[1] = wind_pxy[1] + rects[i].y;
    940 		pxy[2] = rects[i].w;
    941 		pxy[3] = rects[i].h;
    942 
    943 		GEM_wind_redraw(this, GEM_handle, pxy);
    944 	}
    945 }
    946 
    947 static void GEM_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
    948 {
    949 	SDL_Surface *surface;
    950 
    951 	if (GEM_lock_redraw) {
    952 		return;
    953 	}
    954 
    955 	surface = this->screen;
    956 
    957 	if (surface->flags & SDL_FULLSCREEN) {
    958 		GEM_UpdateRectsFullscreen(this, numrects, rects);
    959 	} else {
    960 		GEM_UpdateRectsWindowed(this, numrects, rects);
    961 	}
    962 }
    963 
    964 static int GEM_FlipHWSurfaceFullscreen(_THIS, SDL_Surface *surface)
    965 {
    966 	int surf_width;
    967 
    968 	/* Need to be a multiple of 16 pixels */
    969 	surf_width=surface->w;
    970 	if ((surf_width & 15) != 0) {
    971 		surf_width = (surf_width | 15) + 1;
    972 	}
    973 
    974 	if (GEM_bufops & (B2S_C2P_1TO2|B2S_C2P_1TOS)) {
    975 		void *destscr;
    976 		int destpitch;
    977 
    978 		if (GEM_bufops & B2S_C2P_1TOS) {
    979 			destscr = VDI_screen;
    980 			destpitch = VDI_pitch;
    981 		} else {
    982 			destscr = GEM_buffer2;
    983 			destpitch = surface->pitch;
    984 		}
    985 
    986 		SDL_Atari_C2pConvert(
    987 			surface->pixels, destscr,
    988 			surf_width, surface->h,
    989 			SDL_FALSE,
    990 			surface->pitch, destpitch
    991 		);
    992 	}
    993 
    994 	if (GEM_bufops & (B2S_VROCPYFM_1TOS|B2S_VROCPYFM_2TOS)) {
    995 		MFDB mfdb_src;
    996 		short blitcoords[8];
    997 
    998 		mfdb_src.fd_w=surf_width;
    999 		mfdb_src.fd_h=surface->h;
   1000 		mfdb_src.fd_wdwidth=mfdb_src.fd_w >> 4;
   1001 		mfdb_src.fd_nplanes=surface->format->BitsPerPixel;
   1002 		mfdb_src.fd_stand=
   1003 			mfdb_src.fd_r1=
   1004 			mfdb_src.fd_r2=
   1005 			mfdb_src.fd_r3= 0;
   1006 		if (GEM_bufops & B2S_VROCPYFM_1TOS) {
   1007 			mfdb_src.fd_addr=surface->pixels;
   1008 		} else {
   1009 			mfdb_src.fd_addr=GEM_buffer2;
   1010 		}
   1011 
   1012 		blitcoords[0] = blitcoords[4] = 0;
   1013 		blitcoords[1] = blitcoords[5] = 0;
   1014 		blitcoords[2] = blitcoords[6] = surface->w - 1;
   1015 		blitcoords[3] = blitcoords[7] = surface->h - 1;
   1016 
   1017 		vro_cpyfm(VDI_handle, S_ONLY, blitcoords, &mfdb_src, &VDI_dst_mfdb);
   1018 	}
   1019 
   1020 	return(0);
   1021 }
   1022 
   1023 static int GEM_FlipHWSurfaceWindowed(_THIS, SDL_Surface *surface)
   1024 {
   1025 	short	pxy[8];
   1026 
   1027 	/* Update the whole window */
   1028 	wind_get(GEM_handle, WF_WORKXYWH, &pxy[0], &pxy[1], &pxy[2], &pxy[3]);
   1029 
   1030 	GEM_wind_redraw(this, GEM_handle, pxy);
   1031 
   1032 	return(0);
   1033 }
   1034 
   1035 static int GEM_FlipHWSurface(_THIS, SDL_Surface *surface)
   1036 {
   1037 	if (GEM_lock_redraw) {
   1038 		return(0);
   1039 	}
   1040 
   1041 	if (surface->flags & SDL_FULLSCREEN) {
   1042 		return GEM_FlipHWSurfaceFullscreen(this, surface);
   1043 	} else {
   1044 		return GEM_FlipHWSurfaceWindowed(this, surface);
   1045 	}
   1046 }
   1047 
   1048 static int GEM_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
   1049 {
   1050 	int i;
   1051 	SDL_Surface *surface;
   1052 
   1053 #ifdef DEBUG_VIDEO_GEM
   1054 	printf("sdl:video:gem: setcolors()\n");
   1055 #endif
   1056 
   1057 	/* Do not change palette in True Colour */
   1058 	surface = this->screen;
   1059 	if (surface->format->BitsPerPixel > 8) {
   1060 		return 1;
   1061 	}
   1062 
   1063 	for(i = 0; i < ncolors; i++)
   1064 	{
   1065 		int		r, g, b;
   1066 		short	rgb[3];
   1067 
   1068 		r = colors[i].r;
   1069 		g = colors[i].g;
   1070 		b = colors[i].b;
   1071 
   1072 		rgb[0] = VDI_curpalette[i][0] = (1000 * r) / 255;
   1073 		rgb[1] = VDI_curpalette[i][1] =(1000 * g) / 255;
   1074 		rgb[2] = VDI_curpalette[i][2] =(1000 * b) / 255;
   1075 
   1076 		vs_color(VDI_handle, vdi_index[firstcolor+i], rgb);
   1077 	}
   1078 
   1079 	return(1);
   1080 }
   1081 
   1082 #if 0
   1083 static int GEM_ToggleFullScreen(_THIS, int on)
   1084 {
   1085 	if (on) {
   1086 		GEM_LockScreen(this);
   1087 	} else {
   1088 		GEM_UnlockScreen(this);
   1089 	}
   1090 
   1091 	return(1);
   1092 }
   1093 #endif
   1094 
   1095 /* Note:  If we are terminated, this could be called in the middle of
   1096    another SDL video routine -- notably UpdateRects.
   1097 */
   1098 void GEM_VideoQuit(_THIS)
   1099 {
   1100 	SDL_AtariXbios_RestoreVectors();
   1101 	if (GEM_usedevmouse) {
   1102 		SDL_AtariDevMouse_Close();
   1103 	}
   1104 
   1105 	GEM_FreeBuffers(this);
   1106 
   1107 #if SDL_VIDEO_OPENGL
   1108 	if (gl_active) {
   1109 		SDL_AtariGL_Quit(this, SDL_TRUE);
   1110 	}
   1111 #endif
   1112 
   1113 	/* Destroy window */
   1114 	if (GEM_handle>=0) {
   1115 		wind_close(GEM_handle);
   1116 		wind_delete(GEM_handle);
   1117 		GEM_handle=-1;
   1118 	}
   1119 
   1120 	GEM_UnlockScreen(this);
   1121 	if (GEM_menubar) {
   1122 		Mfree(GEM_menubar);
   1123 		GEM_menubar=NULL;
   1124 	}
   1125 
   1126 	appl_exit();
   1127 
   1128 	GEM_SetNewPalette(this, VDI_oldpalette);
   1129 
   1130 	/* Close VDI workstation */
   1131 	if (VDI_handle) {
   1132 		v_clsvwk(VDI_handle);
   1133 	}
   1134 
   1135 	/* Free mode list */
   1136 	if (SDL_modelist[0]) {
   1137 		SDL_free(SDL_modelist[0]);
   1138 		SDL_modelist[0]=NULL;
   1139 	}
   1140 
   1141 	this->screen->pixels = NULL;
   1142 }
   1143 
   1144 void GEM_wind_redraw(_THIS, int winhandle, short *inside)
   1145 {
   1146 	short todo[4];
   1147 
   1148 	/* Tell AES we are going to update */
   1149 	wind_update(BEG_UPDATE);
   1150 
   1151 	v_hide_c(VDI_handle);
   1152 
   1153 	/* Browse the rectangle list to redraw */
   1154 	if (wind_get(winhandle, WF_FIRSTXYWH, &todo[0], &todo[1], &todo[2], &todo[3])!=0) {
   1155 
   1156 		while (todo[2] && todo[3]) {
   1157 
   1158 			if (rc_intersect((GRECT *)inside,(GRECT *)todo)) {
   1159 				todo[2] += todo[0]-1;
   1160 				todo[3] += todo[1]-1;
   1161 				refresh_window(this, winhandle, todo);
   1162 			}
   1163 
   1164 			if (wind_get(winhandle, WF_NEXTXYWH, &todo[0], &todo[1], &todo[2], &todo[3])==0) {
   1165 				break;
   1166 			}
   1167 		}
   1168 
   1169 	}
   1170 
   1171 	/* Update finished */
   1172 	wind_update(END_UPDATE);
   1173 
   1174 	v_show_c(VDI_handle,1);
   1175 }
   1176 
   1177 static void refresh_window(_THIS, int winhandle, short *rect)
   1178 {
   1179 	MFDB mfdb_src;
   1180 	short pxy[8],wind_pxy[8];
   1181 	SDL_Surface *surface;
   1182 	int iconified;
   1183 
   1184 	/* Is window iconified ? */
   1185 	iconified = 0;
   1186 /*	if (GEM_wfeatures & (1<<WF_ICONIFY))*/ {
   1187 		if (wind_get(winhandle, WF_ICONIFY, &wind_pxy[0], &wind_pxy[1], &wind_pxy[2], &wind_pxy[3])!=0) {
   1188 			iconified = wind_pxy[0];
   1189 		}
   1190 	}
   1191 
   1192 	if (wind_get(winhandle, WF_WORKXYWH, &wind_pxy[0], &wind_pxy[1], &wind_pxy[2], &wind_pxy[3])==0) {
   1193 		return;
   1194 	}
   1195 
   1196 	if (iconified && GEM_icon) {
   1197 		short icon_rect[4], dst_rect[4];
   1198 		short iconx,icony;
   1199 
   1200 		surface = GEM_icon;
   1201 
   1202 		GEM_ClearRect(this, rect);
   1203 
   1204 		/* Calculate centered icon(x,y,w,h) relative to window */
   1205 		iconx = (wind_pxy[2]-surface->w)>>1;
   1206 		icony = (wind_pxy[3]-surface->h)>>1;
   1207 
   1208 		icon_rect[0] = iconx;
   1209 		icon_rect[1] = icony;
   1210 		icon_rect[2] = surface->w;
   1211 		icon_rect[3] = surface->h;
   1212 
   1213 		/* Calculate redraw rectangle(x,y,w,h) relative to window */
   1214 		dst_rect[0] = rect[0]-wind_pxy[0];
   1215 		dst_rect[1] = rect[1]-wind_pxy[1];
   1216 		dst_rect[2] = rect[2]-rect[0]+1;
   1217 		dst_rect[3] = rect[3]-rect[1]+1;
   1218 
   1219 		/* Does the icon rectangle must be redrawn ? */
   1220 		if (!rc_intersect((GRECT *)icon_rect, (GRECT *)dst_rect)) {
   1221 			return;
   1222 		}
   1223 
   1224 #if DEBUG_VIDEO_GEM
   1225 		printf("sdl:video:gem:  clip(0,0,%d,%d) to (%d,%d,%d,%d)\n",
   1226 			surface->w-1,surface->h-1, dst_rect[0],dst_rect[1],dst_rect[2],dst_rect[3]);
   1227 		printf("sdl:video:gem:  icon(%d,%d,%d,%d)\n",
   1228 			icon_rect[0], icon_rect[1], icon_rect[2], icon_rect[3]);
   1229 		printf("sdl:video:gem: refresh_window(): draw icon\n");
   1230 #endif
   1231 
   1232 		/* Calculate icon(x1,y1,x2,y2) relative to screen */
   1233 		icon_rect[0] += wind_pxy[0];
   1234 		icon_rect[1] += wind_pxy[1];
   1235 		icon_rect[2] += icon_rect[0]-1;
   1236 		icon_rect[3] += icon_rect[1]-1;
   1237 
   1238 		/* Calculate intersection rectangle to redraw */
   1239 		pxy[4]=pxy[0]=MAX(icon_rect[0],rect[0]);
   1240 		pxy[5]=pxy[1]=MAX(icon_rect[1],rect[1]);
   1241  		pxy[6]=pxy[2]=MIN(icon_rect[2],rect[2]);
   1242 	 	pxy[7]=pxy[3]=MIN(icon_rect[3],rect[3]);
   1243 
   1244 		/* Calculate icon source image pos relative to window */
   1245 		pxy[0] -= wind_pxy[0]+iconx;
   1246 		pxy[1] -= wind_pxy[1]+icony;
   1247 		pxy[2] -= wind_pxy[0]+iconx;
   1248 		pxy[3] -= wind_pxy[1]+icony;
   1249 
   1250 	} else {
   1251 		surface = this->screen;
   1252 
   1253 #if DEBUG_VIDEO_GEM
   1254 		printf("sdl:video:gem: refresh_window(): draw frame buffer\n");
   1255 #endif
   1256 
   1257 		/* Redraw all window content */
   1258 		pxy[0] = rect[0]-wind_pxy[0];
   1259 		pxy[1] = rect[1]-wind_pxy[1];
   1260 	 	pxy[2] = rect[2]-wind_pxy[0];
   1261 	 	pxy[3] = rect[3]-wind_pxy[1];
   1262 
   1263 		pxy[4] = rect[0];
   1264 		pxy[5] = rect[1];
   1265 		pxy[6] = rect[2];
   1266 		pxy[7] = rect[3];
   1267 	}
   1268 
   1269 	if (GEM_bufops & B2S_C2P_1TO2) {
   1270 		void *src, *dest;
   1271 		int x1,x2;
   1272 
   1273 		x1 = (rect[0]-wind_pxy[0]) & ~15;
   1274 		x2 = rect[2]-wind_pxy[0];
   1275 		if (x2 & 15) {
   1276 			x2 = (x2 | 15) +1;
   1277 		}
   1278 
   1279 		src = surface->pixels;
   1280 		src += surface->pitch * (rect[1]-wind_pxy[1]);
   1281 		src += x1;
   1282 
   1283 		dest = GEM_buffer2;
   1284 		dest += surface->pitch * (rect[1]-wind_pxy[1]);
   1285 		dest += x1;
   1286 
   1287 		SDL_Atari_C2pConvert(
   1288 			src, dest,
   1289 			x2-x1, rect[3]-rect[1]+1,
   1290 			SDL_FALSE,
   1291 			surface->pitch, surface->pitch
   1292 		);
   1293 	}
   1294 
   1295 	mfdb_src.fd_addr=surface->pixels;
   1296 	{
   1297 		int width;
   1298 
   1299 		/* Need to be a multiple of 16 pixels */
   1300 		width=surface->w;
   1301 		if ((width & 15) != 0) {
   1302 			width = (width | 15) + 1;
   1303 		}
   1304 		mfdb_src.fd_w=width;
   1305 	}
   1306 	mfdb_src.fd_h=surface->h;
   1307   	mfdb_src.fd_nplanes=surface->format->BitsPerPixel;
   1308 	mfdb_src.fd_wdwidth=mfdb_src.fd_w>>4;
   1309 	mfdb_src.fd_stand=
   1310 		mfdb_src.fd_r1=
   1311   		mfdb_src.fd_r2=
   1312 	  	mfdb_src.fd_r3= 0;
   1313 
   1314 	if (GEM_bufops & B2S_VROCPYFM_2TOS) {
   1315 		mfdb_src.fd_addr=GEM_buffer2;
   1316 	}
   1317 
   1318 #if DEBUG_VIDEO_GEM
   1319 	printf("sdl:video:gem: redraw %dx%d: (%d,%d,%d,%d) to (%d,%d,%d,%d)\n",
   1320 		surface->w, surface->h,
   1321 		pxy[0],pxy[1],pxy[2],pxy[3],
   1322 		pxy[4],pxy[5],pxy[6],pxy[7]
   1323 	);
   1324 #endif
   1325 
   1326 	vro_cpyfm( VDI_handle, S_ONLY, pxy, &mfdb_src, &VDI_dst_mfdb);
   1327 }
   1328 
   1329 #if SDL_VIDEO_OPENGL
   1330 
   1331 static void GEM_GL_SwapBuffers(_THIS)
   1332 {
   1333 	SDL_AtariGL_SwapBuffers(this);
   1334 	GEM_FlipHWSurface(this, this->screen);
   1335 }
   1336 
   1337 #endif
   1338