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