Home | History | Annotate | Download | only in gapi
      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 /* Pocket PC GAPI SDL video driver implementation;
     25 Implemented by Dmitry Yakimov - support (at) activekitten.com
     26 Inspired by http://arisme.free.fr/ports/SDL.php
     27 */
     28 
     29 // TODO: copy surface on window when lost focus
     30 // TODO: test buttons rotation
     31 // TODO: test on be300 and HPC ( check WinDib fullscreen keys catching )
     32 // TODO: test on smartphones
     33 // TODO: windib on SH3 PPC2000 landscape test
     34 // TODO: optimize 8bpp landscape mode
     35 
     36 // there is some problems in runnings apps from a device landscape mode
     37 // due to WinCE bugs. Some works and some - does not.
     38 // TODO: finish Axim Dell X30 and user landscape mode, device landscape mode
     39 // TODO: finish Axim Dell X30 user portrait, device landscape stylus conversion
     40 // TODO: fix running GAPI apps from landscape mode -
     41 //       wince goes to portrait mode, but does not update video memory
     42 
     43 
     44 #include "SDL.h"
     45 #include "SDL_error.h"
     46 #include "SDL_video.h"
     47 #include "SDL_mouse.h"
     48 #include "../SDL_sysvideo.h"
     49 #include "../SDL_pixels_c.h"
     50 #include "../../events/SDL_events_c.h"
     51 #include "../wincommon/SDL_syswm_c.h"
     52 #include "../wincommon/SDL_sysmouse_c.h"
     53 #include "../windib/SDL_dibevents_c.h"
     54 
     55 #include "../windib/SDL_gapidibvideo.h"
     56 #include "SDL_gapivideo.h"
     57 
     58 #define gapi this->hidden->gapiInfo
     59 
     60 #define GAPIVID_DRIVER_NAME "gapi"
     61 
     62 #if defined(DEBUG) || defined (_DEBUG) || defined(NDEBUG)
     63 #define REPORT_VIDEO_INFO 1
     64 #else
     65 #define REPORT_VIDEO_INFO 0
     66 #endif
     67 
     68 // for testing with GapiEmu
     69 #define USE_GAPI_EMU 0
     70 #define EMULATE_AXIM_X30 0
     71 #define WITHOUT_GAPI 0
     72 
     73 #if USE_GAPI_EMU && !REPORT_VIDEO_INFO
     74 #pragma message("Warning: Using GapiEmu in release build. I assume you'd like to set USE_GAPI_EMU to zero.")
     75 #endif
     76 
     77 #ifndef _T
     78 #define _T(x) L##x
     79 #endif
     80 
     81 #ifndef ASSERT
     82 #define ASSERT(x)
     83 #endif
     84 
     85 // defined and used in SDL_sysevents.c
     86 extern HINSTANCE aygshell;
     87 extern void SDL_UnregisterApp();
     88 extern int DIB_AddMode(_THIS, int bpp, int w, int h);
     89 
     90 /* Initialization/Query functions */
     91 static int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat);
     92 static SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
     93 static SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
     94 static int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
     95 static void GAPI_VideoQuit(_THIS);
     96 
     97 /* Hardware surface functions */
     98 static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface);
     99 static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface);
    100 static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface);
    101 static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface);
    102 
    103 /* Windows message handling functions, will not be processed */
    104 static void GAPI_Activate(_THIS, BOOL active, BOOL minimized);
    105 static void GAPI_RealizePalette(_THIS);
    106 static void GAPI_PaletteChanged(_THIS, HWND window);
    107 static void GAPI_WinPAINT(_THIS, HDC hdc);
    108 
    109 /* etc. */
    110 static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects);
    111 
    112 static HMODULE g_hGapiLib = 0;
    113 #define LINK(type,name,import) \
    114 	if( g_hGapiLib ) \
    115 		name = (PFN##type)GetProcAddress( g_hGapiLib, _T(import) );
    116 
    117 static char g_bRawBufferAvailable = 0;
    118 
    119 /* GAPI driver bootstrap functions */
    120 
    121 /* hi res definitions */
    122 typedef struct _RawFrameBufferInfo
    123 {
    124    WORD wFormat;
    125    WORD wBPP;
    126    VOID *pFramePointer;
    127    int  cxStride;
    128    int  cyStride;
    129    int  cxPixels;
    130    int  cyPixels;
    131 } RawFrameBufferInfo;
    132 
    133 static struct _RawFrameBufferInfo g_RawFrameBufferInfo = {0};
    134 
    135 #define GETRAWFRAMEBUFFER   0x00020001
    136 
    137 #define FORMAT_565 1
    138 #define FORMAT_555 2
    139 #define FORMAT_OTHER 3
    140 
    141 /* Dell Axim x30 hangs when we use GAPI from landscape,
    142    so lets avoid using GxOpenDisplay there via GETGXINFO trick
    143    It seems that GAPI subsystem use the same ExtEscape code.
    144 */
    145 #define GETGXINFO 0x00020000
    146 
    147 typedef struct GXDeviceInfo
    148 {
    149 long Version; //00 (should filled with 100 before calling ExtEscape)
    150 void * pvFrameBuffer; //04
    151 unsigned long cbStride; //08
    152 unsigned long cxWidth; //0c
    153 unsigned long cyHeight; //10
    154 unsigned long cBPP; //14
    155 unsigned long ffFormat; //18
    156 char Unused[0x84-7*4];
    157 } GXDeviceInfo;
    158 
    159 static int GAPI_Available(void)
    160 {
    161 	// try to use VGA display, even on emulator
    162 	HDC hdc = GetDC(NULL);
    163 	int result = ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, sizeof(RawFrameBufferInfo), (char *)&g_RawFrameBufferInfo);
    164 	ReleaseDC(NULL, hdc);
    165 	g_bRawBufferAvailable = result > 0;
    166 
    167 	//My Asus MyPAL 696 reports the RAWFRAMEBUFFER as available, but with a size of 0 x 0
    168 	if(g_RawFrameBufferInfo.cxPixels <= 0 || g_RawFrameBufferInfo.cyPixels <= 0){
    169 		g_bRawBufferAvailable = 0;
    170 	}
    171 
    172 #if WITHOUT_GAPI
    173 	return g_bRawBufferAvailable;
    174 #endif
    175 
    176 #if USE_GAPI_EMU
    177 	g_hGapiLib = LoadLibrary(_T("GAPI_Emu.dll"));
    178 	if( !g_hGapiLib )
    179 	{
    180 		SDL_SetError("Gapi Emu not found!");
    181 	}
    182 	return g_hGapiLib != 0;
    183 #endif
    184 
    185 	// try to find gx.dll
    186 	g_hGapiLib = LoadLibrary(_T("\\Windows\\gx.dll"));
    187 	if( !g_hGapiLib )
    188 	{
    189 		g_hGapiLib = LoadLibrary(_T("gx.dll"));
    190 		if( !g_hGapiLib ) return g_bRawBufferAvailable;
    191 	}
    192 
    193 	return(1);
    194 }
    195 
    196 static int cmpmodes(const void *va, const void *vb)
    197 {
    198     SDL_Rect *a = *(SDL_Rect **)va;
    199     SDL_Rect *b = *(SDL_Rect **)vb;
    200     if ( a->w == b->w )
    201         return b->h - a->h;
    202     else
    203         return b->w - a->w;
    204 }
    205 
    206 static int GAPI_AddMode(_THIS, int bpp, int w, int h)
    207 {
    208 	SDL_Rect *mode;
    209 	int i, index;
    210 	int next_mode;
    211 
    212 	/* Check to see if we already have this mode */
    213 	if ( bpp < 8 ) {  /* Not supported */
    214 		return(0);
    215 	}
    216 	index = ((bpp+7)/8)-1;
    217 	for ( i=0; i<gapi->SDL_nummodes[index]; ++i ) {
    218 		mode = gapi->SDL_modelist[index][i];
    219 		if ( (mode->w == w) && (mode->h == h) ) {
    220 			return(0);
    221 		}
    222 	}
    223 
    224 	/* Set up the new video mode rectangle */
    225 	mode = (SDL_Rect *)SDL_malloc(sizeof *mode);
    226 	if ( mode == NULL ) {
    227 		SDL_OutOfMemory();
    228 		return(-1);
    229 	}
    230 	mode->x = 0;
    231 	mode->y = 0;
    232 	mode->w = w;
    233 	mode->h = h;
    234 
    235 	/* Allocate the new list of modes, and fill in the new mode */
    236 	next_mode = gapi->SDL_nummodes[index];
    237 	gapi->SDL_modelist[index] = (SDL_Rect **)
    238 	       SDL_realloc(gapi->SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *));
    239 	if ( gapi->SDL_modelist[index] == NULL ) {
    240 		SDL_OutOfMemory();
    241 		gapi->SDL_nummodes[index] = 0;
    242 		SDL_free(mode);
    243 		return(-1);
    244 	}
    245 	gapi->SDL_modelist[index][next_mode] = mode;
    246 	gapi->SDL_modelist[index][next_mode+1] = NULL;
    247 	gapi->SDL_nummodes[index]++;
    248 
    249 	return(0);
    250 }
    251 
    252 static void GAPI_DeleteDevice(SDL_VideoDevice *device)
    253 {
    254 	if( g_hGapiLib )
    255 	{
    256 		FreeLibrary(g_hGapiLib);
    257 		g_hGapiLib = 0;
    258 	}
    259 	SDL_free(device->hidden->gapiInfo);
    260 	SDL_free(device->hidden);
    261 	SDL_free(device);
    262 }
    263 
    264 static SDL_VideoDevice *GAPI_CreateDevice(int devindex)
    265 {
    266 	SDL_VideoDevice *device;
    267 
    268 	if( !g_hGapiLib && !g_bRawBufferAvailable)
    269 	{
    270 		if( !GAPI_Available() )
    271 		{
    272 			SDL_SetError("GAPI dll is not found and VGA mode is not available!");
    273 			return 0;
    274 		}
    275 	}
    276 
    277 	/* Initialize all variables that we clean on shutdown */
    278 	device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
    279 	if ( device ) {
    280 		SDL_memset(device, 0, (sizeof *device));
    281 		device->hidden = (struct SDL_PrivateVideoData *)
    282 				SDL_malloc((sizeof *device->hidden));
    283 		if(device->hidden){
    284 			SDL_memset(device->hidden, 0, (sizeof *device->hidden));
    285 			device->hidden->gapiInfo = (GapiInfo *)SDL_malloc((sizeof(GapiInfo)));
    286 			if(device->hidden->gapiInfo == NULL)
    287 			{
    288 				SDL_free(device->hidden);
    289 				device->hidden = NULL;
    290 			}
    291 		}
    292 	}
    293 	if ( (device == NULL) || (device->hidden == NULL) ) {
    294 		SDL_OutOfMemory();
    295 		if ( device ) {
    296 			SDL_free(device);
    297 		}
    298 		return(0);
    299 	}
    300 	SDL_memset(device->hidden->gapiInfo, 0, (sizeof *device->hidden->gapiInfo));
    301 
    302 	/* Set the function pointers */
    303 	device->VideoInit = GAPI_VideoInit;
    304 	device->ListModes = GAPI_ListModes;
    305 	device->SetVideoMode = GAPI_SetVideoMode;
    306 	device->UpdateMouse = WIN_UpdateMouse;
    307 	device->CreateYUVOverlay = NULL;
    308 	device->SetColors = GAPI_SetColors;
    309 	device->UpdateRects = GAPI_UpdateRects;
    310 	device->VideoQuit = GAPI_VideoQuit;
    311 	device->AllocHWSurface = GAPI_AllocHWSurface;
    312 	device->CheckHWBlit = NULL;
    313 	device->FillHWRect = NULL;
    314 	device->SetHWColorKey = NULL;
    315 	device->SetHWAlpha = NULL;
    316 	device->LockHWSurface = GAPI_LockHWSurface;
    317 	device->UnlockHWSurface = GAPI_UnlockHWSurface;
    318 	device->FlipHWSurface = NULL;
    319 	device->FreeHWSurface = GAPI_FreeHWSurface;
    320 	device->SetCaption = WIN_SetWMCaption;
    321 	device->SetIcon = WIN_SetWMIcon;
    322 	device->IconifyWindow = WIN_IconifyWindow;
    323 	device->GrabInput = WIN_GrabInput;
    324 	device->GetWMInfo = WIN_GetWMInfo;
    325 	device->FreeWMCursor = WIN_FreeWMCursor;
    326 	device->CreateWMCursor = WIN_CreateWMCursor;
    327 	device->ShowWMCursor = WIN_ShowWMCursor;
    328 	device->WarpWMCursor = WIN_WarpWMCursor;
    329     device->CheckMouseMode = WIN_CheckMouseMode;
    330 	device->InitOSKeymap = DIB_InitOSKeymap;
    331 	device->PumpEvents = DIB_PumpEvents;
    332 
    333 	/* Set up the windows message handling functions */
    334 	WIN_Activate = GAPI_Activate;
    335 	WIN_RealizePalette = GAPI_RealizePalette;
    336 	WIN_PaletteChanged = GAPI_PaletteChanged;
    337 	WIN_WinPAINT = GAPI_WinPAINT;
    338 	HandleMessage = DIB_HandleMessage;
    339 
    340 	device->free = GAPI_DeleteDevice;
    341 
    342 	/* Load gapi library */
    343 #define gx device->hidden->gapiInfo->gxFunc
    344 
    345     LINK( GXOpenDisplay, gx.GXOpenDisplay,         "?GXOpenDisplay@@YAHPAUHWND__@@K@Z" )
    346     LINK( GXCloseDisplay, gx.GXCloseDisplay,        "?GXCloseDisplay@@YAHXZ" )
    347     LINK( GXBeginDraw, gx.GXBeginDraw,           "?GXBeginDraw@@YAPAXXZ" )
    348     LINK( GXEndDraw, gx.GXEndDraw,             "?GXEndDraw@@YAHXZ" )
    349     LINK( GXOpenInput, gx.GXOpenInput,           "?GXOpenInput@@YAHXZ" )
    350     LINK( GXCloseInput, gx.GXCloseInput,          "?GXCloseInput@@YAHXZ" )
    351     LINK( GXGetDisplayProperties, gx.GXGetDisplayProperties,"?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ" )
    352     LINK( GXGetDefaultKeys, gx.GXGetDefaultKeys,      "?GXGetDefaultKeys@@YA?AUGXKeyList@@H@Z" )
    353     LINK( GXSuspend, gx.GXSuspend,             "?GXSuspend@@YAHXZ" )
    354     LINK( GXResume, gx.GXResume,              "?GXResume@@YAHXZ" )
    355     LINK( GXSetViewport, gx.GXSetViewport,         "?GXSetViewport@@YAHKKKK@Z" )
    356     LINK( GXIsDisplayDRAMBuffer, gx.GXIsDisplayDRAMBuffer, "?GXIsDisplayDRAMBuffer@@YAHXZ" )
    357 
    358 	/* wrong gapi.dll */
    359 	if( !gx.GXOpenDisplay )
    360 	{
    361 		if( g_hGapiLib )
    362 		{
    363 			FreeLibrary(g_hGapiLib);
    364 			g_hGapiLib = 0;
    365 		}
    366 	}
    367 
    368 	if( !gx.GXOpenDisplay && !g_bRawBufferAvailable)
    369 	{
    370 		SDL_SetError("Error: damaged or unknown gapi.dll!\n");
    371 		GAPI_DeleteDevice(device);
    372 		return 0;
    373 	}
    374 
    375 	return device;
    376 }
    377 
    378 VideoBootStrap GAPI_bootstrap = {
    379 	GAPIVID_DRIVER_NAME, "WinCE GAPI video driver",
    380 	GAPI_Available, GAPI_CreateDevice
    381 };
    382 
    383 static void FillStructs(_THIS, BOOL useVga)
    384 {
    385 #ifdef _ARM_
    386 	WCHAR oemstr[100];
    387 #endif
    388 	/* fill a device properties */
    389 
    390 	if( !useVga )
    391 	{
    392 		gapi->gxProperties = gapi->gxFunc.GXGetDisplayProperties();
    393 		gapi->needUpdate = 1;
    394 		gapi->hiresFix = 0;
    395 		gapi->useVga = 0;
    396 		gapi->useGXOpenDisplay = 1;
    397 
    398 #ifdef _ARM_
    399 		/* check some devices and extract addition info */
    400 		SystemParametersInfo( SPI_GETOEMINFO, sizeof( oemstr ), oemstr, 0 );
    401 
    402 		// buggy iPaq38xx
    403 		if ((oemstr[12] == 'H') && (oemstr[13] == '3') && (oemstr[14] == '8') && (gapi->gxProperties.cbxPitch > 0))
    404 		{
    405 			gapi->videoMem = (PIXEL*)0xac0755a0;
    406 			gapi->gxProperties.cbxPitch = -640;
    407 			gapi->gxProperties.cbyPitch = 2;
    408 			gapi->needUpdate = 0;
    409 		}
    410 #if (EMULATE_AXIM_X30 == 0)
    411 		// buggy Dell Axim X30
    412 		if( _tcsncmp(oemstr, L"Dell Axim X30", 13) == 0 )
    413 #endif
    414 		{
    415 			GXDeviceInfo gxInfo = {0};
    416 			HDC hdc = GetDC(NULL);
    417 			int result;
    418 
    419 			gxInfo.Version = 100;
    420 			result = ExtEscape(hdc, GETGXINFO, 0, NULL, sizeof(gxInfo), (char *)&gxInfo);
    421 			if( result > 0 )
    422 			{
    423 				gapi->useGXOpenDisplay = 0;
    424 				gapi->videoMem = gxInfo.pvFrameBuffer;
    425 				gapi->needUpdate = 0;
    426 				gapi->gxProperties.cbxPitch = 2;
    427 				gapi->gxProperties.cbyPitch = 480;
    428 				gapi->gxProperties.cxWidth = gxInfo.cxWidth;
    429 				gapi->gxProperties.cyHeight = gxInfo.cyHeight;
    430 				gapi->gxProperties.ffFormat = gxInfo.ffFormat;
    431 			}
    432 		}
    433 #endif
    434 	} else
    435 	{
    436 		gapi->needUpdate = 0;
    437 		gapi->hiresFix = 0;
    438 		gapi->gxProperties.cBPP = g_RawFrameBufferInfo.wBPP;
    439 		gapi->gxProperties.cbxPitch = g_RawFrameBufferInfo.cxStride;
    440 		gapi->gxProperties.cbyPitch = g_RawFrameBufferInfo.cyStride;
    441 		gapi->gxProperties.cxWidth = g_RawFrameBufferInfo.cxPixels;
    442 		gapi->gxProperties.cyHeight = g_RawFrameBufferInfo.cyPixels;
    443 		gapi->videoMem = g_RawFrameBufferInfo.pFramePointer;
    444 		gapi->useVga = 1;
    445 
    446 		switch( g_RawFrameBufferInfo.wFormat )
    447 		{
    448 		case FORMAT_565:
    449 			gapi->gxProperties.ffFormat = kfDirect565;
    450 			break;
    451 		case FORMAT_555:
    452 			gapi->gxProperties.ffFormat = kfDirect555;
    453 			break;
    454 		default:
    455 			/* unknown pixel format, try define by BPP! */
    456 			switch( g_RawFrameBufferInfo.wBPP )
    457 			{
    458 			case 4:
    459 			case 8:
    460 				gapi->gxProperties.ffFormat = kfDirect;
    461 			case 16:
    462 				gapi->gxProperties.ffFormat = kfDirect565;
    463 			default:
    464 				gapi->gxProperties.ffFormat = kfDirect;
    465 				break;
    466 			}
    467 		}
    468 	}
    469 
    470 	if( gapi->gxProperties.cBPP != 16 )
    471 	{
    472 		gapi->gapiOrientation = SDL_ORIENTATION_UP;
    473 	} else
    474 	if( (gapi->gxProperties.cbxPitch > 0) && (gapi->gxProperties.cbyPitch > 0 ))
    475 	{
    476 		gapi->gapiOrientation = SDL_ORIENTATION_UP;
    477 	} else
    478 	if( (gapi->gxProperties.cbxPitch > 0) && (gapi->gxProperties.cbyPitch < 0 ))
    479 	{
    480 		gapi->gapiOrientation = SDL_ORIENTATION_RIGHT; // ipaq 3660
    481 	} else
    482 	if( (gapi->gxProperties.cbxPitch < 0) && (gapi->gxProperties.cbyPitch > 0 ))
    483 	{
    484 		gapi->gapiOrientation = SDL_ORIENTATION_LEFT; // ipaq 3800
    485 	}
    486 }
    487 
    488 static void GAPI_CreatePalette(int ncolors, SDL_Color *colors)
    489 {
    490   // Setup a custom color palette
    491    BYTE buffer[ sizeof(LOGPALETTE) + 255 * sizeof(PALETTEENTRY) ];
    492    int i;
    493    LOGPALETTE*   pLogical = (LOGPALETTE*)buffer;
    494    PALETTEENTRY* entries  = pLogical->palPalEntry;
    495    HPALETTE hPalette;
    496    HDC hdc;
    497 
    498    for (i = 0; i < ncolors; ++i)
    499    {
    500       // Find intensity by replicating the bit patterns over a byte
    501       entries[i].peRed   = colors[i].r;
    502       entries[i].peGreen = colors[i].g;
    503       entries[i].peBlue  = colors[i].b;
    504       entries[i].peFlags = 0;
    505    }
    506 
    507    // Create the GDI palette object
    508    pLogical->palVersion    = 0x0300;
    509    pLogical->palNumEntries = ncolors;
    510 
    511    hPalette = CreatePalette( pLogical );
    512    ASSERT(hPalette);
    513 
    514 
    515    // Realize the palette
    516    hdc = GetDC(0);
    517 
    518    SelectPalette( hdc, hPalette, FALSE );
    519    RealizePalette( hdc );
    520 
    521    ReleaseDC( 0, hdc );
    522    DeleteObject( hPalette );
    523 }
    524 
    525 int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat)
    526 {
    527 	int i,bpp;
    528 
    529 	/* Create the window */
    530 	if ( DIB_CreateWindow(this) < 0 ) {
    531 		return(-1);
    532 	}
    533 
    534 	if( g_hGapiLib )
    535 	{
    536 		FillStructs(this, 0);
    537 
    538 		// SDL does not supports 2/4bpp mode, so use 16 bpp
    539 		bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP;
    540 
    541 		/* set up normal and landscape mode */
    542 		GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth);
    543 		GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight);
    544 	}
    545 
    546 	/* add hi-res mode */
    547 	if( g_bRawBufferAvailable &&
    548 		!((gapi->gxProperties.cxWidth == (unsigned)g_RawFrameBufferInfo.cxPixels) && (gapi->gxProperties.cyHeight == (unsigned)g_RawFrameBufferInfo.cyPixels)))
    549 	{
    550 		FillStructs(this, 1);
    551 
    552 		// SDL does not supports 2/4bpp mode, so use 16 bpp
    553 		bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP;
    554 
    555 		/* set up normal and landscape mode */
    556 		GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth);
    557 		GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight);
    558 	}
    559 
    560 	/* Determine the current screen size.
    561 	 * This is NOT necessarily the size of the Framebuffer or GAPI, as they return
    562 	 * the displaysize in ORIENTATION_UP */
    563 	this->info.current_w = GetSystemMetrics(SM_CXSCREEN);
    564 	this->info.current_h = GetSystemMetrics(SM_CYSCREEN);
    565 
    566 	/* Sort the mode lists */
    567 	for ( i=0; i<NUM_MODELISTS; ++i ) {
    568 		if ( gapi->SDL_nummodes[i] > 0 ) {
    569 			SDL_qsort(gapi->SDL_modelist[i], gapi->SDL_nummodes[i], sizeof *gapi->SDL_modelist[i], cmpmodes);
    570 		}
    571 	}
    572 
    573 	vformat->BitsPerPixel = gapi->gxProperties.cBPP < 8 ? 16 : (unsigned char)gapi->gxProperties.cBPP;
    574 
    575 	// Get color mask
    576 	if (gapi->gxProperties.ffFormat & kfDirect565) {
    577 		vformat->BitsPerPixel = 16;
    578 		vformat->Rmask = 0x0000f800;
    579 		vformat->Gmask = 0x000007e0;
    580 		vformat->Bmask = 0x0000001f;
    581 		gapi->videoMode = GAPI_DIRECT_565;
    582 	}
    583 	else
    584 	if (gapi->gxProperties.ffFormat & kfDirect555) {
    585 		vformat->BitsPerPixel = 16;
    586 		vformat->Rmask = 0x00007c00;
    587 		vformat->Gmask = 0x000003e0;
    588 		vformat->Bmask = 0x0000001f;
    589 		gapi->videoMode = GAPI_DIRECT_555;
    590 	}
    591 	else
    592 	if ((gapi->gxProperties.ffFormat & kfDirect) && (gapi->gxProperties.cBPP < 8)) {
    593 		// We'll perform the conversion
    594 		vformat->BitsPerPixel = 16;
    595 		vformat->Rmask = 0x0000f800; // 16 bit 565
    596 		vformat->Gmask = 0x000007e0;
    597 		vformat->Bmask = 0x0000001f;
    598 		if (gapi->gxProperties.ffFormat & kfDirectInverted)
    599 			gapi->invert = (1 << gapi->gxProperties.cBPP) - 1;
    600 		gapi->colorscale = gapi->gxProperties.cBPP < 8 ? 8 - gapi->gxProperties.cBPP : 0;
    601 		gapi->videoMode = GAPI_MONO;
    602 	}
    603 	else
    604 	if (gapi->gxProperties.ffFormat & kfPalette) {
    605 		gapi->videoMode = GAPI_PALETTE;
    606 	}
    607 
    608 	/* We're done! */
    609 	return(0);
    610 }
    611 
    612 SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
    613 {
    614 	return(gapi->SDL_modelist[((format->BitsPerPixel+7)/8)-1]);
    615 //  	 return (SDL_Rect **) -1;
    616 }
    617 
    618 SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current,
    619 				int width, int height, int bpp, Uint32 flags)
    620 {
    621 	SDL_Surface *video;
    622 	Uint32 Rmask, Gmask, Bmask;
    623 	DWORD style;
    624 	SDL_Rect allScreen;
    625 
    626 	if( bpp < 4 )
    627 	{
    628 		SDL_SetError("1 bpp and 2 bpp modes is not implemented yet!");
    629 		return 0;
    630 	}
    631 
    632 	/* Recalculate bitmasks if necessary */
    633 	if (bpp == current->format->BitsPerPixel) {
    634 		video = current;
    635 	}
    636 	else {
    637 		switch(bpp) {
    638 			case 8:
    639 				Rmask = 0;
    640 				Gmask = 0;
    641 				Bmask = 0;
    642 				break;
    643 			case 15:
    644 			case 16:
    645 				/* Default is 565 unless the display is specifically 555 */
    646 				if (gapi->gxProperties.ffFormat & kfDirect555) {
    647 					Rmask = 0x00007c00;
    648 					Gmask = 0x000003e0;
    649 					Bmask = 0x0000001f;
    650 				}
    651 				else {
    652 					Rmask = 0x0000f800;
    653 					Gmask = 0x000007e0;
    654 					Bmask = 0x0000001f;
    655 				}
    656 				break;
    657 			case 24:
    658 			case 32:
    659 				Rmask = 0x00ff0000;
    660 				Gmask = 0x0000ff00;
    661 				Bmask = 0x000000ff;
    662 				break;
    663 			default:
    664 				SDL_SetError("Unsupported Bits Per Pixel format requested");
    665 				return NULL;
    666 		}
    667 		video = SDL_CreateRGBSurface(SDL_SWSURFACE,
    668 					0, 0, bpp, Rmask, Gmask, Bmask, 0);
    669 		if ( video == NULL ) {
    670 			SDL_OutOfMemory();
    671 			return(NULL);
    672 		}
    673 	}
    674 
    675 	gapi->userOrientation = SDL_ORIENTATION_UP;
    676 	gapi->systemOrientation = SDL_ORIENTATION_UP;
    677 	video->flags = SDL_FULLSCREEN;	/* Clear flags, GAPI supports fullscreen only */
    678 
    679 	/* GAPI or VGA? */
    680 	if( g_hGapiLib )
    681 	{
    682 		FillStructs(this, 0);
    683 		if( (((unsigned)width != gapi->gxProperties.cxWidth) || ((unsigned)height != gapi->gxProperties.cyHeight))
    684 			&& (((unsigned)width != gapi->gxProperties.cyHeight) || ((unsigned)height != gapi->gxProperties.cxWidth)))
    685 			FillStructs(this, 1); // gapi is found but we use VGA resolution
    686 	} else
    687 		FillStructs(this, 1);
    688 
    689 	if ( !gapi->needUpdate && !gapi->videoMem) {
    690 		SDL_SetError("Couldn't get address of video memory, may be unsupported device or bug");
    691 		return(NULL);
    692 	}
    693 
    694 	/* detect user landscape mode */
    695        if( (width > height) && (gapi->gxProperties.cxWidth < gapi->gxProperties.cyHeight))
    696 		gapi->userOrientation = SDL_ORIENTATION_RIGHT;
    697 
    698        if(GetSystemMetrics(SM_CYSCREEN) < GetSystemMetrics(SM_CXSCREEN))
    699 		gapi->systemOrientation = SDL_ORIENTATION_RIGHT;
    700 
    701 	gapi->hiresFix = 0;
    702 
    703 	/* check hires */
    704 	if(GetSystemMetrics(SM_CXSCREEN) < width && GetSystemMetrics(SM_CYSCREEN) < height)
    705 	{
    706 	    gapi->hiresFix = 1;
    707 	}
    708 
    709 	switch( gapi->userOrientation )
    710 	{
    711 	case SDL_ORIENTATION_UP:
    712 		gapi->startOffset = 0;
    713 		gapi->dstLineStep = gapi->gxProperties.cbyPitch;
    714 		gapi->dstPixelStep = gapi->gxProperties.cbxPitch;
    715 		break;
    716 	case SDL_ORIENTATION_RIGHT:
    717 		switch( gapi->gapiOrientation )
    718 		{
    719 		case SDL_ORIENTATION_UP:
    720 		case SDL_ORIENTATION_RIGHT:
    721 		case SDL_ORIENTATION_LEFT:
    722 			if( (gapi->videoMode == GAPI_MONO) )
    723 				gapi->startOffset = -gapi->gxProperties.cbxPitch + 1; // monochrome mode
    724 			else
    725 				gapi->startOffset = gapi->gxProperties.cbyPitch * (gapi->gxProperties.cyHeight - 1);
    726 
    727 			gapi->dstLineStep = gapi->gxProperties.cbxPitch;
    728 			gapi->dstPixelStep = -gapi->gxProperties.cbyPitch;
    729 			break;
    730 		}
    731 	}
    732 
    733 	video->w = gapi->w = width;
    734 	video->h = gapi->h = height;
    735 	video->pitch = SDL_CalculatePitch(video);
    736 
    737 	/* Small fix for WinCE/Win32 - when activating window
    738 	   SDL_VideoSurface is equal to zero, so activating code
    739 	   is not called properly for fullscreen windows because
    740 	   macros WINDIB_FULLSCREEN uses SDL_VideoSurface
    741 	*/
    742 	SDL_VideoSurface = video;
    743 
    744 	/* GAPI is always fullscreen, title bar is useless */
    745 	style = 0;
    746 
    747 	if (!SDL_windowid)
    748 		SetWindowLong(SDL_Window, GWL_STYLE, style);
    749 
    750 	/* Allocate bitmap */
    751 	if( gapi->buffer )
    752 	{
    753 		SDL_free( gapi->buffer );
    754 		gapi->buffer = NULL;
    755 	}
    756 	gapi->buffer = SDL_malloc(video->h * video->pitch);
    757 	video->pixels = gapi->buffer;
    758 
    759 	if ( ! gapi->buffer ) {
    760 		SDL_SetError("Couldn't allocate buffer for requested mode");
    761 		return(NULL);
    762 	}
    763 
    764 	SDL_memset(gapi->buffer, 255, video->h * video->pitch);
    765 	MoveWindow(SDL_Window, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), FALSE);
    766 	ShowWindow(SDL_Window, SW_SHOW);
    767 	SetForegroundWindow(SDL_Window);
    768 
    769 	/* JC 14 Mar 2006
    770 		Flush the message loop or this can cause big problems later
    771 		Especially if the user decides to use dialog boxes or assert()!
    772 	*/
    773 	WIN_FlushMessageQueue();
    774 
    775        /* Open GAPI display */
    776        if( !gapi->useVga && gapi->useGXOpenDisplay && !gapi->alreadyGXOpened )
    777        {
    778 #if REPORT_VIDEO_INFO
    779                printf("system display width  (orig): %d\n", GetSystemMetrics(SM_CXSCREEN));
    780                printf("system display height (orig): %d\n", GetSystemMetrics(SM_CYSCREEN));
    781 #endif
    782                gapi->alreadyGXOpened = 1;
    783 		if( !gapi->gxFunc.GXOpenDisplay(SDL_Window, GX_FULLSCREEN) )
    784 		{
    785 			SDL_SetError("Couldn't initialize GAPI");
    786 			return(NULL);
    787 		}
    788        }
    789 
    790 	if(gapi->useVga)
    791 		gapi->coordinateTransform = (4 - gapi->systemOrientation + gapi->userOrientation) % 4;
    792 	else
    793 		gapi->coordinateTransform = gapi->userOrientation;
    794 
    795 #if REPORT_VIDEO_INFO
    796 	printf("Video properties:\n");
    797 	printf("display bpp: %d\n", gapi->gxProperties.cBPP);
    798 	printf("display width: %d\n", gapi->gxProperties.cxWidth);
    799 	printf("display height: %d\n", gapi->gxProperties.cyHeight);
    800        printf("system display width: %d\n", GetSystemMetrics(SM_CXSCREEN));
    801        printf("system display height: %d\n", GetSystemMetrics(SM_CYSCREEN));
    802 	printf("x pitch: %d\n", gapi->gxProperties.cbxPitch);
    803 	printf("y pitch: %d\n", gapi->gxProperties.cbyPitch);
    804 	printf("gapi flags: 0x%x\n", gapi->gxProperties.ffFormat);
    805        printf("user orientation: %d\n", gapi->userOrientation);
    806 	printf("system orientation: %d\n", gapi->systemOrientation);
    807        printf("gapi orientation: %d\n", gapi->gapiOrientation);
    808 
    809 
    810 	if( !gapi->useVga && gapi->useGXOpenDisplay && gapi->needUpdate)
    811 	{
    812 		gapi->videoMem = gapi->gxFunc.GXBeginDraw();
    813 		gapi->gxFunc.GXEndDraw();
    814 	}
    815 
    816 	printf("video memory: 0x%x\n", gapi->videoMem);
    817 	printf("need update: %d\n", gapi->needUpdate);
    818 	printf("hi-res fix: %d\n", gapi->hiresFix);
    819 	printf("VGA is available on the device: %d\n", g_bRawBufferAvailable);
    820 	printf("use raw framebuffer: %d\n", gapi->useVga);
    821 	printf("video surface bpp: %d\n", video->format->BitsPerPixel);
    822 	printf("video surface width: %d\n", video->w);
    823 	printf("video surface height: %d\n", video->h);
    824 	printf("mouse/arrows transformation angle: %d\n", gapi->coordinateTransform);
    825 #endif
    826 
    827 
    828 	/* Blank screen */
    829 	allScreen.x = allScreen.y = 0;
    830 	allScreen.w = video->w - 1;
    831 	allScreen.h = video->h - 1;
    832 	GAPI_UpdateRects(this, 1, &allScreen);
    833 
    834 	/* We're done */
    835 	return(video);
    836 }
    837 
    838 /* We don't actually allow hardware surfaces other than the main one */
    839 static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface)
    840 {
    841 	return(-1);
    842 }
    843 static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface)
    844 {
    845 	return;
    846 }
    847 
    848 /* We need to wait for vertical retrace on page flipped displays */
    849 static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface)
    850 {
    851 	return(0);
    852 }
    853 
    854 static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface)
    855 {
    856 	return;
    857 }
    858 
    859 static int updateLine8to8(_THIS, unsigned char *srcPointer, unsigned char *destPointer, int width, int height, int lines)
    860 {
    861 	if( gapi->dstPixelStep == 1) /* optimized blitting on most devices */
    862 	{
    863 		SDL_memcpy(destPointer, srcPointer, width);
    864 		return 1;
    865 	} else
    866 	{
    867 		// TODO: read 4 pixels, write DWORD
    868 		int step = gapi->dstPixelStep;
    869 		while(width--)
    870 		{
    871 			*destPointer = *srcPointer++;
    872 			destPointer += step;
    873 		}
    874 	}
    875 	return 1;
    876 }
    877 
    878 /* Video memory is very slow so lets optimize as much as possible */
    879 static int updateLine16to16(_THIS, PIXEL *srcPointer, PIXEL *destPointer, int width, int height, int lines)
    880 {
    881 	PIXEL *line1, *line2;
    882 	int step = gapi->dstPixelStep / 2;
    883 
    884 	if( step == 1 ) /* optimized blitting on most devices */
    885 	{
    886 		SDL_memcpy(destPointer, srcPointer, width * sizeof(PIXEL));
    887 		return 1;
    888 	}
    889 	else
    890 	{
    891 		if( (gapi->gapiOrientation != SDL_ORIENTATION_UP) &&
    892 			(gapi->userOrientation == SDL_ORIENTATION_UP )) // iPaq 3660/3800 and user orientation up
    893 		{
    894 			// to prevent data misalignment copy only one line
    895 			if( ((((unsigned)destPointer & 3) != 0) && (gapi->gapiOrientation == SDL_ORIENTATION_LEFT))
    896 				|| ((((unsigned)destPointer & 3) == 0) && (gapi->gapiOrientation != SDL_ORIENTATION_LEFT))
    897 				|| (lines == 1) )
    898 			{
    899 				while(width--)
    900 				{
    901 					*destPointer = *srcPointer++;
    902 					destPointer += step;
    903 				}
    904 				return 1;
    905 			}
    906 
    907 			/* read two lines at the same time, write DWORD */
    908 			line1 = srcPointer;
    909 			line2 = srcPointer + SDL_VideoSurface->pitch / 2;
    910 
    911 			if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT )
    912 				while(width--) // iPaq 3800
    913 				{
    914 					*(DWORD*)destPointer =(*line2++ << 16) | *line1++;
    915 					destPointer += step;
    916 				}
    917 			else
    918 			{
    919 				destPointer += gapi->gxProperties.cbyPitch / 2;
    920 
    921 				while(width--) // iPaq 3660
    922 				{
    923 					*(DWORD*)destPointer =(*line1++ << 16) | *line2++;
    924 					destPointer += step;
    925 				}
    926 			}
    927 			return 2;
    928 		} else
    929 		{
    930 			// iPaq 3800 and user orientation landscape
    931 			if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT )
    932 			{
    933 				int w1;
    934 
    935 				// to prevent data misalignment copy only one pixel
    936 				if( (((unsigned)destPointer & 3) == 0) && (width > 0))
    937 				{
    938 					*destPointer-- = *srcPointer++;
    939 					width--;
    940 				}
    941 
    942 				destPointer--;
    943 
    944 				w1 = width / 2;
    945 
    946 				while(w1--)
    947 				{
    948 					DWORD p = *(DWORD*)srcPointer;
    949 					*((DWORD*)destPointer) = (p << 16) | (p >> 16);
    950 					destPointer -= 2;
    951 					srcPointer += 2;
    952 				}
    953 
    954 				if( width & 1 ) // copy the last pixel
    955 				{
    956 					destPointer++;
    957 					*destPointer = *srcPointer;
    958 				}
    959 
    960 				return 1;
    961 			}
    962 
    963 			// modern iPaqs and user orientation landscape
    964 			// read two pixels, write DWORD
    965 
    966 			line1 = srcPointer;
    967 			line2 = srcPointer + SDL_VideoSurface->pitch / 2;
    968 
    969 			if( (((unsigned)destPointer & 3) != 0) || (lines == 1) )
    970 			{
    971 				while(width--)
    972 				{
    973 					*destPointer = *srcPointer++;
    974 					destPointer += step;
    975 				}
    976 				return 1;
    977 			}
    978 
    979 			while(width--)
    980 			{
    981 				*(DWORD*)destPointer =(*line2++ << 16) | *line1++;
    982 				destPointer -= gapi->gxProperties.cbyPitch / 2;
    983 			}
    984 			return 2;
    985 		}
    986 	}
    987 }
    988 
    989 // Color component masks for 565
    990 #define REDMASK (31<<11)
    991 #define GREENMASK (63<<5)
    992 #define BLUEMASK (31)
    993 
    994 
    995 static int updateLine16to4(_THIS, PIXEL *srcPointer, unsigned char *destPointer, int width, int height, int lines, int yNibble, int xNibble)
    996 {
    997 	PIXEL *line1, *line2;
    998 	int step = gapi->dstPixelStep;
    999 
   1000 	if( gapi->userOrientation == SDL_ORIENTATION_UP )
   1001 	{
   1002 		if( yNibble ) // copy bottom half of a line
   1003 		{
   1004 			while(width--)
   1005 			{
   1006 				PIXEL c1 = *srcPointer++;
   1007 				c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
   1008 				*destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4));
   1009 				destPointer += step;
   1010 			}
   1011 			return 1;
   1012 		}
   1013 
   1014 		// either 1 pixel picture or tail, anyway this is the last line
   1015 		if( lines == 1 )
   1016 		{
   1017 			while(width--)
   1018 			{
   1019 				PIXEL c1 = *srcPointer++;
   1020 				c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
   1021 				*destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF));
   1022 				destPointer += step;
   1023 			}
   1024 			return 1;
   1025 		}
   1026 
   1027 		line1 = srcPointer;
   1028 		line2 = srcPointer + SDL_VideoSurface->pitch / 2;
   1029 
   1030 		while(width--)
   1031 		{
   1032 			PIXEL c1 = *line1++;
   1033 			PIXEL c2 = *line2++;
   1034 			c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
   1035 			c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK);
   1036 			*destPointer = ~((c1 >> 3) + ((c2 >> 3) << 4));
   1037 			destPointer += step;
   1038 		}
   1039 		return 2;
   1040 	} else
   1041 	{
   1042 		int w1;
   1043 		w1 = width / 2;
   1044 
   1045 		if( xNibble )
   1046 		{
   1047 			// copy one pixel
   1048 			PIXEL c1 = *srcPointer++;
   1049 			c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
   1050 			*destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF));
   1051 			destPointer++;
   1052 		}
   1053 
   1054 		while(w1--)
   1055 		{
   1056 			PIXEL c1 = *srcPointer;
   1057 			PIXEL c2 = *(srcPointer + 1);
   1058 			c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
   1059 			c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK);
   1060 			*destPointer++ = ~((c2 >> 3) + ((c1 >> 3) << 4));
   1061 			srcPointer += 2;
   1062 		}
   1063 
   1064 		// copy tail
   1065 		if( (width & 1) && !xNibble )
   1066 		{
   1067 			PIXEL c1 = *srcPointer;
   1068 			c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
   1069 			*destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4));
   1070 		}
   1071 
   1072 		return 1;
   1073 	}
   1074 }
   1075 
   1076 static void GAPI_UpdateRectsMono(_THIS, int numrects, SDL_Rect *rects)
   1077 {
   1078 	int i, height;
   1079 	int linesProcessed;
   1080 	int xNibble, yNibble;
   1081 
   1082 	for (i=0; i<numrects; i++)
   1083 	{
   1084 		unsigned char *destPointer;
   1085 		unsigned char *srcPointer;
   1086 
   1087 		if( gapi->userOrientation == SDL_ORIENTATION_UP )
   1088 			destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset - rects[i].y * gapi->gxProperties.cBPP / 8 + rects[i].x * gapi->dstPixelStep;
   1089 		else
   1090 			destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].x * gapi->gxProperties.cBPP / 8 + rects[i].y * gapi->dstLineStep;
   1091 
   1092 		srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * 2;
   1093 		yNibble = rects[i].y & 1; // TODO: only for 4 bpp
   1094 		xNibble = rects[i].x & 1;
   1095 		height = rects[i].h;
   1096 		while (height > 0)
   1097 		{
   1098 			switch(gapi->gxProperties.cBPP)
   1099 			{
   1100 			case 2: // TODO
   1101 			case 4:
   1102 					linesProcessed = updateLine16to4(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height, yNibble, xNibble);
   1103 					yNibble = 0;
   1104 			}
   1105 			height -= linesProcessed;
   1106 			if( gapi->userOrientation == SDL_ORIENTATION_UP )
   1107 				destPointer--; // always fill 1 byte
   1108 			else destPointer += gapi->dstLineStep;
   1109 			srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes
   1110 		}
   1111 	}
   1112 }
   1113 
   1114 static void GAPI_UpdateRectsColor(_THIS, int numrects, SDL_Rect *rects)
   1115 {
   1116 	int i, height;
   1117 	int bytesPerPixel = (gapi->gxProperties.cBPP + 1) / 8;
   1118 	int linesProcessed;
   1119 	for (i=0; i<numrects; i++) {
   1120 		unsigned char *destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].y * gapi->dstLineStep + rects[i].x * gapi->dstPixelStep;
   1121 		unsigned char *srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * bytesPerPixel;
   1122 		height = rects[i].h;
   1123 
   1124 //		fprintf(stderr, "Starting rect %dx%d, dst=0x%x, w = %d, h = %d\n", rects[i].w, rects[i].h,destPointer,rects[i].w,rects[i].h);
   1125 //		fflush(stderr);
   1126 		linesProcessed = height;
   1127 
   1128 		while (height > 0) {
   1129 			switch(bytesPerPixel)
   1130 			{
   1131 			case 1:
   1132 				linesProcessed = updateLine8to8(this, srcPointer, (unsigned char *) destPointer, rects[i].w, rects[i].h, height);
   1133 				break;
   1134 			case 2:
   1135 #pragma warning(disable: 4133)
   1136 				linesProcessed = updateLine16to16(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height);
   1137 				break;
   1138 			}
   1139 			height -= linesProcessed;
   1140 			destPointer += gapi->dstLineStep * linesProcessed;
   1141 			srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes
   1142 		}
   1143 //		fprintf(stderr, "End of rect\n");
   1144 //		fflush(stderr);
   1145 	}
   1146 }
   1147 
   1148 
   1149 static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
   1150 {
   1151 	// we do not want to corrupt video memory
   1152 	if( gapi->suspended ) return;
   1153 
   1154 	if( gapi->needUpdate )
   1155 		gapi->videoMem = gapi->gxFunc.GXBeginDraw();
   1156 
   1157 	if( gapi->gxProperties.cBPP < 8 )
   1158 		GAPI_UpdateRectsMono(this, numrects, rects);
   1159 	else
   1160 		GAPI_UpdateRectsColor(this, numrects, rects);
   1161 
   1162 	if( gapi->needUpdate )
   1163 		gapi->gxFunc.GXEndDraw();
   1164 }
   1165 
   1166 /* Note:  If we are terminated, this could be called in the middle of
   1167    another SDL video routine -- notably UpdateRects.
   1168 */
   1169 void GAPI_VideoQuit(_THIS)
   1170 {
   1171 	int i, j;
   1172 	/* Destroy the window and everything associated with it */
   1173 	if ( SDL_Window )
   1174 	{
   1175 	    if ((g_hGapiLib != 0) && this && gapi && gapi->gxFunc.GXCloseDisplay && !gapi->useVga)
   1176 			gapi->gxFunc.GXCloseDisplay();
   1177 
   1178 		if (this->screen->pixels != NULL)
   1179 		{
   1180 			SDL_free(this->screen->pixels);
   1181 			this->screen->pixels = NULL;
   1182 		}
   1183 		if ( screen_icn ) {
   1184 			DestroyIcon(screen_icn);
   1185 			screen_icn = NULL;
   1186 		}
   1187 
   1188 		DIB_DestroyWindow(this);
   1189 		SDL_UnregisterApp();
   1190 
   1191 		SDL_Window = NULL;
   1192 #if defined(_WIN32_WCE)
   1193 
   1194 // Unload wince aygshell library to prevent leak
   1195 		if( aygshell )
   1196 		{
   1197 			FreeLibrary(aygshell);
   1198 			aygshell = NULL;
   1199 		}
   1200 #endif
   1201 
   1202 	/* Free video mode lists */
   1203 	for ( i=0; i<NUM_MODELISTS; ++i ) {
   1204 		if ( gapi->SDL_modelist[i] != NULL ) {
   1205 			for ( j=0; gapi->SDL_modelist[i][j]; ++j )
   1206 				SDL_free(gapi->SDL_modelist[i][j]);
   1207 			SDL_free(gapi->SDL_modelist[i]);
   1208 			gapi->SDL_modelist[i] = NULL;
   1209 		}
   1210 	}
   1211 
   1212 	}
   1213 
   1214 }
   1215 
   1216 static void GAPI_Activate(_THIS, BOOL active, BOOL minimized)
   1217 {
   1218 	//Nothing to do here (as far as I know)
   1219 }
   1220 
   1221 static void GAPI_RealizePalette(_THIS)
   1222 {
   1223 	OutputDebugString(TEXT("GAPI_RealizePalette NOT IMPLEMENTED !\r\n"));
   1224 }
   1225 
   1226 static void GAPI_PaletteChanged(_THIS, HWND window)
   1227 {
   1228 	OutputDebugString(TEXT("GAPI_PaletteChanged NOT IMPLEMENTED !\r\n"));
   1229 }
   1230 
   1231 static void GAPI_WinPAINT(_THIS, HDC hdc)
   1232 {
   1233 	// draw current offscreen buffer on hdc
   1234 
   1235 	int bpp = 16; // we always use either 8 or 16 bpp internally
   1236 	HGDIOBJ prevObject;
   1237 	unsigned short *bitmapData;
   1238 	HBITMAP hb;
   1239 	HDC srcDC;
   1240 
   1241     // Create a DIB
   1242     BYTE buffer[sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD)] = {0};
   1243     BITMAPINFO*       pBMI    = (BITMAPINFO*)buffer;
   1244     BITMAPINFOHEADER* pHeader = &pBMI->bmiHeader;
   1245     DWORD*            pColors = (DWORD*)&pBMI->bmiColors;
   1246 
   1247 	// CreateDIBSection does not support 332 pixel format on wce
   1248 	if( gapi->gxProperties.cBPP == 8 ) return;
   1249 
   1250     // DIB Header
   1251     pHeader->biSize            = sizeof(BITMAPINFOHEADER);
   1252     pHeader->biWidth           = gapi->w;
   1253     pHeader->biHeight          = -gapi->h;
   1254     pHeader->biPlanes          = 1;
   1255     pHeader->biBitCount        = bpp;
   1256     pHeader->biCompression     = BI_RGB;
   1257     pHeader->biSizeImage       = (gapi->w * gapi->h * bpp) / 8;
   1258 
   1259     // Color masks
   1260 	if( bpp == 16 )
   1261 	{
   1262 		pColors[0] = REDMASK;
   1263 		pColors[1] = GREENMASK;
   1264 		pColors[2] = BLUEMASK;
   1265 		pHeader->biCompression = BI_BITFIELDS;
   1266 	}
   1267     // Create the DIB
   1268     hb =  CreateDIBSection( 0, pBMI, DIB_RGB_COLORS, (void**)&bitmapData, 0, 0 );
   1269 
   1270 	// copy data
   1271 	// FIXME: prevent misalignment, but I've never seen non aligned width of screen
   1272 	memcpy(bitmapData, gapi->buffer, pHeader->biSizeImage);
   1273 	srcDC = CreateCompatibleDC(hdc);
   1274 	prevObject = SelectObject(srcDC, hb);
   1275 
   1276 	BitBlt(hdc, 0, 0, gapi->w, gapi->h, srcDC, 0, 0, SRCCOPY);
   1277 
   1278 	SelectObject(srcDC, prevObject);
   1279 	DeleteObject(hb);
   1280 	DeleteDC(srcDC);
   1281 }
   1282 
   1283 int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
   1284 {
   1285 	GAPI_CreatePalette(ncolors, colors);
   1286 	return 1;
   1287 }
   1288