Updated Windows CE/PocketPC support...adds GAPI driver, landscape mode,
updated project files, VS2005 support, VGA mode, more device support, etc,
etc, etc.
Fixes Bugzilla #47 and #28.
--ryan.
--- a/README.WinCE Thu Jan 19 08:36:41 2006 +0000
+++ b/README.WinCE Thu Jan 19 08:43:00 2006 +0000
@@ -1,5 +1,24 @@
-Project files for embedded Visual C++ 4.0 can be found in VisualCE.zip
+Project files for embedded Visual C++ 3.0, 4.0 and
+Visual Studio 2005 can be found in VisualCE.zip
+
+SDL supports GAPI and WinDib output for Windows CE.
+
+GAPI driver supports:
+
+- all possible WinCE devices (Pocket PC, Smartphones, HPC)
+ with different orientations of video memory and resolutions.
+- 4, 8 and 16 bpp devices
+- special handling of 8bpp on 8bpp devices
+- VGA mode, you can even switch between VGA and GAPI in runtime
+ (between 240x320 and 480x640 for example). On VGA devices you can
+ use either GAPI or VGA.
+- Landscape mode and automatic rotation of buttons and stylus coordinates.
+ To enable landscape mode make width of video screen bigger than height.
+ For example:
+ SDL_SetVideoMode(320,240,16,SDL_FULLSCREEN)
+- WM2005
+- SDL_ListModes
NOTE:
There are several SDL features not available in the WinCE port of SDL.
Binary file VisualCE.zip has changed
--- a/configure.in Thu Jan 19 08:36:41 2006 +0000
+++ b/configure.in Thu Jan 19 08:43:00 2006 +0000
@@ -3140,6 +3140,7 @@
src/video/wincommon/Makefile
src/video/windib/Makefile
src/video/windx5/Makefile
+src/video/gapi/Makefile
src/video/x11/Makefile
src/video/xbios/Makefile
src/video/XFree86/Makefile
--- a/src/thread/win32/SDL_systhread.c Thu Jan 19 08:36:41 2006 +0000
+++ b/src/thread/win32/SDL_systhread.c Thu Jan 19 08:43:00 2006 +0000
@@ -30,7 +30,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
+
+#ifndef _WIN32_WCE
#include <process.h>
+#endif
#include "SDL_error.h"
#include "SDL_thread.h"
@@ -53,9 +56,14 @@
* have to use _beginthreadex if we want the returned handle
* to be accessible after the thread exits
* threads created with _beginthread auto-close the handle
+ * Windows CE still use CreateThread.
*/
+#ifdef _WIN32_WCE
+ thread->handle = CreateThread(NULL, 0, RunThread, args, 0, &threadid);
+#else
thread->handle = (SYS_ThreadHandle) _beginthreadex(NULL, 0, RunThread,
args, 0, &threadid);
+#endif
if (thread->handle == NULL) {
SDL_SetError("Not enough resources to create thread");
return(-1);
--- a/src/thread/win32/win_ce_semaphore.c Thu Jan 19 08:36:41 2006 +0000
+++ b/src/thread/win32/win_ce_semaphore.c Thu Jan 19 08:43:00 2006 +0000
@@ -201,9 +201,9 @@
BOOL ok = TRUE;
if (hSynch == NULL) return NULL;
- if (Flags & 4 == 1 && hSynch->hEvent == NULL) ok = FALSE;
- if (Flags & 2 == 1 && hSynch->hMutex == NULL) ok = FALSE;
- if (Flags & 1 == 1 && hSynch->hEvent == NULL) ok = FALSE;
+ if ((Flags & 4) == 1 && (hSynch->hEvent == NULL)) ok = FALSE;
+ if ((Flags & 2) == 1 && (hSynch->hMutex == NULL)) ok = FALSE;
+ if ((Flags & 1) == 1 && (hSynch->hEvent == NULL)) ok = FALSE;
if (!ok)
{
CloseSynchHandle (hSynch);
--- a/src/video/Makefile.am Thu Jan 19 08:36:41 2006 +0000
+++ b/src/video/Makefile.am Thu Jan 19 08:43:00 2006 +0000
@@ -9,7 +9,7 @@
wincommon windib windx5 \
maccommon macdsp macrom riscos quartz \
bwindow ps2gs photon cybergfx epoc picogui \
- ataricommon xbios gem dc qtopia XFree86 wscons \
+ ataricommon xbios gem dc qtopia XFree86 wscons gapi \
ipod os2fslib
DRIVERS = @VIDEO_DRIVERS@
--- a/src/video/SDL_surface.c Thu Jan 19 08:36:41 2006 +0000
+++ b/src/video/SDL_surface.c Thu Jan 19 08:43:00 2006 +0000
@@ -39,6 +39,7 @@
#include "SDL_memops.h"
#include "SDL_leaks.h"
+
/* Public routines */
/*
* Create an empty RGB surface of the appropriate depth
--- a/src/video/SDL_sysvideo.h Thu Jan 19 08:36:41 2006 +0000
+++ b/src/video/SDL_sysvideo.h Thu Jan 19 08:43:00 2006 +0000
@@ -365,6 +365,9 @@
#ifdef ENABLE_AALIB
extern VideoBootStrap AALIB_bootstrap;
#endif
+#ifdef ENABLE_GAPI
+extern VideoBootStrap GAPI_bootstrap;
+#endif
#ifdef ENABLE_WINDIB
extern VideoBootStrap WINDIB_bootstrap;
#endif
--- a/src/video/SDL_video.c Thu Jan 19 08:36:41 2006 +0000
+++ b/src/video/SDL_video.c Thu Jan 19 08:43:00 2006 +0000
@@ -87,6 +87,9 @@
#ifdef ENABLE_AALIB
&AALIB_bootstrap,
#endif
+#ifdef ENABLE_GAPI
+ &GAPI_bootstrap,
+#endif
#ifdef ENABLE_WINDIB
&WINDIB_bootstrap,
#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/gapi/.cvsignore Thu Jan 19 08:43:00 2006 +0000
@@ -0,0 +1,6 @@
+Makefile.in
+Makefile
+.libs
+*.o
+*.lo
+*.la
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/gapi/Makefile.am Thu Jan 19 08:43:00 2006 +0000
@@ -0,0 +1,10 @@
+
+## Makefile.am for SDL using the PocketPC GAPI video driver
+
+noinst_LTLIBRARIES = libvideo_gapi.la
+libvideo_gapi_la_SOURCES = $(GAPI_SRCS)
+
+# The SDL GAPI driver sources
+GAPI_SRCS = \
+ SDL_gapivideo.c \
+ SDL_gapivideo.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/gapi/SDL_gapivideo.c Thu Jan 19 08:43:00 2006 +0000
@@ -0,0 +1,1127 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2004 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+/* Pocket PC GAPI SDL video driver implementation;
+Implemented by Dmitry Yakimov - support@activekitten.com
+Inspired by http://arisme.free.fr/ports/SDL.php
+*/
+
+// TODO: copy surface on window when lost focus
+// TODO: test buttons rotation
+// TODO: test on be300 and HPC ( check WinDib fullscreen keys catching )
+// TODO: test on smartphones
+// TODO: windib on SH3 PPC2000 landscape test
+// TODO: optimize 8bpp landscape mode
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "SDL.h"
+#include "SDL_error.h"
+#include "SDL_video.h"
+#include "SDL_mouse.h"
+#include "SDL_sysvideo.h"
+#include "SDL_pixels_c.h"
+#include "SDL_events_c.h"
+
+#include "SDL_syswm_c.h"
+#include "SDL_sysmouse_c.h"
+#include "SDL_dibevents_c.h"
+
+#include "SDL_gapivideo.h"
+
+#define GAPIVID_DRIVER_NAME "gapi"
+
+#if defined(DEBUG) || defined (_DEBUG) || defined(NDEBUG)
+#define REPORT_VIDEO_INFO 1
+#else
+#define REPORT_VIDEO_INFO 0
+#endif
+
+// for testing with GapiEmu
+#define USE_GAPI_EMU 0
+
+#if USE_GAPI_EMU && !REPORT_VIDEO_INFO
+#pragma message("Warning: Using GapiEmu in release build. I assume you'd like to set USE_GAPI_EMU to zero.")
+#endif
+
+// defined and used in SDL_sysevents.c
+extern HINSTANCE aygshell;
+extern void SDL_UnregisterApp();
+extern int DIB_AddMode(_THIS, int bpp, int w, int h);
+
+/* Initialization/Query functions */
+static int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat);
+static SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
+static SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
+static int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
+static void GAPI_VideoQuit(_THIS);
+
+/* Hardware surface functions */
+static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface);
+static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface);
+static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface);
+static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface);
+
+/* Windows message handling functions, will not be processed */
+static void GAPI_RealizePalette(_THIS);
+static void GAPI_PaletteChanged(_THIS, HWND window);
+static void GAPI_WinPAINT(_THIS, HDC hdc);
+
+/* etc. */
+static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects);
+
+static HMODULE g_hGapiLib = 0;
+#define LINK(type,name,import) \
+ if( g_hGapiLib ) \
+ name = (PFN##type)GetProcAddress( g_hGapiLib, _T(import) );
+
+static char g_bRawBufferAvailable = 0;
+
+/* GAPI driver bootstrap functions */
+
+/* hi res definitions */
+typedef struct _RawFrameBufferInfo
+{
+ WORD wFormat;
+ WORD wBPP;
+ VOID *pFramePointer;
+ int cxStride;
+ int cyStride;
+ int cxPixels;
+ int cyPixels;
+} RawFrameBufferInfo;
+
+static struct _RawFrameBufferInfo g_RawFrameBufferInfo = {0};
+
+#define GETRAWFRAMEBUFFER 0x00020001
+
+#define FORMAT_565 1
+#define FORMAT_555 2
+#define FORMAT_OTHER 3
+
+static int GAPI_Available(void)
+{
+ // try to use VGA display, even on emulator
+ HDC hdc = GetDC(NULL);
+ int result = ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, sizeof(RawFrameBufferInfo), (char *)&g_RawFrameBufferInfo);
+ ReleaseDC(NULL, hdc);
+ g_bRawBufferAvailable = result > 0;
+
+#if USE_GAPI_EMU
+ g_hGapiLib = LoadLibrary(_T("GAPI_Emu.dll"));
+ if( !g_hGapiLib )
+ {
+ SDL_SetError("Gapi Emu not found!");
+ }
+ return g_hGapiLib != 0;
+#endif
+
+ // try to find gx.dll
+ g_hGapiLib = LoadLibrary(_T("\\Windows\\gx.dll"));
+ if( !g_hGapiLib )
+ {
+ g_hGapiLib = LoadLibrary(_T("gx.dll"));
+ if( !g_hGapiLib ) return g_bRawBufferAvailable;
+ }
+
+ return(1);
+}
+
+static int cmpmodes(const void *va, const void *vb)
+{
+ SDL_Rect *a = *(SDL_Rect **)va;
+ SDL_Rect *b = *(SDL_Rect **)vb;
+ if ( a->w == b->w )
+ return b->h - a->h;
+ else
+ return b->w - a->w;
+}
+
+static int GAPI_AddMode(_THIS, int bpp, int w, int h)
+{
+ SDL_Rect *mode;
+ int i, index;
+ int next_mode;
+
+ /* Check to see if we already have this mode */
+ if ( bpp < 8 ) { /* Not supported */
+ return(0);
+ }
+ index = ((bpp+7)/8)-1;
+ for ( i=0; i<gapi->SDL_nummodes[index]; ++i ) {
+ mode = gapi->SDL_modelist[index][i];
+ if ( (mode->w == w) && (mode->h == h) ) {
+ return(0);
+ }
+ }
+
+ /* Set up the new video mode rectangle */
+ mode = (SDL_Rect *)malloc(sizeof *mode);
+ if ( mode == NULL ) {
+ SDL_OutOfMemory();
+ return(-1);
+ }
+ mode->x = 0;
+ mode->y = 0;
+ mode->w = w;
+ mode->h = h;
+
+ /* Allocate the new list of modes, and fill in the new mode */
+ next_mode = gapi->SDL_nummodes[index];
+ gapi->SDL_modelist[index] = (SDL_Rect **)
+ realloc(gapi->SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *));
+ if ( gapi->SDL_modelist[index] == NULL ) {
+ SDL_OutOfMemory();
+ gapi->SDL_nummodes[index] = 0;
+ free(mode);
+ return(-1);
+ }
+ gapi->SDL_modelist[index][next_mode] = mode;
+ gapi->SDL_modelist[index][next_mode+1] = NULL;
+ gapi->SDL_nummodes[index]++;
+
+ return(0);
+}
+
+static void GAPI_DeleteDevice(SDL_VideoDevice *device)
+{
+ if( g_hGapiLib )
+ {
+ FreeLibrary(g_hGapiLib);
+ g_hGapiLib = 0;
+ }
+ free(device->hidden);
+ free(device);
+}
+
+static SDL_VideoDevice *GAPI_CreateDevice(int devindex)
+{
+ SDL_VideoDevice *device;
+
+ if( !g_hGapiLib && !g_bRawBufferAvailable)
+ {
+ if( !GAPI_Available() )
+ {
+ SDL_SetError("GAPI dll is not found and VGA mode is not available!");
+ return 0;
+ }
+ }
+
+ /* Initialize all variables that we clean on shutdown */
+ device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
+ if ( device ) {
+ memset(device, 0, (sizeof *device));
+ device->hidden = (struct SDL_PrivateVideoData *)
+ malloc((sizeof *device->hidden));
+ }
+ if ( (device == NULL) || (device->hidden == NULL) ) {
+ SDL_OutOfMemory();
+ if ( device ) {
+ free(device);
+ }
+ return(0);
+ }
+ memset(device->hidden, 0, (sizeof *device->hidden));
+
+ /* Set the function pointers */
+ device->VideoInit = GAPI_VideoInit;
+ device->ListModes = GAPI_ListModes;
+ device->SetVideoMode = GAPI_SetVideoMode;
+ device->UpdateMouse = WIN_UpdateMouse;
+ device->CreateYUVOverlay = NULL;
+ device->SetColors = GAPI_SetColors;
+ device->UpdateRects = GAPI_UpdateRects;
+ device->VideoQuit = GAPI_VideoQuit;
+ device->AllocHWSurface = GAPI_AllocHWSurface;
+ device->CheckHWBlit = NULL;
+ device->FillHWRect = NULL;
+ device->SetHWColorKey = NULL;
+ device->SetHWAlpha = NULL;
+ device->LockHWSurface = GAPI_LockHWSurface;
+ device->UnlockHWSurface = GAPI_UnlockHWSurface;
+ device->FlipHWSurface = NULL;
+ device->FreeHWSurface = GAPI_FreeHWSurface;
+ device->SetCaption = WIN_SetWMCaption;
+ device->SetIcon = WIN_SetWMIcon;
+ device->IconifyWindow = WIN_IconifyWindow;
+ device->GrabInput = WIN_GrabInput;
+ device->GetWMInfo = WIN_GetWMInfo;
+ device->FreeWMCursor = WIN_FreeWMCursor;
+ device->CreateWMCursor = WIN_CreateWMCursor;
+ device->ShowWMCursor = WIN_ShowWMCursor;
+ device->WarpWMCursor = WIN_WarpWMCursor;
+ device->CheckMouseMode = WIN_CheckMouseMode;
+ device->InitOSKeymap = DIB_InitOSKeymap;
+ device->PumpEvents = DIB_PumpEvents;
+
+ /* Set up the windows message handling functions */
+ WIN_RealizePalette = GAPI_RealizePalette;
+ WIN_PaletteChanged = GAPI_PaletteChanged;
+ WIN_WinPAINT = GAPI_WinPAINT;
+ HandleMessage = DIB_HandleMessage;
+
+ device->free = GAPI_DeleteDevice;
+
+ /* Load gapi library */
+#define gx device->hidden->gxFunc
+
+ LINK( GXOpenDisplay, gx.GXOpenDisplay, "?GXOpenDisplay@@YAHPAUHWND__@@K@Z" )
+ LINK( GXCloseDisplay, gx.GXCloseDisplay, "?GXCloseDisplay@@YAHXZ" )
+ LINK( GXBeginDraw, gx.GXBeginDraw, "?GXBeginDraw@@YAPAXXZ" )
+ LINK( GXEndDraw, gx.GXEndDraw, "?GXEndDraw@@YAHXZ" )
+ LINK( GXOpenInput, gx.GXOpenInput, "?GXOpenInput@@YAHXZ" )
+ LINK( GXCloseInput, gx.GXCloseInput, "?GXCloseInput@@YAHXZ" )
+ LINK( GXGetDisplayProperties, gx.GXGetDisplayProperties,"?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ" )
+ LINK( GXGetDefaultKeys, gx.GXGetDefaultKeys, "?GXGetDefaultKeys@@YA?AUGXKeyList@@H@Z" )
+ LINK( GXSuspend, gx.GXSuspend, "?GXSuspend@@YAHXZ" )
+ LINK( GXResume, gx.GXResume, "?GXResume@@YAHXZ" )
+ LINK( GXSetViewport, gx.GXSetViewport, "?GXSetViewport@@YAHKKKK@Z" )
+ LINK( GXIsDisplayDRAMBuffer, gx.GXIsDisplayDRAMBuffer, "?GXIsDisplayDRAMBuffer@@YAHXZ" )
+
+ /* wrong gapi.dll */
+ if( !gx.GXOpenDisplay )
+ {
+ if( g_hGapiLib )
+ {
+ FreeLibrary(g_hGapiLib);
+ g_hGapiLib = 0;
+ }
+ }
+
+ if( !gx.GXOpenDisplay && !g_bRawBufferAvailable)
+ {
+ SDL_SetError("Error: damaged or unknown gapi.dll!\n");
+ GAPI_DeleteDevice(device);
+ return 0;
+ }
+
+ return device;
+}
+
+VideoBootStrap GAPI_bootstrap = {
+ GAPIVID_DRIVER_NAME, "WinCE GAPI video driver",
+ GAPI_Available, GAPI_CreateDevice
+};
+
+static void FillStructs(_THIS, BOOL useVga)
+{
+#ifdef _ARM_
+ WCHAR oemstr[100];
+#endif
+ /* fill a device properties */
+
+ if( !useVga )
+ {
+ this->hidden->gxProperties = this->hidden->gxFunc.GXGetDisplayProperties();
+ this->hidden->needUpdate = 1;
+ this->hidden->hiresFix = 0;
+ this->hidden->useVga = 0;
+#ifdef _ARM_
+ /* check some devices and extract addition info */
+ SystemParametersInfo( SPI_GETOEMINFO, sizeof( oemstr ), oemstr, 0 );
+
+ // buggy iPaq38xx
+ if ((oemstr[12] == 'H') && (oemstr[13] == '3') && (oemstr[14] == '8') && (this->hidden->gxProperties.cbxPitch > 0))
+ {
+ this->hidden->videoMem = (PIXEL*)0xac0755a0;
+ this->hidden->gxProperties.cbxPitch = -640;
+ this->hidden->gxProperties.cbyPitch = 2;
+ this->hidden->needUpdate = 0;
+ }
+#endif
+ } else
+ {
+ this->hidden->needUpdate = 0;
+ this->hidden->hiresFix = 0;
+ this->hidden->gxProperties.cBPP = g_RawFrameBufferInfo.wBPP;
+ this->hidden->gxProperties.cbxPitch = g_RawFrameBufferInfo.cxStride;
+ this->hidden->gxProperties.cbyPitch = g_RawFrameBufferInfo.cyStride;
+ this->hidden->gxProperties.cxWidth = g_RawFrameBufferInfo.cxPixels;
+ this->hidden->gxProperties.cyHeight = g_RawFrameBufferInfo.cyPixels;
+ this->hidden->videoMem = g_RawFrameBufferInfo.pFramePointer;
+ this->hidden->useVga = 1;
+
+ switch( g_RawFrameBufferInfo.wFormat )
+ {
+ case FORMAT_565:
+ this->hidden->gxProperties.ffFormat = kfDirect565;
+ break;
+ case FORMAT_555:
+ this->hidden->gxProperties.ffFormat = kfDirect555;
+ break;
+ default:
+ /* unknown pixel format, try define by BPP! */
+ switch( g_RawFrameBufferInfo.wBPP )
+ {
+ case 4:
+ case 8:
+ this->hidden->gxProperties.ffFormat = kfDirect;
+ case 16:
+ this->hidden->gxProperties.ffFormat = kfDirect565;
+ default:
+ this->hidden->gxProperties.ffFormat = kfDirect;
+ break;
+ }
+ }
+ }
+
+ if( this->hidden->gxProperties.cBPP != 16 )
+ {
+ this->hidden->gapiOrientation = SDL_ORIENTATION_UP;
+ } else
+ if( (this->hidden->gxProperties.cbxPitch > 0) && (this->hidden->gxProperties.cbyPitch > 0 ))
+ {
+ this->hidden->gapiOrientation = SDL_ORIENTATION_UP;
+ } else
+ if( (this->hidden->gxProperties.cbxPitch > 0) && (this->hidden->gxProperties.cbyPitch < 0 ))
+ {
+ this->hidden->gapiOrientation = SDL_ORIENTATION_RIGHT; // ipaq 3660
+ } else
+ if( (this->hidden->gxProperties.cbxPitch < 0) && (this->hidden->gxProperties.cbyPitch > 0 ))
+ {
+ this->hidden->gapiOrientation = SDL_ORIENTATION_LEFT; // ipaq 3800
+ }
+}
+
+static void GAPI_CreatePalette(int ncolors, SDL_Color *colors)
+{
+ // Setup a custom color palette
+ BYTE buffer[ sizeof(LOGPALETTE) + 255 * sizeof(PALETTEENTRY) ];
+ int i;
+ LOGPALETTE* pLogical = (LOGPALETTE*)buffer;
+ PALETTEENTRY* entries = pLogical->palPalEntry;
+ HPALETTE hPalette;
+ HDC hdc;
+
+ for (i = 0; i < ncolors; ++i)
+ {
+ // Find intensity by replicating the bit patterns over a byte
+ entries[i].peRed = colors[i].r;
+ entries[i].peGreen = colors[i].g;
+ entries[i].peBlue = colors[i].b;
+ entries[i].peFlags = 0;
+ }
+
+ // Create the GDI palette object
+ pLogical->palVersion = 0x0300;
+ pLogical->palNumEntries = ncolors;
+
+ hPalette = CreatePalette( pLogical );
+ ASSERT(hPalette);
+
+
+ // Realize the palette
+ hdc = GetDC(0);
+
+ SelectPalette( hdc, hPalette, FALSE );
+ RealizePalette( hdc );
+
+ ReleaseDC( 0, hdc );
+ DeleteObject( hPalette );
+}
+
+int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat)
+{
+ int i,bpp;
+
+ /* Create the window */
+ if ( DIB_CreateWindow(this) < 0 ) {
+ return(-1);
+ }
+
+ if( g_hGapiLib )
+ {
+ FillStructs(this, 0);
+
+ // SDL does not supports 2/4bpp mode, so use 16 bpp
+ bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP;
+
+ /* set up normal and landscape mode */
+ GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth);
+ GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight);
+ }
+
+ /* add hi-res mode */
+ if( g_bRawBufferAvailable &&
+ !((gapi->gxProperties.cxWidth == (unsigned)g_RawFrameBufferInfo.cxPixels) && (gapi->gxProperties.cyHeight == (unsigned)g_RawFrameBufferInfo.cyPixels)))
+ {
+ FillStructs(this, 1);
+
+ // SDL does not supports 2/4bpp mode, so use 16 bpp
+ bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP;
+
+ /* set up normal and landscape mode */
+ GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth);
+ GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight);
+ }
+
+ /* Sort the mode lists */
+ for ( i=0; i<NUM_MODELISTS; ++i ) {
+ if ( gapi->SDL_nummodes[i] > 0 ) {
+ qsort(gapi->SDL_modelist[i], gapi->SDL_nummodes[i], sizeof *gapi->SDL_modelist[i], cmpmodes);
+ }
+ }
+
+ vformat->BitsPerPixel = this->hidden->gxProperties.cBPP < 8 ? 16 : (unsigned char)this->hidden->gxProperties.cBPP;
+
+ // Get color mask
+ if (this->hidden->gxProperties.ffFormat & kfDirect565) {
+ vformat->BitsPerPixel = 16;
+ vformat->Rmask = 0x0000f800;
+ vformat->Gmask = 0x000007e0;
+ vformat->Bmask = 0x0000001f;
+ this->hidden->videoMode = GAPI_DIRECT_565;
+ }
+ else
+ if (this->hidden->gxProperties.ffFormat & kfDirect555) {
+ vformat->BitsPerPixel = 16;
+ vformat->Rmask = 0x00007c00;
+ vformat->Gmask = 0x000003e0;
+ vformat->Bmask = 0x0000001f;
+ this->hidden->videoMode = GAPI_DIRECT_555;
+ }
+ else
+ if ((this->hidden->gxProperties.ffFormat & kfDirect) && (this->hidden->gxProperties.cBPP < 8)) {
+ // We'll perform the conversion
+ vformat->BitsPerPixel = 16;
+ vformat->Rmask = 0x0000f800; // 16 bit 565
+ vformat->Gmask = 0x000007e0;
+ vformat->Bmask = 0x0000001f;
+ if (this->hidden->gxProperties.ffFormat & kfDirectInverted)
+ this->hidden->invert = (1 << this->hidden->gxProperties.cBPP) - 1;
+ this->hidden->colorscale = this->hidden->gxProperties.cBPP < 8 ? 8 - this->hidden->gxProperties.cBPP : 0;
+ this->hidden->videoMode = GAPI_MONO;
+ }
+ else
+ if (this->hidden->gxProperties.ffFormat & kfPalette) {
+ this->hidden->videoMode = GAPI_PALETTE;
+ }
+
+ /* We're done! */
+ return(0);
+}
+
+SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
+{
+ return(this->hidden->SDL_modelist[((format->BitsPerPixel+7)/8)-1]);
+// return (SDL_Rect **) -1;
+}
+
+SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current,
+ int width, int height, int bpp, Uint32 flags)
+{
+ SDL_Surface *video;
+ Uint32 Rmask, Gmask, Bmask;
+ DWORD style;
+ SDL_Rect allScreen;
+
+ if( bpp < 4 )
+ {
+ SDL_SetError("1 bpp and 2 bpp modes is not implemented yet!");
+ return 0;
+ }
+
+ /* Recalculate bitmasks if necessary */
+ if (bpp == current->format->BitsPerPixel) {
+ video = current;
+ }
+ else {
+ switch(bpp) {
+ case 8:
+ Rmask = 0;
+ Gmask = 0;
+ Bmask = 0;
+ break;
+ case 15:
+ case 16:
+ /* Default is 565 unless the display is specifically 555 */
+ if (this->hidden->gxProperties.ffFormat & kfDirect555) {
+ Rmask = 0x00007c00;
+ Gmask = 0x000003e0;
+ Bmask = 0x0000001f;
+ }
+ else {
+ Rmask = 0x0000f800;
+ Gmask = 0x000007e0;
+ Bmask = 0x0000001f;
+ }
+ break;
+ case 24:
+ case 32:
+ Rmask = 0x00ff0000;
+ Gmask = 0x0000ff00;
+ Bmask = 0x000000ff;
+ break;
+ default:
+ SDL_SetError("Unsupported Bits Per Pixel format requested");
+ return NULL;
+ }
+ video = SDL_CreateRGBSurface(SDL_SWSURFACE,
+ 0, 0, bpp, Rmask, Gmask, Bmask, 0);
+ if ( video == NULL ) {
+ SDL_OutOfMemory();
+ return(NULL);
+ }
+ }
+
+ gapi->userOrientation = SDL_ORIENTATION_UP;
+ video->flags = SDL_FULLSCREEN; /* Clear flags, GAPI supports fullscreen only */
+
+ /* GAPI or VGA? */
+ if( g_hGapiLib )
+ {
+ FillStructs(this, 0);
+ if( (((unsigned)width != gapi->gxProperties.cxWidth) || ((unsigned)height != gapi->gxProperties.cyHeight))
+ && (((unsigned)width != gapi->gxProperties.cyHeight) || ((unsigned)height != gapi->gxProperties.cxWidth)))
+ FillStructs(this, 1); // gapi is found but we use VGA resolution
+ } else
+ FillStructs(this, 1);
+
+ if ( !this->hidden->needUpdate && !this->hidden->videoMem) {
+ SDL_SetError("Couldn't get address of video memory, may be unsupported device or bug");
+ return(NULL);
+ }
+
+ /* detect landscape mode */
+ if( (width > height) && (GetSystemMetrics(SM_CXSCREEN) < GetSystemMetrics(SM_CYSCREEN)))
+ gapi->userOrientation = SDL_ORIENTATION_RIGHT;
+
+ /* shall we apply hires fix? for example when we do not use hires resource */
+ gapi->hiresFix = 0;
+ if( gapi->userOrientation == SDL_ORIENTATION_RIGHT )
+ {
+ if( (width > GetSystemMetrics(SM_CYSCREEN)) || (height > GetSystemMetrics(SM_CXSCREEN)))
+ gapi->hiresFix = 1;
+ } else
+ if( (width > GetSystemMetrics(SM_CXSCREEN)) || (height > GetSystemMetrics(SM_CYSCREEN)))
+ gapi->hiresFix = 1;
+
+ switch( gapi->userOrientation )
+ {
+ case SDL_ORIENTATION_UP:
+ gapi->startOffset = 0;
+ gapi->dstLineStep = gapi->gxProperties.cbyPitch;
+ gapi->dstPixelStep = gapi->gxProperties.cbxPitch;
+ break;
+ case SDL_ORIENTATION_RIGHT:
+ switch( gapi->gapiOrientation )
+ {
+ case SDL_ORIENTATION_UP:
+ case SDL_ORIENTATION_RIGHT:
+ case SDL_ORIENTATION_LEFT:
+ if( (this->hidden->videoMode == GAPI_MONO) )
+ gapi->startOffset = -gapi->gxProperties.cbxPitch + 1; // monochrome mode
+ else
+ gapi->startOffset = gapi->gxProperties.cbyPitch * (gapi->gxProperties.cyHeight - 1);
+
+ gapi->dstLineStep = gapi->gxProperties.cbxPitch;
+ gapi->dstPixelStep = -gapi->gxProperties.cbyPitch;
+ break;
+ }
+ }
+
+ video->w = this->hidden->w = width;
+ video->h = this->hidden->h = height;
+ video->pitch = SDL_CalculatePitch(video);
+
+ /* Small fix for WinCE/Win32 - when activating window
+ SDL_VideoSurface is equal to zero, so activating code
+ is not called properly for fullscreen windows because
+ macros WINDIB_FULLSCREEN uses SDL_VideoSurface
+ */
+ SDL_VideoSurface = video;
+
+ /* GAPI is always fullscreen, title bar is useless */
+ style = 0;
+
+ if (!SDL_windowid)
+ SetWindowLong(SDL_Window, GWL_STYLE, style);
+
+ /* Allocate bitmap */
+ if(gapiBuffer)
+ {
+ free(gapiBuffer);
+ gapiBuffer = NULL;
+ }
+ gapiBuffer = malloc(video->h * video->pitch);
+ video->pixels = gapiBuffer;
+
+ if ( ! this->hidden->buffer ) {
+ SDL_SetError("Couldn't allocate buffer for requested mode");
+ return(NULL);
+ }
+
+ memset(gapiBuffer, 255, video->h * video->pitch);
+ MoveWindow(SDL_Window, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), FALSE);
+ ShowWindow(SDL_Window, SW_SHOW);
+ SetForegroundWindow(SDL_Window);
+
+#if REPORT_VIDEO_INFO
+ printf("Video properties:\n");
+ printf("display bpp: %d\n", gapi->gxProperties.cBPP);
+ printf("display width: %d\n", gapi->gxProperties.cxWidth);
+ printf("display height: %d\n", gapi->gxProperties.cyHeight);
+ printf("x pitch: %d\n", gapi->gxProperties.cbxPitch);
+ printf("y pitch: %d\n", gapi->gxProperties.cbyPitch);
+ printf("gapi flags: 0x%x\n", gapi->gxProperties.ffFormat);
+ printf("video memory: 0x%x\n", gapi->videoMem);
+ printf("need update: %d\n", gapi->needUpdate);
+ printf("hi-res fix: %d\n", gapi->hiresFix);
+ printf("VGA is available on the device: %d\n", g_bRawBufferAvailable);
+ printf("use VGA resolution: %d\n", gapi->useVga);
+ printf("video surface bpp: %d\n", video->format->BitsPerPixel);
+ printf("video surface width: %d\n", video->w);
+ printf("video surface height: %d\n", video->h);
+#endif
+
+ /* Open GAPI display */
+ if( !gapi->useVga )
+ if( !gapi->gxFunc.GXOpenDisplay(SDL_Window, GX_FULLSCREEN) )
+ {
+ SDL_SetError("Couldn't initialize GAPI");
+ return(NULL);
+ }
+
+ /* Blank screen */
+ allScreen.x = allScreen.y = 0;
+ allScreen.w = video->w - 1;
+ allScreen.h = video->h - 1;
+ GAPI_UpdateRects(this, 1, &allScreen);
+
+ /* We're done */
+ return(video);
+}
+
+/* We don't actually allow hardware surfaces other than the main one */
+static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface)
+{
+ return(-1);
+}
+static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface)
+{
+ return;
+}
+
+/* We need to wait for vertical retrace on page flipped displays */
+static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface)
+{
+ return(0);
+}
+
+static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface)
+{
+ return;
+}
+
+static int updateLine8to8(_THIS, unsigned char *srcPointer, unsigned char *destPointer, int width, int height, int lines)
+{
+ if( gapi->dstPixelStep == 1) /* optimized blitting on most devices */
+ {
+ memcpy(destPointer, srcPointer, width);
+ return 1;
+ } else
+ {
+ // TODO: read 4 pixels, write DWORD
+ int step = gapi->dstPixelStep;
+ while(width--)
+ {
+ *destPointer = *srcPointer++;
+ destPointer += step;
+ }
+ }
+ return 1;
+}
+
+/* Video memory is very slow so lets optimize as much as possible */
+static int updateLine16to16(_THIS, PIXEL *srcPointer, PIXEL *destPointer, int width, int height, int lines)
+{
+ PIXEL *line1, *line2;
+ int step = gapi->dstPixelStep / 2;
+
+ if( step == 1 ) /* optimized blitting on most devices */
+ {
+ memcpy(destPointer, srcPointer, width * sizeof(PIXEL));
+ return 1;
+ }
+ else
+ {
+ if( (gapi->gapiOrientation != SDL_ORIENTATION_UP) &&
+ (gapi->userOrientation == SDL_ORIENTATION_UP )) // iPaq 3660/3800 and user orientation up
+ {
+ // to prevent data misalignment copy only one line
+ if( ((((unsigned)destPointer & 3) != 0) && (gapi->gapiOrientation == SDL_ORIENTATION_LEFT))
+ || ((((unsigned)destPointer & 3) == 0) && (gapi->gapiOrientation != SDL_ORIENTATION_LEFT))
+ || (lines == 1) )
+ {
+ while(width--)
+ {
+ *destPointer = *srcPointer++;
+ destPointer += step;
+ }
+ return 1;
+ }
+
+ /* read two lines at the same time, write DWORD */
+ line1 = srcPointer;
+ line2 = srcPointer + SDL_VideoSurface->pitch / 2;
+
+ if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT )
+ while(width--) // iPaq 3800
+ {
+ *(DWORD*)destPointer =(*line2++ << 16) | *line1++;
+ destPointer += step;
+ }
+ else
+ {
+ destPointer += gapi->gxProperties.cbyPitch / 2;
+ while(width--) // iPaq 3660
+ {
+ *(DWORD*)destPointer =(*line1++ << 16) | *line2++;
+ destPointer += step;
+ }
+ }
+ return 2;
+ } else
+ {
+ // iPaq 3800 and user orientation landscape
+ if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT )
+ {
+ int w1;
+
+ // to prevent data misalignment copy only one pixel
+ if( (((unsigned)destPointer & 3) == 0) && (width > 0))
+ {
+ *destPointer-- = *srcPointer++;
+ width--;
+ }
+
+ destPointer--;
+
+ w1 = width / 2;
+
+ while(w1--)
+ {
+ DWORD p = *(DWORD*)srcPointer;
+ *((DWORD*)destPointer) = (p << 16) | (p >> 16);
+ destPointer -= 2;
+ srcPointer += 2;
+ }
+
+ if( width & 1 ) // copy the last pixel
+ {
+ destPointer++;
+ *destPointer = *srcPointer;
+ }
+
+ return 1;
+ }
+
+ // modern iPaqs and user orientation landscape
+ // read two pixels, write DWORD
+
+ line1 = srcPointer;
+ line2 = srcPointer + SDL_VideoSurface->pitch / 2;
+
+ if( (((unsigned)destPointer & 3) != 0) || (lines == 1) )
+ {
+ while(width--)
+ {
+ *destPointer = *srcPointer++;
+ destPointer += step;
+ }
+ return 1;
+ }
+
+ while(width--)
+ {
+ *(DWORD*)destPointer =(*line2++ << 16) | *line1++;
+ destPointer -= gapi->gxProperties.cbyPitch / 2;
+ }
+ return 2;
+ }
+ }
+}
+
+// Color component masks for 565
+#define REDMASK (31<<11)
+#define GREENMASK (63<<5)
+#define BLUEMASK (31)
+
+
+static int updateLine16to4(_THIS, PIXEL *srcPointer, unsigned char *destPointer, int width, int height, int lines, int yNibble, int xNibble)
+{
+ PIXEL *line1, *line2;
+ int step = gapi->dstPixelStep;
+
+ if( gapi->userOrientation == SDL_ORIENTATION_UP )
+ {
+ if( yNibble ) // copy bottom half of a line
+ {
+ while(width--)
+ {
+ PIXEL c1 = *srcPointer++;
+ c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
+ *destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4));
+ destPointer += step;
+ }
+ return 1;
+ }
+
+ // either 1 pixel picture or tail, anyway this is the last line
+ if( lines == 1 )
+ {
+ while(width--)
+ {
+ PIXEL c1 = *srcPointer++;
+ c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
+ *destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF));
+ destPointer += step;
+ }
+ return 1;
+ }
+
+ line1 = srcPointer;
+ line2 = srcPointer + SDL_VideoSurface->pitch / 2;
+
+ while(width--)
+ {
+ PIXEL c1 = *line1++;
+ PIXEL c2 = *line2++;
+ c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
+ c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK);
+ *destPointer = ~((c1 >> 3) + ((c2 >> 3) << 4));
+ destPointer += step;
+ }
+ return 2;
+ } else
+ {
+ int w1;
+ w1 = width / 2;
+
+ if( xNibble )
+ {
+ // copy one pixel
+ PIXEL c1 = *srcPointer++;
+ c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
+ *destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF));
+ destPointer++;
+ }
+
+ while(w1--)
+ {
+ PIXEL c1 = *srcPointer;
+ PIXEL c2 = *(srcPointer + 1);
+ c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
+ c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK);
+ *destPointer++ = ~((c2 >> 3) + ((c1 >> 3) << 4));
+ srcPointer += 2;
+ }
+
+ // copy tail
+ if( (width & 1) && !xNibble )
+ {
+ PIXEL c1 = *srcPointer;
+ c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
+ *destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4));
+ }
+
+ return 1;
+ }
+}
+
+static void GAPI_UpdateRectsMono(_THIS, int numrects, SDL_Rect *rects)
+{
+ int i, height;
+ int linesProcessed;
+ int xNibble, yNibble;
+
+ for (i=0; i<numrects; i++)
+ {
+ unsigned char *destPointer;
+ unsigned char *srcPointer;
+
+ if( gapi->userOrientation == SDL_ORIENTATION_UP )
+ destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset - rects[i].y * gapi->gxProperties.cBPP / 8 + rects[i].x * gapi->dstPixelStep;
+ else
+ destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].x * gapi->gxProperties.cBPP / 8 + rects[i].y * gapi->dstLineStep;
+
+ srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * 2;
+ yNibble = rects[i].y & 1; // TODO: only for 4 bpp
+ xNibble = rects[i].x & 1;
+ height = rects[i].h;
+ while (height > 0)
+ {
+ switch(gapi->gxProperties.cBPP)
+ {
+ case 2: // TODO
+ case 4:
+ linesProcessed = updateLine16to4(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height, yNibble, xNibble);
+ yNibble = 0;
+ }
+ height -= linesProcessed;
+ if( gapi->userOrientation == SDL_ORIENTATION_UP )
+ destPointer--; // always fill 1 byte
+ else destPointer += gapi->dstLineStep;
+ srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes
+ }
+ }
+}
+
+static void GAPI_UpdateRectsColor(_THIS, int numrects, SDL_Rect *rects)
+{
+ int i, height;
+ int bytesPerPixel = (gapi->gxProperties.cBPP + 1) / 8;
+ int linesProcessed;
+ for (i=0; i<numrects; i++) {
+ unsigned char *destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].y * gapi->dstLineStep + rects[i].x * gapi->dstPixelStep;
+ unsigned char *srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * bytesPerPixel;
+ height = rects[i].h;
+
+// 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);
+// fflush(stderr);
+ linesProcessed = height;
+
+ while (height > 0) {
+ switch(bytesPerPixel)
+ {
+ case 1:
+ linesProcessed = updateLine8to8(this, srcPointer, (unsigned char *) destPointer, rects[i].w, rects[i].h, height);
+ break;
+ case 2:
+#pragma warning(disable: 4133)
+ linesProcessed = updateLine16to16(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height);
+ break;
+ }
+ height -= linesProcessed;
+ destPointer += gapi->dstLineStep * linesProcessed;
+ srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes
+ }
+// fprintf(stderr, "End of rect\n");
+// fflush(stderr);
+ }
+}
+
+
+static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
+{
+ if( gapi->needUpdate )
+ gapi->videoMem = gapi->gxFunc.GXBeginDraw();
+
+ if( gapi->gxProperties.cBPP < 8 )
+ GAPI_UpdateRectsMono(this, numrects, rects);
+ else
+ GAPI_UpdateRectsColor(this, numrects, rects);
+
+ if( gapi->needUpdate )
+ gapi->gxFunc.GXEndDraw();
+}
+
+static void FlushMessageQueue()
+{
+ MSG msg;
+ while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) {
+ if ( msg.message == WM_QUIT ) break;
+ TranslateMessage( &msg );
+ DispatchMessage( &msg );
+ }
+}
+
+
+/* Note: If we are terminated, this could be called in the middle of
+ another SDL video routine -- notably UpdateRects.
+*/
+void GAPI_VideoQuit(_THIS)
+{
+ int i, j;
+ /* Destroy the window and everything associated with it */
+ if ( SDL_Window )
+ {
+ if ((g_hGapiLib != 0) && this && this->hidden && this->hidden->gxFunc.GXCloseDisplay && !this->hidden->useVga)
+ this->hidden->gxFunc.GXCloseDisplay();
+
+ if (this->screen->pixels != NULL)
+ {
+ free(this->screen->pixels);
+ this->screen->pixels = NULL;
+ }
+ if ( screen_icn ) {
+ DestroyIcon(screen_icn);
+ screen_icn = NULL;
+ }
+
+ DIB_DestroyWindow(this);
+ SDL_UnregisterApp();
+ FlushMessageQueue();
+
+ SDL_Window = NULL;
+#if defined(_WIN32_WCE)
+
+// Unload wince aygshell library to prevent leak
+ if( aygshell )
+ {
+ FreeLibrary(aygshell);
+ aygshell = NULL;
+ }
+#endif
+
+ /* Free video mode lists */
+ for ( i=0; i<NUM_MODELISTS; ++i ) {
+ if ( gapi->SDL_modelist[i] != NULL ) {
+ for ( j=0; gapi->SDL_modelist[i][j]; ++j )
+ free(gapi->SDL_modelist[i][j]);
+ free(gapi->SDL_modelist[i]);
+ gapi->SDL_modelist[i] = NULL;
+ }
+ }
+
+ }
+
+}
+
+static void GAPI_RealizePalette(_THIS)
+{
+ OutputDebugString(TEXT("GAPI_RealizePalette NOT IMPLEMENTED !\r\n"));
+}
+
+static void GAPI_PaletteChanged(_THIS, HWND window)
+{
+ OutputDebugString(TEXT("GAPI_PaletteChanged NOT IMPLEMENTED !\r\n"));
+}
+
+/* Exported for the windows message loop only */
+static void GAPI_WinPAINT(_THIS, HDC hdc)
+{
+ OutputDebugString(TEXT("GAPI_WinPAINT NOT IMPLEMENTED !\r\n"));
+}
+
+int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
+{
+ GAPI_CreatePalette(ncolors, colors);
+ return 1;
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/gapi/SDL_gapivideo.h Thu Jan 19 08:43:00 2006 +0000
@@ -0,0 +1,164 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2004 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+#ifndef _SDL_gapivideo_h
+#define _SDL_gapivideo_h
+
+#include "SDL_mouse.h"
+#include "SDL_sysvideo.h"
+#include "SDL_mutex.h"
+
+/* From gx.h, since it's not really C compliant */
+
+struct GXDisplayProperties {
+ DWORD cxWidth;
+ DWORD cyHeight; // notice lack of 'th' in the word height.
+ long cbxPitch; // number of bytes to move right one x pixel - can be negative.
+ long cbyPitch; // number of bytes to move down one y pixel - can be negative.
+ long cBPP; // # of bits in each pixel
+ DWORD ffFormat; // format flags.
+};
+
+struct GXKeyList {
+ short vkUp; // key for up
+ POINT ptUp; // x,y position of key/button. Not on screen but in screen coordinates.
+ short vkDown;
+ POINT ptDown;
+ short vkLeft;
+ POINT ptLeft;
+ short vkRight;
+ POINT ptRight;
+ short vkA;
+ POINT ptA;
+ short vkB;
+ POINT ptB;
+ short vkC;
+ POINT ptC;
+ short vkStart;
+ POINT ptStart;
+};
+
+typedef int (*PFNGXOpenDisplay)(HWND hWnd, DWORD dwFlags);
+typedef int (*PFNGXCloseDisplay)();
+typedef void* (*PFNGXBeginDraw)();
+typedef int (*PFNGXEndDraw)();
+typedef int (*PFNGXOpenInput)();
+typedef int (*PFNGXCloseInput)();
+typedef struct GXDisplayProperties (*PFNGXGetDisplayProperties)();
+typedef struct GXKeyList (*PFNGXGetDefaultKeys)(int iOptions);
+typedef int (*PFNGXSuspend)();
+typedef int (*PFNGXResume)();
+typedef int (*PFNGXSetViewport)( DWORD dwTop, DWORD dwHeight, DWORD dwReserved1, DWORD dwReserved2 );
+typedef BOOL (*PFNGXIsDisplayDRAMBuffer)();
+
+struct GapiFunc
+{
+ PFNGXOpenDisplay GXOpenDisplay;
+ PFNGXCloseDisplay GXCloseDisplay;
+ PFNGXBeginDraw GXBeginDraw;
+ PFNGXEndDraw GXEndDraw;
+ PFNGXOpenInput GXOpenInput;
+ PFNGXCloseInput GXCloseInput;
+ PFNGXGetDisplayProperties GXGetDisplayProperties;
+ PFNGXGetDefaultKeys GXGetDefaultKeys;
+ PFNGXSuspend GXSuspend;
+ PFNGXResume GXResume;
+ PFNGXSetViewport GXSetViewport;
+ PFNGXIsDisplayDRAMBuffer GXIsDisplayDRAMBuffer;
+};
+
+#define kfLandscape 0x8 // Screen is rotated 270 degrees
+#define kfPalette 0x10 // Pixel values are indexes into a palette
+#define kfDirect 0x20 // Pixel values contain actual level information
+#define kfDirect555 0x40 // 5 bits each for red, green and blue values in a pixel.
+#define kfDirect565 0x80 // 5 red bits, 6 green bits and 5 blue bits per pixel
+#define kfDirect888 0x100 // 8 bits each for red, green and blue values in a pixel.
+#define kfDirect444 0x200 // 4 red, 4 green, 4 blue
+#define kfDirectInverted 0x400
+
+#define GX_FULLSCREEN 0x01 // for OpenDisplay()
+#define GX_NORMALKEYS 0x02
+#define GX_LANDSCAPEKEYS 0x03
+
+typedef enum
+{
+ SDL_ORIENTATION_UP,
+ SDL_ORIENTATION_DOWN,
+ SDL_ORIENTATION_LEFT,
+ SDL_ORIENTATION_RIGHT
+} SDL_ScreenOrientation;
+
+/* GAPI video mode */
+typedef enum {
+ GAPI_NONE = 0,
+ GAPI_DIRECT_565,
+ GAPI_DIRECT_555,
+ GAPI_MONO,
+ GAPI_PALETTE
+} GAPIVideoMode;
+
+/* Hidden "this" pointer for the video functions */
+#define _THIS SDL_VideoDevice *this
+
+typedef unsigned short PIXEL;
+
+/* Private display data
+ begin with DIB private structure to allow DIB events code sharing
+*/
+struct SDL_PrivateVideoData {
+ HBITMAP screen_bmp;
+ HPALETTE screen_pal;
+
+#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */
+ int SDL_nummodes[NUM_MODELISTS];
+ SDL_Rect **SDL_modelist[NUM_MODELISTS];
+ enum SDL_ScreenOrientation userOrientation;
+ int invert;
+ char hiresFix; // using hires mode without defining hires resource
+// --------------
+ int w, h;
+ enum SDL_ScreenOrientation gapiOrientation;
+
+ void *buffer; // may be 8, 16, 24, 32 bpp
+ PIXEL *videoMem;
+ BOOL needUpdate;
+ struct GXKeyList keyList;
+ struct GapiFunc gxFunc;
+ struct GXDisplayProperties gxProperties;
+ enum GAPIVideoMode videoMode;
+ int colorscale;
+ int dstLineStep; // in bytes
+ int dstPixelStep; // in bytes
+ int startOffset; // in bytes
+ int useVga;
+};
+
+
+#define gapiBuffer this->hidden->buffer
+#define gapi this->hidden
+
+#endif /* _SDL_gapivideo_h */
--- a/src/video/wincommon/SDL_lowvideo.h Thu Jan 19 08:36:41 2006 +0000
+++ b/src/video/wincommon/SDL_lowvideo.h Thu Jan 19 08:43:00 2006 +0000
@@ -40,7 +40,8 @@
SDL_VideoSurface && \
((SDL_VideoSurface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) && \
(((SDL_VideoSurface->flags & SDL_OPENGL ) == SDL_OPENGL ) || \
- (strcmp(this->name, "windib") == 0)) \
+ ((strcmp(this->name, "windib") == 0) || \
+ (strcmp(this->name, "gapi") == 0))) \
)
#define DDRAW_FULLSCREEN() \
( \
--- a/src/video/wincommon/SDL_sysevents.c Thu Jan 19 08:36:41 2006 +0000
+++ b/src/video/wincommon/SDL_sysevents.c Thu Jan 19 08:43:00 2006 +0000
@@ -47,6 +47,7 @@
#endif
#ifdef _WIN32_WCE
+#include "SDL_gapivideo.h"
#define NO_GETKEYBOARDSTATE
#define NO_CHANGEDISPLAYSETTINGS
#endif
@@ -101,6 +102,38 @@
}
}
+/* for gapi landscape mode */
+static void GapiTransform(SDL_ScreenOrientation rotate, char hires, Sint16 *x, Sint16 *y) {
+ Sint16 rotatedX;
+ Sint16 rotatedY;
+
+ if (hires) {
+ *x = *x * 2;
+ *y = *y * 2;
+ }
+
+ switch(rotate) {
+ case SDL_ORIENTATION_UP:
+ break;
+ case SDL_ORIENTATION_RIGHT:
+ if (!SDL_VideoSurface)
+ break;
+ rotatedX = SDL_VideoSurface->w - *y;
+ rotatedY = *x;
+ *x = rotatedX;
+ *y = rotatedY;
+ break;
+ case SDL_ORIENTATION_LEFT:
+ if (!SDL_VideoSurface)
+ break;
+ rotatedX = *y;
+ rotatedY = SDL_VideoSurface->h - *x;
+ *x = rotatedX;
+ *y = rotatedY;
+ break;
+ }
+}
+
#endif
static void SDL_RestoreGameMode(void)
@@ -319,6 +352,10 @@
posted = SDL_PrivateMouseMotion(0, 1, x, y);
}
} else {
+#ifdef _WIN32_WCE
+ if (SDL_VideoSurface)
+ GapiTransform(this->hidden->userOrientation, this->hidden->hiresFix, &x, &y);
+#endif
posted = SDL_PrivateMouseMotion(0, 0, x, y);
}
}
@@ -407,6 +444,10 @@
} else {
x = (Sint16)LOWORD(lParam);
y = (Sint16)HIWORD(lParam);
+#ifdef _WIN32_WCE
+ if (SDL_VideoSurface)
+ GapiTransform(this->hidden->userOrientation, this->hidden->hiresFix, &x, &y);
+#endif
}
posted = SDL_PrivateMouseButton(
state, button, x, y);
--- a/src/video/wincommon/SDL_sysmouse.c Thu Jan 19 08:36:41 2006 +0000
+++ b/src/video/wincommon/SDL_sysmouse.c Thu Jan 19 08:43:00 2006 +0000
@@ -251,6 +251,7 @@
/* Check to see if we need to enter or leave mouse relative mode */
void WIN_CheckMouseMode(_THIS)
{
+#ifndef _WIN32_WCE
/* If the mouse is hidden and input is grabbed, we use relative mode */
if ( !(SDL_cursorstate & CURSOR_VISIBLE) &&
(this->input_grab != SDL_GRAB_OFF) ) {
@@ -258,4 +259,7 @@
} else {
mouse_relative = 0;
}
+#else
+ mouse_relative = 0;
+#endif
}
--- a/src/video/windib/SDL_dibevents.c Thu Jan 19 08:36:41 2006 +0000
+++ b/src/video/windib/SDL_dibevents.c Thu Jan 19 08:43:00 2006 +0000
@@ -59,6 +59,31 @@
and give him a chance to handle some messages. */
static WNDPROC userWindowProc = NULL;
+
+#ifdef _WIN32_WCE
+
+WPARAM rotateKey(WPARAM key,SDL_ScreenOrientation direction)
+{
+ if (direction != SDL_ORIENTATION_LEFT)
+ return key;
+
+ switch (key) {
+ case 0x26: /* up */
+ return 0x27;
+ case 0x27: /* right */
+ return 0x28;
+ case 0x28: /* down */
+ return 0x25;
+ case 0x25: /* left */
+ return 0x26;
+ }
+
+ return key;
+}
+
+#endif
+
+
/* The main Win32 event handler */
LONG
DIB_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
@@ -70,6 +95,15 @@
case WM_KEYDOWN: {
SDL_keysym keysym;
+#ifdef _WIN32_WCE
+ // Drop GAPI artefacts
+ if (wParam == 0x84 || wParam == 0x5B)
+ return 0;
+
+ // Rotate key if necessary
+ if (this->hidden->orientation != SDL_ORIENTATION_UP)
+ wParam = rotateKey(wParam, this->hidden->orientation);
+#endif
/* Ignore repeated keys */
if ( lParam&REPEATED_KEYMASK ) {
return(0);
@@ -127,6 +161,16 @@
case WM_KEYUP: {
SDL_keysym keysym;
+#ifdef _WIN32_WCE
+ // Drop GAPI artefacts
+ if (wParam == 0x84 || wParam == 0x5B)
+ return 0;
+
+ // Rotate key if necessary
+ if (this->hidden->orientation != SDL_ORIENTATION_UP)
+ wParam = rotateKey(wParam, this->hidden->orientation);
+#endif
+
switch (wParam) {
case VK_CONTROL:
if ( lParam&EXTENDED_KEYMASK )
--- a/src/video/windib/SDL_dibvideo.c Thu Jan 19 08:36:41 2006 +0000
+++ b/src/video/windib/SDL_dibvideo.c Thu Jan 19 08:43:00 2006 +0000
@@ -768,14 +768,15 @@
ReleaseDC(SDL_Window, hdc);
}
+
int DIB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
{
RGBQUAD *pal;
int i;
-#ifndef _WIN32_WCE
+#if (_WIN32_WCE < 400 )
+ HDC hdc;
+#else
HDC hdc, mdc;
-#else
- HDC hdc;
#endif
/* Update the display palette */
@@ -805,7 +806,7 @@
}
/* Set the DIB palette and update the display */
-#ifndef _WIN32_WCE
+#if ( _WIN32_WCE >= 400 )
mdc = CreateCompatibleDC(hdc);
SelectObject(mdc, screen_bmp);
SetDIBColorTable(mdc, firstcolor, ncolors, pal);
@@ -817,6 +818,7 @@
return(1);
}
+
static void DIB_CheckGamma(_THIS)
{
#ifndef NO_GAMMA_SUPPORT
--- a/src/video/windib/SDL_dibvideo.h Thu Jan 19 08:36:41 2006 +0000
+++ b/src/video/windib/SDL_dibvideo.h Thu Jan 19 08:43:00 2006 +0000
@@ -30,6 +30,15 @@
#include <windows.h>
+/* for PDA */
+typedef enum
+{
+ SDL_ORIENTATION_UP,
+ SDL_ORIENTATION_DOWN,
+ SDL_ORIENTATION_LEFT,
+ SDL_ORIENTATION_RIGHT
+} SDL_ScreenOrientation;
+
/* Private display data */
struct SDL_PrivateVideoData {
HBITMAP screen_bmp;
@@ -38,6 +47,10 @@
#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */
int SDL_nummodes[NUM_MODELISTS];
SDL_Rect **SDL_modelist[NUM_MODELISTS];
+
+ SDL_ScreenOrientation orientation;
+ int invert;
+ char hiresFix; // using hires mode without defining hires resource
};
/* Old variable names */
#define screen_bmp (this->hidden->screen_bmp)