Index: trunk/src/ddraw/OS2CLIPPER.CPP
===================================================================
--- trunk/src/ddraw/OS2CLIPPER.CPP	(revision 208)
+++ trunk/src/ddraw/OS2CLIPPER.CPP	(revision 210)
@@ -1,64 +1,32 @@
-/* $Id: OS2CLIPPER.CPP,v 1.3 1999-06-10 17:10:56 phaller Exp $ */
-
-/*
- * DirectDraw Clipper Class
- *
- * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
- *
- * Project Odin Software License can be found in LICENSE.TXT
- *
- */
-
-/*@Const************************************************************************
-*   Defined Constants                                                          *
-*******************************************************************************/
-#define INCL_GUID
-#define WIN32SDK_NOPOSTWRAPPER
-
-/*@Header***********************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#include <os2win.h>
-#include <dive.h>
-
 #include <memory.h>
 
-#include "no.h"
-#include <w_windows.h>
-#include <ddraw.h>
-#include <d3d.h>
-#include <Win32SDKPostWrapper.h>
-
+#define INITGUID
 #include "os2ddraw.h"
 #include "os2clipper.h"
+#define _OS2WIN_H
+#define FAR
 #include "misc.h"
-
-/*** IDirect3D methods ***/
-/* KSO Apr 19 1999: Set correct interface.           *
- * (INTERFACE is used in the THIS and THIS_ macros)  */
-#undef  INTERFACE
-#define INTERFACE   IDirectDrawClipper
-
+#include <winerror.h>
 
 //******************************************************************************
 //******************************************************************************
 OS2IDirectDrawClipper::OS2IDirectDrawClipper(OS2IDirectDraw *lpDirectDraw) :
-                           Referenced(0), lastError(DD_OK),
-                           clipWindow(0)
+                 Referenced(0), lastError(DD_OK),
+                 clipWindow(0)
 {
-  lpVtbl                    = &Vtbl;
-  Vtbl.AddRef               = ClipAddRef;
-  Vtbl.Release              = ClipRelease;
-  Vtbl.QueryInterface       = ClipQueryInterface;
-  Vtbl.GetClipList          = ClipGetClipList;
-  Vtbl.GetHWnd              = ClipGetHWnd;
-  Vtbl.Initialize           = ClipInitialize;
-  Vtbl.IsClipListChanged    = ClipIsClipListChanged;
-  Vtbl.SetClipList          = ClipSetClipList;
-  Vtbl.SetHWnd              = ClipSetHWnd;
+  lpVtbl                  = &Vtbl;
+  Vtbl.AddRef             = ClipAddRef;
+  Vtbl.Release            = ClipRelease;
+  Vtbl.QueryInterface     = ClipQueryInterface;
+  Vtbl.GetClipList        = ClipGetClipList;
+  Vtbl.GetHWnd            = ClipGetHWnd;
+  Vtbl.Initialize         = ClipInitialize;
+  Vtbl.IsClipListChanged  = ClipIsClipListChanged;
+  Vtbl.SetClipList        = ClipSetClipList;
+  Vtbl.SetHWnd            = ClipSetHWnd;
 
-  lpDraw                        = lpDirectDraw;
-  lpDraw->Vtbl.AddRef((IDirectDraw2*)lpDraw);
-  hDive                         = lpDirectDraw->GetDiveInstance();
+  lpDraw                  = lpDirectDraw;
+  lpDraw->Vtbl.AddRef(lpDraw);
+  hDive                   = lpDirectDraw->GetDiveInstance();
 }
 //******************************************************************************
@@ -66,11 +34,14 @@
 OS2IDirectDrawClipper::~OS2IDirectDrawClipper()
 {
-  lpDraw->Vtbl.Release((IDirectDraw2*)lpDraw);
+  lpDraw->Vtbl.Release(lpDraw);
 }
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall ClipQueryInterface(THIS_ REFIID riid, LPVOID FAR * ppvObj)
+HRESULT __stdcall ClipQueryInterface(THIS This, REFIID riid, LPVOID FAR * ppvObj)
 {
-  dprintf(("ClipQueryInterface\n"));
+  #ifdef DEBUG
+    WriteLog("ClipQueryInterface\n");
+  #endif
+
   *ppvObj = NULL;
 
@@ -78,5 +49,5 @@
      !IsEqualGUID(riid, CLSID_DirectDrawClipper))
 //&& !IsEqualGUID(riid, IID_IUnknown))
-    return E_NOINTERFACE;
+  return E_NOINTERFACE;
 
   *ppvObj = This;
@@ -87,42 +58,58 @@
 //******************************************************************************
 //******************************************************************************
-ULONG   __stdcall ClipAddRef(THIS)
+ULONG   __stdcall ClipAddRef(THIS This)
 {
  OS2IDirectDrawClipper *me = (OS2IDirectDrawClipper *)This;
 
-  dprintf(("OS2IDirectDrawClipper::AddRef %d\n", me->Referenced+1));
+  #ifdef DEBUG
+    WriteLog("OS2IDirectDrawClipper::AddRef %d\n", me->Referenced+1);
+  #endif
+
   return ++me->Referenced;
 }
 //******************************************************************************
 //******************************************************************************
-ULONG   __stdcall ClipRelease(THIS)
+ULONG   __stdcall ClipRelease(THIS This)
 {
  OS2IDirectDrawClipper *me = (OS2IDirectDrawClipper *)This;
 
-  dprintf(("OS2IDirectDrawClipper::Release %d\n", me->Referenced-1));
-  if(me->Referenced) {
+  #ifdef DEBUG
+    WriteLog("OS2IDirectDrawClipper::Release %d\n", me->Referenced-1);
+  #endif
+
+  if(me->Referenced)
+  {
     me->Referenced--;
-    if(me->Referenced == 0) {
-        delete me;
-        return(0);
+    if(me->Referenced == 0)
+    {
+      delete me;
+      return(0);
     }
-    else    return me->Referenced;
+    else
+      return me->Referenced;
   }
-  else  return(0);
+  else
+   return(0);
 }
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall ClipGetClipList(THIS_ W32_LPRECT, W32_LPRGNDATA, LPDWORD)
+HRESULT __stdcall ClipGetClipList(THIS, LPRECT, LPRGNDATA, LPDWORD)
 {
-  dprintf(("ClipGetClipList\n"));
+  #ifdef DEBUG
+    WriteLog("ClipGetClipList\n");
+  #endif
+
   return(DD_OK);
 }
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall ClipGetHWnd(THIS_ W32_HWND FAR *pHwnd)
+HRESULT __stdcall ClipGetHWnd(THIS This, HWND FAR *pHwnd)
 {
  OS2IDirectDrawClipper *me = (OS2IDirectDrawClipper *)This;
 
-  dprintf(("ClipGetHWnd\n"));
+  #ifdef DEBUG
+    WriteLog("ClipGetHWnd\n");
+  #endif
+
   *pHwnd = me->clipWindow;
   return(DD_OK);
@@ -130,21 +117,30 @@
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall ClipInitialize(THIS_ LPDIRECTDRAW, DWORD)
+HRESULT __stdcall ClipInitialize(THIS, LPDIRECTDRAW, DWORD)
 {
-  dprintf(("ClipInitialize\n"));
+  #ifdef DEBUG
+    WriteLog("ClipInitialize\n");
+  #endif
+
+  return(DDERR_ALREADYINITIALIZED); // Init is done during creation see M$ Doc
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall ClipIsClipListChanged(THIS, BOOL FAR *)
+{
+  #ifdef DEBUG
+    WriteLog("ClipIsClipListChanged\n");
+  #endif
+
   return(DD_OK);
 }
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall ClipIsClipListChanged(THIS_ BOOL FAR *)
+HRESULT __stdcall ClipSetClipList(THIS, LPRGNDATA,DWORD)
 {
-  dprintf(("ClipIsClipListChanged\n"));
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall ClipSetClipList(THIS_ W32_LPRGNDATA,DWORD)
-{
-  dprintf(("ClipSetClipList\n"));
+  #ifdef DEBUG
+    WriteLog("ClipSetClipList\n");
+  #endif
+
   return(DD_OK);
 }
@@ -152,9 +148,12 @@
 //DWORD param not used in DirectX 3
 //******************************************************************************
-HRESULT __stdcall ClipSetHWnd(THIS_ DWORD reserved, W32_HWND hwnd)
+HRESULT __stdcall ClipSetHWnd(THIS This, DWORD reserved, HWND hwnd)
 {
  OS2IDirectDrawClipper *me = (OS2IDirectDrawClipper *)This;
 
-  dprintf(("ClipSetHWnd\n"));
+  #ifdef DEBUG
+    WriteLog("ClipSetHWnd\n");
+  #endif
+
   me->clipWindow = hwnd;
   return(DD_OK);
Index: trunk/src/ddraw/OS2D3D.CPP
===================================================================
--- trunk/src/ddraw/OS2D3D.CPP	(revision 208)
+++ trunk/src/ddraw/OS2D3D.CPP	(revision 210)
@@ -1,51 +1,20 @@
-/* $Id: OS2D3D.CPP,v 1.3 1999-06-10 17:10:56 phaller Exp $ */
-
-//******************************************************************************
-//******************************************************************************
-// Direct3D Main Class
-//
-// Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
-//******************************************************************************
-//******************************************************************************
-// *
-// * Project Odin Software License can be found in LICENSE.TXT
-// *
-
-/*@Const************************************************************************
-*   Defined Constants                                                          *
-*******************************************************************************/
-#define WIN32SDK_NOPOSTWRAPPER
-
-/*@Header***********************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#include <os2win.h>
-#include <dive.h>
-
-#include <builtin.h>
 #include <memory.h>
 
-#include "no.h"
-#include <w_windows.h>
-#include <ddraw.h>
-#include <d3d.h>
-#include <Win32SDKPostWrapper.h>
-
+#define INITGUID
 #include "os2ddraw.h"
 #include "os2clipper.h"
 #include "os2palette.h"
 #include "os2surface.h"
+#define _OS2WIN_H
+#define FAR
 #include "misc.h"
-
-/*** IDirect3D methods ***/
-/* KSO Apr 19 1999: Set correct interface.           *
- * (INTERFACE is used in the THIS and THIS_ macros)  */
-#undef  INTERFACE
-#define INTERFACE   IDirect3D
-
+#include <winerror.h>
+#include <builtin.h>
+#undef THIS
+#define THIS VOID*
 
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall D3DQueryInterface(THIS, REFIID riid, LPVOID FAR * ppvObj)
+HRESULT __stdcall D3DQueryInterface(THIS This, REFIID riid, LPVOID FAR * ppvObj)
 {
   dprintf(("D3DQueryInterface\n"));
@@ -53,5 +22,5 @@
 
   if(IID_IDirect3D != (GUID &)&riid)
-    return E_NOINTERFACE;
+  return E_NOINTERFACE;
 
   *ppvObj = This;
@@ -62,5 +31,5 @@
 //******************************************************************************
 //******************************************************************************
-ULONG __stdcall D3DAddRef(THIS)
+ULONG __stdcall D3DAddRef(THIS This)
 {
  OS2IDirectDraw *me = (OS2IDirectDraw *)This;
@@ -71,5 +40,5 @@
 //******************************************************************************
 //******************************************************************************
-ULONG __stdcall D3DRelease(THIS)
+ULONG __stdcall D3DRelease(THIS This)
 {
  OS2IDirectDraw *me = (OS2IDirectDraw *)This;
@@ -78,10 +47,10 @@
   dprintf(("OS2IDirectDraw::%X \n", me));
   if(me->Referenced) {
-    me->Referenced--;
-    if(me->Referenced == 0) {
-        delete me;
-        return(0);
-    }
-    else    return me->Referenced;
+  me->Referenced--;
+  if(me->Referenced == 0) {
+    delete me;
+    return(0);
+  }
+  else    return me->Referenced;
   }
   else  return(0);
@@ -89,5 +58,5 @@
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall D3DInitialize(THIS_ REFIID)
+HRESULT __stdcall D3DInitialize(THIS This, REFIID)
 {
   dprintf(("D3DInitialize\n"));
@@ -96,5 +65,5 @@
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall D3DEnumDevices(THIS_ LPD3DENUMDEVICESCALLBACK, LPVOID)
+HRESULT __stdcall D3DEnumDevices(THIS This, LPD3DENUMDEVICESCALLBACK, LPVOID)
 {
   dprintf(("D3DEnumDevices\n"));
@@ -103,5 +72,5 @@
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall D3DCreateLight(THIS_ LPDIRECT3DLIGHT*, IUnknown*)
+HRESULT __stdcall D3DCreateLight(THIS This, LPDIRECT3DLIGHT*, IUnknown*)
 {
   dprintf(("D3DCreateLight\n"));
@@ -110,5 +79,5 @@
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall D3DCreateMaterial(THIS_ LPDIRECT3DMATERIAL*, IUnknown*)
+HRESULT __stdcall D3DCreateMaterial(THIS This, LPDIRECT3DMATERIAL*, IUnknown*)
 {
   dprintf(("D3DCreateMaterial\n"));
@@ -117,5 +86,5 @@
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall D3DCreateViewport(THIS_ LPDIRECT3DVIEWPORT*, IUnknown*)
+HRESULT __stdcall D3DCreateViewport(THIS This, LPDIRECT3DVIEWPORT*, IUnknown*)
 {
   dprintf(("D3DCreateViewport\n"));
@@ -124,5 +93,5 @@
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall D3DFindDevice(THIS_ LPD3DFINDDEVICESEARCH, LPD3DFINDDEVICERESULT)
+HRESULT __stdcall D3DFindDevice(THIS This, LPD3DFINDDEVICESEARCH, LPD3DFINDDEVICERESULT)
 {
   dprintf(("D3DCreateFindDevice\n"));
Index: trunk/src/ddraw/OS2DDRAW.CPP
===================================================================
--- trunk/src/ddraw/OS2DDRAW.CPP	(revision 208)
+++ trunk/src/ddraw/OS2DDRAW.CPP	(revision 210)
@@ -1,114 +1,150 @@
-/* $Id: OS2DDRAW.CPP,v 1.3 1999-06-10 17:10:56 phaller Exp $ */
-
-/*
- * DirectDraw main class
- *
- * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
- *
- * Project Odin Software License can be found in LICENSE.TXT
- *
- */
-/*@Const************************************************************************
-*   Defined Constants                                                          *
-*******************************************************************************/
-#define WIN32SDK_NOPOSTWRAPPER
-
-/*@Header***********************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#include <os2win.h>
-#include <dive.h>
-
 #include <memory.h>
-#include <builtin.h>
-
-#include "no.h"
-#include <w_windows.h>
-#include <ddraw.h>
-#include <d3d.h>
-#include <Win32SDKPostWrapper.h>
-
-#include <fourcc.h>
-
+
+#define INITGUID
 #include "os2ddraw.h"
 #include "os2clipper.h"
 #include "os2palette.h"
 #include "os2surface.h"
+#define _OS2WIN_H
+#define FAR
 #include "misc.h"
-#include "os2util.h"
-
-
-/* KSO Apr 19 1999: Set correct interface.           *
- * (INTERFACE is used in the THIS and THIS_ macros)  */
-#undef  INTERFACE
-#define INTERFACE   IDirectDraw2
-
-
-
-DIVE_CAPS dcaps           = {0};
-FOURCC    fccFormats[100] = {0};        /* Color format code                 */
-
-
+#include <winreg.h>
+#include <winuser.h>
+#include <winerror.h>
+#include <builtin.h>
+#include "cio2.h"
+
+// include with the videomodes we support
+// better would be to get these modes from the card
+// But for now we use standard VESA 2.0 modes with 70Hz
+#include "os2ddrawmodes.h"
+#include "os2DDWindow.h"
+
+#define KEY_DIRECT2 "\\Software\\Win32OS2\\Direct2"
+#define KEY_DIRECT2DRAW "\\Software\\Win32OS2\\Direct2\\Draw"
+
+FOURCC  SupportedFourCCs[] = {FOURCC_LUT8,FOURCC_R565,FOURCC_RGB3,FOURCC_RGB4};
 //******************************************************************************
 //******************************************************************************
 OS2IDirectDraw::OS2IDirectDraw(GUID *lpGUID) :
-       Referenced(0), lastError(DD_OK),
-       pFrameBuffer(NULL), hwndClient(0), screenwidth(640),
-       screenheight(480), screenbpp(8), fFullScreen(TRUE)
-{
-  if(lpGUID && *lpGUID == IID_IDirect3D) {
-      lpVtbl = (IDirectDraw2Vtbl *)&Vtbl3D;
-      Vtbl3D.AddRef             = D3DAddRef;
-      Vtbl3D.Release            = D3DRelease;
-      Vtbl3D.QueryInterface     = D3DQueryInterface;
-      Vtbl3D.Initialize         = D3DInitialize;
-      Vtbl3D.EnumDevices        = D3DEnumDevices;
-      Vtbl3D.CreateLight        = D3DCreateLight;
-      Vtbl3D.CreateMaterial     = D3DCreateMaterial;
-      Vtbl3D.CreateViewport     = D3DCreateViewport;
-      Vtbl3D.FindDevice         = D3DFindDevice;
-  }
-  else {
-      lpVtbl = &Vtbl;
-      Vtbl.AddRef                   = DrawAddRef;
-      Vtbl.Release                  = DrawRelease;
-      Vtbl.QueryInterface           = DrawQueryInterface;
-      Vtbl.Compact                  = DrawCompact;
-      Vtbl.CreateClipper            = DrawCreateClipper;
-      Vtbl.W32_CreatePalette        = DrawCreatePalette; //KSO Apr 19 1999: Sideeffect of the wrapping...
-      Vtbl.CreateSurface            = DrawCreateSurface;
-      Vtbl.DuplicateSurface         = DrawDuplicateSurface;
-      Vtbl.EnumDisplayModes         = DrawEnumDisplayModes;
-      Vtbl.EnumSurfaces             = DrawEnumSurfaces;
-      Vtbl.FlipToGDISurface         = DrawFlipToGDISurface;
-      Vtbl.GetCaps                  = DrawGetCaps;
-      Vtbl.GetDisplayMode           = DrawGetDisplayMode;
-      Vtbl.GetFourCCCodes           = DrawGetFourCCCodes;
-      Vtbl.GetGDISurface            = DrawGetGDISurface;
-      Vtbl.GetMonitorFrequency      = DrawGetMonitorFrequency;
-      Vtbl.GetScanLine              = DrawGetScanLine;
-      Vtbl.GetVerticalBlankStatus   = DrawGetVerticalBlankStatus;
-      Vtbl.Initialize               = DrawInitialize;
-      Vtbl.RestoreDisplayMode       = DrawRestoreDisplayMode;
-      Vtbl.SetCooperativeLevel      = DrawSetCooperativeLevel;
-
-      if(lpGUID && *lpGUID == IID_IDirectDraw2)
-            *(ULONG *)&Vtbl.SetDisplayMode  = (ULONG)DrawSetDisplayMode2;
-      else  *(ULONG *)&Vtbl.SetDisplayMode  = (ULONG)DrawSetDisplayMode;
-
-      Vtbl.WaitForVerticalBlank = DrawWaitForVerticalBlank;
-      Vtbl.GetAvailableVidMem   = DrawGetAvailableVidMem;
+     Referenced(0), lastError(DD_OK),
+     pFrameBuffer(NULL), hwndClient(0), screenwidth(640),
+     screenheight(480), screenbpp(8),PrimaryExists(false)
+
+{
+  HKEY  hkDirectDraw2;
+  DWORD dwVSize, dwVType;
+
+  // Setup table for 3d devices
+  Vtbl3D.AddRef         = D3DAddRef;
+  Vtbl3D.Release        = D3DRelease;
+  Vtbl3D.QueryInterface = D3DQueryInterface;
+  Vtbl3D.Initialize     = D3DInitialize;
+  Vtbl3D.EnumDevices    = D3DEnumDevices;
+  Vtbl3D.CreateLight    = D3DCreateLight;
+  Vtbl3D.CreateMaterial = D3DCreateMaterial;
+  Vtbl3D.CreateViewport = D3DCreateViewport;
+  Vtbl3D.FindDevice     = D3DFindDevice;
+
+  // old V2 Interface
+  Vtbl.AddRef                 = DrawAddRef;
+  Vtbl.Release                = DrawRelease;
+  Vtbl.QueryInterface         = DrawQueryInterface;
+  Vtbl.Compact                = DrawCompact;
+  Vtbl.CreateClipper          = DrawCreateClipper;
+  Vtbl.CreatePalette          = DrawCreatePalette;
+  Vtbl.CreateSurface          = DrawCreateSurface;
+  Vtbl.DuplicateSurface       = DrawDuplicateSurface;
+  Vtbl.EnumDisplayModes       = DrawEnumDisplayModes;
+  Vtbl.EnumSurfaces           = DrawEnumSurfaces;
+  Vtbl.FlipToGDISurface       = DrawFlipToGDISurface;
+  Vtbl.GetCaps                = DrawGetCaps;
+  Vtbl.GetDisplayMode         = DrawGetDisplayMode;
+  Vtbl.GetFourCCCodes         = DrawGetFourCCCodes;
+  Vtbl.GetGDISurface          = DrawGetGDISurface;
+  Vtbl.GetMonitorFrequency    = DrawGetMonitorFrequency;
+  Vtbl.GetScanLine            = DrawGetScanLine;
+  Vtbl.GetVerticalBlankStatus = DrawGetVerticalBlankStatus;
+  Vtbl.Initialize             = DrawInitialize;
+  Vtbl.RestoreDisplayMode     = DrawRestoreDisplayMode;
+  Vtbl.SetCooperativeLevel    = DrawSetCooperativeLevel;
+  if(lpGUID && *lpGUID == IID_IDirectDraw2)
+    *(ULONG *)&Vtbl.SetDisplayMode = (ULONG)DrawSetDisplayMode2;
+  else
+    *(ULONG *)&Vtbl.SetDisplayMode = (ULONG)DrawSetDisplayMode;
+  Vtbl.WaitForVerticalBlank   = DrawWaitForVerticalBlank;
+  Vtbl.GetAvailableVidMem     = DrawGetAvailableVidMem;
+
+  // New V4 interface
+  Vtbl4.AddRef                 = DrawAddRef;   // todo change to a DrawAddRef4 as handling this has changed
+  Vtbl4.Release                = DrawRelease;  // see above
+  Vtbl4.QueryInterface         = DrawQueryInterface;
+  Vtbl4.Compact                = DrawCompact;
+  Vtbl4.CreateClipper          = DrawCreateClipper;
+  Vtbl4.CreateSurface          = DrawCreateSurface4;//
+  Vtbl4.DuplicateSurface       = DrawDuplicateSurface4;//
+  Vtbl4.EnumDisplayModes       = DrawEnumDisplayModes4;//
+  Vtbl4.EnumSurfaces           = DrawEnumSurfaces4; //
+  Vtbl4.FlipToGDISurface       = DrawFlipToGDISurface;
+  Vtbl4.GetCaps                = DrawGetCaps;
+  Vtbl4.GetDisplayMode         = DrawGetDisplayMode4;//
+  Vtbl4.GetFourCCCodes         = DrawGetFourCCCodes;
+  Vtbl4.GetGDISurface          = DrawGetGDISurface4;//
+  Vtbl4.GetMonitorFrequency    = DrawGetMonitorFrequency;
+  Vtbl4.GetScanLine            = DrawGetScanLine;
+  Vtbl4.GetVerticalBlankStatus = DrawGetVerticalBlankStatus;
+  Vtbl4.Initialize             = DrawInitialize;
+  Vtbl4.RestoreDisplayMode     = DrawRestoreDisplayMode;
+  Vtbl4.SetCooperativeLevel    = DrawSetCooperativeLevel;
+  Vtbl4.SetDisplayMode         = DrawSetDisplayMode2;
+  Vtbl4.WaitForVerticalBlank   = DrawWaitForVerticalBlank;
+  Vtbl4.GetAvailableVidMem     = DrawGetAvailableVidMem4;
+  Vtbl4.GetSurfaceFromDC       = DrawGetSurfaceFromDC;
+  Vtbl4.RestoreAllSurfaces     = DrawRestoreAllSurfaces;
+  Vtbl4.TestCooperativeLevel   = DrawTestCooperativeLevel;
+  Vtbl4.GetDeviceIdentifier    = DrawGetDeviceIdentifier;
+
+  if(lpGUID && *lpGUID == IID_IDirect3D)
+  {
+    WriteLog("D3D Interface\n");
+
+    lpVtbl = (IDirectDraw4Vtbl *)&Vtbl3D;
+  }
+  else
+  {
+    if(lpGUID && *lpGUID == IID_IDirectDraw4)
+    {
+      WriteLog("V4 Interface\n");
+      lpVtbl = &Vtbl4;
+    }
+    else
+    {
+      WriteLog("<V4 Interface\n");
+      lpVtbl = (IDirectDraw4Vtbl *) &Vtbl;
+    }
   }
 
   ULONG rc = DiveOpen(&hDive, FALSE, &pFrameBuffer);
-  if(rc) {
-    dprintf(("ERROR: DiveOpen returned %d\n", rc));
+  if(rc)
+  {
+    WriteLog("ERROR: DiveOpen returned %d\n", rc);
     lastError = DDERR_GENERIC;
     hDive     = NULL;
   }
-  dcaps.pFormatData    = fccFormats;
-  dcaps.ulFormatLength = sizeof(fccFormats);
-  dcaps.ulStructLen    = sizeof(dcaps);
-  DiveQueryCaps(&dcaps, DIVE_BUFFER_SCREEN);
+  else
+  {
+    rc = DiveQueryCaps(&dCaps,DIVE_BUFFER_SCREEN);
+  }
+
+  // Shall we run in FS mode ?
+  if(ERROR_SUCCESS==RegOpenKeyA(HKEY_LOCAL_MACHINE,KEY_DIRECT2DRAW,&hkDirectDraw2))
+  {
+    dwVSize = 4;
+    dwVType = REG_DWORD;
+    if(ERROR_SUCCESS!=RegQueryValueExA(hkDirectDraw2,"Fullscreen",NULL,&dwVType,(LPBYTE)&bScale,&dwVSize))
+      bScale = FALSE;
+  }
+  else
+    bScale = FALSE;
 }
 //******************************************************************************
@@ -117,23 +153,44 @@
 {
   dprintf(("OS2IDirectDraw::~OS2IDirectDraw()\n"));
-  if(hDive) DiveClose(hDive);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall DrawQueryInterface(THIS, REFIID riid, LPVOID FAR * ppvObj)
-{
-#ifdef DEBUG
-  WriteLog("OS2IDirectDraw::QueryInterface\n");
-#endif
+  if(hDive)
+    DiveClose(hDive);
+}
+//******************************************************************************
+//******************************************************************************
+FOURCC OS2IDirectDraw::GetScreenFourCC()
+{
+  return SupportedFourCCs[screenbpp>>3];
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawQueryInterface(THIS This, REFIID riid, LPVOID FAR * ppvObj)
+{
+ OS2IDirectDraw *me = (OS2IDirectDraw *)This;
+  #ifdef DEBUG
+    WriteLog("OS2IDirectDraw::QueryInterface\n");
+  #endif
+
   *ppvObj = NULL;
 
   if(!IsEqualGUID(riid, CLSID_DirectDraw) &&
      !IsEqualGUID(riid, IID_IDirectDraw) &&
-     !IsEqualGUID(riid, IID_IDirectDraw2))
+     !IsEqualGUID(riid, IID_IDirectDraw2) &&
+     !IsEqualGUID(riid, IID_IDirectDraw4))
 //&& !IsEqualGUID(riid, IID_IUnknown))
-    return E_NOINTERFACE;
-
+  return E_NOINTERFACE;
+
+  // ToDo Better way of returning differnent intterfaces for same class
+
+  if(IsEqualGUID(riid, IID_IDirectDraw4))
+  {
+    WriteLog("IID_IDirectDraw4 Interface\n");
+    me->lpVtbl = &me->Vtbl4;
+  }
+  else
+  {
+    WriteLog("No IID_IDirectDraw4 Interface\n");
+    me->lpVtbl = (IDirectDraw4Vtbl *) &me->Vtbl;
+  }
   *ppvObj = This;
-
   DrawAddRef(This);
   return(DD_OK);
@@ -141,32 +198,39 @@
 //******************************************************************************
 //******************************************************************************
-ULONG __stdcall DrawAddRef(THIS)
+ULONG __stdcall DrawAddRef(THIS This)
 {
  OS2IDirectDraw *me = (OS2IDirectDraw *)This;
 
-#ifdef DEBUG
-  WriteLog("OS2IDirectDraw::AddRef %d\n", me->Referenced+1);
-#endif
+  #ifdef DEBUG
+    WriteLog("OS2IDirectDraw::AddRef %d\n", me->Referenced+1);
+  #endif
+
   return ++me->Referenced;
 }
 //******************************************************************************
 //******************************************************************************
-ULONG __stdcall DrawRelease(THIS)
+ULONG __stdcall DrawRelease(THIS This)
 {
  OS2IDirectDraw *me = (OS2IDirectDraw *)This;
 
-#ifdef DEBUG
-  WriteLog("OS2IDirectDraw::Release %d\n", me->Referenced-1);
-  WriteLog("OS2IDirectDraw::%X \n", me);
-#endif
-  if(me->Referenced) {
-        me->Referenced--;
-        if(me->Referenced == 0) {
-            delete me;
-            return(0);
-        }
-        else    return me->Referenced;
-  }
-  else  return(0);
+  #ifdef DEBUG
+    WriteLog("OS2IDirectDraw::Release %d\n", me->Referenced-1);
+    WriteLog("OS2IDirectDraw::%X \n", me);
+  #endif
+
+  if(me->Referenced)
+  {
+
+    me->Referenced--;
+    if(me->Referenced == 0)
+    {
+      delete me;
+      return(0);
+    }
+    else
+      return me->Referenced;
+  }
+  else
+    return(0);
 }
 //******************************************************************************
@@ -174,12 +238,13 @@
 HRESULT __stdcall DrawCompact(THIS)
 {
-#ifdef DEBUG
-  WriteLog("Compact\n");
-#endif
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall DrawCreateClipper(THIS, DWORD, LPDIRECTDRAWCLIPPER FAR *lplpDD, IUnknown FAR * )
+  #ifdef DEBUG
+    WriteLog("Compact\n");
+  #endif
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawCreateClipper(THIS This, DWORD, LPDIRECTDRAWCLIPPER FAR *lplpDD, IUnknown FAR * )
 {
  OS2IDirectDraw        *me = (OS2IDirectDraw *)This;
@@ -187,16 +252,20 @@
  HRESULT                rc;
 
-#ifdef DEBUG
-  WriteLog("CreateClipper\n");
-#endif
-  if(newclip == NULL)   return(DDERR_OUTOFMEMORY);
+  #ifdef DEBUG
+    WriteLog("CreateClipper\n");
+  #endif
+
+  if(newclip == NULL)
+    return(DDERR_OUTOFMEMORY);
 
   newclip->Vtbl.AddRef((IDirectDrawClipper *)newclip);
   rc = newclip->GetLastError();
-  if(rc != DD_OK) {
-        *lplpDD = NULL;
-        delete newclip;
-  }
-  else  *lplpDD = (IDirectDrawClipper *)newclip;
+  if(rc != DD_OK)
+  {
+    *lplpDD = NULL;
+    delete newclip;
+  }
+  else
+    *lplpDD = (IDirectDrawClipper *)newclip;
 
   return(rc);
@@ -204,36 +273,50 @@
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall DrawCreatePalette(THIS, DWORD dwFlags,
-                    W32_LPPALETTEENTRY lpColorTable,
-                    LPDIRECTDRAWPALETTE FAR *lplpDD,
-                    IUnknown FAR *pUnkOuter)
-{
- OS2IDirectDraw        *me = (OS2IDirectDraw *)This;
- OS2IDirectDrawPalette *newpal;
- HRESULT                rc;
- int                    palsize = 0;
-
-  if(dwFlags & (DDPCAPS_2BIT | DDPCAPS_4BIT) && !(dwFlags & DDPCAPS_8BITENTRIES)) {
-    //only support 8 bits color palettes...
+HRESULT __stdcall DrawCreatePalette(THIS This, DWORD dwFlags,
+            LPPALETTEENTRY lpColorTable,
+            LPDIRECTDRAWPALETTE FAR *lplpDD,
+            IUnknown FAR *pUnkOuter)
+{
+  OS2IDirectDraw        *me = (OS2IDirectDraw *)This;
+  OS2IDirectDrawPalette *newpal;
+  HRESULT                rc;
+  int                    palsize = 0;
+
+  if(dwFlags & DDPCAPS_8BITENTRIES)
+  {
+    // We Don't support Indexed palettes...
+
     return DDERR_INVALIDPARAMS;
   }
-  if(dwFlags & DDPCAPS_2BIT)     palsize = 4;
-  if(dwFlags & DDPCAPS_4BIT)     palsize = 16;
-  if(dwFlags & DDPCAPS_8BIT)     palsize = 256;
-  if(dwFlags & DDPCAPS_ALLOW256) palsize = 256;
-  if(palsize == 0)  return DDERR_INVALIDPARAMS;
-
-  dprintf(("CreatePalette with %d colors\n", palsize));
-
-  newpal = new OS2IDirectDrawPalette(me, palsize, lpColorTable);
-  if(newpal == NULL)    return(DDERR_OUTOFMEMORY);
+
+  if(dwFlags & DDPCAPS_2BIT)
+    palsize = 4;
+  if(dwFlags & DDPCAPS_4BIT)
+    palsize = 16;
+  if(dwFlags & DDPCAPS_8BIT)
+    palsize = 256;
+  if(dwFlags & DDPCAPS_ALLOW256)
+    palsize = 256;
+
+  if(palsize == 0)
+    return DDERR_INVALIDPARAMS;
+
+  #ifdef DEBUG
+    WriteLog("CreatePalette with %d colors\n", palsize);
+  #endif
+
+  newpal = new OS2IDirectDrawPalette(me, palsize, lpColorTable, dwFlags);
+  if(newpal == NULL)
+    return(DDERR_OUTOFMEMORY);
 
   newpal->Vtbl.AddRef((IDirectDrawPalette *)newpal);
   rc = newpal->GetLastError();
-  if(rc != DD_OK) {
-        *lplpDD = NULL;
-        delete newpal;
-  }
-  else  *lplpDD = (IDirectDrawPalette *)newpal;
+  if(rc != DD_OK)
+  {
+    *lplpDD = NULL;
+    delete newpal;
+  }
+  else
+    *lplpDD = (IDirectDrawPalette *)newpal;
 
   return(rc);
@@ -241,7 +324,7 @@
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall DrawCreateSurface(THIS, LPDDSURFACEDESC lpDDSurfaceDesc,
-                    LPDIRECTDRAWSURFACE FAR *lplpDD,
-                    IUnknown FAR *pUnkOuter)
+HRESULT __stdcall DrawCreateSurface(THIS This, LPDDSURFACEDESC lpDDSurfaceDesc,
+            LPDIRECTDRAWSURFACE FAR *lplpDD,
+            IUnknown FAR *pUnkOuter)
 {
  OS2IDirectDraw        *me = (OS2IDirectDraw *)This;
@@ -249,28 +332,72 @@
  HRESULT                rc;
 
+  #ifdef DEBUG
+    WriteLog("CreateSurface\n");
+    WriteLog("dwSize %d\n", lpDDSurfaceDesc->dwSize);
+    WriteLog("dwFlags %X\n", lpDDSurfaceDesc->dwFlags);
+    WriteLog("dwHeight %d\n", lpDDSurfaceDesc->dwHeight);
+    WriteLog("dwWidth %d\n", lpDDSurfaceDesc->dwWidth);
+    WriteLog("lPitch %d\n", lpDDSurfaceDesc->lPitch);
+    WriteLog("dwBackBufferCount %d\n", lpDDSurfaceDesc->dwBackBufferCount);
+    WriteLog("dwMipMapCount %d\n", lpDDSurfaceDesc->dwMipMapCount);
+    WriteLog("dwAlphaBitDepth %d\n", lpDDSurfaceDesc->dwAlphaBitDepth);
+    WriteLog("ddsCaps.dwCaps %X\n", lpDDSurfaceDesc->ddsCaps.dwCaps);
+  #endif
+
+  newsurf = new OS2IDirectDrawSurface(me, (LPDDSURFACEDESC2)lpDDSurfaceDesc);
+
+  if(newsurf == NULL)
+    return(DDERR_OUTOFMEMORY);
+
+  newsurf->Vtbl.AddRef((IDirectDrawSurface *)newsurf);
+  rc = newsurf->GetLastError();
+  if(rc != DD_OK)
+  {
+    WriteLog("Error createing Surface");
+    *lplpDD = NULL;
+    delete newsurf;
+  }
+  else
+    *lplpDD = (IDirectDrawSurface *)newsurf;
+
+  return(rc);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawCreateSurface4(THIS This, LPDDSURFACEDESC2 lpDDSurfaceDesc2,
+            LPDIRECTDRAWSURFACE4 FAR *lplpDD,
+            IUnknown FAR *pUnkOuter)
+{
+ OS2IDirectDraw         *me = (OS2IDirectDraw *)This;
+ OS2IDirectDrawSurface *newsurf;
+ HRESULT                rc;
+
 #ifdef DEBUG
-  WriteLog("CreateSurface\n");
-  WriteLog("  dwSize %d\n", lpDDSurfaceDesc->dwSize);
-  WriteLog("  dwFlags %X\n", lpDDSurfaceDesc->dwFlags);
-  WriteLog("  dwHeight %d\n", lpDDSurfaceDesc->dwHeight);
-  WriteLog("  dwWidth %d\n", lpDDSurfaceDesc->dwWidth);
-  WriteLog("  lPitch %d\n", lpDDSurfaceDesc->lPitch);
-  WriteLog("  lpSurface %d\n", lpDDSurfaceDesc->lpSurface);
-  WriteLog("  dwBackBufferCount %d\n", lpDDSurfaceDesc->dwBackBufferCount);
-  WriteLog("  dwMipMapCount %d\n", lpDDSurfaceDesc->dwMipMapCount);
-  WriteLog("  dwAlphaBitDepth %d\n", lpDDSurfaceDesc->dwAlphaBitDepth);
-  WriteLog("  ddsCaps.dwCaps %X\n", lpDDSurfaceDesc->ddsCaps.dwCaps);
+  WriteLog("CreateSurface4\n");
+  WriteLog("dwSize %d\n", lpDDSurfaceDesc2->dwSize);
+  WriteLog("dwHeight %d\n", lpDDSurfaceDesc2->dwHeight);
+  WriteLog("dwWidth %d\n", lpDDSurfaceDesc2->dwWidth);
+  WriteLog("lPitch %d\n", lpDDSurfaceDesc2->lPitch);
+  WriteLog("dwBackBufferCount %d\n", lpDDSurfaceDesc2->dwBackBufferCount);
+  WriteLog("dwMipMapCount %d\n", lpDDSurfaceDesc2->dwMipMapCount);
+  WriteLog("dwAlphaBitDepth %d\n", lpDDSurfaceDesc2->dwAlphaBitDepth);
+  WriteLog("ddsCaps.dwCaps %X\n", lpDDSurfaceDesc2->ddsCaps.dwCaps);
 #endif
 
-  newsurf = new OS2IDirectDrawSurface(me, lpDDSurfaceDesc);
-  if(newsurf == NULL)   return(DDERR_OUTOFMEMORY);
-
-  newsurf->Vtbl.AddRef((IDirectDrawSurface2 *)newsurf);
+  newsurf = new OS2IDirectDrawSurface(me, lpDDSurfaceDesc2);
+
+  if(newsurf == NULL)
+    return(DDERR_OUTOFMEMORY);
+
+  newsurf->Vtbl.AddRef((IDirectDrawSurface *)newsurf);
   rc = newsurf->GetLastError();
-  if(rc != DD_OK) {
-        *lplpDD = NULL;
-        delete newsurf;
-  }
-  else  *lplpDD = (IDirectDrawSurface *)newsurf;
+  if(rc != DD_OK)
+  {
+    WriteLog("Error createing Surface");
+    *lplpDD = NULL;
+    delete newsurf;
+  }
+  else
+    *lplpDD = (IDirectDrawSurface4 *)newsurf;
 
   return(rc);
@@ -280,177 +407,983 @@
 HRESULT __stdcall DrawDuplicateSurface(THIS, LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE FAR * )
 {
+  #ifdef DEBUG
+    WriteLog("DuplicateSurface\n");
+  #endif
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawDuplicateSurface4(THIS, LPDIRECTDRAWSURFACE4, LPDIRECTDRAWSURFACE4 FAR * )
+{
+  #ifdef DEBUG
+    WriteLog("DuplicateSurface\n");
+  #endif
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawEnumDisplayModes(THIS This, DWORD dwFlags, LPDDSURFACEDESC lpDDSurfaceDesc,
+                                       LPVOID lpContext, LPDDENUMMODESCALLBACK lpDDEnumModesCallback)
+{
+  int iMode = 0;
+  DDSURFACEDESC DDSurfAct;
+  BOOL fCallAgain;
+  OS2IDirectDraw        *me = (OS2IDirectDraw *)This;
+
+  #ifdef DEBUG
+    WriteLog("EnumDisplayModes\n");
+  #endif
+
+  // Check for Pointer to callback function
+  if (NULL == lpDDEnumModesCallback)
+  {
+    #ifdef DEBUG
+      WriteLog("EnumDisplayModes : Error NO EnumFunction passed in\n");
+    #endif
+
+    return(DDERR_GENERIC);
+  }
+
+
+  // Setting up the surface
+  // During enum we report resolution and bitdepth, maybe we should
+  // also report back : Caps and Pitch
+  memset(&DDSurfAct,0,sizeof(DDSURFACEDESC));
+  DDSurfAct.dwSize = sizeof(DDSURFACEDESC);
+  DDSurfAct.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT ;
+  // Only report the bitdepth hope this is ok this way, we must set the BitMask fields
+
+  DDSurfAct.ddpfPixelFormat.dwSize  = sizeof (DDPIXELFORMAT);
+  DDSurfAct.ddpfPixelFormat.dwFlags = DDPF_RGB;
+  // Check if we use DIVE or Voodoo
+  if(me->lpVtbl != (IDirectDraw4Vtbl *) &(me->Vtbl3D))
+  {
+    // DIVE modes
+
+    // Enumerate all modes ?
+    if (NULL==lpDDSurfaceDesc)
+    {
+      // Check if we shall report 320x200 mode
+
+      if(dwFlags && DDEDM_STANDARDVGAMODES)
+      {
+        DDSurfAct.dwHeight = ModesDive[0].iYRes;
+        DDSurfAct.dwWidth  = ModesDive[0].iXRes;
+        DDSurfAct.ddpfPixelFormat.dwRGBBitCount = ModesDive[0].iBits;
+        if(!lpDDEnumModesCallback(&DDSurfAct,lpContext))
+          return (DD_OK);
+      }
+      // Don't know the flag for Mode X so we skip reporting it
+
+      // Now report all our modes
+      iMode = 2;
+      fCallAgain = TRUE;
+      do
+      {
+        // if the mode fits in the current resolution report it
+        // Change this if we support Fullscreen later !!!
+        if(ModesDive[iMode].iXRes < me->dCaps.ulHorizontalResolution)
+        {
+          DDSurfAct.dwHeight = ModesDive[iMode].iYRes;
+          DDSurfAct.dwWidth  = ModesDive[iMode].iXRes;
+          DDSurfAct.ddpfPixelFormat.dwRGBBitCount = ModesDive[iMode].iBits;
+          switch(ModesDive[iMode].iBits)
+          {
+            case 16:
+              // VESA uses 565 encoding in 16 bit modes
+              lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0x0000F800;
+              lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0x000007E0;
+              lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = 0x0000001F;
+              break;
+            case 24:
+              // VESA uses per default RGB4
+              lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0x00FF0000;
+              lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0x0000FF00;
+              lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = 0x000000FF;
+              break;
+            default:
+              break;
+          }
+          fCallAgain = lpDDEnumModesCallback(&DDSurfAct,lpContext);
+        }
+        iMode++;
+      }
+      while((ModesDive[iMode].iBits <= me->dCaps.ulDepth) &&
+            (iMode < NUM_MODES_DIVE) && (TRUE==fCallAgain));
+    }
+    else
+    {
+      // No, so filter modes with lpDDSurfaceDesc
+
+      // Return Error if the program want to use other than the 3 supported values
+      // for filtering
+
+      if (lpDDSurfaceDesc->dwFlags & !(DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT))
+        return(DDERR_INVALIDPARAMS);
+
+      iMode = 0;
+      if( (dwFlags && DDEDM_STANDARDVGAMODES) &&
+         (
+          (((lpDDSurfaceDesc->dwFlags & DDSD_WIDTH)&&
+            (ModesDive[iMode].iXRes==lpDDSurfaceDesc->dwWidth)
+           )||(!(lpDDSurfaceDesc->dwFlags & DDSD_WIDTH)))&&
+          (((lpDDSurfaceDesc->dwFlags & DDSD_HEIGHT)&&
+            (ModesDive[iMode].iYRes==lpDDSurfaceDesc->dwHeight))||
+           (!(lpDDSurfaceDesc->dwFlags & DDSD_HEIGHT)))&&
+          (((lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT) &&
+            (ModesDive[iMode].iBits==lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount))||
+           (!(lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT)))
+         )
+        )
+      {
+        DDSurfAct.dwHeight = ModesDive[0].iYRes;
+        DDSurfAct.dwWidth  = ModesDive[0].iXRes;
+        DDSurfAct.ddpfPixelFormat.dwRGBBitCount = ModesDive[0].iBits;
+        if(!lpDDEnumModesCallback(&DDSurfAct,lpContext))
+          return (DD_OK);
+      }
+      // Don't know the flag for Mode X so we skip reporting it
+
+      // Now report all our modes
+      iMode = 2;
+      fCallAgain = TRUE;
+      do
+      {
+        // if the mode fits in the current resolution and the filter applies report it
+        // Change this if we support Fullscreen later !!!
+        if( (ModesDive[iMode].iXRes < me->dCaps.ulHorizontalResolution)&&
+           (
+            (((lpDDSurfaceDesc->dwFlags & DDSD_WIDTH)&&
+              (ModesDive[iMode].iXRes==lpDDSurfaceDesc->dwWidth))||
+             (!(lpDDSurfaceDesc->dwFlags & DDSD_WIDTH)))&&
+            (((lpDDSurfaceDesc->dwFlags & DDSD_HEIGHT)&&
+              (ModesDive[iMode].iYRes==lpDDSurfaceDesc->dwHeight))||
+             (!(lpDDSurfaceDesc->dwFlags & DDSD_HEIGHT)))&&
+            (((lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT) &&
+              (ModesDive[iMode].iBits==lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount))||
+             (!(lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT)))
+           )
+          )
+        {
+          DDSurfAct.dwHeight = ModesDive[iMode].iYRes;
+          DDSurfAct.dwWidth  = ModesDive[iMode].iXRes;
+          DDSurfAct.ddpfPixelFormat.dwRGBBitCount = ModesDive[iMode].iBits;
+
+          fCallAgain = lpDDEnumModesCallback(&DDSurfAct,lpContext);
+        }
+        iMode++;
+      }
+      while((ModesDive[iMode].iBits <= me->dCaps.ulDepth) &&
+            (iMode < NUM_MODES_DIVE) && (TRUE==fCallAgain));
+
+    }
+  }
+  else
+  {
+
+    // VOODOO modes
+
+    // Enumerate all modes ?
+    if (NULL==lpDDSurfaceDesc)
+    {
+
+      // report all our modes
+      iMode = 0;
+      fCallAgain = TRUE;
+      do
+      {
+        DDSurfAct.dwHeight = ModesVoodoo[iMode].iYRes;
+        DDSurfAct.dwWidth  = ModesVoodoo[iMode].iXRes;
+        DDSurfAct.ddpfPixelFormat.dwRGBBitCount = ModesVoodoo[iMode].iBits;
+
+        fCallAgain = lpDDEnumModesCallback(&DDSurfAct,lpContext);
+        iMode++;
+      }
+      while((iMode < NUM_MODES_VOODOO) && (TRUE==fCallAgain));
+    }
+    else
+    {
+      // No, so filter modes with lpDDSurfaceDesc
+
+      // Return Error if the program want to use other than the 3 supported values
+      // for filtering
+
+      if (lpDDSurfaceDesc->dwFlags & !(DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT))
+        return(DDERR_INVALIDPARAMS);
+
+      iMode = 2;
+      fCallAgain = TRUE;
+      do
+      {
+        // if the mode fits the filter applies report it
+        if(
+            (((lpDDSurfaceDesc->dwFlags & DDSD_WIDTH)&&
+              (ModesVoodoo[iMode].iXRes==lpDDSurfaceDesc->dwWidth))||
+             (!(lpDDSurfaceDesc->dwFlags & DDSD_WIDTH)))&&
+            (((lpDDSurfaceDesc->dwFlags & DDSD_HEIGHT)&&
+              (ModesVoodoo[iMode].iYRes==lpDDSurfaceDesc->dwHeight))||
+             (!(lpDDSurfaceDesc->dwFlags & DDSD_HEIGHT)))&&
+            (((lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT) &&
+              (ModesVoodoo[iMode].iBits==lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount))||
+             (!(lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT)))
+          )
+        {
+          DDSurfAct.dwHeight = ModesVoodoo[iMode].iYRes;
+          DDSurfAct.dwWidth  = ModesVoodoo[iMode].iXRes;
+          DDSurfAct.ddpfPixelFormat.dwRGBBitCount = ModesVoodoo[iMode].iBits;
+
+          fCallAgain = lpDDEnumModesCallback(&DDSurfAct,lpContext);
+        }
+        iMode++;
+      }
+      while((iMode < NUM_MODES_VOODOO) && (TRUE==fCallAgain));
+
+    }
+
+  }
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawEnumDisplayModes4(THIS This, DWORD dwFlags, LPDDSURFACEDESC2 lpDDSurfaceDesc2,
+                                       LPVOID lpContext, LPDDENUMMODESCALLBACK2 lpDDEnumModesCallback2)
+{
+  int iMode = 0;
+  DDSURFACEDESC DDSurfAct;
+  BOOL fCallAgain;
+  OS2IDirectDraw        *me = (OS2IDirectDraw *)This;
+
+  #ifdef DEBUG
+    WriteLog("EnumDisplayModes4\n");
+  #endif
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawEnumSurfaces(THIS, DWORD, LPDDSURFACEDESC, LPVOID,LPDDENUMSURFACESCALLBACK )
+{
+  #ifdef DEBUG
+    WriteLog("EnumSurfaces\n");
+  #endif
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawEnumSurfaces4(THIS, DWORD, LPDDSURFACEDESC2, LPVOID,LPDDENUMSURFACESCALLBACK2 )
+{
+  #ifdef DEBUG
+    WriteLog("EnumSurfaces4\n");
+  #endif
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawFlipToGDISurface(THIS)
+{
+  #ifdef DEBUG
+    WriteLog("FlipToGDISurface\n");
+  #endif
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawGetCaps(THIS, LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps)
+{
+  #ifdef DEBUG
+    WriteLog("GetCaps\n");
+  #endif
+
+  if( (NULL==lpDDDriverCaps) && (NULL==lpDDHELCaps) )
+    return(DDERR_INVALIDPARAMS);
+
+  if(NULL!=lpDDDriverCaps)
+  {
+    // Caller want Driver Caps
+
+    if(sizeof(DDCAPS)!=lpDDDriverCaps->dwSize)
+      return(DDERR_INVALIDPARAMS);
+
+    // Clear structure so we only have to set the supported flags
+    memset(lpDDDriverCaps,0,sizeof(DDCAPS));
+
+    // Reset the size
+    lpDDDriverCaps->dwSize = sizeof(DDCAPS);
+
+    // Now report the CAPs back which we support
+   lpDDDriverCaps->dwCaps = DDCAPS_BLT |              // We do blitting
+                            DDCAPS_BLTCOLORFILL |     // We do colorfills
+                            DDCAPS_COLORKEY |         // We support Colorkeying
+                            DDCAPS_COLORKEYHWASSIST | // But we (may) use the CPU
+                            DDCAPS_GDI |              // Maybe check if we are on Voodoo ?
+                            DDCAPS_PALETTEVSYNC;      // Got VSync
+
+    lpDDDriverCaps->dwCaps2 = DDCAPS2_CERTIFIED |         // Who cares so say yes
+                              DDCAPS2_CANRENDERWINDOWED | // Better check for Voodoo ?!
+                              DDCAPS2_COPYFOURCC |        // yepp memcpy will do this
+                              DDCAPS2_NONLOCALVIDMEM |    // All surfaces are in memory
+                              DDCAPS2_WIDESURFACES;       // Any size you want!
+
+    lpDDDriverCaps->dwCKeyCaps = DDCKEYCAPS_SRCBLT;      // Only source transparent blitting
+
+//    lpDDDriverCaps->dwFXCaps = DDFXCAPS_BLTMIRRORUPDOWN; // DIVE supports this, do we also ?
+                                                         // Maybe later add stretching support?
+
+    lpDDDriverCaps->dwPalCaps = DDPCAPS_8BIT |          // Only 8 Bits pals
+                                DDPCAPS_ALLOW256 |      // But all 256 colors
+                                DDPCAPS_VSYNC  |        // Vsync yet
+                                DDPCAPS_PRIMARYSURFACE; //
+    lpDDDriverCaps->dwVidMemTotal = 2048*1024;           // total video memory
+    lpDDDriverCaps->dwVidMemFree  = 2048*1024;            // total free video memory
+    lpDDDriverCaps->dwNumFourCCCodes;        // number of supported FOURCC codes
+    lpDDDriverCaps->dwRops[DD_ROP_SPACE];    // supported raster ops
+    lpDDDriverCaps->dwSVBCaps = DDCAPS_BLT |              // We do blitting
+                                DDCAPS_BLTCOLORFILL |     // We do colorfills
+                                DDCAPS_COLORKEY |         // We support Colorkeying
+                                DDCAPS_COLORKEYHWASSIST;
+    lpDDDriverCaps->dwSVBCKeyCaps = DDCKEYCAPS_SRCBLT;      // Only source transparent blitting
+    lpDDDriverCaps->dwSVBFXCaps;             //  .
+    lpDDDriverCaps->dwSVBRops[DD_ROP_SPACE]; //  .
+    lpDDDriverCaps->dwVSBCaps = DDCAPS_BLT |              // We do blitting
+                                DDCAPS_BLTCOLORFILL |     // We do colorfills
+                                DDCAPS_COLORKEY |         // We support Colorkeying
+                                DDCAPS_COLORKEYHWASSIST;
+    lpDDDriverCaps->dwVSBCKeyCaps = DDCKEYCAPS_SRCBLT;      // Only source transparent blitting
+    lpDDDriverCaps->dwVSBFXCaps;             //  .
+    lpDDDriverCaps->dwVSBRops[DD_ROP_SPACE]; //  .
+    lpDDDriverCaps->dwSSBCaps = DDCAPS_BLT |              // We do blitting
+                                DDCAPS_BLTCOLORFILL |     // We do colorfills
+                                DDCAPS_COLORKEY |         // We support Colorkeying
+                                DDCAPS_COLORKEYHWASSIST;
+    lpDDDriverCaps->dwSSBCKeyCaps = DDCKEYCAPS_SRCBLT;      // Only source transparent blitting
+    lpDDDriverCaps->dwSSBFXCaps;            //  .
+    lpDDDriverCaps->dwSSBRops[DD_ROP_SPACE]; //  .
+    lpDDDriverCaps->dwSVBCaps2 = DDCAPS2_CANRENDERWINDOWED | // Better check for Voodoo ?!
+                                 DDCAPS2_COPYFOURCC |        // yepp memcpy will do this
+                                 DDCAPS2_WIDESURFACES;       // Any size you want!
+    lpDDDriverCaps->dwNLVBCaps = DDCAPS_BLT |              // We do blitting
+                                 DDCAPS_BLTCOLORFILL |     // We do colorfills
+                                 DDCAPS_COLORKEY |         // We support Colorkeying
+                                 DDCAPS_COLORKEYHWASSIST;
+    lpDDDriverCaps->dwNLVBCaps2 = DDCAPS2_CANRENDERWINDOWED | // Better check for Voodoo ?!
+                                  DDCAPS2_COPYFOURCC |        // yepp memcpy will do this
+                                  DDCAPS2_WIDESURFACES;       // Any size you want!
+    lpDDDriverCaps->dwNLVBCKeyCaps = DDCKEYCAPS_SRCBLT;      // Only source transparent blitting
+    lpDDDriverCaps->dwNLVBFXCaps;            //  .
+    lpDDDriverCaps->dwNLVBRops[DD_ROP_SPACE];//  .
+    DDSCAPS2 ddsCaps;                 // general surface caps
+
+  }
+
+  if(NULL!=lpDDHELCaps)
+  {
+    // Caler wants HEL Caps
+    if(sizeof(DDCAPS)!=lpDDHELCaps->dwSize)
+      return(DDERR_INVALIDPARAMS);
+
+  }
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawGetDisplayMode(THIS This, LPDDSURFACEDESC lpDDSurfaceDesc)
+{
+  OS2IDirectDraw        *me = (OS2IDirectDraw *)This;
+  #ifdef DEBUG
+    WriteLog("GetDisplayMode\n");
+  #endif
+
+  // Check Parameter
+  if(NULL==lpDDSurfaceDesc)
+    return(DDERR_INVALIDPARAMS);
+
+  if(sizeof(DDSURFACEDESC)!=lpDDSurfaceDesc->dwSize)
+    return(DDERR_INVALIDPARAMS);
+
+  // We report back the DIVE caps. maybe we should set up a local DDSURFACEDESC
+  // for the object so we can change the values when we switch modes (or say so)
+  // as a program may use this function to check the values after a mode change
+  // An other reason to to so is Voodoo supports maybe more functions
+
+  // Tell what we report
+  lpDDSurfaceDesc->dwFlags  = DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
+  lpDDSurfaceDesc->dwHeight = me->dCaps.ulHorizontalResolution;
+  lpDDSurfaceDesc->dwWidth  = me->dCaps.ulVerticalResolution;
+  // Set the PixelFormat
+  lpDDSurfaceDesc->ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+
+  lpDDSurfaceDesc->ddpfPixelFormat.dwFourCC = me->dCaps.fccColorEncoding;
+  lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = me->dCaps.ulDepth;
+  lpDDSurfaceDesc->ddpfPixelFormat.dwRGBAlphaBitMask = 0; // No Alpha support
+  switch(me->dCaps.ulDepth)
+  {
+    case 4:
+      // Assume that no one will run OS/2 PM with less then 16 colors and try
+      // to start a DirectX program ;)
+      lpDDSurfaceDesc->ddpfPixelFormat.dwFlags =  DDPF_RGB | DDPF_PALETTEINDEXED4;
+      lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0;
+      lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0;
+      lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = 0;
+      break;
+    case 8:
+      lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8 |
+                                                 DDPF_FOURCC;
+      lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0;
+      lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0;
+      lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = 0;
+      break;
+    case 15:
+    case 16:
+      lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = 16; // No sure about 15Bit modes
+      lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_FOURCC;
+      if (FOURCC_R555 == me->dCaps.fccColorEncoding)
+      {
+        lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0x00007C00;
+        lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0x000003E0;
+        lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = 0x0000001F;
+      }
+      else
+      {
+        if(FOURCC_R565 == me->dCaps.fccColorEncoding)
+        {
+          lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0x0000F800;
+          lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0x000007E0;
+          lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = 0x0000001F;
+        }
+        else
+        {
+          // R664
+          lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0x0000F800;
+          lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0x000003F0;
+          lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = 0x0000000F;
+        }
+      }
+      break;
+    case 24:
+      lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_FOURCC;
+      if(FOURCC_RGB3 == me->dCaps.fccColorEncoding)
+      {
+        lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0x00FF0000;
+        lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0x0000FF00;
+        lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = 0x000000FF;
+      }
+      else
+      {
+        // BGR3
+        lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0x000000FF;
+        lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0x0000FF00;
+        lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = 0x00FF0000;
+      }
+      break;
+    case 32:
+      lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_FOURCC;
+      if(FOURCC_RGB4 == me->dCaps.fccColorEncoding)
+      {
+        lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0x00FF0000;
+        lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0x0000FF00;
+        lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = 0x000000FF;
+      }
+      else
+      {
+        // BGR4
+        lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0x000000FF;
+        lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0x0000FF00;
+        lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = 0x00FF0000;
+      }
+      break;
+    default:
+      #ifdef DEBUG
+        WriteLog("Unsupported mode\n");
+      #endif
+      return(DDERR_UNSUPPORTEDMODE);
+  }
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawGetDisplayMode4(THIS This, LPDDSURFACEDESC2 lpDDSurfaceDesc2)
+{
+  OS2IDirectDraw        *me = (OS2IDirectDraw *)This;
+  #ifdef DEBUG
+    WriteLog("GetDisplayMode\n");
+  #endif
+
+  // Check Parameter
+  if(NULL==lpDDSurfaceDesc2)
+    return(DDERR_INVALIDPARAMS);
+
+  if(sizeof(DDSURFACEDESC)!=lpDDSurfaceDesc2->dwSize)
+    return(DDERR_INVALIDPARAMS);
+
+  // We report back the DIVE caps. maybe we should set up a local DDSURFACEDESC
+  // for the object so we can change the values when we switch modes (or say so)
+  // as a program may use this function to check the values after a mode change
+  // An other reason to to so is Voodoo supports maybe more functions
+
+  // Tell what we report
+  lpDDSurfaceDesc2->dwFlags  = DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
+  lpDDSurfaceDesc2->dwHeight = me->dCaps.ulHorizontalResolution;
+  lpDDSurfaceDesc2->dwWidth  = me->dCaps.ulVerticalResolution;
+  // Set the PixelFormat
+  lpDDSurfaceDesc2->ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+
+  lpDDSurfaceDesc2->ddpfPixelFormat.dwFourCC = me->dCaps.fccColorEncoding;
+  lpDDSurfaceDesc2->ddpfPixelFormat.dwRGBBitCount = me->dCaps.ulDepth;
+  lpDDSurfaceDesc2->ddpfPixelFormat.dwRGBAlphaBitMask = 0; // No Alpha support
+  switch(me->dCaps.ulDepth)
+  {
+    case 4:
+      // Assume that no one will run OS/2 PM with less then 16 colors and try
+      // to start a DirectX program ;)
+      lpDDSurfaceDesc2->ddpfPixelFormat.dwFlags =  DDPF_RGB | DDPF_PALETTEINDEXED4;
+      lpDDSurfaceDesc2->ddpfPixelFormat.dwRBitMask = 0;
+      lpDDSurfaceDesc2->ddpfPixelFormat.dwGBitMask = 0;
+      lpDDSurfaceDesc2->ddpfPixelFormat.dwBBitMask = 0;
+      break;
+    case 8:
+      lpDDSurfaceDesc2->ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8 |
+                                                 DDPF_FOURCC;
+      lpDDSurfaceDesc2->ddpfPixelFormat.dwRBitMask = 0;
+      lpDDSurfaceDesc2->ddpfPixelFormat.dwGBitMask = 0;
+      lpDDSurfaceDesc2->ddpfPixelFormat.dwBBitMask = 0;
+      break;
+    case 15:
+    case 16:
+      lpDDSurfaceDesc2->ddpfPixelFormat.dwRGBBitCount = 16; // No sure about 15Bit modes
+      lpDDSurfaceDesc2->ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_FOURCC;
+      if (FOURCC_R555 == me->dCaps.ulDepth)
+      {
+        lpDDSurfaceDesc2->ddpfPixelFormat.dwRBitMask = 0x00007C00;
+        lpDDSurfaceDesc2->ddpfPixelFormat.dwGBitMask = 0x000003E0;
+        lpDDSurfaceDesc2->ddpfPixelFormat.dwBBitMask = 0x0000001F;
+      }
+      else
+      {
+        if(FOURCC_R565 == me->dCaps.fccColorEncoding)
+        {
+          lpDDSurfaceDesc2->ddpfPixelFormat.dwRBitMask = 0x0000F800;
+          lpDDSurfaceDesc2->ddpfPixelFormat.dwGBitMask = 0x000007E0;
+          lpDDSurfaceDesc2->ddpfPixelFormat.dwBBitMask = 0x0000001F;
+        }
+        else
+        {
+          // R664
+          lpDDSurfaceDesc2->ddpfPixelFormat.dwRBitMask = 0x0000F800;
+          lpDDSurfaceDesc2->ddpfPixelFormat.dwGBitMask = 0x000003F0;
+          lpDDSurfaceDesc2->ddpfPixelFormat.dwBBitMask = 0x0000000F;
+        }
+      }
+      break;
+    case 24:
+      lpDDSurfaceDesc2->ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_FOURCC;
+      if(FOURCC_RGB3 == me->dCaps.fccColorEncoding)
+      {
+        lpDDSurfaceDesc2->ddpfPixelFormat.dwRBitMask = 0x00FF0000;
+        lpDDSurfaceDesc2->ddpfPixelFormat.dwGBitMask = 0x0000FF00;
+        lpDDSurfaceDesc2->ddpfPixelFormat.dwBBitMask = 0x000000FF;
+      }
+      else
+      {
+        // BGR3
+        lpDDSurfaceDesc2->ddpfPixelFormat.dwRBitMask = 0x000000FF;
+        lpDDSurfaceDesc2->ddpfPixelFormat.dwGBitMask = 0x0000FF00;
+        lpDDSurfaceDesc2->ddpfPixelFormat.dwBBitMask = 0x00FF0000;
+      }
+      break;
+    case 32:
+      lpDDSurfaceDesc2->ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_FOURCC;
+      if(FOURCC_RGB4 == me->dCaps.fccColorEncoding)
+      {
+        lpDDSurfaceDesc2->ddpfPixelFormat.dwRBitMask = 0x00FF0000;
+        lpDDSurfaceDesc2->ddpfPixelFormat.dwGBitMask = 0x0000FF00;
+        lpDDSurfaceDesc2->ddpfPixelFormat.dwBBitMask = 0x000000FF;
+      }
+      else
+      {
+        // BGR4
+        lpDDSurfaceDesc2->ddpfPixelFormat.dwRBitMask = 0x000000FF;
+        lpDDSurfaceDesc2->ddpfPixelFormat.dwGBitMask = 0x0000FF00;
+        lpDDSurfaceDesc2->ddpfPixelFormat.dwBBitMask = 0x00FF0000;
+      }
+      break;
+    default:
+      #ifdef DEBUG
+        WriteLog("Unsupported mode\n");
+      #endif
+      return(DDERR_UNSUPPORTEDMODE);
+  }
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawGetFourCCCodes(THIS, LPDWORD lpNumCodes, LPDWORD lpCodes)
+{
+  DWORD dwFCC[3] = {FOURCC_LUT8,FOURCC_R565,FOURCC_RGB3};
+  #ifdef DEBUG
+    WriteLog("GetFourCCCodes\n");
+  #endif
+
+  if(NULL==lpNumCodes)
+    return(DDERR_INVALIDPARAMS);
+
+  if(NULL==lpCodes)
+  {
+    *lpNumCodes = 3; // LUT8, R565, RGB3 are the FourCC we support for now
+  }
+  else
+  {
+    for(int i=0;(i<3)&&(i<*lpNumCodes);i++)
+    {
+      *lpCodes = dwFCC[i];
+      lpCodes +=4;
+    }
+    if(*lpNumCodes < 3)
+      *lpNumCodes = 3;
+  }
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawGetGDISurface(THIS, LPDIRECTDRAWSURFACE FAR *)
+{
+  #ifdef DEBUG
+    WriteLog("GetGDISurface\n");
+  #endif
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawGetGDISurface4(THIS, LPDIRECTDRAWSURFACE4 FAR *)
+{
+  #ifdef DEBUG
+    WriteLog("GetGDISurface\n");
+  #endif
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawGetMonitorFrequency(THIS This, LPDWORD lpdwFreq)
+{
+  ULONG ulTime1, ulTime2;
+  DWORD dwFlags = DDWAITVB_BLOCKBEGIN;
+  #ifdef DEBUG
+    WriteLog("GetMonitorFrequency\n");
+  #endif
+  if(NULL==lpdwFreq)
+    return(DDERR_INVALIDPARAMS);
+
+  if(DD_OK==DrawWaitForVerticalBlank(This, dwFlags, 0))
+  {
+    ulTime1 = GetTickCount();
+    // Timer has an accuracy of 4 ms so call it al least 4 times
+    DrawWaitForVerticalBlank(This, dwFlags, 0);
+    DrawWaitForVerticalBlank(This, dwFlags, 0);
+    DrawWaitForVerticalBlank(This, dwFlags, 0);
+    DrawWaitForVerticalBlank(This, dwFlags, 0);
+    ulTime2 = GetTickCount();
+    ulTime2 -= ulTime1;
+    if(ulTime2) // paranoid check to avoid DIV0
+      *lpdwFreq = 4000 / ulTime2;
+    else
+      *lpdwFreq = 70;
+  }
+  else
+  {
+    // Assume 70 Hz maybe better return DDERR_UNSUPPORTED if this function isn't mandatory
+    *lpdwFreq = 70;
+  }
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawGetScanLine(THIS, LPDWORD lpdwLine)
+{
+  BOOL bVertBlank;
+  #ifdef DEBUG
+    WriteLog("GetScanLine\n");
+  #endif
+  // ToDO find a way to get this position, so for now simply return DDERR_UNSUPPORTED
+  // as we indicated in DDCAPS we don't support this.
+
+  return(DDERR_UNSUPPORTED);
+
+  //the following code could be used if we implement this
+  /*
+  if(NULL==lpdwLine)
+    return(DDERR_INVALIDPARAMS);
+  DrawGetVertcalBlackStatus(This,&bVertBlank);
+  if(bVertBlank)
+    return (DDERR_VERTICALBLANKINPROGRESS);
+  *lpdwLine = GetLine(); // GetLine would be the function which gets us the line
+  return(DD_OK);
+  */
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawGetVerticalBlankStatus(THIS , LPBOOL lpbIsInVB)
+{
+  #ifdef DEBUG
+    WriteLog("GetVerticalBlankStatus\n");
+  #endif
+  if(NULL==lpbIsInVB)
+    return(DDERR_INVALIDPARAMS);
+  if(0==io_init1())  // try to get IOPL for the thread
+  {
+    *lpbIsInVB = (c_inb1(0x3da)&0x08)!=0;
+    io_exit1(); // reset IOPL
+    return(DD_OK);
+  }
+
+  return(DDERR_UNSUPPORTED);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawInitialize(THIS, GUID FAR *)
+{
+  #ifdef DEBUG
+    WriteLog("Initialize\n");
+  #endif
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawRestoreDisplayMode(THIS)
+{
+  #ifdef DEBUG
+    WriteLog("RestoreDisplayMod\n");
+  #endif
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawSetCooperativeLevel(THIS This, HWND hwndClient, DWORD dwFlags)
+{
+ OS2IDirectDraw        *me = (OS2IDirectDraw *)This;
+
+  #ifdef DEBUG
+    WriteLog("SetCooperativeLevel: hwnd %X, Flags %X\n", hwndClient, dwFlags);
+  #endif
+
+  me->hwndClient = hwndClient;
+  #if 0
+  OS2DDSubclassWindow(hwndClient);
+  #endif
+  return(DD_OK);
+}
+//******************************************************************************
+//Backwards compatibility, what's that??
+//******************************************************************************
+HRESULT __stdcall DrawSetDisplayMode2(THIS This, DWORD dwWidth, DWORD dwHeight,
+              DWORD dwBPP, DWORD dwRefreshRate,
+              DWORD dwFlags)
+{
+ OS2IDirectDraw        *me = (OS2IDirectDraw *)This;
+
 #ifdef DEBUG
-  WriteLog("DuplicateSurface\n");
+  WriteLog("SetDisplayMode2 to %dx%d with %d bits colors\n", dwWidth, dwHeight, dwBPP);
 #endif
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall DrawEnumDisplayModes(THIS, DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK )
-{
-#ifdef DEBUG
-  WriteLog("EnumDisplayModes\n");
-#endif
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall DrawEnumSurfaces(THIS, DWORD, LPDDSURFACEDESC, LPVOID,LPDDENUMSURFACESCALLBACK )
-{
-#ifdef DEBUG
-  WriteLog("EnumSurfaces\n");
-#endif
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall DrawFlipToGDISurface(THIS)
-{
-#ifdef DEBUG
-  WriteLog("FlipToGDISurface\n");
-#endif
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall DrawGetCaps(THIS, LPDDCAPS, LPDDCAPS)
-{
-#ifdef DEBUG
-  WriteLog("GetCaps\n");
-#endif
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall DrawGetDisplayMode(THIS, LPDDSURFACEDESC)
-{
-#ifdef DEBUG
-  WriteLog("GetDisplayMode\n");
-#endif
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall DrawGetFourCCCodes(THIS, LPDWORD, LPDWORD)
-{
-#ifdef DEBUG
-  WriteLog("GetFourCCCodes\n");
-#endif
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall DrawGetGDISurface(THIS, LPDIRECTDRAWSURFACE FAR *)
-{
-#ifdef DEBUG
-  WriteLog("GetGDISurface\n");
-#endif
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall DrawGetMonitorFrequency(THIS, LPDWORD)
-{
-#ifdef DEBUG
-  WriteLog("GetMonitorFrequency\n");
-#endif
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall DrawGetScanLine(THIS, LPDWORD)
-{
-#ifdef DEBUG
-  WriteLog("GetScanLine\n");
-#endif
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall DrawGetVerticalBlankStatus(THIS, LPBOOL)
-{
-#ifdef DEBUG
-  WriteLog("GetVerticalBlankStatus\n");
-#endif
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall DrawInitialize(THIS, GUID FAR *)
-{
-#ifdef DEBUG
-  WriteLog("Initialize\n");
-#endif
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall DrawRestoreDisplayMode(THIS)
-{
-#ifdef DEBUG
-  WriteLog("RestoreDisplayMod\n");
-#endif
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall DrawSetCooperativeLevel(THIS, W32_HWND hwndClient, DWORD dwFlags)
-{
- OS2IDirectDraw        *me = (OS2IDirectDraw *)This;
-
-  dprintf(("SetCooperativeLevel: hwnd %X, Flags %X\n", hwndClient, dwFlags));
-  if(dwFlags & DDSCL_FULLSCREEN) {
-        me->fFullScreen = TRUE;
-  }
-  else  me->fFullScreen = FALSE;
-
-  me->hwndClient = hwndClient;
-  OS2MaximizeWindow((HWND)hwndClient);
-  return(DD_OK);
-}
-//******************************************************************************
-//Backwards compatibility, what's that??
-//******************************************************************************
-HRESULT __stdcall DrawSetDisplayMode2(THIS, DWORD dwWidth, DWORD dwHeight,
-                      DWORD dwBPP, DWORD dwRefreshRate,
-                      DWORD dwFlags)
-{
- OS2IDirectDraw *me = (OS2IDirectDraw *)This;
-
-  dprintf(("SetDisplayMode2 to %dx%d with %d bits colors\n", dwWidth, dwHeight, dwBPP));
   me->screenwidth  = dwWidth;
   me->screenheight = dwHeight;
   me->screenbpp    = dwBPP;
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall DrawSetDisplayMode(THIS, DWORD dwWidth, DWORD dwHeight,
-                     DWORD dwBPP)
+//  _interrupt(3);
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawSetDisplayMode(THIS This, DWORD dwWidth, DWORD dwHeight,
+             DWORD dwBPP)
 {
  OS2IDirectDraw        *me = (OS2IDirectDraw *)This;
 
-//  _interrupt(3);
-  dprintf(("SetDisplayMode to %dx%d with %d bits colors\n", dwWidth, dwHeight, dwBPP));
+#ifdef DEBUG
+  WriteLog("SetDisplayMode to %dx%d with %d bits colors\n", dwWidth, dwHeight, dwBPP);
+#endif
   me->screenwidth  = dwWidth;
   me->screenheight = dwHeight;
   me->screenbpp    = dwBPP;
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall DrawWaitForVerticalBlank(THIS, DWORD, W32_HANDLE)
-{
-  dprintf(("WaitForVerticalBlank\n"));
-  return(DD_OK);
-}
-//******************************************************************************
-/*** Added in the v2 interface ***/
-//******************************************************************************
-HRESULT __stdcall DrawGetAvailableVidMem(THIS, LPDDSCAPS, LPDWORD, LPDWORD)
-{
-  dprintf(("GetAvailableVidMem\n"));
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
+//  _interrupt(3);
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawWaitForVerticalBlank(THIS, DWORD dwFlags, HANDLE hEvent)
+{
+  HRESULT rc;
+  #ifdef DEBUG
+    WriteLog("WaitForVerticalBlank\n");
+  #endif
+
+  if(DDWAITVB_BLOCKBEGINEVENT == dwFlags) // This parameter isn't support in DX
+    return (DDERR_UNSUPPORTED);
+
+  if(io_init1())  // try to get IOPL for the thread
+    return (DDERR_UNSUPPORTED);  // we failed so return error that we don't support this
+
+  // AT this point we should have IOPL so lets use it!
+
+  rc = DDERR_INVALIDPARAMS; // set returnvalue to fail
+
+  if(DDWAITVB_BLOCKBEGIN == dwFlags)
+  {
+    while ((c_inb1(0x3da)&0x08)!=0); // Wait for end of vert. retrace if one is running
+    while ((c_inb1(0x3da)&0x08)==0); // Wait for new start of retrace
+    rc = DD_OK;
+  }
+
+  if(DDWAITVB_BLOCKEND == dwFlags)
+  {
+    rc = DD_OK;
+    if((c_inb1(0x3da)&0x08)!=0)        // Are we in a vert. retrace
+    {
+      while ((c_inb1(0x3da)&0x08)!=0); // Wait for end of retrace
+    }
+    else
+    {
+      while ((c_inb1(0x3da)&0x08)==0); // Wait for new start of retrace
+      while ((c_inb1(0x3da)&0x08)!=0); // Wait for end of vert. retrace
+    }
+
+  }
+
+  io_exit1();
+
+  return (rc);
+
+}
+//******************************************************************************
+//*** Added in the v2 interface ***
+//******************************************************************************
+HRESULT __stdcall DrawGetAvailableVidMem(THIS, LPDDSCAPS lpDDSCaps,
+                                         LPDWORD lpdwTotal, LPDWORD lpdwFree)
+{
+  #ifdef DEBUG
+    WriteLog("GetAvailableVidMem\n");
+  #endif
+
+  // Check parameters
+  if(NULL==lpDDSCaps)
+    return(DDERR_INVALIDPARAMS);
+
+  if((NULL==lpdwTotal)&&(NULL==lpdwFree))
+    return(DDERR_INVALIDPARAMS);
+
+  if(NULL!=lpdwTotal)
+    *lpdwTotal = 2048 *1024;
+
+  if(NULL!=lpdwFree)
+    *lpdwFree = 2048 *1024;
+
+  return(DD_OK);
+}
+//******************************************************************************
+//
+//******************************************************************************
+HRESULT __stdcall DrawGetAvailableVidMem4(THIS, LPDDSCAPS2 lpDDSCaps2,
+                                         LPDWORD lpdwTotal, LPDWORD lpdwFree)
+{
+  #ifdef DEBUG
+    WriteLog("GetAvailableVidMem\n");
+  #endif
+
+  // Check parameters
+  if(NULL==lpDDSCaps2)
+    return(DDERR_INVALIDPARAMS);
+
+  if((NULL==lpdwTotal)&&(NULL==lpdwFree))
+    return(DDERR_INVALIDPARAMS);
+
+  if(NULL!=lpdwTotal)
+    *lpdwTotal = 2048 *1024;
+
+  if(NULL!=lpdwFree)
+    *lpdwFree = 2048 *1024;
+
+  return(DD_OK);
+}
+//******************************************************************************
+//*** Added in the v4 interface ***
+//******************************************************************************
+HRESULT __stdcall DrawGetSurfaceFromDC(THIS, HDC hdc, LPDIRECTDRAWSURFACE4 *)
+{
+  #ifdef DEBUG
+    WriteLog("GetSurfaceFromDC Unimplemented Stub\n");
+  #endif
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawRestoreAllSurfaces(THIS)
+{
+  #ifdef DEBUG
+    WriteLog("RestoreAllSurfaces\n");
+  #endif
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawTestCooperativeLevel(THIS)
+{
+  #ifdef DEBUG
+    WriteLog("TestCooperativeLevel\n");
+  #endif
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall DrawGetDeviceIdentifier( THIS, LPDDDEVICEIDENTIFIER lpdddi,
+                                           DWORD dwFlags)
+{
+  #ifdef DEBUG
+    WriteLog("GetDeviceIdentifier Flags = %d\n",dwFlags);
+  #endif
+  if(NULL==lpdddi)
+    return DDERR_INVALIDPARAMS;
+
+  memset( lpdddi,
+          0,
+          sizeof(DDDEVICEIDENTIFIER));
+  // ToDo: Cretae a GUID and put some better data inside
+  strcpy( lpdddi->szDriver,
+          "OS/2 DIVE Driver");
+  strcpy( lpdddi->szDescription,
+          "ODIN DD Emulation Driver");
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+VOID OS2IDirectDraw::SwitchDisplay(HWND hwnd)
+{
+  DWORD dwVType, dwVSize;
+  HKEY hkDirectDraw2;
+
+  if (bScale)
+  {
+    if (ERROR_SUCCESS==RegOpenKeyA(HKEY_LOCAL_MACHINE,KEY_DIRECT2DRAW,&hkDirectDraw2))
+    {
+      dwVSize = 4;
+      dwVType = REG_DWORD;
+      if (ERROR_SUCCESS!=RegQueryValueExA( hkDirectDraw2, "Fullscreen", NULL, &dwVType,
+                                         (LPBYTE)&bScale, &dwVSize))
+        bScale = FALSE;
+    }
+    else
+      bScale = FALSE;
+  }
+}
+//******************************************************************************
+//******************************************************************************
+
Index: trunk/src/ddraw/OS2PALETTE.CPP
===================================================================
--- trunk/src/ddraw/OS2PALETTE.CPP	(revision 208)
+++ trunk/src/ddraw/OS2PALETTE.CPP	(revision 210)
@@ -1,67 +1,43 @@
-/* $Id: OS2PALETTE.CPP,v 1.3 1999-06-10 17:10:56 phaller Exp $ */
-
-/*
- * DirectDraw Palette class
- *
- * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
- *
- * Project Odin Software License can be found in LICENSE.TXT
- *
- */
-
-/*@Const************************************************************************
-*   Defined Constants                                                          *
-*******************************************************************************/
-#define INCL_GUID
-#define WIN32SDK_NOPOSTWRAPPER
-
-/*@Header***********************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#include <os2win.h>
-#include <dive.h>
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <memory.h>
-
-#include "no.h"
-#include <w_windows.h>
-#include <ddraw.h>
-#include <d3d.h>
-#include <Win32SDKPostWrapper.h>
-
-#include "os2ddraw.h"
+#define INITGUID
 #include "os2palette.h"
+#define _OS2WIN_H
+#define FAR
 #include "misc.h"
 #include "os2palset.h"
-
-extern DIVE_CAPS dcaps;
-
-//******************************************************************************
-//******************************************************************************
-OS2IDirectDrawPalette::OS2IDirectDrawPalette(OS2IDirectDraw *lpDirectDraw,
-                         int palsize,
-                         W32_LPPALETTEENTRY lpColorTable) :
-                         Referenced(0), os2pal(NULL),
-                         lastError(DD_OK), lpDraw(NULL)
-{
-  lpVtbl                        = &Vtbl;
-  Vtbl.AddRef           = PalAddRef;
-  Vtbl.Release              = PalRelease;
-  Vtbl.QueryInterface       = PalQueryInterface;
-  Vtbl.GetCaps          = PalGetCaps;
-  Vtbl.GetEntries       = PalGetEntries;
-  Vtbl.Initialize       = PalInitialize;
-  Vtbl.SetEntries       = PalSetEntries;
+#include <winerror.h>
+
+//******************************************************************************
+//******************************************************************************
+OS2IDirectDrawPalette::OS2IDirectDrawPalette( OS2IDirectDraw *lpDirectDraw,
+                                              int palsize,
+                                              LPPALETTEENTRY lpColorTable,
+                                              DWORD dwPalFlags) :
+                                              Referenced(0), os2pal(NULL),
+                                              lastError(DD_OK), lpDraw(NULL)
+{
+  lpVtbl              = &Vtbl;
+  Vtbl.AddRef         = PalAddRef;
+  Vtbl.Release        = PalRelease;
+  Vtbl.QueryInterface = PalQueryInterface;
+  Vtbl.GetCaps        = PalGetCaps;
+  Vtbl.GetEntries     = PalGetEntries;
+  Vtbl.Initialize     = PalInitialize;
+  Vtbl.SetEntries     = PalSetEntries;
 
   lpDraw                        = lpDirectDraw;
-  lpDraw->Vtbl.AddRef((IDirectDraw2*)lpDraw);
+  lpDraw->Vtbl.AddRef(lpDraw);
   hDive                         = lpDirectDraw->GetDiveInstance();
-  nrColors                      = palsize;
-
-  dprintf(("OS2IDirectDrawPalette::OS2IDirectDrawPalette nr colors %d", palsize));
-  os2pal = (W32_LPPALETTEENTRY)malloc(palsize*sizeof(PALETTEENTRY));
+  dwCaps                        = dwPalFlags;
+
+  dwSize = palsize;
+  if(256==dwSize)
+    dwCaps |= DDPCAPS_ALLOW256;
+  dwCaps &= ~DDPCAPS_VSYNC; // No sync change
+
+  os2pal = (LPPALETTEENTRY)malloc(palsize*sizeof(PALETTEENTRY));
   memcpy((char *)os2pal, (char *)lpColorTable, palsize*sizeof(PALETTEENTRY));
 }
@@ -70,18 +46,21 @@
 OS2IDirectDrawPalette::~OS2IDirectDrawPalette()
 {
-  if(os2pal)    free(os2pal);
-  lpDraw->Vtbl.Release((IDirectDraw2*)lpDraw);
-  RestorePhysPalette();
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall PalQueryInterface(THIS, REFIID riid, LPVOID FAR * ppvObj)
-{
-  dprintf(("OS2IDirectDrawPalette::PalQueryInterface\n"));
+  if(os2pal)
+    free(os2pal);
+  lpDraw->Vtbl.Release(lpDraw);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall PalQueryInterface(THIS This, REFIID riid, LPVOID FAR * ppvObj)
+{
+  #ifdef DEBUG
+    WriteLog("OS2IDirectDrawPalette::PalQueryInterface\n");
+  #endif
+
   *ppvObj = NULL;
 
   if(!IsEqualGUID(riid, IID_IDirectDrawPalette))
 //&& !IsEqualGUID(riid, IID_IUnknown))
-    return E_NOINTERFACE;
+  return E_NOINTERFACE;
 
   *ppvObj = This;
@@ -92,118 +71,110 @@
 //******************************************************************************
 //******************************************************************************
-ULONG __stdcall PalAddRef(THIS)
+ULONG __stdcall PalAddRef(THIS This)
+{
+  OS2IDirectDrawPalette *me = (OS2IDirectDrawPalette *)This;
+
+  #ifdef DEBUG
+    WriteLog("OS2IDirectDrawPalette::PalAddRef %d\n", me->Referenced+1);
+  #endif
+
+  return (++me->Referenced);
+}
+//******************************************************************************
+//******************************************************************************
+ULONG __stdcall PalRelease(THIS This)
+{
+  OS2IDirectDrawPalette *me = (OS2IDirectDrawPalette *)This;
+
+  #ifdef DEBUG
+    WriteLog("OS2IDirectDrawPalette::PalRelease %d\n", me->Referenced-1);
+  #endif
+
+  if(me->Referenced)
+  {
+    me->Referenced--;
+    if(me->Referenced == 0)
+    {
+      delete me;
+      return(0);
+    }
+    else
+      return (me->Referenced);
+  }
+  else
+    return(0);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall PalGetCaps(THIS This, LPDWORD lpdwCaps)
+{
+  OS2IDirectDrawPalette *me = (OS2IDirectDrawPalette *)This;
+
+  #ifdef DEBUG
+    WriteLog("OS2IDirectDrawPalette::GetCaps\n");
+  #endif
+
+  if(NULL== lpdwCaps)
+    return(DDERR_INVALIDPARAMS);
+
+  *lpdwCaps = me->dwCaps;
+
+  if(me->fAttachedToPrimary)
+    *lpdwCaps |= DDPCAPS_PRIMARYSURFACE;
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall PalGetEntries(THIS This, DWORD dwFlags,
+                                      DWORD dwBase,
+                                      DWORD dwNumEntries,
+                                      LPPALETTEENTRY lpEntries)
 {
  OS2IDirectDrawPalette *me = (OS2IDirectDrawPalette *)This;
 
-  dprintf(("OS2IDirectDrawPalette::PalAddRef %d\n", me->Referenced+1));
-  return ++me->Referenced;
-}
-//******************************************************************************
-//******************************************************************************
-ULONG __stdcall PalRelease(THIS)
+  #ifdef DEBUG
+    WriteLog("OS2IDirectDrawPalette::PalGetEntries\n");
+  #endif
+
+  if( (NULL== lpEntries) ||(0!=dwFlags) ||(dwBase<0) ||((dwBase + dwNumEntries)>me->dwSize) )
+    return(DDERR_INVALIDPARAMS);
+
+  memcpy( (char *)lpEntries,
+          (char *)(me->os2pal + dwBase),
+          dwNumEntries*sizeof(PALETTEENTRY));
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall PalInitialize(THIS, LPDIRECTDRAW, DWORD, LPPALETTEENTRY)
+{
+  #ifdef DEBUG
+    WriteLog("OS2IDirectDrawPalette::PalInitialize\n");
+  #endif
+  return(DDERR_ALREADYINITIALIZED);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall PalSetEntries(THIS This, DWORD dwFlags,
+                                      DWORD dwBase,
+                                      DWORD dwNumEntries,
+                                      LPPALETTEENTRY lpNewEntries)
 {
  OS2IDirectDrawPalette *me = (OS2IDirectDrawPalette *)This;
 
-  dprintf(("OS2IDirectDrawPalette::PalRelease %d\n", me->Referenced-1));
-  if(me->Referenced) {
-    me->Referenced--;
-    if(me->Referenced == 0) {
-        delete me;
-        return(0);
-    }
-    else    return me->Referenced;
-  }
-  else  return(0);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall PalGetCaps(THIS_ LPDWORD)
-{
-  dprintf(("OS2IDirectDrawPalette::GetCaps\n"));
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall PalGetEntries(THIS_ DWORD dwFlags, DWORD dwBase, DWORD dwNumEntries,
-                        W32_LPPALETTEENTRY lpEntries)
-{
- OS2IDirectDrawPalette *me = (OS2IDirectDrawPalette *)This;
-
-  dprintf(("OS2IDirectDrawPalette::PalGetEntries %d %d\n", dwBase, dwNumEntries));
-
-  if(dwBase + dwNumEntries > 256)
-    return(DDERR_UNSUPPORTED);
-
-  memcpy((char *)lpEntries, (char *)(me->os2pal + dwBase), dwNumEntries*sizeof(PALETTEENTRY));
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall PalInitialize(THIS_ LPDIRECTDRAW, DWORD, W32_LPPALETTEENTRY)
-{
-  dprintf(("OS2IDirectDrawPalette::PalInitialize\n"));
-  return(DD_OK);
-}
-//******************************************************************************
-   #pragma pack(1)          /* pack on wordboundary */
-
-   typedef struct _RGB2         /* rgb2 */
-   {
-      BYTE bBlue;              /* Blue component of the color definition */
-      BYTE bGreen;             /* Green component of the color definition*/
-      BYTE bRed;               /* Red component of the color definition  */
-      BYTE fcOptions;          /* Reserved, must be zero                 */
-   } RGB2;
-   typedef RGB2 *PRGB2;
- #pragma pack()
-//******************************************************************************
-HRESULT __stdcall PalSetEntries(THIS_ DWORD dwFlags, DWORD dwStartingEntry,
-                DWORD dwCount, W32_LPPALETTEENTRY lpEntries)
-{
- OS2IDirectDrawPalette *me = (OS2IDirectDrawPalette *)This;
- int i, rc;
- RGB2 os2rgb[256];
-
-   dprintf(("OS2IDirectDrawPalette::PalSetEntries %X %X %d %d\n", me, dwFlags, dwStartingEntry, dwCount));
-   memcpy(&me->os2pal[dwStartingEntry], lpEntries, sizeof(PALETTEENTRY)*dwCount);
-
-   for(i=0;i<256;i++) {
-    os2rgb[i].bBlue     = me->os2pal[i].peBlue;
-    os2rgb[i].bGreen    = me->os2pal[i].peGreen;
-    os2rgb[i].bRed      = me->os2pal[i].peRed;
-    os2rgb[i].fcOptions = 0;
-//  dprintf(("pal (%3d,%3d,%3d) %d\n", me->os2pal[i].peBlue, me->os2pal[i].peGreen, me->os2pal[i].peRed, me->os2pal[i].peFlags));
-   }
-#if 0
-   rc = DiveSetSourcePalette(me->hDive, dwStartingEntry, dwCount, (PBYTE)os2rgb);
-   if(rc != DIVE_SUCCESS) {
-    dprintf(("DiveSetSourcePalette returned %d\n", rc));
+  #ifdef DEBUG
+    WriteLog("OS2IDirectDrawPalette::PalSetEntries\n");
+  #endif
+  if( (NULL== lpNewEntries) ||(0!=dwFlags) ||(dwBase<0) ||((dwBase + dwNumEntries)>me->dwSize) )
     return(DDERR_INVALIDPARAMS);
-   }
-   if(dcaps.ulDepth == 8) {
-    rc = DiveSetDestinationPalette(me->hDive, dwStartingEntry, dwCount, (PBYTE)os2rgb);
-    if(rc != DIVE_SUCCESS) {
-        dprintf(("DiveSetDestinationPalette returned %d\n", rc));
-        return(DDERR_INVALIDPARAMS);
-    }
-   }
-#else
-   if(dcaps.ulDepth == 8) {
-    OS2SetPhysPalette((HWND)me->lpDraw->GetWindowHandle(), me->os2pal);
-    rc = DiveSetDestinationPalette(me->hDive, 0, 0, 0);
-    if(rc != DIVE_SUCCESS) {
-        dprintf(("DiveSetDestinationPalette returned %d\n", rc));
-        return(DDERR_INVALIDPARAMS);
-    }
-   }
-   else {
-    rc = DiveSetSourcePalette(me->hDive, 0, me->nrColors, (PBYTE)os2rgb);
-    if(rc != DIVE_SUCCESS) {
-        dprintf(("DiveSetSourcePalette returned %d\n", rc));
-        return(DDERR_INVALIDPARAMS);
-    }
-   }
-#endif
-   return(DD_OK);
+  memcpy((char *)(me->os2pal + dwBase),
+         (char *)lpNewEntries,
+         dwNumEntries*sizeof(PALETTEENTRY));
+
+  if(me->fAttachedToPrimary)
+    me->SetPhysPalette();
+
+  return(DD_OK);
 }
 //******************************************************************************
@@ -211,54 +182,24 @@
 void OS2IDirectDrawPalette::SetPhysPalette()
 {
- int i, rc;
- RGB2 os2rgb[256];
-
-   for(i=0;i<nrColors;i++) {
-    os2rgb[i].bBlue     = os2pal[i].peBlue;
-    os2rgb[i].bGreen    = os2pal[i].peGreen;
-    os2rgb[i].bRed      = os2pal[i].peRed;
-    os2rgb[i].fcOptions = 0;
-    dprintf(("pal (%3d,%3d,%3d) %d\n", os2pal[i].peBlue, os2pal[i].peGreen, os2pal[i].peRed, os2pal[i].peFlags));
-   }
-#if 0
-   rc = DiveSetSourcePalette(hDive, 0, nrColors, (PBYTE)os2rgb);
-   if(rc != DIVE_SUCCESS) {
-    dprintf(("DiveSetSourcePalette returned %d\n", rc));
+  OS2SetPhysPalette(os2pal);
+}
+//******************************************************************************
+//******************************************************************************
+void OS2IDirectDrawPalette::RestorePhysPalette()
+{
+  OS2ResetPhysPalette();
+}
+//******************************************************************************
+//******************************************************************************
+void OS2IDirectDrawPalette::SetIsPrimary(BOOL fNewVal)
+{
+  if(fNewVal==fAttachedToPrimary)
     return;
-   }
-   if(dcaps.ulDepth == 8) {
-    rc = DiveSetDestinationPalette(hDive, 0, nrColors, (PBYTE)os2rgb);
-    if(rc != DIVE_SUCCESS) {
-        dprintf(("DiveSetDestinationPalette returned %d\n", rc));
-        return;
-    }
-   }
-#else
-   if(dcaps.ulDepth == 8) {
-    OS2SetPhysPalette((HWND)lpDraw->GetWindowHandle(), os2pal);
-    rc = DiveSetDestinationPalette(hDive, 0, 0, 0);
-    if(rc != DIVE_SUCCESS) {
-        dprintf(("DiveSetDestinationPalette returned %d\n", rc));
-        return;
-    }
-  }
-  else {
-    rc = DiveSetSourcePalette(hDive, 0, nrColors, (PBYTE)os2rgb);
-    if(rc != DIVE_SUCCESS) {
-        dprintf(("DiveSetSourcePalette returned %d\n", rc));
-        return;
-    }
-  }
-#endif
-}
-//******************************************************************************
-//******************************************************************************
-void OS2IDirectDrawPalette::RestorePhysPalette()
-{
-   if(dcaps.ulDepth == 8) {
-    OS2ResetPhysPalette();
-   }
-}
-//******************************************************************************
-//******************************************************************************
-
+  fAttachedToPrimary = fNewVal;
+  if(fAttachedToPrimary)
+    SetPhysPalette();
+
+}
+//******************************************************************************
+//******************************************************************************
+
Index: trunk/src/ddraw/OS2PALSET.CPP
===================================================================
--- trunk/src/ddraw/OS2PALSET.CPP	(revision 208)
+++ trunk/src/ddraw/OS2PALSET.CPP	(revision 210)
@@ -1,26 +1,16 @@
-/* $Id: OS2PALSET.CPP,v 1.3 1999-06-10 17:10:56 phaller Exp $ */
-
-/*
- * OS/2 Palette functions
- *
- * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
- *
- * Project Odin Software License can be found in LICENSE.TXT
- *
- */
 #define INCL_GREALL
-#define INCL_WIN
 #define INCL_GPI
-#include <os2.h>
+#include <os2wrap.h>
 #include <pmddi.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include "os2palset.h"
+#define FAR
 #include "misc.h"
-#include "os2palset.h"
 
 //******************************************************************************
 //******************************************************************************
-void OS2SetPhysPalette(HWND hwndClient, void *pal)
+void OS2SetPhysPalette(void *pal)
 {
  PALETTEENTRY *pDirectXPal = (PALETTEENTRY *)pal;
@@ -29,21 +19,29 @@
  RGB2 os2rgb[256];
  int  i;
- ULONG cclr;
 
-   hps = WinGetPS(HWND_DESKTOP);
-   hdc = GpiQueryDevice(hps);
-   for(i=0;i<256;i++) {
+  hps = WinGetPS(HWND_DESKTOP);
+  hdc = GpiQueryDevice(hps);
+
+  for(i=0;i<256;i++)
+  {
     os2rgb[i].bBlue     = pDirectXPal[i].peBlue;
     os2rgb[i].bGreen    = pDirectXPal[i].peGreen;
     os2rgb[i].bRed      = pDirectXPal[i].peRed;
-    os2rgb[i].fcOptions = PC_RESERVED;
-   }
+    os2rgb[i].fcOptions = 0;
+  }
 
-   GpiCreateLogColorTable(hps, LCOL_PURECOLOR | LCOL_REALIZABLE,
-                          LCOLF_CONSECRGB, 0, 256, (PLONG)&os2rgb);
-   Gre32Entry3(hdc, 0L, 0x000060C6L);
-//   WinInvalidateRect(HWND_DESKTOP, (PRECTL)NULL, TRUE);
-   WinRealizePalette(hwndClient, hps, &cclr);
-   WinReleasePS(hps);
+  GpiCreateLogColorTable( hps, LCOL_PURECOLOR | LCOL_REALIZABLE,
+                          LCOLF_CONSECRGB,
+                          0,
+                          256,
+                          (PLONG)&os2rgb);
+  Gre32Entry3( hdc,
+               0L,
+               0x000060C6L);
+
+  WinInvalidateRect( HWND_DESKTOP,
+                     (PRECTL)NULL,
+                     TRUE);
+  WinReleasePS(hps);
 }
 //******************************************************************************
@@ -54,9 +52,17 @@
  HDC hdc;
 
-   hps = WinGetPS(HWND_DESKTOP);
-   hdc = GpiQueryDevice(hps);
-   Gre32Entry3(hdc, 0L, 0x000060C7L);
-   WinInvalidateRect(HWND_DESKTOP, (PRECTL)NULL, TRUE);
-   WinReleasePS(hps);
+  hps = WinGetPS( HWND_DESKTOP);
+
+  hdc = GpiQueryDevice( hps);
+
+  Gre32Entry3( hdc,
+               0L,
+               0x000060C7L);
+
+  WinInvalidateRect( HWND_DESKTOP,
+                    (PRECTL)NULL,
+                    TRUE);
+
+  WinReleasePS(hps);
 }
 //******************************************************************************
Index: trunk/src/ddraw/OS2SURFACE.CPP
===================================================================
--- trunk/src/ddraw/OS2SURFACE.CPP	(revision 208)
+++ trunk/src/ddraw/OS2SURFACE.CPP	(revision 210)
@@ -1,248 +1,1129 @@
-/* $Id: OS2SURFACE.CPP,v 1.3 1999-06-10 17:10:56 phaller Exp $ */
-
-/*
- * DirectDraw Surface class
- *
- * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
- *
- * Project Odin Software License can be found in LICENSE.TXT
- *
- */
-/*@Const************************************************************************
-*   Defined Constants                                                          *
-*******************************************************************************/
-#define INIT_GUID
-#define INCL_MM_OS2
-#define WIN32SDK_NOPOSTWRAPPER
-
-#define BYTE0(a)    (char)(a & 0xFF)
-#define BYTE1(a)    (char)((a>>8) & 0xFF)
-#define BYTE2(a)    (char)((a>>16) & 0xFF)
-#define BYTE3(a)    (char)(a>>24)
-
-/*@Header***********************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#include <os2win.h>
-#include <dive.h>
 #include <stdlib.h>
 #include <string.h>
 #include <memory.h>
-
-#include "no.h"
-#include <w_windows.h>
-#include <ddraw.h>
-#include <d3d.h>
-#include <Win32SDKPostWrapper.h>
-
+#define mmioFOURCC( ch0, ch1, ch2, ch3 )                         \
+                  ( (DWORD)(BYTE)(ch0) | ( (DWORD)(BYTE)(ch1) << 8 ) |    \
+                  ( (DWORD)(BYTE)(ch2) << 16 ) | ( (DWORD)(BYTE)(ch3) << 24 ) )
 #include <fourcc.h>
-
-#include "os2ddraw.h"
 #include "os2surface.h"
+#define _OS2WIN_H
+#define FAR
 #include "misc.h"
-#include "os2util.h"
 #include "asmutil.h"
-
+#include <winerror.h>
 #ifndef __WATCOMC__
-    #include <builtin.h>
+#include <builtin.h>
 #endif
 
-
-/* KSO Apr 19 1999: Set correct interface.           *
- * (INTERFACE is used in the THIS and THIS_ macros)  */
-#undef  INTERFACE
-#define INTERFACE   IDirectDrawSurface2
-
-extern DIVE_CAPS dcaps;
-extern FOURCC    fccFormats[100];
-
-//******************************************************************************
-//Assumes 8 bits or more per pixel
+extern FOURCC  SupportedFourCCs[];
+// ToDo: Move the following 2 defines in the right WINE headers.
+
+#define CBM_CREATEDIB   0x02L   /* create DIB bitmap */
+#define BI_BITFIELDS  0x03L
+#ifdef DEBUG
+
+// ******************************************************************************
+// *    internal helper functions from WINE
+// *
+
+static void _dump_DDBLTFX(DWORD flagmask) {
+  int  i;
+  const struct {
+    DWORD  mask;
+    char  *name;
+  } flags[] = {
+#define FE(x) { x, #x},
+    FE(DDBLTFX_ARITHSTRETCHY)
+    FE(DDBLTFX_MIRRORLEFTRIGHT)
+    FE(DDBLTFX_MIRRORUPDOWN)
+    FE(DDBLTFX_NOTEARING)
+    FE(DDBLTFX_ROTATE180)
+    FE(DDBLTFX_ROTATE270)
+    FE(DDBLTFX_ROTATE90)
+    FE(DDBLTFX_ZBUFFERRANGE)
+    FE(DDBLTFX_ZBUFFERBASEDEST)
+  };
+  for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
+     if (flags[i].mask & flagmask) {
+        WriteLog("%s ",flags[i].name);
+     };
+  WriteLog("\n");
+
+}
+
+static void _dump_DDBLTFAST(DWORD flagmask) {
+  int  i;
+  const struct {
+    DWORD  mask;
+    char  *name;
+  } flags[] = {
+#define FE(x) { x, #x},
+    FE(DDBLTFAST_NOCOLORKEY)
+    FE(DDBLTFAST_SRCCOLORKEY)
+    FE(DDBLTFAST_DESTCOLORKEY)
+    FE(DDBLTFAST_WAIT)
+  };
+  for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
+    if (flags[i].mask & flagmask)
+      WriteLog("%s ",flags[i].name);
+  WriteLog("\n");
+}
+
+static void _dump_DDBLT(DWORD flagmask) {
+  int  i;
+  const struct {
+    DWORD  mask;
+    char  *name;
+  } flags[] = {
+#define FE(x) { x, #x},
+    FE(DDBLT_ALPHADEST)
+    FE(DDBLT_ALPHADESTCONSTOVERRIDE)
+    FE(DDBLT_ALPHADESTNEG)
+    FE(DDBLT_ALPHADESTSURFACEOVERRIDE)
+    FE(DDBLT_ALPHAEDGEBLEND)
+    FE(DDBLT_ALPHASRC)
+    FE(DDBLT_ALPHASRCCONSTOVERRIDE)
+    FE(DDBLT_ALPHASRCNEG)
+    FE(DDBLT_ALPHASRCSURFACEOVERRIDE)
+    FE(DDBLT_ASYNC)
+    FE(DDBLT_COLORFILL)
+    FE(DDBLT_DDFX)
+    FE(DDBLT_DDROPS)
+    FE(DDBLT_KEYDEST)
+    FE(DDBLT_KEYDESTOVERRIDE)
+    FE(DDBLT_KEYSRC)
+    FE(DDBLT_KEYSRCOVERRIDE)
+    FE(DDBLT_ROP)
+    FE(DDBLT_ROTATIONANGLE)
+    FE(DDBLT_ZBUFFER)
+    FE(DDBLT_ZBUFFERDESTCONSTOVERRIDE)
+    FE(DDBLT_ZBUFFERDESTOVERRIDE)
+    FE(DDBLT_ZBUFFERSRCCONSTOVERRIDE)
+    FE(DDBLT_ZBUFFERSRCOVERRIDE)
+    FE(DDBLT_WAIT)
+    FE(DDBLT_DEPTHFILL)
+  };
+  for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
+    if (flags[i].mask & flagmask)
+      WriteLog("%s ",flags[i].name);
+}
+
+static void _dump_DDSCAPS(DWORD flagmask) {
+  int  i;
+  const struct {
+    DWORD  mask;
+    char  *name;
+  } flags[] = {
+#define FE(x) { x, #x},
+    FE(DDSCAPS_RESERVED1)
+    FE(DDSCAPS_ALPHA)
+    FE(DDSCAPS_BACKBUFFER)
+    FE(DDSCAPS_COMPLEX)
+    FE(DDSCAPS_FLIP)
+    FE(DDSCAPS_FRONTBUFFER)
+    FE(DDSCAPS_OFFSCREENPLAIN)
+    FE(DDSCAPS_OVERLAY)
+    FE(DDSCAPS_PALETTE)
+    FE(DDSCAPS_PRIMARYSURFACE)
+    FE(DDSCAPS_PRIMARYSURFACELEFT)
+    FE(DDSCAPS_SYSTEMMEMORY)
+    FE(DDSCAPS_TEXTURE)
+    FE(DDSCAPS_3DDEVICE)
+    FE(DDSCAPS_VIDEOMEMORY)
+    FE(DDSCAPS_VISIBLE)
+    FE(DDSCAPS_WRITEONLY)
+    FE(DDSCAPS_ZBUFFER)
+    FE(DDSCAPS_OWNDC)
+    FE(DDSCAPS_LIVEVIDEO)
+    FE(DDSCAPS_HWCODEC)
+    FE(DDSCAPS_MODEX)
+    FE(DDSCAPS_MIPMAP)
+    FE(DDSCAPS_RESERVED2)
+    FE(DDSCAPS_ALLOCONLOAD)
+    FE(DDSCAPS_VIDEOPORT)
+    FE(DDSCAPS_LOCALVIDMEM)
+    FE(DDSCAPS_NONLOCALVIDMEM)
+    FE(DDSCAPS_STANDARDVGAMODE)
+    FE(DDSCAPS_OPTIMIZED)
+  };
+  for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
+    if (flags[i].mask & flagmask)
+      WriteLog("%s ",flags[i].name);
+  WriteLog("\n");
+}
+
+static void _dump_DDSD(DWORD flagmask) {
+  int  i;
+  const struct {
+    DWORD  mask;
+    char  *name;
+  } flags[] = {
+    FE(DDSD_CAPS)
+    FE(DDSD_HEIGHT)
+    FE(DDSD_WIDTH)
+    FE(DDSD_PITCH)
+    FE(DDSD_BACKBUFFERCOUNT)
+    FE(DDSD_ZBUFFERBITDEPTH)
+    FE(DDSD_ALPHABITDEPTH)
+    FE(DDSD_PIXELFORMAT)
+    FE(DDSD_CKDESTOVERLAY)
+    FE(DDSD_CKDESTBLT)
+    FE(DDSD_CKSRCOVERLAY)
+    FE(DDSD_CKSRCBLT)
+    FE(DDSD_MIPMAPCOUNT)
+    FE(DDSD_REFRESHRATE)
+    FE(DDSD_LINEARSIZE)
+    FE(DDSD_LPSURFACE)
+    FE(DDSD_TEXTURESTAGE)
+  };
+  for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
+    if (flags[i].mask & flagmask)
+      WriteLog("%s ",flags[i].name);
+  WriteLog("\n");
+}
+
+static void _dump_DDCOLORKEY(DWORD flagmask) {
+  int  i;
+  const struct {
+    DWORD  mask;
+    char  *name;
+  } flags[] = {
+#define FE(x) { x, #x},
+          FE(DDPF_ALPHAPIXELS)
+    FE(DDPF_ALPHA)
+    FE(DDPF_FOURCC)
+    FE(DDPF_PALETTEINDEXED4)
+    FE(DDPF_PALETTEINDEXEDTO8)
+    FE(DDPF_PALETTEINDEXED8)
+    FE(DDPF_RGB)
+    FE(DDPF_COMPRESSED)
+    FE(DDPF_RGBTOYUV)
+    FE(DDPF_YUV)
+    FE(DDPF_ZBUFFER)
+    FE(DDPF_PALETTEINDEXED1)
+    FE(DDPF_PALETTEINDEXED2)
+    FE(DDPF_ZPIXELS)
+  };
+  for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
+    if (flags[i].mask & flagmask)
+      WriteLog("%s ",flags[i].name);
+  WriteLog("\n");
+}
+
+static void _dump_pixelformat(LPDDPIXELFORMAT pf) {
+  _dump_DDCOLORKEY(pf->dwFlags);
+  WriteLog("dwFourCC : %ld\n", pf->dwFourCC);
+  WriteLog("RBG bit cbout : %ld\n", pf->dwRGBBitCount);
+  WriteLog("Masks : R %08lx  G %08lx  B %08lx  A %08lx\n",
+       pf->dwRBitMask, pf->dwGBitMask, pf->dwBBitMask, pf->dwRGBAlphaBitMask);
+}
+
+// End of Internal Helpers
+#endif
+
+//******************************************************************************
 //******************************************************************************
 OS2IDirectDrawSurface::OS2IDirectDrawSurface(OS2IDirectDraw *lpDirectDraw,
-                         LPDDSURFACEDESC lpDDSurfaceDesc) :
-                           Referenced(0), lastError(DD_OK),
-                           diveBufNr(-1), lpClipper(NULL),
-                           lpPalette(NULL), lpDraw(NULL),
-                           fLocked(FALSE), hdcImage(NULL),
-                           hbmImage(NULL), bitmapData(NULL),
-                           pFrameBuffer(NULL), attached(NULL),
-                           flip(NULL),lpBuffer(NULL), ColorKeyFlags(0)
-{
- ULONG rc;
-
-  lpVtbl                        = &Vtbl;
-  Vtbl.AddRef                   = SurfAddRef;
-  Vtbl.Release                  = SurfRelease;
-  Vtbl.QueryInterface           = SurfQueryInterface;
-  Vtbl.AddAttachedSurface       = SurfAddAttachedSurface;
-  Vtbl.AddOverlayDirtyRect      = SurfAddOverlayDirtyRect;
-  Vtbl.Blt                      = SurfBlt;
-  Vtbl.BltBatch                 = SurfBltBatch;
-  Vtbl.BltFast                  = SurfBltFast;
-  Vtbl.DeleteAttachedSurface    = SurfDeleteAttachedSurface;
-  Vtbl.EnumAttachedSurfaces     = SurfEnumAttachedSurfaces;
-  Vtbl.EnumOverlayZOrders       = SurfEnumOverlayZOrders;
-  Vtbl.Flip                     = SurfFlip;
-  Vtbl.GetAttachedSurface       = SurfGetAttachedSurface;
-  Vtbl.GetBltStatus             = SurfGetBltStatus;
-  Vtbl.GetCaps                  = SurfGetCaps;
-  Vtbl.GetClipper               = SurfGetClipper;
-  Vtbl.GetColorKey              = SurfGetColorKey;
-  Vtbl.W32_GetDC                = SurfGetDC;    //KSO Apr 19 1999: side effect of the wrapper...
-  Vtbl.GetFlipStatus            = SurfGetFlipStatus;
-  Vtbl.GetOverlayPosition       = SurfGetOverlayPosition;
-  Vtbl.GetPalette               = SurfGetPalette;
-  Vtbl.GetPixelFormat           = SurfGetPixelFormat;
-  Vtbl.GetSurfaceDesc           = SurfGetSurfaceDesc;
-  Vtbl.Initialize               = SurfInitialize;
-  Vtbl.IsLost                   = SurfIsLost;
-  Vtbl.Lock                     = SurfLock;
-  Vtbl.W32_ReleaseDC            = SurfReleaseDC;//KSO Apr 19 1999: side effect of the wrapper...
-  Vtbl.Restore                  = SurfRestore;
-  Vtbl.SetClipper               = SurfSetClipper;
-  Vtbl.SetColorKey              = SurfSetColorKey;
-  Vtbl.SetOverlayPosition       = SurfSetOverlayPosition;
-  Vtbl.SetPalette               = SurfSetPalette;
-  Vtbl.Unlock                   = SurfUnlock;
-  Vtbl.UpdateOverlay            = SurfUpdateOverlay;
-  Vtbl.UpdateOverlayDisplay     = SurfUpdateOverlayDisplay;
-  Vtbl.UpdateOverlayZOrder      = SurfUpdateOverlayZOrder;
-  Vtbl.GetDDInterface           = SurfGetDDInterface;
-  Vtbl.PageLock                 = SurfPageLock;
-  Vtbl.PageUnlock               = SurfPageUnlock;
-
-  lpDraw                        = lpDirectDraw;
-  lpDraw->Vtbl.AddRef((IDirectDraw2*)lpDraw);
-  hDive                         = lpDirectDraw->GetDiveInstance();
-  surfaceType                   = DDSCAPS_OFFSCREENPLAIN;
-
-  memcpy((char *)&DDSurfaceDesc, (char *)lpDDSurfaceDesc, sizeof(DDSURFACEDESC));
-
-  //TODO: finish up and do better error checking (can't create multiple
-  //      primary surfaces etc etc
-  if(lpDDSurfaceDesc->dwFlags & DDSD_HEIGHT)
-        height = lpDDSurfaceDesc->dwHeight;
-  if(lpDDSurfaceDesc->dwFlags & DDSD_WIDTH)
-        width = lpDDSurfaceDesc->dwWidth;
-
-  if(height == 0)
-        height = lpDraw->GetScreenHeight();
-  if(width == 0)
-        width = lpDraw->GetScreenWidth();
-//test
-  lpDDSurfaceDesc->dwHeight = height;
-  lpDDSurfaceDesc->dwWidth  = width;
-
-  //SvL: TODO: Check if DIVE supports all ddraw fourcc codes
-  if(lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT) {
-    if(lpDDSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_FOURCC) {
-        fccColorFormat = lpDDSurfaceDesc->ddpfPixelFormat.dwFourCC;
-    }
-    else {
-        dprintf(("   Unsupported pixel format, defaulting to LUT8"));
-        fccColorFormat = FOURCC_LUT8;
-    }
-  }
-  else  fccColorFormat = FOURCC_LUT8;
-  screenXFact    = 1.0;
-  screenYFact    = 1.0;
-  //TODO: base this on the fourcc value!!
-  bpp            = 8;
-
-  if(lpDDSurfaceDesc->dwFlags & DDSD_CAPS) {
+               LPDDSURFACEDESC2 lpDDSurfaceDesc, BOOL Implicit, BOOL Mainchain) :
+                  Referenced(0), lastError(DD_OK),
+                 diveBufNr(-1), lpClipper(NULL),
+                 lpPalette(NULL), lpDraw(NULL),
+                 fLocked(FALSE), hdcImage(NULL),
+                 hbmImage(NULL),
+                 pFrameBuffer(NULL),Updated(FALSE),
+                 fOverlayValid(FALSE),
+                 BackBuffer(NULL),FrontBuffer(NULL)
+
+{
+  ULONG rc;
+  DWORD i;
+  DIVE_CAPS dCaps;
+  DDSURFACEDESC2 ComplexSurfaceDesc;
+  OS2IDirectDrawSurface *AttachedSurface;
+
+  lpVtbl                     = &Vtbl;
+  Vtbl.AddRef                = SurfAddRef;
+  Vtbl.Release               = SurfRelease;
+  Vtbl.QueryInterface        = SurfQueryInterface;
+  Vtbl.AddAttachedSurface    = SurfAddAttachedSurface4;
+  Vtbl.AddOverlayDirtyRect   = SurfAddOverlayDirtyRect;
+  Vtbl.Blt                   = SurfBlt4;
+  Vtbl.BltBatch              = SurfBltBatch;
+  Vtbl.BltFast               = SurfBltFast4;
+  Vtbl.DeleteAttachedSurface = SurfDeleteAttachedSurface4;
+  Vtbl.EnumAttachedSurfaces  = SurfEnumAttachedSurfaces4;
+  Vtbl.EnumOverlayZOrders    = SurfEnumOverlayZOrders4;
+  Vtbl.Flip                  = SurfFlip4;
+  Vtbl.GetAttachedSurface    = SurfGetAttachedSurface4;
+  Vtbl.GetBltStatus          = SurfGetBltStatus;
+  Vtbl.GetCaps               = SurfGetCaps4;
+  Vtbl.GetClipper            = SurfGetClipper;
+  Vtbl.GetColorKey           = SurfGetColorKey;
+  Vtbl.GetDC                 = SurfGetDC;
+  Vtbl.GetFlipStatus         = SurfGetFlipStatus;
+  Vtbl.GetOverlayPosition    = SurfGetOverlayPosition;
+  Vtbl.GetPalette            = SurfGetPalette;
+  Vtbl.GetPixelFormat        = SurfGetPixelFormat;
+  Vtbl.GetSurfaceDesc        = SurfGetSurfaceDesc4;
+  Vtbl.Initialize            = SurfInitialize4;
+  Vtbl.IsLost                = SurfIsLost;
+  Vtbl.Lock                  = SurfLock4;
+  Vtbl.ReleaseDC             = SurfReleaseDC;
+  Vtbl.Restore               = SurfRestore;
+  Vtbl.SetClipper            = SurfSetClipper;
+  Vtbl.SetColorKey           = SurfSetColorKey;
+  Vtbl.SetOverlayPosition    = SurfSetOverlayPosition;
+  Vtbl.SetPalette            = SurfSetPalette;
+  Vtbl.Unlock                = SurfUnlock;
+  Vtbl.UpdateOverlay         = SurfUpdateOverlay4;
+  Vtbl.UpdateOverlayDisplay  = SurfUpdateOverlayDisplay;
+  Vtbl.UpdateOverlayZOrder   = SurfUpdateOverlayZOrder4;
+  Vtbl.GetDDInterface        = SurfGetDDInterface;
+  Vtbl.PageLock              = SurfPageLock;
+  Vtbl.PageUnlock            = SurfPageUnlock;
+  Vtbl.SetSurfaceDesc        = SurfSetSurfaceDesc4;
+  Vtbl.SetPrivateData        = SurfSetPrivateData;
+  Vtbl.GetPrivateData        = SurfGetPrivateData;
+  Vtbl.FreePrivateData       = SurfFreePrivateData;
+  Vtbl.ChangeUniquenessValue = SurfChangeUniquenessValue;
+  Vtbl.GetUniquenessValue    = SurfGetUniquenessValue;
+  lpDraw                     = lpDirectDraw;
+  lpDraw->Vtbl.AddRef(lpDraw);
+
+  ImplicitSurface = Implicit;
+
+  hDive                      = lpDirectDraw->GetDiveInstance();
+  surfaceType                = DDSCAPS_OFFSCREENPLAIN;
+  memcpy((char *)&DDSurfaceDesc, (char *)lpDDSurfaceDesc, sizeof(DDSURFACEDESC2));
+
+  if(lpDraw->dCaps.ulDepth != 15)
+  {
+    if(lpDraw->dCaps.ulDepth >= 8)
+      dwBytesPPDive = lpDraw->dCaps.ulDepth >> 3;
+    else
+      dwBytesPPDive = 1; // not sure if this is the case
+  }
+  else
+    dwBytesPPDive = 2; // 2 bytes for 15Bit
+
+  // Setting up Cursors for handling attached Surfaces
+  try
+  {
+    SurfaceCursorMipMap = SurfaceSequenceMipMap.newCursor();
+  }
+  catch(IOutOfMemory)
+  {
+    #ifdef DEBUG
+      WriteLog("Internal : Error creating Cursor\n");
+    #endif
+    lastError = DDERR_OUTOFMEMORY ;
+    return;
+  }
+
+  try
+  {
+    SurfaceCursorAttached = SurfaceSequenceAttached.newCursor();
+  }
+  catch(IOutOfMemory)
+  {
+    #ifdef DEBUG
+      WriteLog("Internal : Error creating Cursor\n");
+    #endif
+    lastError = DDERR_OUTOFMEMORY ;
+    return;
+  }
+
+  if( lpDDSurfaceDesc->dwFlags & DDSD_CAPS )
+  {
+    // First check if we want to create a primary surface while the ddraw object already has one
     surfaceType = lpDDSurfaceDesc->ddsCaps.dwCaps;
-    if(surfaceType & DDSCAPS_PRIMARYSURFACE) {
-        dprintf(("   Primary surface!\n"));
+
+    if( surfaceType & DDSCAPS_PRIMARYSURFACE)
+    {
+      if( lpDraw->HasPrimarySurface())
+      {
+        lastError = DDERR_PRIMARYSURFACEALREADYEXISTS;
+        return;
+      }
+
+      #ifdef DEBUG
+        WriteLog("Primary surface!\n");
+      #endif
+      if( (lpDDSurfaceDesc->dwFlags & DDSD_HEIGHT) ||
+          (lpDDSurfaceDesc->dwFlags & DDSD_WIDTH)  ||
+          (lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT)
+        )
+      {
+        // Dx doc says passing width,height etc. for primary surface in not permitted!!
+        WriteLog("Invalid parameters\n\n");
+        lastError = DDERR_INVALIDPARAMS;
+        return;
+      }
+
+      // Check if OS/2 is running in the requested colormode
+
+      if( lpDraw->dCaps.ulDepth == lpDraw->GetScreenBpp() )
+      {
+        WriteLog("DirectScreenAccess possible\n");
+
+        // Yes so direct access to framebuffer is possible
+
         diveBufNr    = DIVE_BUFFER_SCREEN;
         pFrameBuffer = lpDraw->GetFrameBuffer();
-        //SvL: Needed for stretching if we're not running in 640x480
-        if(lpDraw->IsFullScreen() == TRUE) {
-            screenYFact  = (double)dcaps.ulVerticalResolution/(double)height;
-            screenXFact  = (double)dcaps.ulHorizontalResolution/(double)width;
-        }
-        fccColorFormat = FOURCC_SCRN;
-        bpp            = dcaps.ulDepth;
-    }
-    if(!(surfaceType & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN))) {
-        lastError = DDERR_INVALIDPARAMS;
-    }
-  }
-  else  surfaceType = 0;
-
-  dprintf(("   fccColorFormat %c%c%c%c", BYTE0(fccColorFormat), BYTE1(fccColorFormat), BYTE2(fccColorFormat), BYTE3(fccColorFormat)));
-
-  if(height && width && diveBufNr == -1) {
-    diveBufNr = 0;  //need to set to 0 for new buffer!
-    lpBuffer = (PBYTE)OS2AllocMem(width*height*bpp/8);
-    if(lpBuffer == NULL) {
-        lastError = DDERR_INVALIDPARAMS;
-        return;
-    }
-    dprintf(("   lpBuffer = %X", lpBuffer));
-    rc = DiveAllocImageBuffer(hDive, &diveBufNr, fccColorFormat, width, height, width, lpBuffer);
-    if(rc != DIVE_SUCCESS) {
-        dprintf(("   DiveAllocImageBuffer failed with %d", rc));
-        lastError = DDERR_INVALIDPARAMS;    //TODO: better errors
-        return;
-    }
-    else {
-        dprintf(("   DiveAllocImageBuffer returned %d", diveBufNr));
-    }
-  }
-
-  dprintf(("   Buf %X Screen Caps (%d,%d), bitcount %d\n", this, dcaps.ulVerticalResolution, dcaps.ulHorizontalResolution,
-       dcaps.ulDepth));
-
-  //todo: checking for flip & complex bits if backbuffer bit present!
-  if(lpDDSurfaceDesc->dwFlags & DDSD_BACKBUFFERCOUNT) {
-    OS2IDirectDrawSurface *attachedSurface, *tmpSurface = NULL;
-    DDSURFACEDESC          surfDescription;
-
-    dprintf(("   Create %d background surface(s)", lpDDSurfaceDesc->dwBackBufferCount));
-    memcpy((char *)&surfDescription, (char *)lpDDSurfaceDesc, sizeof(DDSURFACEDESC));
-    surfDescription.ddsCaps.dwCaps   &= ~DDSCAPS_PRIMARYSURFACE;
-    surfDescription.dwBackBufferCount = 0;
-    surfDescription.ddsCaps.dwCaps    = DDSCAPS_BACKBUFFER; //only the first one!
-
-    //SvL: Create background surfaces
-    for(int i=0;i<lpDDSurfaceDesc->dwBackBufferCount;i++) {
-        attachedSurface = new OS2IDirectDrawSurface(lpDirectDraw,
-                                    &surfDescription);
-        if(tmpSurface) {
-            tmpSurface->attached = attachedSurface;
-        }
-        else {
-            attached = attachedSurface;
-            flip     = attached;
-        }
-
-        tmpSurface = attachedSurface;
-        //SvL: All other back surfaces have the flip bit set
-        surfDescription.ddsCaps.dwCaps = DDSCAPS_FLIP;
-    }
-  }
-  memset((char *)&SurfaceCaps, 0, sizeof(DDCAPS));
-  SurfaceCaps.ddsCaps.dwCaps = surfaceType;
-  SurfaceCaps.dwSize         = sizeof(DDCAPS);
-  //TODO: might need to change some flags
-  SurfaceCaps.dwCaps         = DDCAPS_COLORKEY | DDCAPS_NOHARDWARE;
-  SurfaceCaps.dwCaps2        = DDCAPS2_CERTIFIED; //of course we're certified
-  //TODO: might need to change some flags as we might support more in the future
-  SurfaceCaps.dwCKeyCaps     = DDCKEYCAPS_SRCBLT;
-  SurfaceCaps.dwFXCaps       = 0;
-  SurfaceCaps.dwFXAlphaCaps  = 0;
-  //TODO
-  if(bpp == 8) {
-      SurfaceCaps.dwPalCaps = DDPCAPS_8BIT | DDPCAPS_ALLOW256;
-  }
-  SurfaceCaps.dwVidMemTotal  = 1024*1024;   //todo
-  SurfaceCaps.dwVidMemFree   = SurfaceCaps.dwVidMemTotal - dcaps.ulVerticalResolution*dcaps.ulVerticalResolution*dcaps.ulDepth/8;
-  SurfaceCaps.dwNumFourCCCodes   = 1;
-  SurfaceCaps.dwAlignBoundarySrc = 4;
-  SurfaceCaps.dwAlignSizeDest    = 4;
-  SurfaceCaps.dwAlignStrideAlign = 4;
-
-  dprintf(("DirectDrawSurface ctor end!"));
+        pDiveBuffer  = pFrameBuffer;
+        dwPitchDB    = lpDraw->dCaps.ulScanLineBytes;
+        dwPitchFB    = dwPitchDB;
+        DDSurfaceDesc.lPitch = dwPitchDB;
+      }
+      else
+      {
+        // No so we create a virtual framebuffer which the program can access
+        // and blit to the real framebuffer on Unlock to do color conversion
+
+        WriteLog( "Need Color conversation %d => %d Bit\n",
+                  lpDraw->GetScreenBpp(),
+                  lpDraw->dCaps.ulDepth
+                );
+
+        dwPitchFB = (lpDraw->GetScreenWidth() * lpDraw->GetScreenBpp() +7) & ~7;
+        DDSurfaceDesc.lPitch = dwPitchFB;
+
+        // 24 byte more to enable alignment and speed up blitting
+
+        pFBreal = (char*)malloc( lpDraw->GetScreenHeight() * dwPitchFB + 24);
+        pFrameBuffer = (char*)(((int)pFBreal + 7) & ~7); // align to QWORD
+
+        // DiveBuffer points to real framebuffer
+        dwPitchDB    = lpDraw->dCaps.ulScanLineBytes;
+        pDiveBuffer = lpDraw->GetFrameBuffer();
+
+      }
+
+      // Update passed in and local Surface description
+
+      #ifdef DEBUG
+        WriteLog("Setting up Surface\n");
+      #endif
+      DDSurfaceDesc.dwFlags     |= DDSD_WIDTH | DDSD_HEIGHT |
+                                   DDSD_PITCH | DDSD_LPSURFACE |
+                                   DDSD_PIXELFORMAT;
+      DDSurfaceDesc.dwHeight     = lpDraw->GetScreenHeight();
+      DDSurfaceDesc.dwWidth      = lpDraw->GetScreenWidth();
+      DDSurfaceDesc.lpSurface    = pFrameBuffer;
+      lpDDSurfaceDesc->dwFlags   = DDSurfaceDesc.dwFlags;
+      lpDDSurfaceDesc->dwHeight  = DDSurfaceDesc.dwHeight;
+      lpDDSurfaceDesc->dwWidth   = DDSurfaceDesc.dwWidth;
+      lpDDSurfaceDesc->lpSurface = pFrameBuffer;
+      lpDDSurfaceDesc->lPitch    = DDSurfaceDesc.lPitch;
+
+      lpDDSurfaceDesc->ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
+      DDSurfaceDesc.ddsCaps.dwCaps    |= DDSCAPS_VISIBLE;
+      lpDraw->SetPrimarySurface(TRUE);
+      lpDDSurfaceDesc->ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+      lpDDSurfaceDesc->ddpfPixelFormat.dwFourCC = (DWORD) lpDraw->GetScreenFourCC();
+      lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = lpDraw->GetScreenBpp();
+      DDSurfaceDesc.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+      DDSurfaceDesc.ddpfPixelFormat.dwFourCC = (DWORD) lpDraw->GetScreenFourCC();
+      DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount = lpDraw->GetScreenBpp();
+
+      switch(DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount)
+      {
+        case 4:
+          lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED4 | DDPF_RGB;
+          DDSurfaceDesc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED4 | DDPF_RGB;
+          break;
+        case 8:
+          lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_FOURCC | DDPF_RGB;
+          DDSurfaceDesc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_FOURCC | DDPF_RGB;
+          break;
+        case 16:
+          lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_FOURCC | DDPF_RGB;
+          lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0x0000F800;
+          lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0x000007E0;
+          lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = 0x0000001F;
+          DDSurfaceDesc.ddpfPixelFormat.dwFlags = DDPF_FOURCC | DDPF_RGB;
+          DDSurfaceDesc.ddpfPixelFormat.dwRBitMask = 0x0000F800;
+          DDSurfaceDesc.ddpfPixelFormat.dwGBitMask = 0x000007E0;
+          DDSurfaceDesc.ddpfPixelFormat.dwBBitMask = 0x0000001F;
+          break;
+        case 24:
+        case 32:
+          lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_FOURCC | DDPF_RGB;
+          lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0x00FF0000;
+          lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0x0000FF00;
+          lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = 0x000000FF;
+          DDSurfaceDesc.ddpfPixelFormat.dwFlags = DDPF_FOURCC | DDPF_RGB;
+          DDSurfaceDesc.ddpfPixelFormat.dwRBitMask = 0x00FF0000;
+          DDSurfaceDesc.ddpfPixelFormat.dwGBitMask = 0x0000FF00;
+          DDSurfaceDesc.ddpfPixelFormat.dwBBitMask = 0x000000FF;
+          break;
+        default:
+          // Remove the Pixelformat flag
+          lpDDSurfaceDesc->dwFlags &= ~DDSD_PIXELFORMAT;
+          DDSurfaceDesc.dwFlags    &= ~DDSD_PIXELFORMAT;
+          #ifdef DEBUG
+            WriteLog("Unexpected BitDepth : %d\n",lpDraw->GetScreenBpp());
+          #endif
+          break;
+      } // end switch
+
+      #ifdef DEBUG
+        WriteLog("Surface set up, checking other Caps\n");
+      #endif
+
+      if( DDSurfaceDesc.ddsCaps.dwCaps & DDSCAPS_COMPLEX)
+      {
+        #ifdef DEBUG
+          WriteLog("Complex Surface\n");
+        #endif
+
+        if(lpDDSurfaceDesc->dwFlags & DDSD_BACKBUFFERCOUNT)
+        {
+          #ifdef DEBUG
+            WriteLog("Backbuffer # = %d\n",lpDDSurfaceDesc->dwBackBufferCount);
+          #endif
+          memset( &ComplexSurfaceDesc,
+                  0,
+                  sizeof(DDSURFACEDESC2));
+
+          ComplexSurfaceDesc.dwSize  = sizeof(DDSURFACEDESC2);
+          ComplexSurfaceDesc.dwFlags = DDSD_CAPS |
+                                       DDSD_WIDTH |
+                                       DDSD_HEIGHT |
+                                       DDSD_PIXELFORMAT;
+          ComplexSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_FLIP;
+          ComplexSurfaceDesc.dwHeight = DDSurfaceDesc.dwHeight;
+          ComplexSurfaceDesc.dwWidth = DDSurfaceDesc.dwWidth;
+          ComplexSurfaceDesc.ddpfPixelFormat.dwFlags = DDSurfaceDesc.ddpfPixelFormat.dwFlags;
+          ComplexSurfaceDesc.ddpfPixelFormat.dwRBitMask = DDSurfaceDesc.ddpfPixelFormat.dwRBitMask;
+          ComplexSurfaceDesc.ddpfPixelFormat.dwGBitMask = DDSurfaceDesc.ddpfPixelFormat.dwGBitMask;
+          ComplexSurfaceDesc.ddpfPixelFormat.dwBBitMask = DDSurfaceDesc.ddpfPixelFormat.dwBBitMask;
+          ComplexSurfaceDesc.ddpfPixelFormat.dwRGBBitCount = DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount;
+
+          if(lpDDSurfaceDesc->dwBackBufferCount>1)
+          {
+            ComplexSurfaceDesc.dwFlags |=DDSD_BACKBUFFERCOUNT;
+            ComplexSurfaceDesc.dwBackBufferCount = lpDDSurfaceDesc->dwBackBufferCount -1;
+            ComplexSurfaceDesc.ddsCaps.dwCaps|= DDSCAPS_COMPLEX;
+          }
+
+          BackBuffer = new OS2IDirectDrawSurface(lpDraw, &ComplexSurfaceDesc, TRUE, TRUE);
+          if (BackBuffer->GetLastError()==DD_OK)
+          {
+            // Our Primary Buffer is also the frontbuffer of a flipchain
+            DDSurfaceDesc.dwFlags |= DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP;
+            BackBuffer->SetFrontBuffer(this);
+          }
+        }
+        else
+        {
+          #ifdef DEBUG
+            WriteLog("Unsupported Complex Surface\n");
+            _dump_DDSCAPS(lpDDSurfaceDesc->dwFlags);
+          #endif
+          lastError = DDERR_OUTOFMEMORY;
+          return;
+        } //endif Backbuffer
+      } // endif DDSCAPS_COMPLEX
+      lastError = DD_OK;
+      return;
+    } // endif  DDSCAPS_PRIMARYSURFACE
+
+    //
+    // ToDo : Do better calulation of Bitmap Size to support the compressed Bitmaps in Dx6
+    //
+
+    if( (DDSurfaceDesc.dwFlags & DDSD_HEIGHT) &&
+        (DDSurfaceDesc.dwFlags & DDSD_WIDTH)
+      )
+
+    {
+      DWORD dwBpp;
+      DWORD dwCaps;
+      if(DDSurfaceDesc.dwFlags & DDSD_PIXELFORMAT)         // Pixelformat passed in ?
+      {
+        // YES use it
+        if(DDSurfaceDesc.ddpfPixelFormat.dwFlags & DDPF_RGB)
+        {
+          dwBpp = DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount;
+        }
+        else
+        {
+          if(DDSurfaceDesc.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)
+            dwBpp = 8;
+          if(DDSurfaceDesc.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4)
+            dwBpp = 4;
+        }
+      }
+      else
+        dwBpp = dwBytesPPDive << 3; // No use Screenformat
+
+      // three possible situaltions
+      // 1. User supplied pointer to surface -> use it
+      // 2. Delayed allocation of a texture -> don't alloc
+      // 3. Normal allocation
+      // After this check for complex flag.
+
+      dwCaps = DDSurfaceDesc.ddsCaps.dwCaps;
+
+      if(DDSurfaceDesc.dwFlags & DDSD_LPSURFACE)
+      {
+        // 1.
+
+        if(NULL==DDSurfaceDesc.lpSurface)
+        {
+          // pointer is NULL! Stupid user ;)
+          lastError = DDERR_INVALIDPARAMS;
+          return;
+        }
+
+        // User allocated the Buffer for the surface so we don't have to
+
+        Updated = TRUE; // Set Flag to indicate User supplied buffer so we don't free it
+
+        // As we allready copied the surface description we are done if the # of colors
+        // of the surface is the same then the screen
+
+        pFrameBuffer = (char*)DDSurfaceDesc.lpSurface;
+        diveBufNr    = -1;
+        dwPitchFB    = DDSurfaceDesc.lPitch;
+
+        if( (lpDraw->dCaps.ulDepth ) == dwBpp )
+        {
+          // Yes No Colorconversion is needed so point to the same buffer
+          dwPitchDB    = dwPitchFB;
+          pDiveBuffer  = pFrameBuffer;
+        }
+        else
+        {
+          // No so we must create the Divebuffer to do the color conversion
+          // and blit to the real framebuffer on Unlock to do color conversion
+
+          dwPitchDB = (lpDDSurfaceDesc->dwWidth * dwBytesPPDive +7) & ~7;
+
+          // 24 byte more to enable alignment and speed up blitting
+
+          pDBreal = (char*)malloc( lpDDSurfaceDesc->dwHeight * dwPitchDB + 24);
+          pDiveBuffer = (char*)(((int)pDBreal + 7) & ~7); // align to QWORD
+
+          // Not sure if that is ok but we need this for translation
+          // I hope no game uses YUV or such a crap
+
+          DDSurfaceDesc.ddpfPixelFormat.dwFourCC = SupportedFourCCs[dwBpp>>3];
+        }
+
+      }
+      else
+      {
+
+        if(dwCaps & DDSCAPS_ALLOCONLOAD)
+        {
+          // 2.
+
+          dwCaps &= ~DDSCAPS_ALLOCONLOAD; // remove flag
+
+          // only allow this flag for textures
+          if(!dwCaps & DDSCAPS_TEXTURE)
+          {
+            lastError = DDERR_INVALIDPARAMS;
+            return;
+          }
+
+          dwCaps &= ~DDSCAPS_TEXTURE; // remove flag
+          pFrameBuffer = NULL;
+          pDiveBuffer  = NULL;
+
+          // This surface isn't allocated yet, but when the texture is loaded
+          #ifdef DEBUG
+            WriteLog("Warning : Delayed memory allocation on request\n");
+          #endif
+          DDSurfaceDesc.lpSurface = NULL;
+          lpDDSurfaceDesc->lpSurface = NULL;
+        }
+        else
+        {
+          // 3.
+
+          lpDDSurfaceDesc->dwFlags  |= DDSD_PITCH|DDSD_LPSURFACE;
+          DDSurfaceDesc.dwFlags      = lpDDSurfaceDesc->dwFlags;
+
+          dwPitchFB = lpDDSurfaceDesc->dwWidth * (dwBpp<8?1:dwBpp/8);
+          dwPitchFB = (dwPitchFB +7) & ~7;  // Align on QWords
+
+          DDSurfaceDesc.lPitch    = dwPitchFB;
+          lpDDSurfaceDesc->lPitch = dwPitchFB;
+
+          #ifdef DEBUG
+            if(dwBpp<8)
+            {
+              WriteLog("1 or 4 Bit Surface encountered may not work !");
+            }
+          #endif
+
+
+          // 24 byte more to enable alignment and speed up blitting
+
+          pFBreal = (char*)malloc( lpDDSurfaceDesc->dwHeight * dwPitchFB + 24);
+
+          if(NULL==pFBreal)
+          {
+            lastError = DDERR_OUTOFMEMORY;
+            return;
+          }
+
+          pFrameBuffer = (char*)(((int)pFBreal + 7) & ~7); // align to QWORD
+
+          lpDDSurfaceDesc->lpSurface = pFrameBuffer;
+          DDSurfaceDesc.lpSurface    = pFrameBuffer;
+
+          if(Mainchain)
+          {
+            // This surface is part of flipchain with the primary surface use dive to alloc
+            diveBufNr = 0;
+            DiveAllocImageBuffer( hDive,
+                                  &diveBufNr,
+                                  lpDraw->dCaps.fccColorEncoding,
+                                  lpDDSurfaceDesc->dwWidth,
+                                  lpDDSurfaceDesc->dwHeight,
+                                  (lpDDSurfaceDesc->dwWidth * (lpDraw->dCaps.ulDepth/8) +7) & ~7,
+                                  (PBYTE)pDiveBuffer);
+          }
+
+          if( (lpDraw->dCaps.ulDepth ) == dwBpp )
+          {
+            // Yes => No Colorconversion is needed so point to the same buffer
+            pDiveBuffer  = pFrameBuffer;
+          }
+          else
+          {
+            // No so we must create the Divebuffer to do the colortranslation
+            // and blit to the real framebuffer on Unlock to do color conversion
+            pDiveBuffer = (char*)malloc( lpDDSurfaceDesc->dwHeight *
+                                 ((lpDDSurfaceDesc->dwWidth * (lpDraw->dCaps.ulDepth/8) +7) & ~7) );
+
+          }
+
+        }  // end of 3rd case
+      } // End of alloc surfaces
+
+      if( dwCaps & DDSCAPS_COMPLEX)
+      {
+        // remove the flag
+        dwCaps &= ~DDSCAPS_COMPLEX;
+        #ifdef DEBUG
+          WriteLog("Complex Surface\n");
+        #endif
+
+        if(lpDDSurfaceDesc->dwFlags & DDSD_BACKBUFFERCOUNT)
+        {
+          lpDDSurfaceDesc->dwFlags &= ~DDSD_BACKBUFFERCOUNT;
+          #ifdef DEBUG
+            WriteLog("Backbuffer # = %d\n",lpDDSurfaceDesc->dwBackBufferCount);
+          #endif
+          memcpy(&ComplexSurfaceDesc,lpDDSurfaceDesc,sizeof(DDSURFACEDESC2));
+          ComplexSurfaceDesc.ddsCaps.dwCaps |= DDSCAPS_FLIP;        // set flip
+          ComplexSurfaceDesc.ddsCaps.dwCaps &= ~DDSCAPS_BACKBUFFER; // remove backbuffer
+
+          if(ComplexSurfaceDesc.dwBackBufferCount>1)
+          {
+            ComplexSurfaceDesc.dwBackBufferCount--;
+          }
+          else
+          {
+            ComplexSurfaceDesc.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
+            ComplexSurfaceDesc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
+          }
+
+          BackBuffer = new OS2IDirectDrawSurface(lpDraw, &ComplexSurfaceDesc, TRUE, Mainchain);
+          if (BackBuffer->GetLastError()==DD_OK)
+          {
+            DDSurfaceDesc.dwFlags |= DDSCAPS_FLIP;
+            BackBuffer->SetFrontBuffer(this);
+          }
+
+        }
+
+        // MipMap Surfaces are handled here
+        if( (lpDDSurfaceDesc->dwFlags & DDSD_MIPMAPCOUNT) &&
+            (dwCaps & DDSCAPS_TEXTURE) &&
+            (dwCaps & DDSCAPS_MIPMAP) )
+        {
+          dwCaps &= ~ (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP);
+
+          lpDDSurfaceDesc->dwFlags &= ~DDSD_MIPMAPCOUNT;
+          #ifdef DEBUG
+            WriteLog("Mipmpa # = %d\n",lpDDSurfaceDesc->dwMipMapCount);
+          #endif
+          memcpy(&ComplexSurfaceDesc,lpDDSurfaceDesc,sizeof(DDSURFACEDESC2));
+          ComplexSurfaceDesc.dwMipMapCount = 0;
+
+          for(int i =0; i < lpDDSurfaceDesc->dwMipMapCount; i++)
+          {
+            #ifdef DEBUG
+              WriteLog("Creating MipMap %d\n",i);
+            #endif
+            // Mpmaps shirnk by 2
+            ComplexSurfaceDesc.dwWidth  /= 2;
+            ComplexSurfaceDesc.dwHeight /= 2;
+            try
+            {
+              SurfaceSequenceMipMap.addAsLast(new OS2IDirectDrawSurface(lpDraw, &ComplexSurfaceDesc, TRUE),
+                                      *SurfaceCursorMipMap);
+            }
+            catch(IOutOfMemory)
+            {
+              #ifdef DEBUG
+                WriteLog("Internal : ISet.add OutOfMemory\n");
+              #endif
+              lastError = DDERR_OUTOFMEMORY;
+              return;
+            }
+            catch(ICursorInvalidException)
+            {
+              #ifdef DEBUG
+                WriteLog("Internal: Invalid Cursor\n");
+              #endif
+              lastError = DDERR_OUTOFMEMORY;
+              return;
+            }
+
+            if( !SurfaceCursorMipMap->isValid() )
+            {
+              // We shouldn't get in here as add sould have raised IOutOfMemory
+              // If it couldn't create the surface
+              #ifdef DEBUG
+                WriteLog("Internal : Cursor is Invalid => OutOfMemory\n");
+              #endif
+              lastError = DDERR_OUTOFMEMORY;
+              return;
+            }
+            else
+            {
+              AttachedSurface = SurfaceCursorMipMap->element();
+              if(AttachedSurface->GetLastError() != DD_OK)
+              {
+                lastError = AttachedSurface->GetLastError();
+                #ifdef DEBUG
+                  WriteLog("Attached surface creation returned error %d\n",lastError);
+                #endif
+                return;
+              } // Endif Errorcheck
+            } //Endif Cursorcheck
+          } //End for(i =0; i < lpDDSurfaceDesc->dwMipMapCount; i++)
+        } // End of MipMaps
+
+        #ifdef DEBUG
+          if(lpDDSurfaceDesc->dwFlags)
+            WriteLog("Unsupported Complex Surface\n");
+        #endif
+      } // Endif DDSCAPS_COMPLEX
+    }
+    else
+    {
+      lastError = DDERR_INVALIDPARAMS;
+    }
+  } // Endif DDCAPS is valid
+  else
+    lastError = DDERR_INVALIDPARAMS;
+
+  #ifdef DEBUG
+    WriteLog("Buf %X Screen Caps (%d,%d), bitcount %d\n\n", this, lpDraw->GetScreenHeight(), lpDraw->GetScreenWidth(),
+    lpDraw->dCaps.ulDepth);
+    if(DD_OK!=lastError)
+    {
+      WriteLog("Some Error Check Flags\n");
+      _dump_DDSCAPS(lpDDSurfaceDesc->dwFlags);
+    }
+  #endif
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT OS2IDirectDrawSurface::ColorFill(LPRECT lpDestRect,DWORD dwFillColor)
+{
+
+  int i,j, FillWidth, FillHeight;
+  char *pLine, *pFillPos;
+
+  DWORD *pColor, dwColor,y;
+
+  #ifdef DEBUG
+    WriteLog("ColorFill\n");
+  #endif
+
+  if(NULL!=lpDestRect)
+  {
+    #ifdef DEBUG
+      WriteLog("Fill only Rect(%d,%d)(%d,%d)\n", lpDestRect->left, lpDestRect->top,
+               lpDestRect->right, lpDestRect->bottom);
+    #endif
+    FillWidth  = lpDestRect->right - lpDestRect->left;
+    FillHeight = lpDestRect->bottom - lpDestRect->top -1;
+    pLine = pDiveBuffer +
+            (lpDestRect->top*dwPitchDB) +
+            (lpDestRect->left*dwBytesPPDive);
+  }
+  else
+  {
+    FillWidth  = width;
+    FillHeight = height -1;
+    pLine = pDiveBuffer;
+  }
+
+
+  switch(dwBytesPPDive)
+  {
+    case 1:
+      dwColor = (dwFillColor<<24) + (dwFillColor<<16) +
+                (dwFillColor<<8)  + (dwFillColor);
+      for(i=0,pColor = (DWORD*)pLine;i<(FillWidth/4);i++)
+        pColor[i] = dwColor;
+      if(FillWidth % 4)
+      {
+         pFillPos = (char*) (&pColor[i-1]);
+        for(i=0;i<FillWidth % 4;i++)
+         pFillPos[i] = (UCHAR) dwColor;
+      }
+      break;
+    case 2:
+      dwColor = (dwFillColor<<16) + (dwFillColor);
+      for(i=0,pColor = (DWORD*)pLine;i<(FillWidth/2);i++)
+        pColor[i] = dwColor;
+      if(FillWidth % 2)
+      {
+         pFillPos = (char*)(&pColor[i-1]);
+        *((USHORT*)pFillPos) = (USHORT)dwColor;
+      }
+      break;
+    case 3:
+      dwColor = (dwFillColor<<8);
+      for(i=0 ; i<FillWidth ; i++)
+      {
+         char* pColor = (char*)pLine+(i*3);
+        *pColor = dwColor;
+      }
+      break;
+    case 4:
+      dwColor = dwFillColor;
+      for(i=0,pColor = (DWORD*)pLine;i<FillWidth;i++)
+        pColor[i] = dwColor;
+      break;
+    default:
+      #ifdef DEBUG
+        WriteLog("Unexpected Bitdepth\n");
+      #endif
+      return DDERR_GENERIC;
+  } // end switch(dest->DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount)
+
+
+  pFillPos = pLine + dwPitchDB;
+
+  for( y=0;y<FillHeight;y++,pFillPos+=dwPitchDB)
+  {
+    #ifdef USE_ASM
+      // ToDo get the loop into an asm function as well to speed up filling
+      // maybe remove the creation of the first fill line in an all asm
+      // function and use MMX regs to set 8 bytes
+      MemFlip(pFillPos,pLine,FillWidth);
+    #else
+      memcpy(pFillPos,pLine,FillWidth);
+    #endif
+  }
+
+  return(DD_OK);
+
+#if 0 // rest of old code for resuse/move to a function to get closest syscolor
+      // for colorconversion modes color fills
+  else
+  {
+    // Yeah! Color conversion needed ;)
+    #ifdef DEBUG
+       WriteLog("Color converion ! Urks, may not work \n");
+    #endif
+
+    switch(dest->lpDraw->dCaps.ulDepth)
+    {
+      case 8:  // 256 Mode bad thing as programm wants to run in a higher mode might look ugly
+        GetSystemPaletteEntries(GetDC(HWND_DESKTOP),0,255,&SysPal[1]);
+        pLogPal->palVersion = 0;
+        pLogPal->palNumEntries = 256;
+
+        hPal = CreatePalette(pLogPal);
+        if(hPal!=NULL)
+        {
+          if(dest->DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount==16)
+          {
+            ulColor = ((lpDDBltFx->dwFillColor & 0x0000001F) <<3) +
+                      ((lpDDBltFx->dwFillColor & 0x000007E0) <<5) +
+                      ((lpDDBltFx->dwFillColor & 0x0000F800) <<8);
+          }
+          else
+            ulColor = lpDDBltFx->dwFillColor;
+
+          ulColor = GetNearestPaletteIndex(hPal,ulColor);
+          ulColor = (ulColor & 0x000000FF) + ((ulColor & 0x000000FF) << 8) +
+                    ((ulColor & 0x000000FF) << 16) + ((ulColor & 0x000000FF) << 24);
+        }
+        else
+        {
+          #ifdef DEBUG
+            WriteLog("Error creating Palette default to 0");
+          #endif
+          ulColor = 0;
+        }
+        for(i=0,(char*)pColor = ScanLine;i<(FillWidth/4)+1;i++)
+           *(pColor+i) = ulColor;
+        break;
+      case 16:
+        if(dest->DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount==8)
+        {
+          if(lpDDBltFx->dwFillColor > 255)
+            return DDERR_INVALIDPARAMS;
+
+          if(dest->lpPalette!=NULL)
+            dest->lpPalette->lpVtbl->GetEntries(dest->lpPalette,0,0,256,(LPPALETTEENTRY)&SysPal);
+          else
+            GetSystemPaletteEntries(GetDC(HWND_DESKTOP),0,255,(PPALETTEENTRY)&SysPal);
+
+          SysPal[lpDDBltFx->dwFillColor].peBlue  >>3;
+          SysPal[lpDDBltFx->dwFillColor].peGreen >>2;
+          SysPal[lpDDBltFx->dwFillColor].peRed   >>3;
+          ulColor = ULONG(SysPal[lpDDBltFx->dwFillColor].peRed) << 11 +
+                    ULONG(SysPal[lpDDBltFx->dwFillColor].peGreen) << 5 +
+                    ULONG(SysPal[lpDDBltFx->dwFillColor].peBlue);
+        }
+        else
+        {
+          ulColor = (lpDDBltFx->dwFillColor & 0x000000FF)>>3 +
+                    (((lpDDBltFx->dwFillColor & 0x0000FF00)>>5) & 0x000007E0) +
+                    (((lpDDBltFx->dwFillColor & 0x00FF0000)>>8) & 0x0000F800);
+        }
+        ulColor += ulColor << 16;
+        for(i=0,(char*)pColor = ScanLine;i<(FillWidth/2)+1;i++)
+          *(pColor+i) = ulColor;
+        break;
+      case 24:
+        if(dest->DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount==8)
+        {
+          if(lpDDBltFx->dwFillColor > 255)
+            return DDERR_INVALIDPARAMS;
+
+          if(dest->lpPalette!=NULL)
+            dest->lpPalette->lpVtbl->GetEntries(dest->lpPalette,0,0,256,(LPPALETTEENTRY)&SysPal);
+          else
+            GetSystemPaletteEntries(GetDC(HWND_DESKTOP),0,255,(PPALETTEENTRY)&SysPal);
+
+          ulColor = ULONG(SysPal[lpDDBltFx->dwFillColor].peRed) <<24 +
+                    ULONG(SysPal[lpDDBltFx->dwFillColor].peGreen) <<16 +
+                    ULONG(SysPal[lpDDBltFx->dwFillColor].peBlue) <<8;
+        }
+        else
+        {
+          if(dest->DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount==16)
+          {
+            ulColor = ((lpDDBltFx->dwFillColor & 0x0000001F) <<11) +
+                       ((lpDDBltFx->dwFillColor & 0x000007E0) <<13) +
+                       ((lpDDBltFx->dwFillColor & 0x0000F800) <<18);
+          }
+          else
+            ulColor = lpDDBltFx->dwFillColor << 8 ;
+        }
+
+        for(i=0;i<FillWidth;i++)
+        {
+          char* pColor = (char*)Scanline+(i*3);
+          *pColor = ulColor;
+        }
+        break;
+      case 32:
+        if(dest->DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount==8)
+        {
+          if(lpDDBltFx->dwFillColor > 255)
+            return DDERR_INVALIDPARAMS;
+
+          if(dest->lpPalette!=NULL)
+            dest->lpPalette->lpVtbl->GetEntries(dest->lpPalette,0,0,256,(LPPALETTEENTRY)&SysPal);
+          else
+            GetSystemPaletteEntries(GetDC(HWND_DESKTOP),0,255,(PPALETTEENTRY)&SysPal);
+
+          ulColor = ULONG(SysPal[lpDDBltFx->dwFillColor].peRed) <<16 +
+                    ULONG(SysPal[lpDDBltFx->dwFillColor].peGreen) <<8 +
+                    ULONG(SysPal[lpDDBltFx->dwFillColor].peBlue);
+        }
+        else
+        {
+          if(dest->DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount==16)
+          {
+            ulColor = ((lpDDBltFx->dwFillColor & 0x0000001F) <<3) +
+                      ((lpDDBltFx->dwFillColor & 0x000007E0) <<5) +
+                      ((lpDDBltFx->dwFillColor & 0x0000F800) <<8);
+          }
+          else
+            ulColor = lpDDBltFx->dwFillColor & 0x00FFFFFF;
+        }
+
+        for(i=0,(char*)pColor = ScanLine;i<(FillWidth/4);i++)
+          *(pColor+i) = ulColor;
+        break;
+      default:
+        #ifdef DEBUG
+          WriteLog("Unexpected Bitdepth\n");
+        #endif
+        return DDERR_GENERIC;
+    } // end switch (dest->lpDraw->dCaps.ulDepth)
+  }// end of Scanline setup
+#endif
+
+}
+//******************************************************************************
+//******************************************************************************
+void OS2IDirectDrawSurface::ColorConversion(LPRECT lpRect)
+{
+  SETUP_BLITTER sBlt;
+  ULONG ulDN1, ulDN2;
+
+  ulDN1 = ulDN2 = 0;
+
+  memset(&sBlt,0,sizeof(sBlt));
+  sBlt.ulStructLen = sizeof(sBlt);
+  sBlt.fccSrcColorFormat = (FOURCC) DDSurfaceDesc.ddpfPixelFormat.dwFourCC;
+  if (NULL!=lpRect)
+  {
+    sBlt.ulSrcWidth        = lpRect->right - lpRect->left;
+    sBlt.ulSrcHeight       = lpRect->top   - lpRect->bottom;
+    sBlt.ulSrcPosX         = lpRect->left;
+    sBlt.ulSrcPosY         = height - lpRect->top;
+  }
+  else
+  {
+    sBlt.ulSrcWidth        = width;
+    sBlt.ulSrcHeight       = height;
+    sBlt.ulSrcPosX         = 0;
+    sBlt.ulSrcPosY         = 0;
+  }
+  sBlt.fccDstColorFormat = FOURCC_SCRN;
+  sBlt.ulDstWidth        = sBlt.ulSrcWidth;
+  sBlt.ulDstHeight       = sBlt.ulSrcHeight;
+  sBlt.lDstPosX          = sBlt.ulSrcPosX;
+  sBlt.lDstPosY          = sBlt.ulSrcPosY;
+  sBlt.ulNumDstRects     = DIVE_FULLY_VISIBLE;
+
+  DiveAllocImageBuffer( hDiveCC,
+                        &ulDN1,
+                        sBlt.fccSrcColorFormat,
+                        width,
+                        height,
+                        dwPitchFB,
+                        (PBYTE)pFrameBuffer);
+  DiveAllocImageBuffer( hDiveCC,
+                        &ulDN2,
+                        sBlt.fccDstColorFormat,
+                        width,
+                        height,
+                        dwPitchDB,
+                        (PBYTE)pDiveBuffer);
+  DiveSetupBlitter(hDiveCC,&sBlt);
+  DiveBlitImage(hDiveCC,ulDN1,ulDN2);
+  DiveFreeImageBuffer(hDiveCC,ulDN1);
+  DiveFreeImageBuffer(hDiveCC,ulDN2);
 }
 //******************************************************************************
@@ -250,36 +1131,143 @@
 OS2IDirectDrawSurface::~OS2IDirectDrawSurface()
 {
-  if(diveBufNr != -1) {
-    if(fLocked)
+  OS2IDirectDrawSurface  *AttachedSurface;
+
+  if(DDSurfaceDesc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
+  {
+    lpDraw->SetPrimarySurface(FALSE);
+    if(lpPalette)
+      lpPalette->RestorePhysPalette();
+  }
+  else
+  {
+    if( diveBufNr != -1)
+    {
+      if(fLocked)
         DiveEndImageBufferAccess(hDive, diveBufNr);
+      DiveFreeImageBuffer(hDive, diveBufNr);
+    }
+    else
+    {
+      // Memory Surfaces
+      if (!Updated)  // check for user handled buffer
+        free(DDSurfaceDesc.lpSurface);
+    }
+
+
     fLocked = FALSE;
-    DiveFreeImageBuffer(hDive, diveBufNr);
     diveBufNr = -1;
   }
-  if(lpClipper) {
+
+  // Free the translation buffer
+  if(pFrameBuffer != pDiveBuffer)
+    free(pDiveBuffer);
+
+  // Clear the list of locked rectangles
+  if (!LockedRectSequence.isEmpty())
+    LockedRectSequence.removeAll();
+
+  if(lpClipper)
+  {
     lpClipper->Vtbl.Release((IDirectDrawClipper*)lpClipper);
     lpClipper = NULL;
   }
-  if(lpPalette) {
-    if(surfaceType & DDSCAPS_PRIMARYSURFACE)
-        lpPalette->RestorePhysPalette();
+
+  if(lpPalette)
+  {
     lpPalette->Vtbl.Release((IDirectDrawPalette*)lpPalette);
     lpPalette = NULL;
   }
-  if(lpBuffer)
-    OS2FreeMem((char *)lpBuffer);
+
   if(hbmImage)
-    DeleteObject((HANDLE)hbmImage);
+    DeleteObject(hbmImage);
+
   if(hdcImage)
     DeleteDC(hdcImage);
-  if(bitmapData)
-    free(bitmapData);
-  lpDraw->Vtbl.Release((IDirectDraw2*)lpDraw);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall SurfQueryInterface(THIS, REFIID riid, LPVOID FAR * ppvObj)
-{
-  dprintf(("OS2IDirectDrawSurface::SurfQueryInterface\n"));
+
+  if (NULL!=BackBuffer)
+    BackBuffer->Vtbl.Release(AttachedSurface);
+
+  while( !SurfaceSequenceMipMap.isEmpty())
+  {
+    try
+    {
+      AttachedSurface = SurfaceSequenceMipMap.firstElement();
+      AttachedSurface->Vtbl.Release(AttachedSurface);
+      SurfaceSequenceMipMap.removeFirst();
+    }
+    catch(...)
+    {
+      #ifdef DEBUG
+        WriteLog("Internal : Error deleting MipMap Surfaces\n");
+      #endif
+    }
+  }
+
+  while( !SurfaceSequenceAttached.isEmpty())
+  {
+    try
+    {
+      AttachedSurface = SurfaceSequenceAttached.firstElement();
+      AttachedSurface->Vtbl.Release(AttachedSurface);
+      SurfaceSequenceAttached.removeFirst();
+    }
+    catch(...)
+    {
+      #ifdef DEBUG
+        WriteLog("Internal : Error deleting other attached\n");
+      #endif
+    }
+  }
+
+  lpDraw->Vtbl.Release(lpDraw);
+}
+//******************************************************************************
+//******************************************************************************
+inline  void OS2IDirectDrawSurface::SetFrontBuffer( OS2IDirectDrawSurface* NewFBuffer)
+{
+  FrontBuffer = NewFBuffer;
+  if (NULL==NewFBuffer)
+  {
+    // The real Frontbuffer was removed check if I'm now the one
+    if(NULL!=BackBuffer)
+    {
+      DDSurfaceDesc.ddsCaps.dwCaps &= ~DDSCAPS_BACKBUFFER;
+      DDSurfaceDesc.ddsCaps.dwCaps |=  DDSCAPS_FRONTBUFFER;
+      BackBuffer->SetFrontBuffer(this);
+    }
+    else
+    {
+      // Flipchain is destroyed
+      DDSurfaceDesc.ddsCaps.dwCaps &= ~(DDSCAPS_BACKBUFFER | DDSCAPS_FLIP);
+    }
+  }
+  else
+  {
+    if(NULL==NewFBuffer->GetFrontBuffer())
+    {
+      DDSurfaceDesc.ddsCaps.dwCaps |=  DDSCAPS_BACKBUFFER | DDSCAPS_FLIP;
+    }
+    else
+    {
+      DDSurfaceDesc.ddsCaps.dwCaps &=  ~DDSCAPS_BACKBUFFER ;
+      DDSurfaceDesc.ddsCaps.dwCaps |=  DDSCAPS_FLIP;
+    }
+
+    if(NULL!=BackBuffer)
+      BackBuffer->SetFrontBuffer(this);
+
+    DDSurfaceDesc.ddsCaps.dwCaps &= ~DDSCAPS_FRONTBUFFER;
+  }
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfQueryInterface(THIS This, REFIID riid, LPVOID FAR * ppvObj)
+{
+  // ToDo: Add Interface handling for D3D Textures
+
+  #ifdef DEBUG
+    WriteLog("OS2IDirectDrawSurface::SurfQueryInterface\n");
+  #endif
+
   *ppvObj = NULL;
 
@@ -297,826 +1285,2676 @@
 //******************************************************************************
 //******************************************************************************
-ULONG __stdcall SurfAddRef(THIS)
+ULONG __stdcall SurfAddRef(THIS This)
 {
  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
 
-  dprintf(("OS2IDirectDrawSurface::SurfAddRef %d\n", me->Referenced+1));
+  #ifdef DEBUG
+    WriteLog("OS2IDirectDrawSurface::SurfAddRef %d\n", me->Referenced+1);
+  #endif
+
   return ++me->Referenced;
 }
 //******************************************************************************
 //******************************************************************************
-ULONG __stdcall SurfRelease(THIS)
+ULONG __stdcall SurfRelease(THIS This)
 {
  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
 
-  dprintf(("OS2IDirectDrawSurface::SurfRelease %d\n", me->Referenced-1));
-  if(me->Referenced) {
+  #ifdef DEBUG
+    WriteLog("OS2IDirectDrawSurface::SurfRelease %d\n", me->Referenced-1);
+    WriteLog("OS2IDirectDrawSurface::Surface %X\n", me);
+  #endif
+  if(me->Referenced)
+  {
     me->Referenced--;
-    if(me->Referenced == 0) {
-        delete me;
-        return(0);
-    }
-    else    return me->Referenced;
-  }
-  else  return(0);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall SurfAddAttachedSurface(THIS_ LPDIRECTDRAWSURFACE2)
-{
-  dprintf(("SurfAddAttachedSurfacer\n"));
+    if(me->Referenced == 0)
+    {
+      delete me;
+      #ifndef __WATCOMC__
+        //_interrupt(3);
+      #endif
+      return(0);
+    }
+    else
+      return me->Referenced;
+  }
+  else
+    return(0);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfAddAttachedSurface(THIS This, LPDIRECTDRAWSURFACE2 lpDDSurface)
+{
+
+  #ifdef DEBUG
+    WriteLog("SurfAddAttachedSurface\n");
+  #endif
+  return SurfAddAttachedSurface4(This, (LPDIRECTDRAWSURFACE4)lpDDSurface);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfAddAttachedSurface4(THIS This, LPDIRECTDRAWSURFACE4 lpDDSurface)
+{
+  OS2IDirectDrawSurface *AttachedSurface;
+  OS2IDirectDrawSurface *BBCursor;
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+  #ifdef DEBUG
+    WriteLog("SurfAddAttachedSurface4\n");
+  #endif
+
+  if (NULL==lpDDSurface)
+    return DDERR_INVALIDPARAMS;
+
+  AttachedSurface = (OS2IDirectDrawSurface*) lpDDSurface;
+
+  if(AttachedSurface->IsImplicitSurface())
+  {
+    #ifdef DEBUG
+     WriteLog("Internal : Can't attach an implicit created surface to an other surface\n");
+    #endif
+    return(DDERR_CANNOTATTACHSURFACE);
+  }
+
+  if(This == AttachedSurface)
+  {
+    #ifdef DEBUG
+     WriteLog("Can't attach an surface to itself\n");
+    #endif
+    return(DDERR_CANNOTATTACHSURFACE);
+  }
+
+  if(AttachedSurface->DDSurfaceDesc.ddsCaps.dwCaps & DDSCAPS_TEXTURE)
+  {
+    if(AttachedSurface->DDSurfaceDesc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
+    {
+      if(me->DDSurfaceDesc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
+      {
+        try
+        {
+          me->SurfaceSequenceMipMap.addAsLast(AttachedSurface);
+          me->SurfaceCursorMipMap->setToFirst();
+
+          me->DDSurfaceDesc.dwFlags |= DDSD_MIPMAPCOUNT;
+          me->DDSurfaceDesc.dwMipMapCount++;
+
+          AttachedSurface->Vtbl.AddRef(AttachedSurface);
+        }
+        catch(...)
+        {
+          #ifdef DEBUG
+            WriteLog("Internal : Error attaching to MipMap\n");
+          #endif
+          return(DDERR_CANNOTATTACHSURFACE);
+        }
+      }
+      else
+      {
+        #ifdef DEBUG
+          WriteLog("Target Surface isn't a MipMap\n");
+        #endif
+        return(DDERR_CANNOTATTACHSURFACE);
+      }
+    }
+    else
+    {
+      try
+      {
+        me->SurfaceSequenceAttached.addAsLast(AttachedSurface);
+        // add made the last cursor invalid so start from the begining
+        me->SurfaceCursorAttached->setToFirst();
+
+        AttachedSurface->Vtbl.AddRef(AttachedSurface);
+      }
+      catch(...)
+      {
+        #ifdef DEBUG
+          WriteLog("Internal : Error attaching to general Set\n");
+        #endif
+        return(DDERR_CANNOTATTACHSURFACE);
+      }
+    }
+  } // endif DDSCAPS_TEXTURE
+  else
+  {
+    if( (AttachedSurface->DDSurfaceDesc.dwWidth != me->DDSurfaceDesc.dwWidth)
+        || (AttachedSurface->DDSurfaceDesc.dwHeight != me->DDSurfaceDesc.dwHeight)
+    //    || (AttachedSurface->DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount !=
+    //        me->DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount)
+       )
+    {
+      #ifdef DEBUG
+        WriteLog("Surfaces don't have same dimensions\n");
+      #endif
+      return(DDERR_CANNOTATTACHSURFACE);
+    }
+    else
+    {
+      if(AttachedSurface->DDSurfaceDesc.ddsCaps.dwCaps & DDSCAPS_BACKBUFFER)
+      {
+        if( (AttachedSurface->GetFrontBuffer()!=NULL) || (AttachedSurface->BackBuffer!= NULL))
+        {
+          #ifdef DEBUG
+            WriteLog("Surfaces already has a front/backbuffer\n");
+          #endif
+          return(DDERR_SURFACEALREADYATTACHED);
+        }
+
+        if(me->DDSurfaceDesc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
+        {
+          if(NULL!=me->BackBuffer)
+          {
+            BBCursor = me->BackBuffer;
+            while(NULL!=BBCursor)
+            {
+              BBCursor->DDSurfaceDesc.dwFlags |= DDSD_BACKBUFFERCOUNT;
+              BBCursor->DDSurfaceDesc.dwBackBufferCount++;
+              BBCursor->DDSurfaceDesc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
+              BBCursor = BBCursor->BackBuffer;
+            }
+            BBCursor->BackBuffer = AttachedSurface;
+            AttachedSurface->SetFrontBuffer(BBCursor);
+          }
+          else
+          {
+            me->BackBuffer = AttachedSurface;
+            AttachedSurface->SetFrontBuffer(me);
+          }
+          me->DDSurfaceDesc.dwFlags |= DDSD_BACKBUFFERCOUNT;
+          me->DDSurfaceDesc.dwBackBufferCount++;
+          me->DDSurfaceDesc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
+
+          AttachedSurface->Vtbl.AddRef(AttachedSurface);
+          return (DD_OK);
+        }
+        else
+        {
+          #ifdef DEBUG
+            WriteLog("Can't attach backbuffer to anything but a frontbuffer\n");
+          #endif
+         return(DDERR_CANNOTATTACHSURFACE);
+        }
+      }
+      else
+      {
+        if(AttachedSurface->DDSurfaceDesc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
+        {
+          if(me->DDSurfaceDesc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
+          {
+            try
+            {
+              me->SurfaceSequenceMipMap.addAsLast(AttachedSurface);
+              me->SurfaceCursorMipMap->setToFirst();
+
+              me->DDSurfaceDesc.dwFlags |= DDSD_MIPMAPCOUNT;
+              me->DDSurfaceDesc.dwMipMapCount++;
+              me->DDSurfaceDesc.ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
+
+              AttachedSurface->Vtbl.AddRef(AttachedSurface);
+            }
+            catch(...)
+            {
+              #ifdef DEBUG
+                WriteLog("Internal : Error attaching to MipMap\n");
+              #endif
+             return(DDERR_CANNOTATTACHSURFACE);
+            }
+          }
+          else
+          {
+            #ifdef DEBUG
+              WriteLog("Tagget Surface isn't a MipMap\n");
+            #endif
+           return(DDERR_CANNOTATTACHSURFACE);
+          }
+        }
+        else
+        {
+          try
+          {
+            me->SurfaceSequenceAttached.addAsLast(AttachedSurface);
+            // add made the last cursor invalid so start from the begining
+            me->SurfaceCursorAttached->setToFirst();
+
+            AttachedSurface->Vtbl.AddRef(AttachedSurface);
+          }
+          catch(...)
+          {
+            #ifdef DEBUG
+              WriteLog("Internal : Error attaching to general Set\n");
+            #endif
+           return(DDERR_CANNOTATTACHSURFACE);
+          }
+        }
+      }// End if not DDSCAPS_BACKBUFFER
+    }
+  }
+
   return(DD_OK);
 }
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall SurfAddOverlayDirtyRect(THIS_ W32_LPRECT)
-{
-  dprintf(("SurfAddOverlayDirtyRect\n"));
+HRESULT __stdcall SurfAddOverlayDirtyRect(THIS, LPRECT)
+{
+  #ifdef DEBUG
+    WriteLog("SurfAddOverlayDirtyRect Not implemented by M$ in V 6.0! \n");
+  #endif
+
   return(DD_OK);
 }
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall SurfBlt(THIS_ W32_LPRECT lpDestRect, LPDIRECTDRAWSURFACE2 lpDDSrcSurface,
-              W32_LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx)
-{
+HRESULT __stdcall SurfBlt(THIS This, LPRECT lpDestRect, LPDIRECTDRAWSURFACE2 lpDDSrcSurface,
+        LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx)
+{
+ return SurfBlt4( This,
+                  lpDestRect,
+                  (LPDIRECTDRAWSURFACE4)lpDDSrcSurface,
+                  lpSrcRect,
+                  dwFlags,
+                  lpDDBltFx);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfBlt4(THIS This, LPRECT lpDestRect, LPDIRECTDRAWSURFACE4 lpDDSrcSurface,
+        LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx)
+{
+   // We have determine between 3 different blit senarios.
+   // 1. Blitting between Divebuffers (Front/Backbuffer and primary surface)
+   // 2. Blitting between memory and Divebuffers (Front/Backbuffer and primary surface).
+   // 3. Blitting between memory buffers.
+   // 1 and 3 are easy. DiveBlitImage or memcpy will do the job for non transparent blits
+   // 2 is now also easy as we do colorconverion via Dive after each unlocking of a surface
+   // The advantage is that we don't have to call DiveSetupBlitter each time. The Blitter will be
+   // setup only when the screen resolution is changed by ddraw. I guess we should see a big performance
+   // increase by doing it this way, unless the software blits directly from memory to the primary surface)
+   // But even then this could be faster as the SetupBlitter call is timeconsumeing and DIVE does emulate
+   // the blit in SW anyway as there is no interface in the driver to blit with HW support from the sysmem.
+
  OS2IDirectDrawSurface *dest = (OS2IDirectDrawSurface *)This;
  OS2IDirectDrawSurface *src  = (OS2IDirectDrawSurface *)lpDDSrcSurface;
- SETUP_BLITTER          blit;
- ULONG                  rc;
+ ISequence<IRectangle*>::Cursor *EnumCursor;
+
+ HRESULT                rc;
+ ULONG                  ulColor, *pColor;
  RECTL                  cliprect;
 
-  dprintf(("SurfBlt to (%d,%d)(%d,%d) from (%d,%d)(%d,%d)\n", lpDestRect->left, lpDestRect->top,
-           lpDestRect->right, lpDestRect->bottom, lpSrcRect->left, lpSrcRect->top,
-       lpSrcRect->right, lpSrcRect->bottom));
-
-  blit.ulStructLen = sizeof(blit);
-  blit.fInvert     = FALSE;
-  blit.fccSrcColorFormat = src->fccColorFormat;
-  blit.ulSrcWidth  = lpSrcRect->right  - lpSrcRect->left;
-  blit.ulSrcHeight = lpSrcRect->bottom - lpSrcRect->top;
-  blit.ulSrcPosX   = lpSrcRect->left;
-  blit.ulSrcPosY   = lpSrcRect->top;
-
-  blit.fccDstColorFormat = dest->fccColorFormat;
-  blit.ulDstWidth  = lpDestRect->right  - lpDestRect->left;
-  blit.ulDstHeight = lpDestRect->bottom - lpDestRect->top;
-  blit.lDstPosX    = lpDestRect->left;
-  blit.lDstPosY    = dcaps.ulVerticalResolution - lpDestRect->bottom;
-  blit.lScreenPosX = 0;
-  blit.lScreenPosY = 0;
-  blit.ulNumDstRects = 1;
-  blit.pVisDstRects  = &cliprect;
-  cliprect.top     = 0;
-  cliprect.bottom  = dcaps.ulVerticalResolution;
-  cliprect.left    = lpDestRect->left;
-  cliprect.right   = lpDestRect->right;
-#if 0
-  rc = DiveSetupBlitter(dest->hDive, &blit);
-  if(rc != DIVE_SUCCESS) {
-    dprintf(("Error setting up blitter %d\n", rc));
-    return(DDERR_GENERIC);
-  }
-  rc = DiveBlitImage(dest->hDive, src->diveBufNr, dest->diveBufNr);
-  if(rc != DIVE_SUCCESS) {
-    dprintf(("Error while blitting %d\n", rc));
-    return(DDERR_GENERIC);
-  }
-#else
-  char *srcbuf, *destbuf;
-  ULONG srcscanbytes, destscanbytes, i, nrScanLines;
-  OS2RECTL rectl;
-
-  if(dest->diveBufNr == DIVE_BUFFER_SCREEN) {
-        dprintf(("Dest == DIVE_BUFFER_SCREEN\n"));
-        rectl.xLeft    = blit.lDstPosX;
-        rectl.yBottom  = blit.lDstPosY;
-        rectl.xRight   = blit.lDstPosX + blit.ulSrcWidth;
-        rectl.yTop     = blit.lDstPosY + blit.ulSrcHeight;
-        destscanbytes  = dcaps.ulHorizontalResolution;
-        destbuf        = dest->pFrameBuffer;
-        rc = DiveAcquireFrameBuffer(dest->hDive, (PRECTL)&rectl);
-        if(rc != DIVE_SUCCESS) {
-            dprintf(("frame buffer access error %d\n", rc));
-            return(DDERR_INVALIDPARAMS);
-        }
-  }
-  else {
-    rc = DiveBeginImageBufferAccess(dest->hDive, dest->diveBufNr, (PBYTE *)&destbuf,
-                            &destscanbytes, &nrScanLines);
-    if(rc != DIVE_SUCCESS) {
-        dprintf(("dest bufffer access error %d\n", rc));
-        return(DDERR_INVALIDPARAMS);
-    }
-  }
-  rc = DiveBeginImageBufferAccess(src->hDive, src->diveBufNr, (PBYTE *)&srcbuf,
-                      &srcscanbytes, &nrScanLines);
-  if(rc != DIVE_SUCCESS) {
-    dprintf(("src bufffer access error %d\n", rc));
+ int                    x, y, i, j, BlitWidth, BlitHeight;
+ PALETTEENTRY           SysPal[257];
+ PLOGPALETTE            pLogPal = (PLOGPALETTE) SysPal;
+ char                   *pBltPos, *pSrcPos;
+ DDSURFACEDESC2         DestSurfaceDesc, SrcSurfaceDesc;
+ IRectangle             *pIRectDest,*pIRectSrc,*pIRectTest;
+ RECTL                  DestRect, SrcRect;
+ BOOL Found;
+ DWORD dwSrcColor, dwDestColor;
+
+  #ifdef DEBUG
+    if ( (NULL!=lpDestRect)&& (NULL!=lpSrcRect))
+      WriteLog("SurfBlt4 to (%d,%d)(%d,%d) from (%d,%d)(%d,%d)\n", lpDestRect->left, lpDestRect->top,
+               lpDestRect->right, lpDestRect->bottom, lpSrcRect->left, lpSrcRect->top,
+               lpSrcRect->right, lpSrcRect->bottom);
+  #endif
+
+  if (NULL!=lpDestRect)
+  {
+    pIRectDest = new IRectangle( lpDestRect->left,
+                                 lpDestRect->bottom,
+                                 lpDestRect->right,
+                                 lpDestRect->top);
+    memcpy(&DestRect,lpDestRect,sizeof(RECTL) );
+  }
+  else
+  {
+    pIRectDest = new IRectangle( 0, dest->height, dest->width, 0);
+    DestRect.top    = 0;
+    DestRect.left   = 0;
+    DestRect.bottom = dest->height;
+    DestRect.right  = dest->width;
+  }
+
+  if(dest->fLocked)
+  {
+    if (NULL==lpDestRect)
+    {
+      // If anything is locked we can't blit to the complete surface as
+      // a part is locked
+      Found = TRUE;
+    }
+    else
+    {
+      // If the dest Rectangle intersects with any of the locked rectangles
+      // we can't blit to it
+
+      EnumCursor = dest->LockedRectSequence.newCursor();
+      EnumCursor->setToFirst();
+      Found = FALSE;
+
+      while((EnumCursor->isValid() ) && !Found)
+      {
+        pIRectTest = EnumCursor->element();
+        Found = pIRectDest->intersects(*pIRectTest);
+        EnumCursor->setToNext();
+      }
+
+      delete EnumCursor;
+
+    }
+
+    if (Found)
+    {
+      delete pIRectDest;
+      #ifdef DEBUG
+        WriteLog("Blt: Dest Surface partly locked\n");
+      #endif
+      return(DDERR_SURFACEBUSY);
+    }
+  }
+
+  DestSurfaceDesc.dwSize = sizeof(DDSURFACEDESC2);
+  SrcSurfaceDesc.dwSize = sizeof(DDSURFACEDESC2);
+
+  // First check the simple first
+
+  dwFlags &= ~(DDBLT_WAIT|DDBLT_ASYNC); // FIXME: can't handle right now
+
+  if(dwFlags & DDBLT_COLORFILL)
+  {
+    if((NULL==lpDDBltFx)||(lpDDBltFx->dwSize!=sizeof(DDBLTFX)) )
+      return DDERR_INVALIDPARAMS;
+
+    // ToDo : as we fill the DiveBuffer check if we need to convert the
+    // specified color
+
+    dest->ColorFill(lpDestRect,lpDDBltFx->dwFillColor);
+
+    return(DD_OK); // according to the M$ DDK only one flag shall/can be set.
+  } // end of colorfill
+
+  if (dwFlags & DDBLT_DEPTHFILL)
+  {
+  #ifdef USE_OPENGL
+    GLboolean ztest;
+    // Todo support more than one Z-Buffer
+    // Clears the screen
+    WriteLog("Filling depth buffer with %ld\n", lpbltfx->b.dwFillDepth);
+    glClearDepth(lpDDBltFx->b.dwFillDepth / 65535.0); // We suppose a 16 bit Z Buffer
+    glGetBooleanv(GL_DEPTH_TEST, &ztest);
+    glDepthMask(GL_TRUE); // Enables Z writing to be sure to delete also the Z buffer
+    glClear(GL_DEPTH_BUFFER_BIT);
+    glDepthMask(ztest);
+
+    return (DD_OK);
+  #endif // USE_OPENGL
+  }
+
+  if(dwFlags & DDBLT_ROP)
+  {
+    // HEL and we only support the following ROPS
+    // SRC_COPY
+    // BLACKNESS
+    // WHITENESS
+    //
+    if(lpDDBltFx->dwROP & SRCCOPY)
+      dwFlags = 0;  // srccopy is a normal fast blt
+    else
+    {
+      if(lpDDBltFx->dwROP & BLACKNESS)
+      {
+        if(1==dest->dwBytesPPDive)
+        {
+          // ToDo: Realy implement code to get the correct index for black in 8 Bitmode
+          dest->ColorFill(lpDestRect, 0 );
+        }
+        else
+          dest->ColorFill(lpDestRect, 0);
+        return DD_OK;
+      }
+
+      if(lpDDBltFx->dwROP & WHITENESS)
+      {
+        if(1==dest->dwBytesPPDive)
+        {
+          // ToDo: Realy implement code to get the correct index for black in 8 Bitmode
+          dest->ColorFill(lpDestRect, 0xFFFFFFFF );
+        }
+        else
+          dest->ColorFill(lpDestRect, 0xFFFFFFFF);
+        return DD_OK;
+      }
+
+      return DDERR_NORASTEROPHW;
+    }
+  }
+
+  if(NULL==src)
+  {
+    #ifdef DEBUG
+      WriteLog("Unsupported sourceless FX operation. Flags = 0x%04X\n",dwFlags);
+    #endif
+    return DD_OK;
+  }
+
+  if (NULL!=lpSrcRect)
+  {
+    pIRectSrc = new IRectangle( lpSrcRect->left,
+                                lpSrcRect->bottom,
+                                lpSrcRect->right,
+                                lpSrcRect->top);
+    memcpy(&SrcRect,lpSrcRect,sizeof(RECTL) );
+  }
+  else
+  {
+    pIRectSrc = new IRectangle( 0, src->height, src->width, 0);
+    SrcRect.top    = 0;
+    SrcRect.left   = 0;
+    SrcRect.bottom = src->height;
+    SrcRect.right  = src->width;
+  }
+
+  if(src->fLocked)
+  {
+    if (NULL==lpSrcRect)
+    {
+      // If anything is locked we can't blit from the complete surface as
+      // a part is locked
+      Found = TRUE;
+    }
+    else
+    {
+      // If the src Rectangle intersects with any of the locked rectangles of the
+      // source surface we can't blit from it
+
+      EnumCursor = src->LockedRectSequence.newCursor();
+      EnumCursor->setToFirst();
+      Found = FALSE;
+
+      while((EnumCursor->isValid() ) && !Found)
+      {
+        pIRectTest = EnumCursor->element();
+        Found = pIRectSrc->intersects(*pIRectTest);
+        EnumCursor->setToNext();
+      }
+
+      delete EnumCursor;
+
+    }
+
+    if (Found)
+    {
+      delete pIRectSrc;
+      #ifdef DEBUG
+        WriteLog("Blt: Src Surface partly locked\n");
+      #endif
+      return(DDERR_SURFACEBUSY);
+    }
+  }
+
+  if( ( (NULL==lpDestRect) && (NULL!=lpSrcRect) ) ||
+      ( (NULL==lpSrcRect) && (NULL!=lpDestRect) ) )
+  {
+    #ifdef DEBUG
+      WriteLog("Blitting with scaleing\n Not supported.\n");
+    #endif
+    return DDERR_NOSTRETCHHW;
+  }
+
+  if( ( pIRectDest->width()  != pIRectSrc->width() ) ||
+      ( pIRectDest->height() != pIRectSrc->height() )
+    )
+  {
+    // Stretching not supported
+    return DDERR_NOSTRETCHHW;
+  }
+
+  if (dest->DDSurfaceDesc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
+  {
+    if(src->DDSurfaceDesc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
+    {
+      // special Type 1 : Bliting between parts of the screen
+
+      if( *pIRectDest == *pIRectSrc)
+        return DD_OK; // rects are the same => no blit needed
+
+      // Todo: might add transparent blits but I don't think they are used here, so later!
+
+      MoveRects( dest->pDiveBuffer,
+                 (LPRECT)&DestRect,
+                 (LPRECT)&SrcRect,
+                 dest->dwBytesPPDive,
+                 dest->dwPitchDB);
+
+      // End of Special Type 1 blitting on the screen
+    }
+    else
+    {
+      if( src->diveBufNr>0)
+      {
+
+        if( (NULL==lpSrcRect)&&( NULL== lpDestRect))
+        {
+          // No Rectangles so use Dive to blit everything
+          // ToDo : Implement transparent blitting but that seams more
+          //        inportant for partial blits.
+          //        If we do this later we could skip this check and don't
+          //        use Dive .This keeps our simpler and smaler
+          //
+          DiveBlitImage(dest->hDive, src->diveBufNr, dest->diveBufNr);
+
+        }
+      }
+
+      // Everything else we do yourselfs
+      // Type 2 Sysmem to Primarysurface ca also be handled by this
+
+      pBltPos = (char*) dest->pDiveBuffer + (DestRect.top * dest->dwPitchDB) +
+                (DestRect.left * dest->dwBytesPPDive);
+
+      pSrcPos = (char*) src->pDiveBuffer + (SrcRect.top * src->dwPitchDB) +
+                (SrcRect.left * src->dwBytesPPDive);
+
+      BlitHeight = pIRectDest->height();
+      BlitWidth = pIRectDest->width();
+
+      if(!dwFlags)
+      {
+        BlitWidth *= dest->dwBytesPPDive;
+
+        #ifdef USE_ASM
+        BltRec(pBltPos, pSrcPos, BlitWidth, BlitHeight,
+               dest->dwPitchDB,
+               src->dwPitchDB);
+        #else
+        // Solid Blit
+        while(1)
+        {
+          memcpy(pBltPos,pSrcPos,BlitWidth);
+          pBltPos += dest->dwPitchDB;
+          pSrcPos += src->dwPitchDB;
+          if(! (--BlitHeight))
+            break;
+        }
+        #endif
+      }
+      else
+      {
+        // Transparent Blit
+        if( (dwFlags &DDBLT_KEYSRC) || (dwFlags & DDBLT_KEYSRCOVERRIDE) )
+        {
+        }
+        else
+        {
+          WriteLog("Unhandled Flags Destination colorkey ? 0x%04X",dwFlags);
+        }
+      }
+    } // end of handling blitting to primary
+  }  // end of target primary surface
+  else
+  {
+    if(0==src->diveBufNr)
+    {
+      // copy from the screen to a buffer
+
+      if( (NULL==lpDestRect) &&
+          (NULL==lpSrcRect) &&
+          (dest->diveBufNr>0) )
+      {
+        // Blitting everything from frontbuffer to a Divebuffer
+        // ToDo: Might should add checking for flags here
+        DiveBlitImage(dest->hDive, src->diveBufNr, dest->diveBufNr);
+      }
+      else
+      {
+        // DIVE => DIVE  or Mem => Dive
+        // or a rectangle from streen to a buffer can be handelt in the same way
+        pBltPos = (char*) dest->pDiveBuffer + (DestRect.top * dest->dwPitchDB) +
+                  (DestRect.left * dest->dwBytesPPDive);
+
+        pSrcPos = (char*) src->pDiveBuffer + (SrcRect.top * src->dwPitchDB) +
+                  (SrcRect.left * src->dwBytesPPDive);
+
+        BlitHeight = pIRectDest->height();
+        BlitWidth = pIRectDest->width();
+
+        // Check for transparent blit
+        if(!dwFlags)
+        {
+          BlitWidth *= dest->dwBytesPPDive;
+
+          #ifdef USE_ASM
+          BltRec(pBltPos, pSrcPos, BlitWidth, BlitHeight,
+                 dest->dwPitchDB,
+                 src->dwPitchDB);
+          #else
+          // Solid Blit
+          while(1)
+          {
+            memcpy(pBltPos,pSrcPos,BlitWidth);
+            pBltPos += dest->dwPitchDB;
+            pSrcPos += src->dwPitchDB;
+            if(! (--BlitHeight))
+              break;
+          }
+          #endif
+        }
+        else
+        {
+          if(dwFlags & DDBLT_KEYSRC)
+          {
+            if(!(src->DDSurfaceDesc.dwFlags & DDCKEY_SRCBLT))
+            {
+            }
+          }
+          else
+          {
+            if(dwFlags & DDBLT_KEYSRCOVERRIDE)
+            {
+            }
+            else
+            {
+            }
+          }
+        }
+      }
+    } // end handling source screen
+    else
+    {
+      // DIVE => DIVE  or Mem => Dive can be handelt in the same way
+
+      if( (src->pDiveBuffer == dest->pDiveBuffer) &&
+          (pIRectDest->intersects(*pIRectSrc) ) )
+      {
+        // Overlapping rects  on the same surface ?
+
+        // ToDo : Maybe implement all the fancy blit flags here too ? ;)
+
+        MoveRects( dest->pDiveBuffer,
+                   (LPRECT)&DestRect,
+                   (LPRECT)&SrcRect,
+                   dest->dwBytesPPDive,
+                   dest->dwPitchDB);
+
+        return DD_OK;
+      }
+
+      pBltPos = (char*) dest->pDiveBuffer + (DestRect.top * dest->dwPitchDB) +
+                (DestRect.left * dest->dwBytesPPDive);
+
+      pSrcPos = (char*) src->pDiveBuffer + (SrcRect.top * src->dwPitchDB) +
+                (SrcRect.left * src->dwBytesPPDive);
+
+      BlitHeight = pIRectDest->height();
+      BlitWidth = pIRectDest->width();
+
+      // Check for transparent blit
+      if(!dwFlags)
+      {
+        BlitWidth *= dest->dwBytesPPDive;
+
+        #ifdef USE_ASM
+        BltRec(pBltPos, pSrcPos, BlitWidth, BlitHeight,
+               dest->dwPitchDB,
+               src->dwPitchDB);
+        #else
+        // Solid Blit
+        while(1)
+        {
+          memcpy(pBltPos,pSrcPos,BlitWidth);
+          pBltPos += dest->dwPitchDB;
+          pSrcPos += src->dwPitchDB;
+          if(! (--BlitHeight))
+            break;
+        }
+        #endif
+      }
+      else
+      {
+        DWORD dwPitch = dest->dwPitchDB;
+
+        if(dwFlags &DDBLT_ROTATIONANGLE)
+        {
+          return DDERR_NOROTATIONHW;
+        }
+
+        if(dwFlags & DDBLT_DDFX)
+        {
+          DWORD dwFx;
+          DWORD dwSrcColor, dwDestColor;
+
+          dwFlags &= ~DDBLT_DDFX; // remove the handled flag
+
+          if( NULL==lpDDBltFx)
+            return DDERR_INVALIDPARAMS;
+
+          dwFx = lpDDBltFx->dwDDFX;
+
+          // Remove unsupported Flags
+          dwFx &= ~(DDBLTFX_ARITHSTRETCHY |    // Not streach support
+                    DDBLTFX_ZBUFFERBASEDEST |  // All ZBuffer flags are not
+                    DDBLTFX_ZBUFFERRANGE |     // implementet in M$ Dx 6
+                    DDBLTFX_NOTEARING );       // No sync with VRetrace yet
+
+          if(dwFx & DDBLTFX_ROTATE180)
+          {
+            // 180 degree turn is a mix of a flip up/down and one left/right
+            dwFx |= (DDBLTFX_MIRRORUPDOWN | DDBLTFX_MIRRORLEFTRIGHT);
+            dwFx &= ~DDBLTFX_ROTATE180; // remove handled flag
+          }
+          if(dwFx & DDBLTFX_MIRRORUPDOWN)
+          {
+            // switching the the direction can be integrated with other flags
+            dwPitch = -dwPitch;
+            pBltPos = (char*) dest->pDiveBuffer +
+                      ((DestRect.top +BlitHeight)* dest->dwPitchDB) +
+                      (DestRect.left * dest->dwBytesPPDive);
+
+            dwFx &= ~DDBLTFX_MIRRORUPDOWN;  // remove handled flag
+          }
+
+          if(dwFx & DDBLTFX_MIRRORLEFTRIGHT)
+          {
+            // 180 degree turn or a LR Mirroring
+            // don't support any other dwFlags like transparent at the moment
+
+            switch(dest->dwBytesPPDive)
+            {
+              case 1:
+                while(BlitHeight--)
+                {
+                  x = BlitWidth;
+                  while(x)
+                  {
+                    pBltPos[BlitWidth-x] = pSrcPos[x];
+                    x--;
+                  }
+                  pBltPos += dwPitch;
+                  pSrcPos += src->dwPitchDB;
+                }
+                break;
+              case 2:
+                while(BlitHeight--)
+                {
+                  x = BlitWidth;
+                  while(x)
+                  {
+                    ((USHORT*)pBltPos)[BlitWidth-x] = ((USHORT*)pSrcPos)[x];
+                    x--;
+                  }
+                  pBltPos += dwPitch;
+                  pSrcPos += src->dwPitchDB;
+                }
+                break;
+              case 3:
+                BlitWidth *= 3;
+                while(BlitHeight--)
+                {
+                  x = BlitWidth;
+                  while(x)
+                  {
+                    pBltPos[BlitWidth-x] = pSrcPos[x-2];
+                    x--;
+                    pBltPos[BlitWidth-x] = pSrcPos[x];
+                    x--;
+                    pBltPos[BlitWidth-x] = pSrcPos[x+2];
+                    x--;
+                  }
+                  pBltPos += dwPitch;
+                  pSrcPos += src->dwPitchDB;
+                }
+                break;
+              case 4:
+                while(BlitHeight--)
+                {
+                  x = BlitWidth;
+                  while(x)
+                  {
+                    ((DWORD*)pBltPos)[BlitWidth-x] = ((DWORD*)pSrcPos)[x];
+                    x--;
+                  }
+                  pBltPos += dwPitch;
+                  pSrcPos += src->dwPitchDB;
+                }
+                break;
+            }  // end switch
+            dest->lpVtbl->ChangeUniquenessValue(dest);
+            return DD_OK;
+          }
+
+          #ifdef DEBUG
+            if(dwFx)
+              _dump_DDBLTFX(dwFx);
+          #endif
+          // We ignore unhandled flags at the moment
+        }
+
+        if( (dwFlags & DDBLT_KEYSRC) |
+            (dwFlags & DDBLT_KEYSRCOVERRIDE) )
+        {
+          if(dwFlags & DDBLT_KEYSRCOVERRIDE)
+          {
+
+            if( NULL==lpDDBltFx)
+              return DDERR_INVALIDPARAMS;
+
+            dwFlags &= ~DDBLT_KEYSRCOVERRIDE;
+
+            // We work like the HEL and test only the low value
+            dwSrcColor = lpDDBltFx->ddckSrcColorkey.dwColorSpaceLowValue;
+
+          }
+          else
+          {
+
+            dwFlags &= ~DDBLT_KEYSRC;
+
+            // Not sure if that is OK maybe check if one is set ?
+            // if(!(src->DDSurfaceDesc.dwFlags & DDCKEY_SRCBLT)) return DDERR_WRONGPARAM;?
+
+            dwSrcColor = src->DDSurfaceDesc.ddckCKSrcBlt.dwColorSpaceLowValue;
+          }
+
+          // ToDo : We currently indicate that we don't support
+          // DDBLT_KEYDEST but HEL does change that!
+          // also add this key in the get/setColorKey functions
+
+          if( (dwFlags & DDBLT_KEYDEST) |
+              (dwFlags & DDBLT_KEYDESTOVERRIDE) )
+          {
+            // Source and dest color keying SLOW!!!
+            if(dwFlags & DDBLT_KEYDESTOVERRIDE)
+            {
+              if( NULL==lpDDBltFx)
+                return DDERR_INVALIDPARAMS;
+
+              dwFlags &= ~DDBLT_KEYDESTOVERRIDE;
+
+              // We work like the HEL and test only the low value
+              dwDestColor = lpDDBltFx->ddckDestColorkey.dwColorSpaceLowValue;
+
+            }
+            else
+            {
+
+              dwFlags &= ~DDBLT_KEYDEST;
+
+              // Not sure if that is OK maybe check if one is set ?
+              // if(!(Dest->DDSurfaceDesc.dwFlags & DDCKEY_DESTBLT)) return DDERR_WRONGPARAM;?
+
+              dwDestColor = dest->DDSurfaceDesc.ddckCKDestBlt.dwColorSpaceLowValue;
+            }
+
+            // This will be be slow maybe move to ASM ?
+            // using MMX should be much faster
+            switch(dest->dwBytesPPDive)
+            {
+              case 1:
+                while(BlitHeight--)
+                {
+                  x = 0;
+                  while(x<BlitWidth)
+                  {
+                    if(pSrcPos[x] != (char) dwSrcColor)
+                    {
+                      if(pBltPos[x] != (char) dwDestColor)
+                        pBltPos[x] = pSrcPos[x];
+                    }
+                    x++;
+                  }
+                  pBltPos += dwPitch;
+                  pSrcPos += src->dwPitchDB;
+                }
+                break;
+              case 2:
+                while(BlitHeight--)
+                {
+                  x = 0;
+                  while(x<BlitWidth)
+                  {
+                    if(((USHORT*)pSrcPos)[x] != (USHORT) dwSrcColor)
+                    {
+                      if(((USHORT*)pBltPos)[x] != (USHORT) dwDestColor)
+                        ((USHORT*)pBltPos)[x] = ((USHORT*)pSrcPos)[x];
+                    }
+                    x++;
+                  }
+                  pBltPos += dwPitch;
+                  pSrcPos += src->dwPitchDB;
+                }
+                break;
+              case 3:
+              {
+                char *pSC, *pDC;
+                pSC = (char*)&dwSrcColor;
+                pDC = (char*)&dwDestColor;
+                BlitWidth *=3;
+
+                while(BlitHeight--)
+                {
+                  x = 0;
+
+                  while(x<BlitWidth)
+                  {
+                    if( (pSrcPos[x]   != pSC[1]) &&
+                        (pSrcPos[x+1] != pSC[2]) &&
+                        (pSrcPos[x+2] != pSC[3])
+                      )
+                    {
+                      if( (pBltPos[x]   != pDC[1]) &&
+                          (pBltPos[x+1] != pDC[2]) &&
+                          (pBltPos[x+2] != pDC[3])
+                        )
+                        {
+                          pBltPos[x] = pSrcPos[x];
+                          pBltPos[x+1] = pSrcPos[x+2];
+                          pBltPos[x+1] = pSrcPos[x+2];
+                        }
+                    }
+                    x +=3;
+                  }
+                  pBltPos += dwPitch;
+                  pSrcPos += src->dwPitchDB;
+                }
+                break;
+              }
+              case 4:
+                while(BlitHeight--)
+                {
+                  x = 0;
+                  while(x<BlitWidth)
+                  {
+                    if(((DWORD*)pSrcPos)[x] != dwSrcColor)
+                    {
+                      if(((DWORD*)pBltPos)[x] != dwDestColor)
+                        ((DWORD*)pBltPos)[x] = ((DWORD*)pSrcPos)[x];
+                    }
+                    x++;
+                  }
+                  pBltPos += dwPitch;
+                  pSrcPos += src->dwPitchDB;
+                }
+                break;
+            }  // End switch
+          }
+          else
+          {
+            // Only Source colorkey
+          }
+          dest->lpVtbl->ChangeUniquenessValue(dest);
+          return DD_OK;
+        }
+
+        if( (dwFlags & DDBLT_KEYDEST) |
+            (dwFlags & DDBLT_KEYDESTOVERRIDE) )
+        {
+          // Dest color keying SLOW!!!
+          if(dwFlags & DDBLT_KEYSRCOVERRIDE)
+          {
+            if( NULL==lpDDBltFx)
+              return DDERR_INVALIDPARAMS;
+
+            dwFlags &= ~DDBLT_KEYSRCOVERRIDE;
+
+            // We work like the HEL and test only the low value
+            dwDestColor = lpDDBltFx->ddckDestColorkey.dwColorSpaceLowValue;
+
+          }
+          else
+          {
+
+            dwFlags &= ~DDBLT_KEYDEST;
+
+            // Not sure if that is OK maybe check if one is set ?
+            // if(!(src->DDSurfaceDesc.dwFlags & DDCKEY_DESTBLT)) return DDERR_WRONGPARAM;?
+
+            dwDestColor = dest->DDSurfaceDesc.ddckCKDestBlt.dwColorSpaceLowValue;
+          }
+
+          // This will be be slow maybe move to ASM ?
+          // using MMX should be much faster
+          switch(dest->dwBytesPPDive)
+          {
+            case 1:
+              while(BlitHeight--)
+              {
+                x = 0;
+                while(x<BlitWidth)
+                {
+                  if(pBltPos[x] != (char) dwDestColor)
+                    pBltPos[x] = pSrcPos[x];
+                  x++;
+                }
+                pBltPos += dwPitch;
+                pSrcPos += src->dwPitchDB;
+              }
+              break;
+            case 2:
+              while(BlitHeight--)
+              {
+                x = 0;
+                while(x<BlitWidth)
+                {
+                  if(((USHORT*)pBltPos)[x] != (USHORT) dwDestColor)
+                    ((USHORT*)pBltPos)[x] = ((USHORT*)pSrcPos)[x];
+                  x++;
+                }
+                pBltPos += dwPitch;
+                pSrcPos += src->dwPitchDB;
+              }
+              break;
+            case 3:
+            {
+              char *pSC, *pDC;
+              pSC = (char*)&dwSrcColor;
+              pDC = (char*)&dwDestColor;
+              BlitWidth *=3;
+
+              while(BlitHeight--)
+              {
+                x = 0;
+
+                while(x<BlitWidth)
+                {
+                  if( (pBltPos[x]   != pDC[1]) &&
+                      (pBltPos[x+1] != pDC[2]) &&
+                      (pBltPos[x+2] != pDC[3])
+                    )
+                  {
+                    pBltPos[x] = pSrcPos[x];
+                    pBltPos[x+1] = pSrcPos[x+2];
+                    pBltPos[x+1] = pSrcPos[x+2];
+                  }
+                  x +=3;
+                }
+                pBltPos += dwPitch;
+                pSrcPos += src->dwPitchDB;
+              }
+              break;
+            }
+            case 4:
+              while(BlitHeight--)
+              {
+                x = 0;
+                while(x<BlitWidth)
+                {
+                  if( ((DWORD*)pBltPos)[x] != dwDestColor)
+                    ((DWORD*)pBltPos)[x] = ((DWORD*)pSrcPos)[x];
+                  x++;
+                }
+                pBltPos += dwPitch;
+                pSrcPos += src->dwPitchDB;
+              }
+              break;
+          }  // End switch
+        } // End of Dest ColorKey
+
+
+      }// end  handling dwFlags
+    } // End handling source not Framebuffer
+
+  }// end handling destination not framebuffer
+
+  dest->lpVtbl->ChangeUniquenessValue(dest);
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfBltBatch(THIS, LPDDBLTBATCH, DWORD, DWORD )
+{
+  #ifdef DEBUG
+    WriteLog("SurfBltBatch Not implemented by M$\n");
+  #endif
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfBltFast(THIS, DWORD,DWORD,LPDIRECTDRAWSURFACE2, LPRECT,DWORD)
+{
+  #ifdef DEBUG
+    WriteLog("SurfBltFast\n");
+  #endif
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfBltFast4( THIS This,
+                                DWORD dwX,
+                                DWORD dwY,
+                                LPDIRECTDRAWSURFACE4 lpDDSrcSurface,
+                                LPRECT lpSrcRect,
+                                DWORD dwTrans)
+{
+  OS2IDirectDrawSurface *dest = (OS2IDirectDrawSurface *)This;
+  OS2IDirectDrawSurface *src  = (OS2IDirectDrawSurface *)lpDDSrcSurface;
+  RECTL SrcRect;
+  char *pBltPos, *pSrcPos;
+  DWORD dwDestColor, dwSrcColor, BlitWidth, BlitHeight,x,y;
+  #ifdef DEBUG
+    WriteLog("SurfBltFast (%d, %d)\n",dwX,dwY);
+  #endif
+
+  if( (NULL==lpDDSrcSurface) ||
+      (dwX<0) || (dwY<0) ||
+      (dwX>dest->width) ||
+      (dwY>dest->height))
+    return DDERR_INVALIDPARAMS;
+
+  if (NULL!=lpSrcRect)
+  {
+    memcpy(&SrcRect,lpSrcRect,sizeof(RECTL) );
+  }
+  else
+  {
+    SrcRect.top    = 0;
+    SrcRect.left   = 0;
+    SrcRect.bottom = src->height;
+    SrcRect.right  = src->width;
+  }
+
+  pBltPos = (char*) dest->pDiveBuffer + (dwY * dest->dwPitchDB) +
+            (dwX * dest->dwBytesPPDive);
+
+  pSrcPos = (char*) src->pDiveBuffer + (SrcRect.top * src->dwPitchDB) +
+            (SrcRect.left * src->dwBytesPPDive);
+
+  BlitHeight = SrcRect.bottom - SrcRect.top;
+  BlitWidth  = (SrcRect.right - SrcRect.left) * src->dwBytesPPDive;
+
+  if(dwTrans & DDBLTFAST_NOCOLORKEY)
+  {
+    #ifdef USE_ASM
+    BltRec(pBltPos, pSrcPos, BlitWidth, BlitHeight,
+           dest->dwPitchDB,
+           src->dwPitchDB);
+    #else
+    // Solid Blit
+    while(1)
+    {
+      memcpy(pBltPos,pSrcPos,BlitWidth);
+      pBltPos += dest->dwPitchDB;
+      pSrcPos += src->dwPitchDB;
+      if(! (--BlitHeight))
+        break;
+    }
+    #endif
+
+  }
+  else
+  {
+    if(dwTrans & DDBLTFAST_SRCCOLORKEY)
+    {
+      // transparent source
+      dwSrcColor = src->DDSurfaceDesc.ddckCKSrcBlt.dwColorSpaceLowValue;
+      if(dwTrans & DDBLTFAST_DESTCOLORKEY)
+      {
+        dwDestColor = dest->DDSurfaceDesc.ddckCKDestBlt.dwColorSpaceLowValue;
+        // Source and dest colorkeying
+        switch(dest->dwBytesPPDive)
+        {
+          case 1:
+            while(BlitHeight--)
+            {
+              x = 0;
+              while(x<BlitWidth)
+              {
+                if(pSrcPos[x] != (char) dwSrcColor)
+                {
+                  if(pBltPos[x] != (char) dwDestColor)
+                    pBltPos[x] = pSrcPos[x];
+                }
+                x++;
+              }
+              pBltPos += dest->dwPitchDB;
+              pSrcPos += src->dwPitchDB;
+            }
+            break;
+          case 2:
+            while(BlitHeight--)
+            {
+              x = 0;
+              while(x<BlitWidth)
+              {
+                if(((USHORT*)pSrcPos)[x] != (USHORT) dwSrcColor)
+                {
+                  if(((USHORT*)pBltPos)[x] != (USHORT) dwDestColor)
+                    ((USHORT*)pBltPos)[x] = ((USHORT*)pSrcPos)[x];
+                }
+                x++;
+              }
+              pBltPos += dest->dwPitchDB;
+              pSrcPos += src->dwPitchDB;
+            }
+            break;
+          case 3:
+          {
+            char *pSC, *pDC;
+            pSC = (char*)&dwSrcColor;
+            pDC = (char*)&dwDestColor;
+            BlitWidth *=3;
+
+            while(BlitHeight--)
+            {
+              x = 0;
+
+              while(x<BlitWidth)
+              {
+                if( (pSrcPos[x]   != pSC[1]) &&
+                    (pSrcPos[x+1] != pSC[2]) &&
+                    (pSrcPos[x+2] != pSC[3])
+                  )
+                {
+                  if( (pBltPos[x]   != pDC[1]) &&
+                      (pBltPos[x+1] != pDC[2]) &&
+                      (pBltPos[x+2] != pDC[3])
+                    )
+                    {
+                      pBltPos[x] = pSrcPos[x];
+                      pBltPos[x+1] = pSrcPos[x+2];
+                      pBltPos[x+1] = pSrcPos[x+2];
+                    }
+                }
+                x +=3;
+              }
+              pBltPos += dest->dwPitchDB;
+              pSrcPos += src->dwPitchDB;
+            }
+            break;
+          }
+          case 4:
+            while(BlitHeight--)
+            {
+              x = 0;
+              while(x<BlitWidth)
+              {
+                if(((DWORD*)pSrcPos)[x] != dwSrcColor)
+                {
+                  if(((DWORD*)pBltPos)[x] != dwDestColor)
+                    ((DWORD*)pBltPos)[x] = ((DWORD*)pSrcPos)[x];
+                }
+                x++;
+              }
+              pBltPos += dest->dwPitchDB;
+              pSrcPos += src->dwPitchDB;
+            }
+            break;
+        }  // End switch
+      }
+      else
+      {
+        // This MMX detection should be moved into OS2Draw
+        // and into the surface constructor a setup for blitting pointers
+
+        switch(dest->dwBytesPPDive)
+        {
+          case 1:
+            if(CPUHasMMX())
+              while(BlitHeight--)
+              {
+                BlitColorKey8MMX((PBYTE)pBltPos,(PBYTE)pSrcPos,dwSrcColor,BlitWidth);
+                pBltPos += dest->dwPitchDB;
+                pSrcPos += src->dwPitchDB;
+              }
+            else
+              while(BlitHeight--)
+              {
+                BlitColorKey8((PBYTE)pBltPos,(PBYTE)pSrcPos,dwSrcColor,BlitWidth);
+                pBltPos += dest->dwPitchDB;
+                pSrcPos += src->dwPitchDB;
+              }
+            break;
+          case 2:
+
+            if(CPUHasMMX())
+              while(BlitHeight--)
+              {
+                BlitColorKey16MMX((PBYTE)pBltPos,(PBYTE)pSrcPos,dwSrcColor,BlitWidth);
+                pBltPos += dest->dwPitchDB;
+                pSrcPos += src->dwPitchDB;
+              }
+            else
+              while(BlitHeight--)
+              {
+                BlitColorKey16((PBYTE)pBltPos,(PBYTE)pSrcPos,dwSrcColor,BlitWidth);
+                pBltPos += dest->dwPitchDB;
+                pSrcPos += src->dwPitchDB;
+              }
+            break;
+          case 3:
+            char *pSC;
+            pSC = (char*)&dwSrcColor;
+            BlitWidth *=3;
+
+            while(BlitHeight--)
+            {
+              x = 0;
+
+              while(x<BlitWidth)
+              {
+                if( (pSrcPos[x]   != pSC[1]) &&
+                    (pSrcPos[x+1] != pSC[2]) &&
+                    (pSrcPos[x+2] != pSC[3])
+                  )
+                {
+                  pBltPos[x] = pSrcPos[x];
+                  pBltPos[x+1] = pSrcPos[x+1];
+                  pBltPos[x+1] = pSrcPos[x+2];
+                }
+                x +=3;
+              }
+              pBltPos += dest->dwPitchDB;
+              pSrcPos += src->dwPitchDB;
+            }
+            break;
+          case 4:
+            break;
+        }
+      }
+    }
+    else
+    {
+      if(dwTrans & DDBLTFAST_DESTCOLORKEY)
+      {
+        dwDestColor = dest->DDSurfaceDesc.ddckCKDestBlt.dwColorSpaceLowValue;
+        switch(dest->dwBytesPPDive)
+        {
+          case 1:
+            while(BlitHeight--)
+            {
+              x = 0;
+              while(x<BlitWidth)
+              {
+                if(pBltPos[x] != (char) dwDestColor)
+                  pBltPos[x] = pSrcPos[x];
+                x++;
+              }
+              pBltPos += dest->dwPitchDB;
+              pSrcPos += src->dwPitchDB;
+            }
+            break;
+          case 2:
+            while(BlitHeight--)
+            {
+              x = 0;
+              while(x<BlitWidth)
+              {
+                if(((USHORT*)pBltPos)[x] != (USHORT) dwDestColor)
+                  ((USHORT*)pBltPos)[x] = ((USHORT*)pSrcPos)[x];
+                x++;
+              }
+              pBltPos += dest->dwPitchDB;
+              pSrcPos += src->dwPitchDB;
+            }
+            break;
+          case 3:
+          {
+            char *pSC, *pDC;
+            pSC = (char*)&dwSrcColor;
+            pDC = (char*)&dwDestColor;
+            BlitWidth *=3;
+
+            while(BlitHeight--)
+            {
+              x = 0;
+
+              while(x<BlitWidth)
+              {
+                if( (pBltPos[x]   != pDC[1]) &&
+                    (pBltPos[x+1] != pDC[2]) &&
+                    (pBltPos[x+2] != pDC[3])
+                  )
+                {
+                  pBltPos[x] = pSrcPos[x];
+                  pBltPos[x+1] = pSrcPos[x+2];
+                  pBltPos[x+1] = pSrcPos[x+2];
+                }
+                x +=3;
+              }
+              pBltPos += dest->dwPitchDB;
+              pSrcPos += src->dwPitchDB;
+            }
+            break;
+          }
+          case 4:
+            while(BlitHeight--)
+            {
+              x = 0;
+              while(x<BlitWidth)
+              {
+                if(((DWORD*)pBltPos)[x] != dwDestColor)
+                  ((DWORD*)pBltPos)[x] = ((DWORD*)pSrcPos)[x];
+                x++;
+              }
+              pBltPos += dest->dwPitchDB;
+              pSrcPos += src->dwPitchDB;
+            }
+            break;
+        }  // End switch
+      }
+    }
+  }
+  dest->lpVtbl->ChangeUniquenessValue(dest);
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfDeleteAttachedSurface(THIS This, DWORD dwFlags, LPDIRECTDRAWSURFACE2 lpDDSurface)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+  #ifdef DEBUG
+    WriteLog("SurfDeleteAttachedSurface\n");
+  #endif
+
+  return(SurfDeleteAttachedSurface4(me, dwFlags, (LPDIRECTDRAWSURFACE4)lpDDSurface));
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfDeleteAttachedSurface4(THIS This, DWORD dwFlags , LPDIRECTDRAWSURFACE4 lpDDSurface)
+{
+
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+  OS2IDirectDrawSurface *AttachedSurface;
+  OS2IDirectDrawSurface *SurfaceCursor;
+
+  ISequence<OS2IDirectDrawSurface*>::Cursor *EnumCursor;
+  BOOL Found = FALSE;
+  #ifdef DEBUG
+    WriteLog("SurfDeleteAttachedSurface\n");
+  #endif
+
+  if((0!=dwFlags)||(NULL==lpDDSurface))
     return(DDERR_INVALIDPARAMS);
-  }
-  dprintf(("src %X, dest %X\n", srcbuf, destbuf));
-
-  for(i=0;i<blit.ulSrcHeight;i++) {
- #ifdef DEBUG1
-    dprintf(("%d blit (%d,%d) from (%d,%d) len %d\n", i, blit.lDstPosX, destscanbytes*lpDestRect->top + i*destscanbytes,
-         blit.ulSrcPosX, srcscanbytes*blit.ulSrcPosY + i*srcscanbytes, blit.ulSrcWidth));
-    dprintf(("dest address %X\n", destbuf + blit.lDstPosX + destscanbytes*lpDestRect->top + i*destscanbytes + blit.ulSrcWidth - 1));
- #endif
-    memcpy(destbuf + blit.lDstPosX + destscanbytes*lpDestRect->top + i*destscanbytes,
-           srcbuf  + blit.ulSrcPosX + srcscanbytes*blit.ulSrcPosY + i*srcscanbytes,
-           blit.ulSrcWidth);
-  }
-
-  if(dest->diveBufNr == DIVE_BUFFER_SCREEN) {
-       DiveDeacquireFrameBuffer(dest->hDive);
-  }
-  else DiveEndImageBufferAccess(dest->hDive, dest->diveBufNr);
-
-  DiveEndImageBufferAccess(src->hDive, src->diveBufNr);
-
-#endif
+
+  AttachedSurface = (OS2IDirectDrawSurface*) lpDDSurface;
+  if (AttachedSurface->IsImplicitSurface())
+    return (DDERR_CANNOTDETACHSURFACE);
+
+  if ( (AttachedSurface->DDSurfaceDesc.ddsCaps.dwCaps & ( DDSCAPS_FLIP | DDSCAPS_BACKBUFFER)) &&
+       !(AttachedSurface->DDSurfaceDesc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER) )
+  {
+    // Surface seams to be a backbuffer in a flipchain search it
+
+    // Goto top of list
+    if(me->FrontBuffer!=NULL)
+    {
+      SurfaceCursor = me->FrontBuffer;
+      while(SurfaceCursor->GetFrontBuffer()!=NULL)
+        SurfaceCursor = SurfaceCursor->GetFrontBuffer();
+    }
+    else
+      SurfaceCursor = me;
+
+    // now iterrate through the list skip first in list as we don't remove the frontbuffer
+
+    SurfaceCursor = SurfaceCursor->BackBuffer;
+    while((SurfaceCursor!= AttachedSurface)&&(SurfaceCursor!=NULL))
+      SurfaceCursor = SurfaceCursor->BackBuffer;
+
+    if(SurfaceCursor!=NULL)
+    {
+      Found = TRUE;
+      // remove the Surface from the list
+      SurfaceCursor->FrontBuffer->BackBuffer = SurfaceCursor->BackBuffer;
+      if(SurfaceCursor->BackBuffer!=NULL)
+      {
+        SurfaceCursor->BackBuffer->SetFrontBuffer(SurfaceCursor->FrontBuffer);
+
+      }
+      else
+      {
+        // we were the last buffer in the list have we been the only backbuffer?
+        if(SurfaceCursor->FrontBuffer->FrontBuffer == NULL)
+        {
+          // Yepp so "destroy" the flipchain
+          SurfaceCursor->FrontBuffer->DDSurfaceDesc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
+          SurfaceCursor->FrontBuffer->DDSurfaceDesc.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
+        }
+      }
+      // decrement the backbuffer count of all buffers in the chain in front of us
+      while(SurfaceCursor->GetFrontBuffer()!=NULL)
+      {
+        SurfaceCursor = SurfaceCursor->GetFrontBuffer();
+        SurfaceCursor->DDSurfaceDesc.dwBackBufferCount-- ;
+      }
+
+      AttachedSurface->DDSurfaceDesc.dwBackBufferCount = 0;
+      AttachedSurface->DDSurfaceDesc.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
+      AttachedSurface->DDSurfaceDesc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
+      AttachedSurface->DDSurfaceDesc.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER; // Set this flag as adding to the chain removed it
+      AttachedSurface->lpVtbl->Release(AttachedSurface);
+
+    }
+  } //endif delete back/frontbuffers
+
+  if ( (!Found) && (AttachedSurface->DDSurfaceDesc.ddsCaps.dwCaps & ( DDSCAPS_FLIP & DDSCAPS_FRONTBUFFER)) )
+  {
+    // seams like someone wants a new frontbuffer
+
+    // Goto top of list
+
+    if(me->FrontBuffer!=NULL)
+    {
+      SurfaceCursor = me->FrontBuffer;
+      while(SurfaceCursor->GetFrontBuffer()!=NULL)
+        SurfaceCursor = SurfaceCursor->GetFrontBuffer();
+    }
+    else
+      SurfaceCursor = me;
+
+    if(SurfaceCursor == AttachedSurface)
+    {
+      Found = TRUE;
+      SurfaceCursor->BackBuffer->SetFrontBuffer(NULL);
+      AttachedSurface->DDSurfaceDesc.dwBackBufferCount = 0;
+      AttachedSurface->DDSurfaceDesc.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
+      AttachedSurface->DDSurfaceDesc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
+      AttachedSurface->lpVtbl->Release(AttachedSurface);
+    }
+
+  }
+
+  if ( (!Found) && (AttachedSurface->DDSurfaceDesc.ddsCaps.dwCaps &  DDSCAPS_MIPMAP ) )
+  {
+    // Surface seams to be a mipmap
+    EnumCursor = me->SurfaceSequenceMipMap.newCursor();
+    EnumCursor->setToFirst();
+    while((EnumCursor->isValid() ) && !Found)
+    {
+      if (EnumCursor->element() == AttachedSurface)
+      {
+        Found = TRUE;
+        me->SurfaceSequenceMipMap.removeAt(*EnumCursor);
+        me->SurfaceCursorMipMap->setToFirst();
+        AttachedSurface->lpVtbl->Release(AttachedSurface);
+        // adjust our info
+        me->DDSurfaceDesc.dwMipMapCount-- ;
+        if (!me->DDSurfaceDesc.dwMipMapCount)
+        {
+          me->DDSurfaceDesc.dwFlags &= ~DDSD_MIPMAPCOUNT;
+        }
+      }
+    }
+    delete EnumCursor;
+  }
+
+  if(!Found)
+  {
+    // Surface seams to be a mipmap
+    EnumCursor = me->SurfaceSequenceAttached.newCursor();
+    EnumCursor->setToFirst();
+    while((EnumCursor->isValid() ) && !Found)
+    {
+      if (EnumCursor->element() == AttachedSurface)
+      {
+        Found = TRUE;
+        me->SurfaceSequenceAttached.removeAt(*EnumCursor);
+        me->SurfaceCursorAttached->setToFirst();
+        AttachedSurface->lpVtbl->Release(AttachedSurface);
+      }
+    }
+    delete EnumCursor;
+  }
+
+  return(Found?DD_OK:DDERR_SURFACENOTATTACHED);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfEnumAttachedSurfaces(THIS This, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpCallBack)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+  #ifdef DEBUG
+    WriteLog("SurfEnumAttachedSurfaces\n");
+  #endif
+
+  return(SurfEnumAttachedSurfaces4(me,lpContext, (LPDDENUMSURFACESCALLBACK2) lpCallBack));
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfEnumAttachedSurfaces4(THIS This, LPVOID lpContext ,LPDDENUMSURFACESCALLBACK2 lpCallBack)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+  OS2IDirectDrawSurface *EnumSurface;
+  DDSURFACEDESC2         EnumDesc;
+
+  ISequence<OS2IDirectDrawSurface*>::Cursor *EnumCursor;
+  HRESULT rc;
+
+  #ifdef DEBUG
+    WriteLog("SurfEnumAttachedSurfaces\n");
+  #endif
+  if (NULL==lpCallBack)
+    return (DDERR_INVALIDPARAMS);
+
+  rc = DDENUMRET_OK;
+
+  if(me->BackBuffer != NULL)
+  {
+    memcpy(&EnumDesc,&(me->DDSurfaceDesc),sizeof(DDSURFACEDESC2));
+    rc = lpCallBack((LPDIRECTDRAWSURFACE4)me->BackBuffer,&EnumDesc,lpContext);
+  }
+
+  if(!me->SurfaceSequenceMipMap.isEmpty())
+  {
+    EnumCursor = me->SurfaceSequenceMipMap.newCursor();
+    EnumCursor->setToFirst();
+    while( (DDENUMRET_OK == rc) && EnumCursor->isValid() )
+    {
+      EnumSurface = EnumCursor->element();
+      memcpy(&EnumDesc,&(EnumSurface->DDSurfaceDesc),sizeof(DDSURFACEDESC2));
+      rc = lpCallBack((LPDIRECTDRAWSURFACE4)EnumSurface,&EnumDesc,lpContext);
+      EnumCursor->setToNext();
+    }
+    delete EnumCursor;
+  }
+
+  if(!me->SurfaceSequenceAttached.isEmpty())
+  {
+    EnumCursor = me->SurfaceSequenceAttached.newCursor();
+    EnumCursor->setToFirst();
+    while( (DDENUMRET_OK == rc) && EnumCursor->isValid() )
+    {
+      EnumSurface = EnumCursor->element();
+      memcpy(&EnumDesc,&(EnumSurface->DDSurfaceDesc),sizeof(DDSURFACEDESC2));
+      rc = lpCallBack((LPDIRECTDRAWSURFACE4)EnumSurface,&EnumDesc,lpContext);
+      EnumCursor->setToNext();
+    }
+    delete EnumCursor;
+  }
+
   return(DD_OK);
 }
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall SurfBltBatch(THIS_ LPDDBLTBATCH, DWORD, DWORD )
-{
-  dprintf(("SurfBltBatch\n"));
+HRESULT __stdcall SurfEnumOverlayZOrders(THIS, DWORD,LPVOID,LPDDENUMSURFACESCALLBACK)
+{
+  #ifdef DEBUG
+    WriteLog("SurfEnumOverlayZOrders\n");
+  #endif
+
   return(DD_OK);
 }
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall SurfBltFast(THIS_ DWORD dwDestX, DWORD dwDestY,
-                  LPDIRECTDRAWSURFACE2 srcSurface,
-                  W32_LPRECT lpSrcRect, DWORD dwTrans)
-{
- OS2IDirectDrawSurface *src  = (OS2IDirectDrawSurface *)srcSurface;
- OS2IDirectDrawSurface *dest = (OS2IDirectDrawSurface *)This;
- SETUP_BLITTER          blit;
- ULONG                  rc;
- RECTL                  cliprect;
-
-  dprintf(("SurfBltFast (%d,%d) (%d,%d) to (%d,%d) dest %X src %X\n", lpSrcRect->left, lpSrcRect->top, lpSrcRect->right, lpSrcRect->bottom, dwDestX, dwDestY, dest, src));
-
-  blit.ulStructLen = sizeof(blit);
-  blit.fInvert     = FALSE;
-  blit.fccSrcColorFormat = src->fccColorFormat;
-  blit.ulSrcWidth  = lpSrcRect->right  - lpSrcRect->left;
-  blit.ulSrcHeight = lpSrcRect->bottom - lpSrcRect->top;
-  blit.ulSrcPosX   = lpSrcRect->left;
-  blit.ulSrcPosY   = lpSrcRect->top;
-
-  //to prevent inaccuracies when stretching
-  if(blit.ulSrcWidth == src->lpDraw->GetScreenWidth()) {
-    blit.ulDstWidth  = dcaps.ulHorizontalResolution;
-  }
-  else  blit.ulDstWidth  = (int)((double)blit.ulSrcWidth*dest->screenXFact);
-
-  //to prevent inaccuracies when stretching
-  if(blit.ulSrcHeight == src->lpDraw->GetScreenHeight()) {
-    blit.ulDstHeight = dcaps.ulVerticalResolution;
-  }
-  else  blit.ulDstHeight = (int)((double)blit.ulSrcHeight*dest->screenYFact);
-
-  blit.fccDstColorFormat = dest->fccColorFormat;
-  blit.lDstPosX    = (int)((double)dwDestX*dest->screenXFact);
-  blit.lDstPosY    = (int)((double)dwDestY*dest->screenXFact);
-  blit.lScreenPosX = 0;
-  blit.lScreenPosY = 0;
-
-  blit.ulNumDstRects = 1;
-  blit.pVisDstRects  = &cliprect;
-  cliprect.top       = 0;
-  cliprect.bottom    = dcaps.ulVerticalResolution;
-  cliprect.left      = 0;
-  cliprect.right     = dcaps.ulHorizontalResolution;
-
-  //We can't do anything but simple 1:1 blitting ourselves
-  if(src->diveBufNr == DIVE_BUFFER_SCREEN || dest->diveBufNr == DIVE_BUFFER_SCREEN ||
-     blit.fccSrcColorFormat != blit.fccDstColorFormat ||
-     blit.ulDstWidth != blit.ulSrcWidth || blit.ulDstHeight != blit.ulSrcHeight)
-  {
-//SvL: Other color key types not supported in dive (dest)
-    if(dwTrans & DDBLTFAST_SRCCOLORKEY && src->ColorKeyFlags & DDCKEY_SRCBLT) {
-        dprintf(("Set colorkey for blitting"));
-        rc = DiveSetTransparentBlitMode(dest->hDive, DIVE_TBM_EXCLUDE_SOURCE_VALUE,
-                        src->ColorSpaceLowValue[COLORKEY_SRC],
-                        src->ColorSpaceHighValue[COLORKEY_SRC]);
-        if(rc != DIVE_SUCCESS) {
-            dprintf(("Error setting up colorkey for blitter %d\n", rc));
-            return(DDERR_GENERIC);
-        }
-    }
-//  dprintf(("Blit: (%d,%d) (%d,%d) to (%d,%d) (%d,%d)", blit.ulSrcPosX, blit.ulSrcPosY, blit.ulSrcWidth, blit.ulSrcHeight, blit.lDstPosX, blit.lDstPosY, blit.ulDstWidth, blit.ulDstHeight));
-    rc = DiveSetupBlitter(dest->hDive, &blit);
-    if(rc != DIVE_SUCCESS) {
-        dprintf(("Error setting up blitter %d\n", rc));
-        return(DDERR_GENERIC);
-    }
-    rc = DiveBlitImage(dest->hDive, src->diveBufNr, dest->diveBufNr);
-    if(rc != DIVE_SUCCESS) {
-        dprintf(("Error while blitting %d\n", rc));
-        return(DDERR_GENERIC);
-    }
-  }
-  else { //manual blit
-   PBYTE srcbuf, destbuf;
-   ULONG i, j, destscanlinesize, srcscanlinesize, blitlinesize;
-
-     srcbuf   = src->lpBuffer  + blit.ulSrcPosX + src->width*blit.ulSrcPosY;
-     destbuf  = dest->lpBuffer + blit.lDstPosX  + dest->width*blit.lDstPosY;
-
-     if(blit.ulSrcWidth == src->width && blit.ulSrcWidth == dest->width) {
-    //TODO: other colorkey types, ranges and only 8 bits supported now!!
-    if(dwTrans & DDBLTFAST_SRCCOLORKEY && src->ColorKeyFlags & DDCKEY_SRCBLT) {
-        BlitColorKey8(destbuf, srcbuf, src->ColorSpaceLowValue[COLORKEY_SRC],
-                  blit.ulSrcWidth*blit.ulSrcHeight*src->bpp/8);
-    }
-    else {
-        memcpy(destbuf, srcbuf, blit.ulSrcWidth*blit.ulSrcHeight*src->bpp/8);
-    }
-     }
-     else {
-        destscanlinesize = dest->width*dest->bpp/8;
-        srcscanlinesize  = src->width*src->bpp/8;
-    blitlinesize     = blit.ulSrcWidth*src->bpp/8;
-
-    //TODO: other colorkey types, ranges and only 8 bits supported now!!
-    if(dwTrans & DDBLTFAST_SRCCOLORKEY && src->ColorKeyFlags & DDCKEY_SRCBLT) {
-#if 0
-         BYTE colorkey = (BYTE)src->ColorSpaceLowValue[COLORKEY_SRC];
-     PBYTE endpos;
-        for(i=0;i<blit.ulSrcHeight;i++) {
-            endpos = destbuf + blitlinesize;
-            while(destbuf < endpos) {
-                if(*srcbuf == colorkey) {
-                    destbuf++;
-                }
-                else    *destbuf++ = *srcbuf;
-                srcbuf++;
-            }
-            destbuf += (destscanlinesize-blitlinesize);
-            srcbuf  += (srcscanlinesize-blitlinesize);
-        }
-#else
-        for(i=0;i<blit.ulSrcHeight;i++) {
-            BlitColorKey8(destbuf+i*destscanlinesize, srcbuf+i*srcscanlinesize,
-                      src->ColorSpaceLowValue[COLORKEY_SRC], blitlinesize);
-        }
-#endif
-    }
-    else {
-        for(i=0;i<blit.ulSrcHeight;i++) {
-         memcpy(destbuf + i*destscanlinesize, srcbuf + i*srcscanlinesize,
-                blitlinesize);
-        }
-         }
-    }
-  }
+HRESULT __stdcall SurfEnumOverlayZOrders4(THIS, DWORD,LPVOID,LPDDENUMSURFACESCALLBACK2)
+{
+  #ifdef DEBUG
+    WriteLog("SurfEnumOverlayZOrders\n");
+  #endif
+
   return(DD_OK);
 }
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall SurfDeleteAttachedSurface(THIS_ DWORD,LPDIRECTDRAWSURFACE2)
-{
-  dprintf(("SurfDeleteAttachedSurface\n"));
+HRESULT __stdcall SurfFlip(THIS This, LPDIRECTDRAWSURFACE2 lpDDSurf, DWORD dwFlags)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+  #ifdef DEBUG
+    WriteLog("SurfFlip\n");
+  #endif
+
+  return(SurfFlip4(me, (LPDIRECTDRAWSURFACE4) lpDDSurf, dwFlags));
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfFlip4(THIS This, LPDIRECTDRAWSURFACE4 lpDDSurf, DWORD dwFlags)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+  OS2IDirectDrawSurface *FlipSurface;
+  OS2IDirectDrawSurface *FlipCursor;
+  LPVOID Data;
+  char *pcrFB,*pcFB,*pcrDB,*pcDB;
+
+  #ifdef DEBUG
+    WriteLog("SurfFlip4\n");
+  #endif
+  if(!((me->DDSurfaceDesc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER) &&
+       (me->DDSurfaceDesc.ddsCaps.dwCaps & DDSCAPS_FLIP))
+    )
+  {
+    #ifdef DEBUG
+      WriteLog("Flip called on none Frontbuffer/Flip surface\n Flags:\n");
+      _dump_DDSCAPS(me->DDSurfaceDesc.ddsCaps.dwCaps);
+    #endif
+    return(DDERR_NOTFLIPPABLE);
+  }
+
+  if(NULL!=lpDDSurf)
+  {
+    // We got an override surface check if it is in the flipchain
+    FlipSurface = (OS2IDirectDrawSurface*) lpDDSurf;
+    FlipCursor = me->BackBuffer;
+    while((NULL!=FlipCursor)&&(FlipCursor!=FlipSurface))
+    {
+      FlipCursor = FlipCursor->BackBuffer;
+    }
+
+    if(FlipCursor!=FlipSurface)
+    {
+      #ifdef DEBUG
+        WriteLog("Surface not in Flipchain!\n");
+      #endif
+      return (DDERR_INVALIDPARAMS); // Not sure if the returnvalue is right
+    }
+  }
+  else
+    FlipSurface = me->NextFlip; // Take the next Surface in the Flipchain
+
+
+  if((me->fLocked)||(FlipSurface->fLocked))
+  {
+    #ifdef DEBUG
+      WriteLog("Locked surface(s) Dest %d Src %d\n",me->fLocked,FlipSurface->fLocked);
+    #endif
+    return(DDERR_SURFACEBUSY);
+  }
+
+  if(-1 != me->diveBufNr)
+  {
+    // we got some DIVE surfaces
+    // On Dive Buffers More then Double buffering won't get any perf. gain
+    // as we have to move all the data to the Frontbuffer and can't simply exchange the pointers
+    // Doulebuffering should work best.
+
+    DiveBlitImage(me->hDive, FlipSurface->diveBufNr, me->diveBufNr);
+
+    if(NULL==lpDDSurf)
+    {
+      // advance in the flipchain if no valid override surface was passed in
+      me->NextFlip = FlipSurface->BackBuffer!=NULL?FlipSurface->BackBuffer:me->BackBuffer;
+    }
+  }
+  else
+  {
+    // Memory Flipchain
+    //
+    // ToDo : Check what happens to src/dest colorkeys etc do the move also ?
+    //
+    // We only change the memory pointer to the buffers no need to copy all the data
+    // So the NextFlip is here allways the Backbuffer so we won't advance this
+    //
+    // Sample  (triple buffering) :               Before Flip    After Flip
+    //                               Buffer:      FB  BB  TB     FB  BB  TB
+    //                               Memory:      11  22  33     22  33  11
+    //
+    Data  = me->DDSurfaceDesc.lpSurface;
+    pcrFB = me->pFBreal;
+    pcFB  = me->pFrameBuffer;
+    pcrDB = me->pDBreal;
+    pcDB  = me->pDiveBuffer;
+    me->DDSurfaceDesc.lpSurface = FlipSurface->DDSurfaceDesc.lpSurface;
+    me->pFBreal                 = FlipSurface->pFBreal;
+    me->pFrameBuffer            = FlipSurface->pFrameBuffer;
+    me->pDBreal                 = FlipSurface->pDBreal;
+    me->pDiveBuffer             = FlipSurface->pDiveBuffer;
+
+    if(NULL==lpDDSurf)
+    {
+      while(NULL!=FlipSurface->BackBuffer)
+      {
+        FlipSurface->DDSurfaceDesc.lpSurface = FlipSurface->BackBuffer->DDSurfaceDesc.lpSurface;
+        FlipSurface->pFBreal                 = FlipSurface->BackBuffer->pFBreal;
+        FlipSurface->pFrameBuffer            = FlipSurface->BackBuffer->pFrameBuffer;
+        FlipSurface->pDBreal                 = FlipSurface->BackBuffer->pDBreal;
+        FlipSurface->pDiveBuffer             = FlipSurface->BackBuffer->pDiveBuffer;
+        FlipSurface = FlipSurface->BackBuffer;
+      }
+    }
+    FlipSurface->DDSurfaceDesc.lpSurface = Data;
+    FlipSurface->pFBreal                 = pcrFB;
+    FlipSurface->pFrameBuffer            = pcFB;
+    FlipSurface->pDBreal                 = pcrDB;
+    FlipSurface->pDiveBuffer             = pcDB;
+  }
+
   return(DD_OK);
 }
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall SurfEnumAttachedSurfaces(THIS_ LPVOID,LPDDENUMSURFACESCALLBACK)
-{
-  dprintf(("SurfEnumAttachedSurfaces\n"));
+HRESULT __stdcall SurfGetAttachedSurface(THIS This, LPDDSCAPS lpDDCaps,
+                                         LPDIRECTDRAWSURFACE2 FAR * lpDDSurf)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+  #ifdef DEBUG
+    WriteLog("SurfGetAttachedSurface\n");
+  #endif
+
+  return(SurfGetAttachedSurface4(me, (LPDDSCAPS2)lpDDCaps , (LPDIRECTDRAWSURFACE4*)lpDDSurf));
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfGetAttachedSurface4(THIS This, LPDDSCAPS2 lpDDCaps,
+                                          LPDIRECTDRAWSURFACE4 FAR * lpDDSurf)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+  OS2IDirectDrawSurface *EnumSurface = NULL;
+  OS2IDirectDrawSurface *AttachedSurface = NULL;
+  ISequence<OS2IDirectDrawSurface*>::Cursor *EnumCursor;
+  #ifdef DEBUG
+    WriteLog("SurfGetAttachedSurface4\n>Requested Caps: ");
+    _dump_DDSCAPS(lpDDCaps->dwCaps);
+    WriteLog("\n");
+  #endif
+
+  if( (NULL==lpDDCaps)||(NULL==lpDDSurf))
+  {
+    WriteLog("Invalid params\n\n");
+    return (DDERR_INVALIDPARAMS);
+  }
+
+  if( (me->BackBuffer!=NULL) && (me->BackBuffer->DDSurfaceDesc.ddsCaps.dwCaps & lpDDCaps->dwCaps) )
+  {
+    WriteLog("Return Backbuffer\n");
+    AttachedSurface = me->BackBuffer;
+  }
+
+  if(!me->SurfaceSequenceMipMap.isEmpty())
+  {
+    EnumCursor = me->SurfaceSequenceMipMap.newCursor();
+    EnumCursor->setToFirst();
+    while( EnumCursor->isValid() )
+    {
+      EnumSurface = EnumCursor->element();
+      if(EnumSurface->DDSurfaceDesc.ddsCaps.dwCaps == lpDDCaps->dwCaps)
+      {
+        if(NULL==AttachedSurface)
+          AttachedSurface = EnumSurface;
+        else
+          return(DDERR_NOTFOUND); // Not sure if this is the right return value,
+                                  // but function must fail if more then one surface fits
+
+      }
+      EnumCursor->setToNext();
+    }
+    delete EnumCursor;
+  }
+
+  if(!me->SurfaceSequenceAttached.isEmpty())
+  {
+    EnumCursor = me->SurfaceSequenceAttached.newCursor();
+    EnumCursor->setToFirst();
+    while( EnumCursor->isValid() )
+    {
+      EnumSurface = EnumCursor->element();
+      if(EnumSurface->DDSurfaceDesc.ddsCaps.dwCaps == lpDDCaps->dwCaps)
+      {
+        if(NULL==AttachedSurface)
+          AttachedSurface = EnumSurface;
+        else
+          return(DDERR_NOTFOUND); // Not sure if this is the right return value,
+                                  // but function must fail if more then one surface fits
+
+      }
+      EnumCursor->setToNext();
+    }
+    delete EnumCursor;
+  }
+
+  if(NULL!=AttachedSurface)
+  {
+    *lpDDSurf = (IDirectDrawSurface4*)AttachedSurface;
+    // not sure but as we returned an reference rains usage count
+    AttachedSurface->lpVtbl->AddRef(AttachedSurface);
+    return(DD_OK);
+  }
+  else
+    *lpDDSurf = NULL;
+
+  return(DDERR_NOTFOUND);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfGetBltStatus(THIS This, DWORD)
+{
+  #ifdef DEBUG
+    WriteLog("SurfGetBltStatus\n");
+  #endif
+
   return(DD_OK);
 }
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall SurfEnumOverlayZOrders(THIS_ DWORD,LPVOID,LPDDENUMSURFACESCALLBACK)
-{
-  dprintf(("SurfEnumOverlayZOrders\n"));
+HRESULT __stdcall SurfGetCaps(THIS This, LPDDSCAPS lpDDCaps)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+
+  #ifdef DEBUG
+    WriteLog("SurfGetCaps\n");
+  #endif
+
+  if(NULL==lpDDCaps)
+    return(DDERR_INVALIDPARAMS);
+
+  lpDDCaps->dwCaps = me->DDSurfaceDesc.ddsCaps.dwCaps;
+
   return(DD_OK);
 }
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall SurfFlip(THIS_ LPDIRECTDRAWSURFACE2 lpDDSurfaceTargetOverride, DWORD dwFlags)
-{
- OS2IDirectDrawSurface *dest = (OS2IDirectDrawSurface *)This;
- OS2IDirectDrawSurface *src  = (OS2IDirectDrawSurface *)dest->flip;
- SETUP_BLITTER          blit;
- ULONG                  rc;
- RECTL                  cliprect;
-
-  dprintf(("SurfFlip dest %X, src %X", dest, src));
-  if(dest == NULL || src == NULL) {
-    return DDERR_INVALIDOBJECT;
-  }
-  if(lpDDSurfaceTargetOverride) {
-    dprintf(("SurfFlip, lpDDSurfaceTargetOverride not supported yet\n"));
-    return(DDERR_UNSUPPORTED);
-  }
-  if(!(dest->surfaceType & DDSCAPS_PRIMARYSURFACE) ||
-     src == NULL) {
-    return(DDERR_INVALIDOBJECT);
-  }
-
-  dprintf(("SurfFlip (%d,%d) (%d,%d) %d %d", src->width, src->height, dest->width, dest->height, src->diveBufNr, dest->diveBufNr));
-
-  blit.ulStructLen = sizeof(blit);
-  blit.fInvert     = FALSE;
-  blit.fccSrcColorFormat = src->fccColorFormat;
-  blit.ulSrcWidth  = src->width;
-  blit.ulSrcHeight = src->height;
-  blit.ulSrcPosX   = 0;
-  blit.ulSrcPosY   = 0;
-
-  //to prevent inaccuracies when stretching
-  if(blit.ulSrcWidth == src->lpDraw->GetScreenWidth()) {
-    blit.ulDstWidth  = dcaps.ulHorizontalResolution;
-  }
-  else  blit.ulDstWidth  = (int)((double)blit.ulSrcWidth*dest->screenXFact);
-
-  //to prevent inaccuracies when stretching
-  if(blit.ulSrcHeight == src->lpDraw->GetScreenHeight()) {
-    blit.ulDstHeight = dcaps.ulVerticalResolution;
-  }
-  else  blit.ulDstHeight = (int)((double)blit.ulSrcHeight*dest->screenYFact);
-
-  blit.fccDstColorFormat = dest->fccColorFormat;
-  blit.lDstPosX    = 0;
-  blit.lDstPosY    = 0;
-  blit.lScreenPosX = 0;
-  blit.lScreenPosY = 0;
-  blit.ulNumDstRects = 1;
-  blit.pVisDstRects  = &cliprect;
-  cliprect.top     = 0;
-  cliprect.bottom  = blit.ulDstHeight;
-  cliprect.left    = 0;
-  cliprect.right   = blit.ulDstWidth;
-
-//  dprintf(("Flip: (%d,%d) (%d,%d) to (%d,%d) (%d,%d)", blit.ulSrcPosX, blit.ulSrcPosY, blit.ulSrcWidth, blit.ulSrcHeight, blit.lDstPosX, blit.lDstPosY, blit.ulDstWidth, blit.ulDstHeight));
-  rc = DiveSetupBlitter(dest->hDive, &blit);
-  if(rc != DIVE_SUCCESS) {
-    dprintf(("Error setting up blitter %d\n", rc));
-    return(DDERR_GENERIC);
-  }
-  rc = DiveBlitImage(dest->hDive, src->diveBufNr, dest->diveBufNr);
-  if(rc != DIVE_SUCCESS) {
-    dprintf(("Error while blitting %d\n", rc));
-    return(DDERR_GENERIC);
-  }
-
-  //find next flip back surface if present
-  if(src->attached) {
-    dest->flip = src->attached;
-  }
-  else  dest->flip = dest->attached;    //start with first back buffer
+HRESULT __stdcall SurfGetCaps4(THIS This, LPDDSCAPS2 lpDDCaps)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+  #ifdef DEBUG
+    WriteLog("SurfGetCaps4\n");
+  #endif
+
+  if(NULL==lpDDCaps)
+    return(DDERR_INVALIDPARAMS);
+
+  memcpy(lpDDCaps, &(me->DDSurfaceDesc.ddsCaps), sizeof(DDSCAPS2) );
+
   return(DD_OK);
 }
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall SurfGetAttachedSurface(THIS_ LPDDSCAPS lpddscaps, LPDIRECTDRAWSURFACE2 FAR *lpAttachedSurface)
-{
- OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
- OS2IDirectDrawSurface *attached = me->attached;
-
-  if(me == NULL) {
-    return DDERR_INVALIDOBJECT;
-  }
-  while(attached) {
-    dprintf(("SurfGetAttachedSurface %x %x\n", attached->DDSurfaceDesc.ddsCaps.dwCaps, lpddscaps->dwCaps));
-    if(attached->DDSurfaceDesc.ddsCaps.dwCaps == lpddscaps->dwCaps) {
-        *lpAttachedSurface = (LPDIRECTDRAWSURFACE2)attached;
-        return(DD_OK);
-    }
-    attached = attached->attached;
-  }
-  return(DDERR_NOTFOUND);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall SurfGetBltStatus(THIS_ DWORD)
-{
- OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
-
-  dprintf(("SurfGetBltStatus\n"));
-  if(me == NULL) {
-    return DDERR_INVALIDOBJECT;
-  }
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall SurfGetCaps(THIS_ LPDDSCAPS lpCaps)
-{
- OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
-
-  dprintf(("SurfGetCaps\n"));
-  if(me == NULL || lpCaps == NULL) {
-    return DDERR_INVALIDOBJECT;
-  }
-  lpCaps->dwCaps = me->surfaceType;
-
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall SurfGetClipper(THIS_ LPDIRECTDRAWCLIPPER FAR *lplpClipper)
-{
- OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
-
-  dprintf(("SurfGetClipper\n"));
-  if(me == NULL) {
-    return DDERR_INVALIDOBJECT;
-  }
-  if(me->lpClipper) {
+HRESULT __stdcall SurfGetClipper(THIS This, LPDIRECTDRAWCLIPPER FAR *lplpClipper)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+
+  #ifdef DEBUG
+    WriteLog("SurfGetClipper\n");
+  #endif
+
+  if(me->lpClipper)
+  {
     *lplpClipper = (LPDIRECTDRAWCLIPPER) me->lpClipper;
     return(DD_OK);
   }
-  else  return(DDERR_NOCLIPPERATTACHED);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall SurfGetColorKey(THIS_ DWORD dwFlags, LPDDCOLORKEY lpColorkey)
+  else
+    return(DDERR_NOCLIPPERATTACHED);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfGetColorKey(THIS This, DWORD dwFlags, LPDDCOLORKEY lpDDColKey)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+
+#ifdef DEBUG
+  WriteLog("SurfGetColorKey\n");
+#endif
+
+  if ((0==dwFlags) || (NULL==lpDDColKey))
+    return (DDERR_INVALIDPARAMS);
+
+  // as we report only src colorkey in the caps return error on all others flags
+  if( (DDCKEY_DESTBLT|DDCKEY_DESTOVERLAY|DDCKEY_SRCOVERLAY) & dwFlags)
+    return(DDERR_UNSUPPORTED);
+
+  if(me->DDSurfaceDesc.dwFlags & dwFlags)
+  {
+    if(DDCKEY_SRCBLT & dwFlags)
+    {
+      memcpy(lpDDColKey,&(me->DDSurfaceDesc.ddckCKSrcBlt),sizeof(DDCOLORKEY) );
+    }
+    else
+      return (DDERR_INVALIDPARAMS); // some other flags where set => error
+  }
+  else
+    return(DDERR_NOCOLORKEY); // surface doesn't have a color key set
+
+  return (DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfGetDC(THIS This, HDC FAR *hdc)
 {
  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
-
-  dprintf(("SurfGetColorKey\n"));
-  if(me == NULL) {
-    return DDERR_INVALIDOBJECT;
-  }
-
-  if(dwFlags & DDCKEY_DESTBLT) {
-    lpColorkey->dwColorSpaceLowValue  = me->ColorSpaceLowValue[COLORKEY_DEST];
-    lpColorkey->dwColorSpaceHighValue = me->ColorSpaceHighValue[COLORKEY_DEST];
-    return(DD_OK);
-  }
-  if(dwFlags & DDCKEY_DESTOVERLAY) {
-    lpColorkey->dwColorSpaceLowValue  = me->ColorSpaceLowValue[COLORKEY_DESTOVERLAY];
-    lpColorkey->dwColorSpaceHighValue = me->ColorSpaceHighValue[COLORKEY_DESTOVERLAY];
-    return(DD_OK);
-  }
-  if(dwFlags & DDCKEY_SRCBLT) {
-    lpColorkey->dwColorSpaceLowValue  = me->ColorSpaceLowValue[COLORKEY_SRC];
-    lpColorkey->dwColorSpaceHighValue = me->ColorSpaceHighValue[COLORKEY_SRC];
-    return(DD_OK);
-  }
-  if(dwFlags & DDCKEY_SRCOVERLAY) {
-    lpColorkey->dwColorSpaceLowValue  = me->ColorSpaceLowValue[COLORKEY_SRCOVERLAY];
-    lpColorkey->dwColorSpaceHighValue = me->ColorSpaceHighValue[COLORKEY_SRCOVERLAY];
-    return(DD_OK);
-  }
-  return(DDERR_INVALIDPARAMS);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall SurfGetDC(THIS_ W32_HDC FAR *hdc)
+ DDSURFACEDESC2        LockedSurfaceDesc;
+
+ struct
+ {
+   BITMAPINFOHEADER  bmiHead;
+   RGBQUAD           bmiCols[256];
+ } BitmapInfo;
+
+  #ifdef DEBUG
+    WriteLog("SurfGetDC\n");
+  #endif
+
+  if (NULL==hdc)
+    return(DDERR_INVALIDPARAMS);
+
+  LockedSurfaceDesc.dwSize = sizeof(DDSURFACEDESC2);
+
+  if(DD_OK != me->Vtbl.Lock(me,NULL,&LockedSurfaceDesc,0,0))
+  {
+    return(DDERR_DCALREADYCREATED);
+  }
+
+  if(me->hdcImage == NULL)
+  {
+    // Create a Device context
+    me->hdcImage = CreateCompatibleDC(NULL);
+    if(me->hdcImage == NULL)
+    {
+      #ifdef DEBUG
+        WriteLog("Can't create compatible DC!\n");
+      #endif
+      me->Vtbl.Unlock(me,NULL);
+      return(DDERR_GENERIC);
+    }
+  }
+
+  if(me->hbmImage == NULL)
+  {
+    memset(&BitmapInfo, 0, sizeof(BitmapInfo));
+    BitmapInfo.bmiHead.biSize   = sizeof(BITMAPINFOHEADER);
+    BitmapInfo.bmiHead.biWidth  = LockedSurfaceDesc.lPitch/ (LockedSurfaceDesc.ddpfPixelFormat.dwRGBBitCount>>3);
+    BitmapInfo.bmiHead.biHeight = LockedSurfaceDesc.dwHeight;
+    BitmapInfo.bmiHead.biPlanes = 1;
+    BitmapInfo.bmiHead.biBitCount    = LockedSurfaceDesc.ddpfPixelFormat.dwRGBBitCount;
+    switch(LockedSurfaceDesc.ddpfPixelFormat.dwRGBBitCount)
+    {
+      case 1:
+      case 4:
+      case 8:
+        BitmapInfo.bmiHead.biCompression = BI_RGB;
+        GetSystemPaletteEntries(me->hdcImage,0,255,(PPALETTEENTRY)&BitmapInfo.bmiCols[0]);
+        me->hbmImage = CreateDIBitmap( me->hdcImage,
+                                       NULL,
+                                       CBM_CREATEDIB,
+                                       LockedSurfaceDesc.lpSurface,
+                                       (PBITMAPINFO)&BitmapInfo,
+                                       DIB_RGB_COLORS);
+        break;
+      case 16:
+      case 32:
+        BitmapInfo.bmiHead.biCompression = BI_BITFIELDS;
+        BitmapInfo.bmiHead.biClrUsed     = 3;
+        *((DWORD *) &(BitmapInfo.bmiCols[0])) = LockedSurfaceDesc.ddpfPixelFormat.dwRBitMask;
+        *((DWORD *) &(BitmapInfo.bmiCols[1])) = LockedSurfaceDesc.ddpfPixelFormat.dwGBitMask;
+        *((DWORD *) &(BitmapInfo.bmiCols[2])) = LockedSurfaceDesc.ddpfPixelFormat.dwBBitMask;
+        me->hbmImage = CreateDIBitmap(me->hdcImage,NULL,CBM_CREATEDIB,LockedSurfaceDesc.lpSurface,
+                                      (PBITMAPINFO)&BitmapInfo,DIB_RGB_COLORS);
+        break;
+      case 24:
+        BitmapInfo.bmiHead.biCompression = BI_RGB;
+        me->hbmImage = CreateDIBitmap(me->hdcImage,NULL,CBM_CREATEDIB,LockedSurfaceDesc.lpSurface,
+                                      (PBITMAPINFO)&BitmapInfo,DIB_RGB_COLORS);
+        break;
+      default:
+        #ifdef DEBUG
+          WriteLog("Unexptected BitCount %d \n",LockedSurfaceDesc.ddpfPixelFormat.dwRGBBitCount);
+        #endif
+        me->hbmImage=NULL;
+    } // end switch (me->DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount)
+
+    if(me->hbmImage == NULL)
+    {
+      #ifdef DEBUG
+        WriteLog("Can't create bitmap!\n");
+      #endif
+      DeleteDC(me->hdcImage);
+      me->hdcImage = NULL;
+      me->Vtbl.Unlock(me,NULL);
+      return(DDERR_GENERIC);
+    }
+  }
+  else
+  {
+    if(me->dwLastDCUnique != me->dwUniqueValue)
+    {
+      #ifdef DEBUG
+        WriteLog("The Surface was locked/unlocked after the last DC was created =>Update Bitmap!\n");
+      #endif
+
+      memset(&BitmapInfo,0, sizeof(BitmapInfo));
+      BitmapInfo.bmiHead.biSize     = sizeof(BITMAPINFOHEADER);
+      BitmapInfo.bmiHead.biWidth    = LockedSurfaceDesc.lPitch/ (LockedSurfaceDesc.ddpfPixelFormat.dwRGBBitCount>>3);
+      BitmapInfo.bmiHead.biHeight   = LockedSurfaceDesc.dwHeight;
+      BitmapInfo.bmiHead.biPlanes   = 1;
+      BitmapInfo.bmiHead.biBitCount = LockedSurfaceDesc.ddpfPixelFormat.dwRGBBitCount;
+
+      switch(LockedSurfaceDesc.ddpfPixelFormat.dwRGBBitCount)
+      {
+        case 1:
+        case 4:
+        case 8:
+          BitmapInfo.bmiHead.biCompression = BI_RGB;
+          GetSystemPaletteEntries(me->hdcImage,0,255,(PPALETTEENTRY)&BitmapInfo.bmiCols[0]);
+          SetDIBits(me->hdcImage, me->hbmImage, 0, LockedSurfaceDesc.dwHeight,
+                    me->DDSurfaceDesc.lpSurface,(PBITMAPINFO)&BitmapInfo,DIB_RGB_COLORS);
+          break;
+        case 16:
+        case 32:
+          BitmapInfo.bmiHead.biCompression = BI_BITFIELDS;
+          BitmapInfo.bmiHead.biClrUsed     = 3;
+          *((DWORD *) &(BitmapInfo.bmiCols[0])) = me->DDSurfaceDesc.ddpfPixelFormat.dwRBitMask;
+          *((DWORD *) &(BitmapInfo.bmiCols[1])) = me->DDSurfaceDesc.ddpfPixelFormat.dwGBitMask;
+          *((DWORD *) &(BitmapInfo.bmiCols[2])) = me->DDSurfaceDesc.ddpfPixelFormat.dwBBitMask;
+          SetDIBits(me->hdcImage, me->hbmImage, 0, me->DDSurfaceDesc.dwHeight,
+                    me->DDSurfaceDesc.lpSurface,(PBITMAPINFO)&BitmapInfo,DIB_RGB_COLORS);
+          break;
+        case 24:
+          BitmapInfo.bmiHead.biCompression = BI_RGB;
+          SetDIBits(me->hdcImage, me->hbmImage, 0, me->DDSurfaceDesc.dwHeight,
+                    me->DDSurfaceDesc.lpSurface,(PBITMAPINFO)&BitmapInfo,DIB_RGB_COLORS);
+          break;
+        default:
+          #ifdef DEBUG
+            WriteLog("Unexptected BitCount %d => Bitmap not updated!\n",LockedSurfaceDesc.ddpfPixelFormat.dwRGBBitCount);
+          #endif
+          break;
+      } // end switch (me->DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount)
+
+    }
+  }
+
+  // Allways selct the bitmap into the DC! No matter if the old or a new one
+
+  if((me->hgdiOld = SelectObject(me->hdcImage, me->hbmImage)) == NULL)
+  {
+    #ifdef DEBUG
+      WriteLog("Can't select bitmap into dc!\n");
+    #endif
+    DeleteDC(me->hdcImage);
+    me->hdcImage = NULL;
+    DeleteObject(me->hbmImage);
+    me->hbmImage = NULL;
+    me->Vtbl.Unlock(me,NULL);
+    return(DDERR_GENERIC);
+  }
+
+  *hdc = me->hdcImage;
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfGetFlipStatus(THIS This, DWORD dwFlags)
+{
+  #ifdef DEBUG
+    WriteLog("SurfGetFlipStatus\n");
+  #endif
+
+  if( (DDGFS_CANFLIP!=dwFlags) && (DDGFS_ISFLIPDONE!=dwFlags) )
+    return DDERR_INVALIDPARAMS;
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfGetOverlayPosition(THIS This, LPLONG lplX, LPLONG lplY)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+  #ifdef DEBUG
+    WriteLog("SurfGetOverlayPosition\n");
+  #endif
+
+  // Maybe simply return dderr_notsupported as we retun a max overlay value of 0 in the caps ?
+
+  if( (NULL==lplX) || (NULL==lplY))
+    return DDERR_INVALIDPARAMS;
+
+  if(!(me->DDSurfaceDesc.ddsCaps.dwCaps & DDSCAPS_OVERLAY))
+    return DDERR_NOTAOVERLAYSURFACE;
+
+  if(!(me->DDSurfaceDesc.ddsCaps.dwCaps & DDSCAPS_VISIBLE))
+    return DDERR_OVERLAYNOTVISIBLE;
+
+  if(!me->fOverlayValid)
+    return DDERR_NOOVERLAYDEST;
+
+  *lplX = me->lOverlayX;
+  *lplY = me->lOverlayY;
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfGetPalette(THIS This, LPDIRECTDRAWPALETTE FAR *lplpPalette)
 {
  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
 
-  dprintf(("SurfGetDC %X\n", me));
-  if(me == NULL) {
-    return DDERR_INVALIDOBJECT;
-  }
-
-  if(me->surfaceType & DDSCAPS_PRIMARYSURFACE) {
-    dprintf(("Primary surface!\n"));
-  }
-
-  if(me->fLocked) {
-    return(DDERR_DCALREADYCREATED);
-  }
-  me->fLocked = TRUE;
-  if(me->hdcImage == NULL && me->hbmImage == NULL) {
-    me->hdcImage = CreateCompatibleDC(NULL);
-    if(me->hdcImage == NULL) {
-        dprintf(("Can't create compatible DC!\n"));
-        me->fLocked = FALSE;
-        return(DDERR_GENERIC);
-    }
-    dprintf(("CreateBitmap %d %d", me->width, me->height));
-    me->hbmImage = (HBITMAP)CreateBitmap(me->width, me->height, 1, me->bpp, NULL); //KSO Apr 19 1999: TODO! Why do I have to case this?
-    if(me->hbmImage == NULL) {
-        dprintf(("Can't create compatible bitmap!\n"));
-        DeleteDC(me->hdcImage);
-        me->hdcImage = NULL;
-        me->fLocked = FALSE;
-        return(DDERR_GENERIC);
-    }
-    if((me->hgdiOld = SelectObject(me->hdcImage, (HGDIOBJ)me->hbmImage)) == NULL) {
-        dprintf(("Can't select bitmap into dc!\n"));
-        DeleteDC(me->hdcImage);
-        me->hdcImage = NULL;
-        DeleteObject((HANDLE)me->hbmImage);
-        me->hbmImage = NULL;
-        me->fLocked = FALSE;
-        return(DDERR_GENERIC);
-    }
-    me->bitmapData = (char *)malloc(sizeof(BITMAPINFOHEADER) +
-                        me->width*me->height*me->bpp/8);
-  }
-  *hdc = (W32_HDC)me->hdcImage;
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall SurfGetFlipStatus(THIS_ DWORD)
-{
-  dprintf(("SurfGetFlipStatus\n"));
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall SurfGetOverlayPosition(THIS_ LPLONG, LPLONG )
-{
-  dprintf(("SurfGetOverlayPosition\n"));
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall SurfGetPalette(THIS_ LPDIRECTDRAWPALETTE FAR *lplpPalette)
-{
- OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
-
-  dprintf(("SurfGetPalette\n"));
-  if(me == NULL) {
-    return DDERR_INVALIDOBJECT;
-  }
-  if(me->lpPalette) {
+  #ifdef DEBUG
+    WriteLog("SurfGetPalette\n");
+  #endif
+
+  if(me->lpPalette)
+  {
     *lplpPalette = (LPDIRECTDRAWPALETTE)me->lpPalette;
     return(DD_OK);
   }
-  else  return(DDERR_NOPALETTEATTACHED);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall SurfGetPixelFormat(THIS_ LPDDPIXELFORMAT)
-{
-  dprintf(("SurfGetPixelFormat\n"));
+  else
+    return(DDERR_NOPALETTEATTACHED);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfGetPixelFormat(THIS This, LPDDPIXELFORMAT lpPixelFormat)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+
+  #ifdef DEBUG
+    WriteLog("SurfGetPixelFormat\n");
+  #endif
+
+  if(NULL==lpPixelFormat)
+    return DDERR_INVALIDPARAMS;
+
+  memcpy((char*)lpPixelFormat,(char*)&(me->DDSurfaceDesc.ddpfPixelFormat), sizeof(DDPIXELFORMAT));
+
   return(DD_OK);
 }
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall SurfGetSurfaceDesc(THIS_ LPDDSURFACEDESC lpSurface)
+HRESULT __stdcall SurfGetSurfaceDesc(THIS This, LPDDSURFACEDESC lpSurface)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+
+  #ifdef DEBUG
+    WriteLog("SurfGetSurfaceDesc\n");
+  #endif
+
+  if((lpSurface == NULL)||(lpSurface->dwSize != sizeof(DDSURFACEDESC)) )
+    return(DDERR_INVALIDPARAMS);
+
+  memcpy((char *)lpSurface, (char *)&me->DDSurfaceDesc, sizeof(DDSURFACEDESC));
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfGetSurfaceDesc4(THIS This, LPDDSURFACEDESC2 lpSurface)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+
+  #ifdef DEBUG
+    WriteLog("SurfGetSurfaceDesc4\n");
+  #endif
+
+  if((lpSurface == NULL)||(lpSurface->dwSize != sizeof(DDSURFACEDESC2)) )
+    return(DDERR_INVALIDPARAMS);
+
+  memcpy((char *)lpSurface, (char *)&me->DDSurfaceDesc, sizeof(DDSURFACEDESC2));
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfInitialize(THIS, LPDIRECTDRAW, LPDDSURFACEDESC)
+{
+  #ifdef DEBUG
+    WriteLog("SurfInitialize\n");
+  #endif
+
+  return(DDERR_ALREADYINITIALIZED); // Init is done during creation see M$ Doc
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfInitialize4(THIS, LPDIRECTDRAW, LPDDSURFACEDESC2)
+{
+  #ifdef DEBUG
+    WriteLog("SurfInitialize\n");
+  #endif
+
+  return(DDERR_ALREADYINITIALIZED); // Init is done during creation see M$ Doc
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfIsLost(THIS)
+{
+  // We don't loose any surface ;)
+  // But we might shoud check for primary and/or Dive Buffers as I don't know
+  // if  they are preserved if switching to a FS DOS/OS2 session
+  //
+  #ifdef DEBUG
+    WriteLog("SurfIsLost\n");
+  #endif
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfLock(THIS This, LPRECT lpRect, LPDDSURFACEDESC lpSurfaceDesc,
+         DWORD dwFlags, HANDLE hEvent)
+{
+  DDSURFACEDESC2 SurfaceDesc4;
+  HRESULT rc;
+
+  #ifdef DEBUG
+    WriteLog("SurfLock %d %d %d %d\n", (int)lpRect, (int)lpSurfaceDesc, dwFlags, hEvent);
+  #endif
+
+  if((NULL==lpSurfaceDesc)||(NULL!=hEvent))
+    return DDERR_INVALIDPARAMS;
+
+  if(lpSurfaceDesc->dwSize != sizeof(DDSURFACEDESC))
+    return DDERR_INVALIDPARAMS;
+
+  SurfaceDesc4.dwSize = sizeof(DDSURFACEDESC2);
+
+  rc = SurfLock4(This, lpRect, &SurfaceDesc4, dwFlags, hEvent);
+  if (DD_OK==rc)
+  {
+    memcpy((char*)lpSurfaceDesc,(char*)&SurfaceDesc4, sizeof(DDSURFACEDESC) );
+  }
+
+  return(rc);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfLock4(THIS This, LPRECT lpRect, LPDDSURFACEDESC2 lpSurfaceDesc,
+         DWORD dwFlags, HANDLE hEvent)
+{
+
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+  ISequence<IRectangle*>::Cursor *EnumCursor;
+
+  BOOL Found;
+  ULONG  nrScanLines, rc;
+  char *pBuffer;
+  IRectangle *pIRectCurrent,*pIRectNew;
+  static int times = 0;
+
+  #ifdef DEBUG
+    WriteLog("SurfLock4 %d %d %d %d\n", (int)lpRect, (int)lpSurfaceDesc, dwFlags, hEvent);
+  #endif
+
+  if( (NULL==lpSurfaceDesc) ||
+      (NULL!=hEvent)
+    )
+    return DDERR_INVALIDPARAMS;
+
+  if (NULL!=lpRect)
+    pIRectNew = new IRectangle( lpRect->left, lpRect->bottom, lpRect->right, lpRect->top);
+  else
+    pIRectNew = new IRectangle( 0, me->height, me->width, 0);
+
+  // ToDo : the lockchecking should be done in a critcal seq.
+
+  if(me->fLocked)
+  {
+    if (NULL==lpRect)
+    {
+      // If anything is locked we can't locke the complete surface
+      Found = TRUE;
+    }
+    else
+    {
+      // If the new Rectangle intersects with any of the already locked rectangles it can't
+      // be locked so check for this
+
+      EnumCursor = me->LockedRectSequence.newCursor();
+      EnumCursor->setToFirst();
+      Found = FALSE;
+
+      while((EnumCursor->isValid() ) && !Found)
+      {
+        pIRectCurrent = EnumCursor->element();
+        Found = pIRectCurrent->intersects(*pIRectNew);
+        EnumCursor->setToNext();
+      }
+
+      delete EnumCursor;
+
+    }
+
+    if (Found)
+    {
+      delete pIRectNew;
+      #ifdef DEBUG
+        WriteLog("SurfLock4: Surface already locked\n");
+      #endif
+      return(DDERR_SURFACEBUSY);
+    }
+  }
+
+  memcpy((char *)lpSurfaceDesc, (char *)&me->DDSurfaceDesc, sizeof(DDSURFACEDESC2));
+
+  if(lpRect != NULL)
+  {
+    lpSurfaceDesc->lpSurface =  (LPVOID)((char*)me->pFrameBuffer +
+                                (lpRect->top * me->dwPitchFB) +
+                                (lpRect->left * (lpSurfaceDesc->ddpfPixelFormat.dwRGBBitCount>>3)));
+    #ifdef DEBUG
+      WriteLog("SurfLock4 %d (x,y) = (%d,%d)\n", lpSurfaceDesc->lpSurface, lpRect->top, lpRect->left);
+    #endif
+  }
+  else
+  {
+    #ifdef DEBUG
+      WriteLog("SurfLock4 %d \n", lpSurfaceDesc->lpSurface);
+    #endif
+  }
+  // Add the rectangle to the list of locked rectangles
+
+  me->LockedRectSequence.addAsLast(pIRectNew);
+
+  me->fLocked = TRUE;
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfReleaseDC(THIS This, HDC hdc)
 {
  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
- ULONG dwFlags;
-
-  if(me == NULL) {
-    return DDERR_INVALIDOBJECT;
-  }
-  if(lpSurface == NULL)
-    return(DDERR_INVALIDPARAMS);
-
-  dwFlags = lpSurface->dwFlags;
-  dprintf(("SurfGetSurfaceDesc %X\n", lpSurface->dwFlags));
-  memcpy((char *)lpSurface, (char *)&me->DDSurfaceDesc, sizeof(DDSURFACEDESC));
-
-  lpSurface->dwFlags = dwFlags;
-  if(lpSurface->dwFlags & DDSD_HEIGHT) {
-    lpSurface->dwHeight = me->height;
-  }
-  if(lpSurface->dwFlags & DDSD_WIDTH) {
-    lpSurface->dwWidth = me->width;
-  }
-  //TODO: handle rest of flags
+ struct
+ {
+   BITMAPINFOHEADER  bmiHead;
+   RGBQUAD           bmiCols[256];
+ } BitmapInfo;
+ int                    i;
+
+  #ifdef DEBUG
+    WriteLog("SurfReleaseDC\n");
+  #endif
+
+  if(hdc != me->hdcImage)
+    return(DDERR_INVALIDOBJECT);
+
+  //unselect our bitmap
+  SelectObject(me->hdcImage, me->hgdiOld);
+
+  memset(&BitmapInfo,0, sizeof(BitmapInfo));
+  BitmapInfo.bmiHead.biSize     = sizeof(BITMAPINFOHEADER);
+  BitmapInfo.bmiHead.biWidth    = me->DDSurfaceDesc.lPitch/ (me->DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount>>3);
+  BitmapInfo.bmiHead.biHeight   = me->DDSurfaceDesc.dwHeight;
+  BitmapInfo.bmiHead.biPlanes   = 1;
+  BitmapInfo.bmiHead.biBitCount = me->DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount;
+
+  switch(me->DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount)
+  {
+    case 1:
+    case 4:
+    case 8:
+      BitmapInfo.bmiHead.biCompression = BI_RGB;
+      GetSystemPaletteEntries(me->hdcImage,0,255,(PPALETTEENTRY)&BitmapInfo.bmiCols[0]);
+      GetDIBits(hdc, me->hbmImage, 0, me->DDSurfaceDesc.dwHeight,
+                me->DDSurfaceDesc.lpSurface,(PBITMAPINFO)&BitmapInfo,DIB_PAL_COLORS);
+      break;
+    case 16:
+    case 32:
+      BitmapInfo.bmiHead.biCompression = BI_BITFIELDS;
+      BitmapInfo.bmiHead.biClrUsed     = 3;
+      *((DWORD *) &(BitmapInfo.bmiCols[0])) = me->DDSurfaceDesc.ddpfPixelFormat.dwRBitMask;
+      *((DWORD *) &(BitmapInfo.bmiCols[1])) = me->DDSurfaceDesc.ddpfPixelFormat.dwGBitMask;
+      *((DWORD *) &(BitmapInfo.bmiCols[2])) = me->DDSurfaceDesc.ddpfPixelFormat.dwBBitMask;
+      GetDIBits(hdc, me->hbmImage, 0, me->DDSurfaceDesc.dwHeight,
+                me->DDSurfaceDesc.lpSurface,(PBITMAPINFO)&BitmapInfo,DIB_RGB_COLORS);
+      break;
+    case 24:
+      BitmapInfo.bmiHead.biCompression = BI_RGB;
+      GetDIBits(hdc, me->hbmImage, 0, me->DDSurfaceDesc.dwHeight,
+                me->DDSurfaceDesc.lpSurface,(PBITMAPINFO)&BitmapInfo,DIB_RGB_COLORS);
+      break;
+    default:
+      #ifdef DEBUG
+        WriteLog("Unexptected BitCount %d => Surface unlocked but no data copied back\n",me->DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount);
+      #endif
+      // we might could keep the surface locked and return an error but this is more "safe"
+      break;
+  } // end switch (me->DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount)
+
+  me->Vtbl.Unlock(me,NULL);
+  me->dwLastDCUnique = me->dwUniqueValue; // Store this to see if the surface was locked after we released the DC
+
   return(DD_OK);
 }
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall SurfInitialize(THIS_ LPDIRECTDRAW, LPDDSURFACEDESC)
-{
-  dprintf(("SurfInitialize\n"));
+HRESULT __stdcall SurfRestore(THIS)
+{
+  #ifdef DEBUG
+    WriteLog("SurfRestore\n");
+  #endif
+
   return(DD_OK);
 }
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall SurfIsLost(THIS)
-{
-  dprintf(("SurfIsLost\n"));
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall SurfLock(THIS_ W32_LPRECT lpRect, LPDDSURFACEDESC lpSurfaceDesc,
-               DWORD dwFlags, W32_HANDLE hEvent)
+HRESULT __stdcall SurfSetClipper(THIS This, LPDIRECTDRAWCLIPPER lpClipper)
 {
  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
- ULONG                  pImageBuffer, nrBytesPerScanLine, nrScanLines, rc;
- OS2RECTL   rectl;
- static int times = 0;
-
-  dprintf(("SurfLock %X %X %d %d\n", me, (int)lpRect, dwFlags, hEvent));
-  if(me == NULL) {
-    return DDERR_INVALIDOBJECT;
-  }
-
-  if(me->fLocked) {
-    dprintf(("SurfLock: Surface already locked\n"));
-    return(DDERR_SURFACEBUSY);
-  }
-  me->fLocked = TRUE;       //TODO: not really safe
-  if(me->diveBufNr == DIVE_BUFFER_SCREEN) {
-    if(lpRect) {
-        rectl.xLeft    = lpRect->left;
-            rectl.yBottom  = lpRect->bottom;
-            rectl.xRight   = lpRect->right;
-            rectl.yTop     = lpRect->top;
-    }
-    else {
-        rectl.xLeft    = 0;
-            rectl.yBottom  = me->lpDraw->GetScreenHeight();
-            rectl.xRight   = me->lpDraw->GetScreenWidth();
-            rectl.yTop     = 0;
-    }
-    dprintf(("SurfLock: Screen buffer!\n"));
-    rc = DiveAcquireFrameBuffer(me->hDive, (PRECTL)&rectl);
-    if(rc != DIVE_SUCCESS) {
-        dprintf(("frame buffer access error %d\n", rc));
-        me->fLocked = FALSE;
-        return(DDERR_INVALIDPARAMS);
-    }
-    pImageBuffer = (ULONG)me->pFrameBuffer;
-  }
-  else {
-    rc = DiveBeginImageBufferAccess(me->hDive, me->diveBufNr, (PBYTE *)&pImageBuffer,
-                            &nrBytesPerScanLine, &nrScanLines);
-    if(rc != DIVE_SUCCESS) {
-        dprintf(("SurfLock: DiveBeginImageBufferAccess returned %d\n", rc));
-        me->fLocked = FALSE;
-        return(DDERR_INVALIDPARAMS);
-    }
-  }
-
-  if(!(dwFlags & DDLOCK_SURFACEMEMORYPTR) && lpRect != NULL) {
-    pImageBuffer += lpRect->top*nrBytesPerScanLine + lpRect->left;
-    lpSurfaceDesc->lpSurface = (LPVOID)pImageBuffer;
-        dprintf(("SurfLock %X (x,y) = (%d,%d)\n", pImageBuffer, lpRect->top, lpRect->left));
-  }
-  else {
-    dprintf(("SurfLock %X \n", pImageBuffer));
-  }
-  //copy buffer address in surface structure
-  me->DDSurfaceDesc.lpSurface = (LPVOID)pImageBuffer;
-  memcpy((char *)lpSurfaceDesc, (char *)&me->DDSurfaceDesc, sizeof(DDSURFACEDESC));
-
-  lpSurfaceDesc->dwFlags |= DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH | DDSD_PIXELFORMAT;
-  lpSurfaceDesc->dwHeight = me->height;
-  lpSurfaceDesc->dwWidth  = me->width;
-  lpSurfaceDesc->lPitch   = me->width*me->bpp/8;
-  memset((char *)&lpSurfaceDesc->ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT));
-  lpSurfaceDesc->ddpfPixelFormat.dwFourCC = me->fccColorFormat;
-  lpSurfaceDesc->ddpfPixelFormat.dwSize   = sizeof(DDPIXELFORMAT);
-  lpSurfaceDesc->ddpfPixelFormat.dwFlags  = DDPF_FOURCC | DDPF_PALETTEINDEXED8 | DDPF_RGB;
-  lpSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = 8;
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall SurfReleaseDC(THIS_ W32_HDC hdc)
-{
- OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
- ULONG                  pImageBuffer, nrBytesPerScanLine, nrScanLines, rc;
- int                    i;
-
-  dprintf(("SurfReleaseDC %X\n", me));
-  if(me == NULL) {
-    return DDERR_INVALIDOBJECT;
-  }
-
-  if((HDC)hdc != me->hdcImage) {
-    dprintf(("hdc != me->hdcImage %d != %d", hdc, me->hdcImage));
-    return(DDERR_INVALIDOBJECT);
-  }
-  rc = GetBitmapBits((HANDLE)me->hbmImage, me->width*me->height*me->bpp/8, me->bitmapData);
-  if(rc == 0) {
-    dprintf(("GetBitmapBits error"));
-    return(DDERR_INVALIDOBJECT);
-  }
-
-  rc = DiveBeginImageBufferAccess(me->hDive, me->diveBufNr, (PBYTE *)&pImageBuffer,
-                      &nrBytesPerScanLine, &nrScanLines);
-  if(rc != DIVE_SUCCESS) {
-    dprintf(("DiveBeginImageBufferAccess returned %d", rc));
-    me->fLocked = FALSE;
-    return(DDERR_GENERIC);
-  }
-  dprintf(("SurfReleaseDC; copy bitmap to image buffer %d %d", me->width, me->height));
-
-  if(memcmp((char *)pImageBuffer, me->bitmapData, me->height*me->width*me->bpp/8) == 0) {
-    dprintf(("identical!!"));
-  }
-  memcpy((char *)pImageBuffer, me->bitmapData, me->height*me->width*me->bpp/8);
-
-  DiveEndImageBufferAccess(me->hDive, me->diveBufNr);
-  me->fLocked = FALSE;
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall SurfRestore(THIS)
-{
-  dprintf(("SurfRestore\n"));
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall SurfSetClipper(THIS_ LPDIRECTDRAWCLIPPER lpClipper)
-{
- OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
-
-  dprintf(("SurfSetClipper\n"));
-  if(me == NULL) {
-    return DDERR_INVALIDOBJECT;
-  }
-  if(lpClipper == NULL) {//deattach surface
-    if(me->lpClipper) {
-        me->lpClipper->Vtbl.Release((IDirectDrawClipper*)me->lpClipper);
-        me->lpClipper = NULL;
-        return(DD_OK);
-    }
-    else    return(DDERR_NOCLIPPERATTACHED);
-  }
+
+  #ifdef DEBUG
+    WriteLog("SurfSetClipper\n");
+  #endif
+
+  if(lpClipper == NULL)
+  {
+    //deattach surface
+    if(me->lpClipper)
+    {
+      me->lpClipper->Vtbl.Release((IDirectDrawClipper*)me->lpClipper);
+      me->lpClipper = NULL;
+      return(DD_OK);
+    }
+    else
+      return(DDERR_NOCLIPPERATTACHED);
+  }
+
   if(lpClipper == (LPDIRECTDRAWCLIPPER)me->lpClipper)
     return(DD_OK);  //already attached
-  if(me->lpClipper != NULL) {
-    me->lpClipper->Vtbl.Release((IDirectDrawClipper*)me->lpClipper); //attach other surface
+
+  if(me->lpClipper != NULL)
+  {
+    me->lpClipper->Vtbl.Release((IDirectDrawClipper*)me->lpClipper);  //attach other surface
     return(DD_OK);
   }
+
   me->lpClipper = (OS2IDirectDrawClipper *)lpClipper;
   me->lpClipper->Vtbl.AddRef((IDirectDrawClipper*)me->lpClipper);
+
   return(DD_OK);
 }
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall SurfSetColorKey(THIS_ DWORD dwFlags, LPDDCOLORKEY lpColorkey)
-{
- OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
-
-  dprintf(("SurfSetColorKey\n"));
-  if(me == NULL) {
-    return DDERR_INVALIDOBJECT;
-  }
-  me->ColorKeyFlags |= dwFlags;
-  if(dwFlags & DDCKEY_DESTBLT) {
-    me->ColorSpaceLowValue[COLORKEY_DEST]  = lpColorkey->dwColorSpaceLowValue;
-    me->ColorSpaceHighValue[COLORKEY_DEST] = lpColorkey->dwColorSpaceHighValue;
+HRESULT __stdcall SurfSetColorKey(THIS  This, DWORD dwFlags, LPDDCOLORKEY lpDDColKey)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+
+  #ifdef DEBUG
+    WriteLog("SurfSetColorKey\n");
+  #endif
+
+  if (0==dwFlags)
+    return (DDERR_INVALIDPARAMS);
+
+  // as we report only src colorkey in the caps return error on all others flags
+  if( (DDCKEY_DESTBLT|DDCKEY_DESTOVERLAY|DDCKEY_SRCOVERLAY|DDCKEY_COLORSPACE) & dwFlags)
+    return(DDERR_UNSUPPORTED);
+
+  if(DDCKEY_SRCBLT & dwFlags)
+  {
+    me->lpVtbl->ChangeUniquenessValue(me); // we changed somethin so change this value
+    if(NULL!=lpDDColKey)
+    {
+      memcpy(&(me->DDSurfaceDesc.ddckCKSrcBlt), lpDDColKey, sizeof(DDCOLORKEY) );
+      me->DDSurfaceDesc.dwFlags |= DDCKEY_SRCBLT;
+
+      // ToDo: Generate a maskbitmap for transparent blitting here
+    }
+    else
+    {
+      memset(&(me->DDSurfaceDesc.ddckCKSrcBlt), 0, sizeof(DDCOLORKEY) );
+      me->DDSurfaceDesc.dwFlags &= ~DDCKEY_SRCBLT;
+    }
+  }
+  else
+    return (DDERR_INVALIDPARAMS); // some other flags where set => error
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfSetOverlayPosition(THIS This, LONG lX, LONG lY)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+
+  #ifdef DEBUG
+    WriteLog("SurfSetOverlayPosition\n");
+  #endif
+
+  if( (me->DDSurfaceDesc.dwFlags & DDSD_CAPS) &&
+      (me->DDSurfaceDesc.ddsCaps.dwCaps & DDSCAPS_OVERLAY) )
+  {
+    if(me->fOverlayValid)
+      return(DDERR_NOOVERLAYDEST);
+
+    if(!(me->DDSurfaceDesc.dwFlags & DDSCAPS_VISIBLE))
+      return(DDERR_OVERLAYNOTVISIBLE);
+
+    // ToDo: If we implement alignment restricions to the Overlay position
+    // check if the new values are OK otherwiese return DDERR_INVALIDPOSITION
+
+    me->lOverlayX = lX;
+    me->lOverlayY = lY;
     return(DD_OK);
   }
-  if(dwFlags & DDCKEY_DESTOVERLAY) {
-    me->ColorSpaceLowValue[COLORKEY_DESTOVERLAY]  = lpColorkey->dwColorSpaceLowValue;
-    me->ColorSpaceHighValue[COLORKEY_DESTOVERLAY] = lpColorkey->dwColorSpaceHighValue;
-    return(DD_OK);
-  }
-  if(dwFlags & DDCKEY_SRCBLT) {
-    me->ColorSpaceLowValue[COLORKEY_SRC]  = lpColorkey->dwColorSpaceLowValue;
-    me->ColorSpaceHighValue[COLORKEY_SRC] = lpColorkey->dwColorSpaceHighValue;
-    return(DD_OK);
-  }
-  if(dwFlags & DDCKEY_SRCOVERLAY) {
-    me->ColorSpaceLowValue[COLORKEY_SRCOVERLAY]  = lpColorkey->dwColorSpaceLowValue;
-    me->ColorSpaceHighValue[COLORKEY_SRCOVERLAY] = lpColorkey->dwColorSpaceHighValue;
-    return(DD_OK);
-  }
-  return(DDERR_INVALIDPARAMS);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall SurfSetOverlayPosition(THIS_ LONG, LONG )
-{
-  dprintf(("SurfSetOverlayPosition\n"));
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall SurfSetPalette(THIS_ LPDIRECTDRAWPALETTE lpPalette)
-{
- OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
-
-  dprintf(("SurfSetPalette %X\n", me));
-  if(me == NULL) {
-    return DDERR_INVALIDOBJECT;
-  }
-  if(lpPalette == NULL) {//deattach palette
-    if(me->lpPalette) {
-        me->lpPalette->Vtbl.Release((IDirectDrawPalette*)me->lpPalette);
-        me->lpPalette = NULL;
-        return(DD_OK);
-    }
-    else    return(DDERR_NOCLIPPERATTACHED);
-  }
+
+  return(DDERR_NOTAOVERLAYSURFACE);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfSetPalette(THIS This, LPDIRECTDRAWPALETTE lpPalette)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+
+  #ifdef DEBUG
+    WriteLog("SurfSetPalette\n");
+  #endif
+
+  if(lpPalette == NULL)
+  {
+    //deattach palette
+    if(me->lpPalette)
+    {
+      // If removed from a primary surface notify
+      // palette that it is no longer attached to the
+      // primary surface => doesn't modify physical palette
+      if(me->surfaceType & DDSCAPS_PRIMARYSURFACE)
+        me->lpPalette->SetIsPrimary(FALSE);
+
+      me->lpPalette->Vtbl.Release((IDirectDrawPalette*)me->lpPalette);
+      me->lpPalette = NULL;
+      return(DD_OK);
+    }
+    else
+      return(DDERR_NOPALETTEATTACHED);
+  }
+
   if(lpPalette == (LPDIRECTDRAWPALETTE)me->lpPalette)
     return(DD_OK);  //already attached
-//?????
-#if 0
-  if(me->lpPalette != NULL) {
-    me->lpClipper->Vtbl.Release(me->lpPalette); //attach other palette
+
+  if(me->lpPalette != NULL)
+  {
+    me->lpPalette->Vtbl.Release((IDirectDrawPalette*)me->lpPalette);  //attach other palette
     return(DD_OK);
   }
-#endif
-
   me->lpPalette = (OS2IDirectDrawPalette *)lpPalette;
   me->lpPalette->Vtbl.AddRef((IDirectDrawPalette*)me->lpPalette);
+
+  // If Attached to a primary surface notify
+  // palette that it is attached to the primary surface
+  //  => It does modify physical palette.
+  // This is important as an palette can be attached to
+  // multiple surfaces. If one is the primary surface
+  // changes done to it via any surface must result in
+  // changes in the phys pal.
+
   if(me->surfaceType & DDSCAPS_PRIMARYSURFACE)
-    me->lpPalette->SetPhysPalette();
+    me->lpPalette->SetIsPrimary(TRUE);
+
+  me->lpVtbl->ChangeUniquenessValue(me);
 
   return(DD_OK);
@@ -1124,65 +3962,155 @@
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall SurfUnlock(THIS_ LPVOID lpSurfaceData)
+HRESULT __stdcall SurfUnlock(THIS This, LPRECT lpSurfaceRect)
+{
+
+
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+  ISequence<IRectangle*>::Cursor *EnumCursor;
+  IRectangle *pIRectUnlock;
+  BOOL Found = FALSE;
+
+  #ifdef DEBUG
+    WriteLog("SurfUnlock\n");
+  #endif
+
+  if(me->fLocked == FALSE)
+  {
+    #ifdef DEBUG
+      WriteLog("Surface not locked!\n");
+    #endif
+    return(DDERR_NOTLOCKED);
+  }
+
+  if(NULL!=lpSurfaceRect)
+  {
+    WriteLog("Unlock rectangle\n");
+    pIRectUnlock = new IRectangle( lpSurfaceRect->left,
+                                   lpSurfaceRect->bottom,
+                                   lpSurfaceRect->right,
+                                   lpSurfaceRect->top);
+  }
+  else
+  {
+    WriteLog("Unlock complete surface\n");
+    pIRectUnlock = new IRectangle( 0, me->height, me->width, 0);
+  }
+
+  #ifdef DEBUG
+    WriteLog("StartEmuneration of Locked Rects\n");
+  #endif
+
+  EnumCursor = me->LockedRectSequence.newCursor();
+  EnumCursor->setToFirst();
+  while(EnumCursor->isValid() && !Found)
+  {
+    Found = (*(EnumCursor->element()) == *pIRectUnlock);
+    if(!Found)
+    {
+      #ifdef DEBUG
+        WriteLog("Not Found, try Next rect\n");
+      #endif
+      EnumCursor->setToNext();
+    }
+    #ifdef DEBUG
+    else
+    {
+      WriteLog("Found Rect\n");
+    }
+    #endif
+  }
+
+  if(!Found)
+  {
+    #ifdef DEBUG
+      WriteLog("Rectangle not locked, wrong Rect!\n\n");
+    #endif
+    return(DDERR_INVALIDRECT);
+  }
+
+  #ifdef DEBUG
+    WriteLog("Remove Rect from Seq.\n");
+  #endif
+
+  me->LockedRectSequence.removeAt(*EnumCursor);
+
+  if(me->LockedRectSequence.isEmpty())  // Do we have unlocked last rectangle
+  {
+    #ifdef DEBUG
+      WriteLog("No Locked Rects left for surface\n");
+    #endif
+    me->fLocked = FALSE;
+  }
+
+  if(me->pFrameBuffer != me->pDiveBuffer)
+  {
+    #ifdef DEBUG
+      WriteLog( "ColorConversion Needed %08X != %08X\n",
+                me->pFrameBuffer,
+                me->pDiveBuffer);
+    #endif
+    me->ColorConversion(lpSurfaceRect);
+  }
+
+  me->lpVtbl->ChangeUniquenessValue(me);
+
+  WriteLog("Unlock OK\n\n");
+
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfUpdateOverlay(THIS This, LPRECT, LPDIRECTDRAWSURFACE2,LPRECT,DWORD, LPDDOVERLAYFX)
+{
+  #ifdef DEBUG
+    WriteLog("SurfUpdateOverlay\n");
+  #endif
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfUpdateOverlay4(THIS, LPRECT, LPDIRECTDRAWSURFACE4,LPRECT,DWORD, LPDDOVERLAYFX)
+{
+  #ifdef DEBUG
+    WriteLog("SurfUpdateOverlay\n");
+  #endif
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfUpdateOverlayDisplay(THIS, DWORD)
+{
+  #ifdef DEBUG
+    WriteLog("SurfUpdateOverlayDisplay\n");
+  #endif
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfUpdateOverlayZOrder(THIS, DWORD, LPDIRECTDRAWSURFACE2)
+{
+  #ifdef DEBUG
+    WriteLog("SurfUpdateOverlayZOrder\n");
+  #endif
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfUpdateOverlayZOrder4(THIS, DWORD, LPDIRECTDRAWSURFACE4)
+{
+  #ifdef DEBUG
+    WriteLog("SurfUpdateOverlayZOrder4\n");
+  #endif
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfGetDDInterface(THIS This, LPVOID FAR *lplpDirectDraw)
 {
  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
 
-  dprintf(("SurfUnlock\n"));
-  if(me == NULL) {
-    return DDERR_INVALIDOBJECT;
-  }
-  if(me->fLocked == FALSE)
-    return(DDERR_NOTLOCKED);
-
-  if(me->diveBufNr == DIVE_BUFFER_SCREEN) {
-        DiveDeacquireFrameBuffer(me->hDive);
-    dprintf(("SurfUnlock: Frame buffer unlocked\n"));
-    me->fLocked = FALSE;
-    return(DD_OK);
-  }
-
-  if(lpSurfaceData != NULL &&
-     ((int)lpSurfaceData < (int)me->DDSurfaceDesc.lpSurface ||
-      (int)lpSurfaceData > (int)me->DDSurfaceDesc.lpSurface + me->height*me->width)) {
-    dprintf(("SurfUnlock: invalid params\n"));
-    return(DDERR_INVALIDPARAMS);
-  }
-  me->fLocked = FALSE;
-  DiveEndImageBufferAccess(me->hDive, me->diveBufNr);
-
-  dprintf(("SurfUnlock ok\n"));
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall SurfUpdateOverlay(THIS_ W32_LPRECT, LPDIRECTDRAWSURFACE2, W32_LPRECT,DWORD, LPDDOVERLAYFX)
-{
-  dprintf(("SurfUpdateOverlay\n"));
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall SurfUpdateOverlayDisplay(THIS_ DWORD)
-{
-  dprintf(("SurfUpdateOverlayDisplay\n"));
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall SurfUpdateOverlayZOrder(THIS_ DWORD, LPDIRECTDRAWSURFACE2)
-{
-  dprintf(("SurfUpdateOverlayZOrder\n"));
-  return(DD_OK);
-}
-//******************************************************************************
-//******************************************************************************
-HRESULT __stdcall SurfGetDDInterface(THIS_ LPVOID FAR *lplpDirectDraw)
-{
- OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
-
-  dprintf(("SurfGetDDInterface\n"));
-  if(me == NULL) {
-    return DDERR_INVALIDOBJECT;
-  }
+  #ifdef DEBUG
+    WriteLog("SurfGetDDInterface\n");
+  #endif
   *lplpDirectDraw = (LPVOID FAR *)me->lpDraw;
   return(DD_OK);
@@ -1190,16 +4118,550 @@
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall SurfPageLock(THIS_ DWORD)
-{
-  dprintf(("SurfPageLock\n"));
+HRESULT __stdcall SurfPageLock(THIS, DWORD)
+{
+  // Only used for DMA memory access
+  // If we implement this for the None dive buffers with a pdd the we must change
+  // from malloc to DosAllocMem and use OBJ_TILE flag
+  #ifdef DEBUG
+    WriteLog("SurfPageLock\n");
+  #endif
   return(DD_OK);
 }
 //******************************************************************************
 //******************************************************************************
-HRESULT __stdcall SurfPageUnlock(THIS_ DWORD)
-{
-  dprintf(("SurfPageUnlock\n"));
+HRESULT __stdcall SurfPageUnlock(THIS, DWORD)
+{
+  #ifdef DEBUG
+    WriteLog("SurfPageUnlock\n");
+  #endif
   return(DD_OK);
 }
 //******************************************************************************
 //******************************************************************************
+// V3 Interface Functions
+
+HRESULT __stdcall SurfSetSurfaceDesc(THIS This, LPDDSURFACEDESC lpSurfDesc, DWORD dwFlags)
+{
+  #ifdef DEBUG
+    WriteLog("SurfSetSurfaceDesc\n");
+  #endif
+
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+  if ( (NULL==lpSurfDesc) || (dwFlags!=0) )
+    return DDERR_INVALIDPARAMS;
+
+  // Is this ok ? Not sure if Front/BackBuffer should be handled like the Primary one.
+  //  if ( ( DDSCAPS_PRIMARYSURFACE == me->DDSurfaceDesc.ddsCaps.dwCaps) ||
+  //       ( DDSCAPS_FRONTBUFFER == me->DDSurfaceDesc.ddsCaps.dwCaps) ||
+  //       ( DDSCAPS_BACKBUFFER  == me->DDSurfaceDesc.ddsCaps.dwCaps) )
+  if(-1==me->diveBufNr)
+    return DDERR_INVALIDSURFACETYPE; // only work for system alloced surfaces
+
+  if (!me->Updated)
+  {
+    me->Updated = TRUE;
+    // free our allocated Memory
+    if(me->DDSurfaceDesc.dwFlags & DDSD_LPSURFACE)
+      free(me->DDSurfaceDesc.lpSurface);
+  }
+  me->lpVtbl->ChangeUniquenessValue(me);
+  memcpy((char *)&(me->DDSurfaceDesc), (char *)lpSurfDesc, sizeof(DDSURFACEDESC));
+
+
+  return DD_OK;
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfSetSurfaceDesc4(THIS This, LPDDSURFACEDESC2 lpSurfDesc, DWORD dwFlags)
+{
+  #ifdef DEBUG
+    WriteLog("SurfSetSurfaceDesc4\n");
+  #endif
+
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+  if ( (NULL==lpSurfDesc) || (dwFlags!=0) )
+    return DDERR_INVALIDPARAMS;
+
+  // Is this ok ? Not sure if Front/BackBuffer should be handled like the Primary one.
+  //  if ( ( DDSCAPS_PRIMARYSURFACE == me->DDSurfaceDesc.ddsCaps.dwCaps) ||
+  //       ( DDSCAPS_FRONTBUFFER == me->DDSurfaceDesc.ddsCaps.dwCaps) ||
+  //       ( DDSCAPS_BACKBUFFER  == me->DDSurfaceDesc.ddsCaps.dwCaps) )
+  if(-1==me->diveBufNr)
+    return DDERR_INVALIDSURFACETYPE; // only work for system alloced surfaces
+
+  if (!me->Updated)
+  {
+    me->Updated = TRUE;
+    // free our allocated Memory
+    if(me->DDSurfaceDesc.dwFlags & DDSD_LPSURFACE)
+      free(me->DDSurfaceDesc.lpSurface);
+  }
+  me->lpVtbl->ChangeUniquenessValue(me);
+  memcpy((char *)&(me->DDSurfaceDesc), (char *)lpSurfDesc, sizeof(DDSURFACEDESC2));
+
+  return DD_OK;
+}
+//******************************************************************************
+//******************************************************************************
+// V4 Interface Functions
+
+HRESULT __stdcall SurfSetPrivateData(THIS This, REFGUID refGUID, LPVOID lpData,
+                                     DWORD dwDataSize, DWORD dwFlags)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+  ISequence<PSURFPRIVATEDATA>::Cursor * EnumCursor;
+  PSURFPRIVATEDATA pSData;
+  void *pBuffer;
+  BOOL bFound = FALSE;
+
+  #ifdef DEBUG
+    WriteLog("SurfSetPrivateData\n");
+  #endif
+
+  if(NULL==me)
+    return(DDERR_INVALIDOBJECT);
+
+  if((NULL==lpData)||(0==dwDataSize)||
+     (dwFlags & ~(DDSPD_IUNKNOWNPOINTER|DDSPD_VOLATILE)))
+    return(DDERR_INVALIDPARAMS);
+
+  // first check if the refGUID is stored as then the content will be updated
+  if(! me->SurfaceSequencePrivateData.isEmpty() )
+  {
+    EnumCursor = me->SurfaceSequencePrivateData.newCursor();
+    EnumCursor->setToFirst();
+    while(EnumCursor->isValid() && !bFound)
+    {
+      pSData = EnumCursor->element();
+
+      if (IsEqualGUID(pSData->guidTag,refGUID))
+        bFound = TRUE;
+
+      EnumCursor->setToNext();
+    }
+    delete EnumCursor;
+  }
+
+  if(bFound)
+  {
+    // update Private Data
+
+    if (!pSData->isValid)
+    {
+      // Current data is invalid we need to update/allocate
+
+      if(dwFlags & DDSPD_IUNKNOWNPOINTER)
+      {
+        pSData->pData = lpData;
+        pSData->dwSize = 4;
+        pSData->dwFlags = dwFlags;
+        pSData->isValid = TRUE;
+        ((OS2IDirectDrawSurface *) lpData)->lpVtbl->AddRef(lpData);
+      }
+      else
+      {
+        pSData->pData = malloc(dwDataSize);
+        if(NULL!=pSData->pData)
+        {
+          memcpy(pSData->pData,lpData,dwDataSize);
+          pSData->dwSize  = dwDataSize;
+          pSData->dwFlags = dwFlags;
+          pSData->isValid = TRUE;
+        }
+        else
+        {
+          delete pSData;
+          return (DDERR_OUTOFMEMORY);
+        }
+      }
+    }
+    else
+    {
+      if(pSData->dwFlags & DDSPD_IUNKNOWNPOINTER)
+      {
+        if(dwFlags & DDSPD_IUNKNOWNPOINTER)
+        {
+          if(pSData->pData != lpData)
+          {
+            // Change of IUNKOWNPOINTER => release old and add ref to new one
+            ((OS2IDirectDrawSurface *)pSData->pData)->lpVtbl->Release(pSData->pData);
+            ((OS2IDirectDrawSurface *)lpData)->lpVtbl->AddRef(lpData);
+            pSData->pData = lpData;
+          }
+          pSData->dwFlags = dwFlags; // Update the flags, size is the same
+        }
+        else
+        {
+          // Replace IUNKOWN through data
+          pBuffer = malloc(dwDataSize); // get new buffer first
+          if(NULL!=pBuffer)
+          {
+            // release old ref and copy data
+            ((OS2IDirectDrawSurface *)pSData->pData)->lpVtbl->Release(pSData->pData);
+            memcpy(pBuffer,lpData,dwDataSize);
+            pSData->pData = pBuffer;
+            pSData->dwSize = dwDataSize; // Update the size
+            pSData->dwFlags = dwFlags;   // Update the flags
+          }
+          else
+            return(DDERR_OUTOFMEMORY);
+        }
+      }
+      else
+      {
+        if(dwFlags & DDSPD_IUNKNOWNPOINTER)
+        {
+          // Change of data to IUNKOWNPOINTER => free old memory and add ref to new one
+          free(pSData->pData);
+          ((OS2IDirectDrawSurface *)lpData)->lpVtbl->AddRef(lpData);
+          pSData->pData = lpData;
+          pSData->dwSize = dwDataSize; // Update the size
+          pSData->dwFlags = dwFlags;   // Update the flags
+        }
+        else
+        {
+          //  Update/Replace data
+          if(pSData->dwSize!=dwDataSize)
+            pBuffer = realloc(pSData->pData,dwDataSize); // update buffer to new size
+          else
+            pBuffer = pSData->pData;
+
+          if(NULL!=pBuffer)
+          {
+            // release old ref and copy data
+            memcpy(pBuffer,lpData,dwDataSize);
+            pSData->pData = pBuffer;
+            pSData->dwSize = dwDataSize; // Update the size
+            pSData->dwFlags = dwFlags;   // Update the flags
+          }
+          else
+            return(DDERR_OUTOFMEMORY);
+        }
+      }
+    }
+  }
+  else
+  {
+    // New data
+
+    pSData = new(SURFPRIVATEDATA);
+    if (NULL!=pSData)
+    {
+      if(dwFlags & DDSPD_IUNKNOWNPOINTER)
+      {
+        memcpy(&(pSData->guidTag),&refGUID,sizeof(GUID));
+        pSData->pData = lpData;
+        pSData->dwSize = 4;
+        pSData->dwFlags = dwFlags;
+        pSData->isValid = TRUE;
+        ((OS2IDirectDrawSurface *)lpData)->lpVtbl->AddRef(lpData);
+      }
+      else
+      {
+        pSData->pData = malloc(dwDataSize);
+        if(NULL!=pSData->pData)
+        {
+          memcpy(&(pSData->guidTag),&refGUID,sizeof(GUID));
+          memcpy(pSData->pData,lpData,dwDataSize);
+          pSData->dwSize  = dwDataSize;
+          pSData->dwFlags = dwFlags;
+          pSData->isValid = TRUE;
+        }
+        else
+        {
+          delete pSData;
+          return (DDERR_OUTOFMEMORY);
+        }
+      }
+    }
+    else
+      return (DDERR_OUTOFMEMORY);
+  }
+  return(DD_OK);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfGetPrivateData(THIS This, REFGUID refGUID, LPVOID lpData, LPDWORD lpDataSize)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+  ISequence<PSURFPRIVATEDATA>::Cursor * EnumCursor;
+  PSURFPRIVATEDATA pSData;
+  BOOL bFound = FALSE;
+  #ifdef DEBUG
+    WriteLog("SurfGetPrivateData\n");
+  #endif
+  if(NULL==me)
+    return(DDERR_INVALIDOBJECT);
+
+  if((NULL==lpData)||(NULL==lpDataSize))
+    return(DDERR_INVALIDPARAMS);
+
+  if(! me->SurfaceSequencePrivateData.isEmpty() )
+  {
+    EnumCursor = me->SurfaceSequencePrivateData.newCursor();
+    EnumCursor->setToFirst();
+    while(EnumCursor->isValid() && !bFound)
+    {
+      pSData = EnumCursor->element();
+
+      if (IsEqualGUID(pSData->guidTag,refGUID))
+        bFound = TRUE;
+
+      EnumCursor->setToNext();
+    }
+    delete EnumCursor;
+  }
+
+  if(bFound)
+  {
+    if(!pSData->isValid)
+      return(DDERR_EXPIRED);
+
+    if(pSData->dwSize > *lpDataSize)
+    {
+      // Buffer to small return needed Size
+      *lpDataSize = pSData->dwSize;
+      return(DDERR_MOREDATA);
+    }
+
+    memcpy(lpData,pSData->pData,pSData->dwSize);
+    return(DD_OK);
+  }
+
+  return (DDERR_NOTFOUND);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfFreePrivateData(THIS This, REFGUID refGUID)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+  ISequence<PSURFPRIVATEDATA>::Cursor * EnumCursor;
+  PSURFPRIVATEDATA pSData;
+  BOOL bFound = FALSE;
+  #ifdef DEBUG
+    WriteLog("SurfFreePrivateData\n");
+  #endif
+  if(NULL==me)
+    return(DDERR_INVALIDOBJECT);
+
+  if(! me->SurfaceSequencePrivateData.isEmpty() )
+  {
+    EnumCursor = me->SurfaceSequencePrivateData.newCursor();
+    EnumCursor->setToFirst();
+    while(EnumCursor->isValid() && !bFound)
+    {
+      pSData = EnumCursor->element();
+
+      if (IsEqualGUID(pSData->guidTag,refGUID))
+      {
+        bFound = TRUE;
+
+        if(pSData->isValid)
+        {
+          // delete the data if valid
+          if (pSData->dwFlags & DDSPD_IUNKNOWNPOINTER)
+          {
+            // pointer to com stored so calll its release
+            ((OS2IDirectDrawSurface *) pSData->pData)->lpVtbl->Release(pSData->pData);
+          }
+          else
+          {
+            // Free allocated data
+            free( pSData->pData);
+          }
+        }
+        // Now remove the entry from the list
+        me->SurfaceSequencePrivateData.removeAt(*EnumCursor);
+        delete pSData; // free alocated Data
+      }
+      EnumCursor->setToNext();
+    }
+    delete EnumCursor;
+  }
+  return (bFound?DD_OK:DDERR_NOTFOUND);
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfGetUniquenessValue(THIS This, LPDWORD lpValue)
+{
+  #ifdef DEBUG
+    WriteLog("SurfGetUniquenessValue\n");
+  #endif
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+  if (NULL==lpValue)
+    return DDERR_INVALIDPARAMS;
+
+  *lpValue = me->dwUniqueValue;
+  return DD_OK;
+}
+//******************************************************************************
+//******************************************************************************
+HRESULT __stdcall SurfChangeUniquenessValue(THIS This)
+{
+  OS2IDirectDrawSurface *me = (OS2IDirectDrawSurface *)This;
+  ISequence<PSURFPRIVATEDATA>::Cursor * EnumCursor;
+  PSURFPRIVATEDATA pSData;
+
+  #ifdef DEBUG
+    WriteLog("SurfChangeUniquenessValue\n");
+  #endif
+  me->dwUniqueValue++;
+
+  if(! me->SurfaceSequencePrivateData.isEmpty() )
+  {
+    EnumCursor = me->SurfaceSequencePrivateData.newCursor();
+    EnumCursor->setToFirst();
+    while(EnumCursor->isValid())
+    {
+      pSData = EnumCursor->element();
+      if (pSData->dwFlags & DDSPD_VOLATILE)
+      {
+        // Data becomes unvalid after a Surface change
+        if (pSData->dwFlags & DDSPD_IUNKNOWNPOINTER)
+        {
+          // pointer to com stored so calll its release
+          ((OS2IDirectDrawSurface *) pSData->pData)->lpVtbl->Release(pSData->pData);
+        }
+        else
+        {
+          // Free allocated data
+          free( pSData->pData);
+        }
+        pSData->pData = NULL;
+        pSData->isValid = FALSE; // set flag to invalid
+      }
+      EnumCursor->setToNext();
+    }
+    delete EnumCursor;
+  }
+
+  return (DD_OK);
+}
+
+//******************************************************************************
+//
+//  Pupose function copies one part of the bitmap inside the same bitmap
+//
+//******************************************************************************
+
+void __cdecl MoveRects(char* pBuffer, LPRECT lpDestRect, LPRECT lpSrcRect, int bpp, LONG lPitch)
+{
+  char *pBltPos, *pSrcPos;
+  int BlitWidth,BlitHeight;
+  static char Scanline[6400];  // sufficient for 1600 at 32 bit
+  // Bridge, we may got a problem ;)
+  // Check for Overlapping Rects
+
+  pBltPos = pBuffer;
+  pSrcPos = pBuffer;
+
+  if(lpDestRect->top <= lpSrcRect->top)
+  {
+    //  +-------+     +-------+      +-------+
+    //  |S      |     |S      |      |S      |  +---+---+---+
+    //  |   +---|---+ +-------+  +---|---+   |  |S/D|D/S|   |
+    //  |   | D |   | | D     |  | D |   |   |  |   |   |   |
+    //  +-------+   | +-------+  |   +-------+  |   |   |   |
+    //      |       | |       |  |       |      +---+---+---+
+    //      +-------+ +-------+  +-------+
+    //
+    // We got one of the above cases (or no overlapping) so copy from bottom up
+
+    pBltPos += (lpDestRect->left * bpp) + lPitch * lpDestRect->top;
+    pSrcPos += (lpSrcRect->left * bpp)  + lPitch * (lpSrcRect->bottom-1);
+    BlitHeight = lpDestRect->bottom - lpDestRect->top;
+    BlitWidth  = (lpDestRect->right - lpDestRect->left) * bpp;
+
+    while(1)
+    {
+      memcpy(Scanline,pSrcPos,BlitWidth);
+      memcpy(pBltPos,Scanline,BlitWidth);
+      pBltPos += lPitch;
+      pSrcPos -= lPitch;
+      if(! (--BlitHeight))
+        break;
+    }
+  }
+  else
+  {
+    //  +-------+     +-------+      +-------+
+    //  | D     |     | D     |      | D     |
+    //  |   +---|---+ +-------+  +---|---+   |
+    //  |   |S  |   | |S      |  |S  |   |   |
+    //  +-------+   | +-------+  |   +-------+
+    //      |       | |       |  |       |
+    //      +-------+ +-------+  +-------+
+    //
+    // We got one of the above cases so copy top down
+
+    pBltPos += (lpDestRect->left * bpp) + lPitch * lpDestRect->top;
+    pSrcPos += (lpSrcRect->left  * bpp) + lPitch * lpSrcRect->top;
+    BlitHeight = lpDestRect->bottom - lpDestRect->top;
+    BlitWidth  = (lpDestRect->right - lpDestRect->left) * bpp;
+
+    while(1)
+    {
+      memcpy(Scanline,pSrcPos,BlitWidth);
+      memcpy(pBltPos,Scanline,BlitWidth);
+      pBltPos += lPitch;
+      pSrcPos += lPitch;
+      if(! (--BlitHeight))
+        break;
+    }
+  }
+
+}
+
+//******************************************************************************
+//
+//  Purpose : Do a blit using the precalced Transbuffer
+//            That is the only way to do fast blits if a colorrange is used
+//            and we can find totally transparent lines and don't blit them
+//            and detect if the part of the line is transparent
+//
+//            Idea for a kind of mask buffer
+//            Format of Transparentbuffer (each line):
+//            the first DWORD contains 2 WORDS with Offset of First Non transparent
+//            pixel in the low word and the last non transparent pixel in a row in
+//            the high word. => 0 = line totally transparent!
+//            This limits the max supported width to 2^16 but I thing this is enougth
+//            The size per line is 1+((Width+31) & ~31) DWORDS => each Bit represents
+//            1 pixel
+//
+//            TransparentBufferCreate(lpDDSurfaceDesc->dwWidth, lpDDSurfaceDesc->dwHeight);
+//
+//          Layout of a DWORD:
+//             UUVVWWXX  dword is processed LS Byte FIRST ...
+//             Each bit in a byte stands for one pixel. MS Bit First
+//
+//          example: Bitmap (16x5) (X= opaque, . = Transparent)
+//                   ...XX...XX....XX
+//                   ..XXXX....XXXX..
+//                   ................
+//                   .........XXXXXX.
+//                   ...XX...X......X
+//
+//                   Transparent buffer (2DWORDS) per line
+//
+//         0x00100003, 0x0000C318
+//         0x000E0002, 0x00003C3C
+//         0x00000000, 0x00000000
+//         0x000F000A, 0x00007E00
+//         0x00100003, 0x00008118
+//******************************************************************************
+
+void __cdecl TransSRCBlit8(LPDDSURFACEDESC2 pDestDesc, LPDDSURFACEDESC2 pSrcDesc,  char *pAlpha, LPRECT lpSrcRect)
+{
+  DWORD *pdwTLine; // pointer to the transparent buffer
+  DWORD dwTLineLen;      // # of DWORDS in each tBuffer line
+  DWORD dwTLineStart;     // # DWORD in which the first transinfo is
+  DWORD dwTDWStart;       // byte in which the firs transinfo is
+  DWORD dwTrans;          // current transparentvalue
+  DWORD BlitWidth;
+  dwTLineLen = 1 + ((pSrcDesc->dwWidth + 31) & ~31);
+  pdwTLine = (DWORD*)pAlpha + (dwTLineLen* lpSrcRect->top);
+  dwTLineStart = 1+(lpSrcRect->left/32);
+  dwTDWStart   = (lpSrcRect->left+8)/8;
+}
+
+
Index: trunk/src/ddraw/ddraw.CPP
===================================================================
--- trunk/src/ddraw/ddraw.CPP	(revision 208)
+++ trunk/src/ddraw/ddraw.CPP	(revision 210)
@@ -1,78 +1,110 @@
-/* $Id: ddraw.CPP,v 1.3 1999-06-10 17:10:57 phaller Exp $ */
+#include <memory.h>
 
-/*
- * DirectDraw exported APIs
- *
- * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
- *
- * Project Odin Software License can be found in LICENSE.TXT
- *
- */
-
-/*@Const************************************************************************
-*   Defined Constants                                                          *
-*******************************************************************************/
+#include <builtin.h>
 #define INITGUID
-#define INCL_GUIDS
-#define WIN32SDK_NOPOSTWRAPPER
-
-/*@Header***********************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#include <os2win.h>
-#include <memory.h>
-#include <builtin.h>
-#include <dive.h>
-
-#include <w_windows.h>
-#include <ddraw.h>
-#include <d3d.h>
-#include <Win32SDKPostWrapper.h>
-
 #include "os2ddraw.h"
+// define the following as we include winnt.h
+#define _OS2WIN_H
+#define FAR
 #include "misc.h"
 
 //******************************************************************************
 //******************************************************************************
-HRESULT WIN32API OS2DirectDrawCreate(GUID FAR *lpGUID,
-                                 LPDIRECTDRAW FAR *lplpDD,
-                             IUnknown FAR *pUnkOuter)
+HRESULT WIN32API OS2DirectDrawCreate( GUID FAR *lpGUID,
+                                      LPDIRECTDRAW FAR *lplpDD,
+                                      IUnknown FAR *pUnkOuter)
 {
- OS2IDirectDraw *newdraw = new OS2IDirectDraw(lpGUID);;
- HRESULT         rc;
+  OS2IDirectDraw *newdraw;
+  HRESULT         rc;
 
-  dprintf(("DirectDrawCreate %X %X %X\n", lpGUID, lplpDD, pUnkOuter));
+  WriteLog("DirectDrawCreate %X %X %X\n", lpGUID, lplpDD, pUnkOuter);
+  newdraw = new OS2IDirectDraw(lpGUID);
 
-  if(newdraw == NULL)   return(DDERR_NODIRECTDRAWHW);
+  if(newdraw == NULL)
+    return(DDERR_NODIRECTDRAWHW);
 
 //  newdraw->Vtbl.AddRef((IDirectDraw *)newdraw);
   rc = newdraw->GetLastError();
-  if(rc != DD_OK) {
+  if(rc != DD_OK)
+  {
     *lplpDD = NULL;
     delete newdraw;
   }
-  else  *lplpDD = (LPDIRECTDRAW)newdraw;
+  else
+    *lplpDD = (LPDIRECTDRAW)newdraw;
+
   return(rc);
 }
 //******************************************************************************
-#if 0  //KSO Apr 19 1999: not needed any longer!
 typedef BOOL (FAR PASCAL * LPDDENUMCALLBACKA)(GUID FAR *, LPSTR, LPSTR, LPVOID);
-#endif
 //******************************************************************************
 HRESULT WIN32API OS2DirectDrawEnumerateA(LPDDENUMCALLBACKA lpCallback,
-                             LPVOID lpContext)
+               LPVOID lpContext)
 {
-  dprintf(("DirectDrawEnumerateA\n"));
+  WriteLog("DirectDrawEnumerateA\n Callback for DIVE\n");
   //call it twice for the DirectDraw & Direct3D classes
-  if(lpCallback(NULL, "DIVE DirectDraw for OS/2",
-        "DirectDraw/2 v0.1", lpContext) == DDENUMRET_CANCEL) {
+ if(lpCallback(NULL, "DIVE DirectDraw for OS/2",
+                "DirectDraw/2 v0.1", lpContext) == DDENUMRET_CANCEL)
+  {
+    WriteLog("Cancel Callback\n");
     return(DD_OK);
   }
   else //now for Direct3D
-  if(lpCallback((GUID *)&IID_IDirect3D, "3Dfx Voodoo Direct3D/2",
-        "Direct3D/2 v0.1", lpContext) == DDENUMRET_CANCEL) {
-    return(DD_OK);
+  {
+    WriteLog("Callback for 3Dfx Voodoo");
+    if(lpCallback((GUID *)&IID_IDirect3D, "3Dfx Voodoo Direct3D/2",
+      "Direct3D/2 v0.1", lpContext) == DDENUMRET_CANCEL)
+    {
+      WriteLog("Cancel Callback\n");
+      return(DD_OK);
+    }
   }
+  WriteLog("Done Enumeration\n\n");
+
   return(DD_OK);
+}
+//******************************************************************************
+typedef struct
+{
+  LPDDENUMCALLBACKEXA lpCallbackEx;
+  LPVOID lpContext;
+} ENUMDATA, *PENUMDATA;
+
+BOOL FAR PASCAL SimpleEnum ( GUID FAR *lpGUID,
+                             LPSTR  lpDriverDescription,
+                             LPSTR  lpDriverName,
+                             LPVOID lpContext)
+{
+  BOOL rc;
+  PENUMDATA pData;
+
+  WriteLog("SimpleEnum\n");
+
+  pData = (PENUMDATA)lpContext;
+  rc = pData->lpCallbackEx( lpGUID,
+                            lpDriverDescription,
+                            lpDriverName,
+                            pData->lpContext,
+                            NULL);
+
+  WriteLog("Callback returned");
+  return rc;
+}
+
+//******************************************************************************
+HRESULT WIN32API OS2DirectDrawEnumerateExA( LPDDENUMCALLBACKEXA lpCallbackEx,
+                                            LPVOID lpContext,
+                                            DWORD dwFlags)
+{
+  ENUMDATA data;
+
+  WriteLog("DirectDrawEnumerateExA\n");
+
+  data.lpCallbackEx = lpCallbackEx;
+  data.lpContext    = lpContext;
+
+   OS2DirectDrawEnumerateA( SimpleEnum,
+                            &data);
+  return (DD_OK);
 }
 //******************************************************************************
@@ -80,5 +112,5 @@
 DWORD WIN32API DDHAL32_VidMemFree(DWORD address)
 {
-  dprintf(("DDHAL32_VidMemFree, not supported\n"));
+  WriteLog("DDHAL32_VidMemFree, not supported\n");
   return(0);
 }
@@ -87,5 +119,5 @@
 DWORD WIN32API DDHAL32_VidMemAlloc(DWORD size)
 {
-  dprintf(("DDHAL32_VidMemAlloc, not supported\n"));
+  WriteLog("DDHAL32_VidMemAlloc, not supported\n");
   return(0);
 }
Index: trunk/src/ddraw/initterm.cpp
===================================================================
--- trunk/src/ddraw/initterm.cpp	(revision 208)
+++ trunk/src/ddraw/initterm.cpp	(revision 210)
@@ -1,13 +1,9 @@
-/* $Id: initterm.cpp,v 1.3 1999-06-19 10:54:39 sandervl Exp $ */
 
 /*
- * DLL entry point
- *
- * Copyright 1998 Sander van Leeuwen
- * Copyright 1998 Peter Fitzsimmons
- *
- *
- * Project Odin Software License can be found in LICENSE.TXT
- *
+
+ * This file was created for Sander van Leeuwen
+
+ * by Project Smarts on 8 May 1997.
+
  */
 
@@ -27,17 +23,16 @@
 #define  INCL_DOSMODULEMGR
 #define  INCL_DOSPROCESS
-#include <os2wrap.h>	//Odin32 OS/2 api wrappers
+#include <os2wrap.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <odin.h>
-#include <misc.h>       /*PLF Wed  98-03-18 23:18:15*/
+#include <misc.h>       /*PLF Wed  98-03-18 23:18:29*/
 
-extern "C" {
 /*-------------------------------------------------------------------*/
 /* _CRT_init is the C run-time environment initialization function.  */
 /* It will return 0 to indicate success and -1 to indicate failure.  */
 /*-------------------------------------------------------------------*/
-int CDECL CRT_init(void);
+int _CRT_init(void);
 /*-------------------------------------------------------------------*/
 /* _CRT_term is the C run-time environment termination function.     */
@@ -45,8 +40,7 @@
 /* statically linked.                                                */
 /*-------------------------------------------------------------------*/
-void CDECL CRT_term(void);
-void CDECL _ctordtorInit( void );
-void CDECL _ctordtorTerm( void );
-}
+void _CRT_term(void);
+void __ctordtorInit( void );
+void __ctordtorTerm( void );
 
 /*-------------------------------------------------------------------*/
@@ -59,4 +53,5 @@
 
 
+
 /****************************************************************************/
 /* _DLL_InitTerm is the function that gets called by the operating system   */
@@ -67,6 +62,6 @@
 /* calling this function.                                                   */
 /****************************************************************************/
-unsigned long SYSTEM _DLL_InitTerm(unsigned long hModule, unsigned long
-                                   ulFlag)
+unsigned long _System _DLL_InitTerm(unsigned long hModule, unsigned long
+                                    ulFlag)
 {
    size_t i;
@@ -88,9 +83,13 @@
          /*******************************************************************/
 
-         if (CRT_init() == -1)
+         if (_CRT_init() == -1)
             return 0UL;
-  	 _ctordtorInit();
+     __ctordtorInit();
 
-         CheckVersionFromHMOD(PE2LX_VERSION, hModule); /*PLF Wed  98-03-18 05:28:48*/
+//SvL: Temporarily disabled
+#if 0
+        CheckVersionFromHMOD(PE2LX_VERSION, hModule); /*PLF Wed  98-03-18 05:28:48*/
+#endif
+
          /*******************************************************************/
          /* A DosExitList routine must be used to clean up if runtime calls */
@@ -100,5 +99,5 @@
          rc = DosExitList(0x0000FF00|EXLST_ADD, cleanup);
          if(rc)
-		return 0UL;
+    return 0UL;
 
          break;
@@ -118,6 +117,6 @@
 static void APIENTRY cleanup(ULONG ulReason)
 {
-   _ctordtorTerm();  
-   CRT_term();
+   __ctordtorTerm();
+   _CRT_term();
    DosExitList(EXLST_EXIT, cleanup);
    return ;
Index: trunk/src/ddraw/misc.cpp
===================================================================
--- trunk/src/ddraw/misc.cpp	(revision 210)
+++ trunk/src/ddraw/misc.cpp	(revision 210)
@@ -0,0 +1,311 @@
+#define INCL_BASE
+#define INCL_WIN
+#define INCL_WINERRORS
+#define INCL_DOSFILEMGR
+#include <os2wrap.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include "misc.h"
+
+
+//#define PMPRINTF
+#ifdef PMPRINTF
+
+/* ----- Customization variables ----- */
+#define PRINTFID      ""
+#define PRINTFMAXLEN  300
+#define PRINTFLINELEN 100
+#define PRINTFTHREADS  54
+#define PRINTFQNAME   "\\QUEUES\\PRINTF32"
+
+/* ----- Includes and externals ----- */
+#include <stddef.h>                /* .. */
+#include <time.h>                  /* .. */
+
+extern ULONG flAllocMem;  /*Tue 03.03.1998: knut */
+
+/* ----- Local defines ----- */
+#define PRINTFIDSIZE sizeof(PRINTFID)
+#define PRINTFMAXBUF PRINTFIDSIZE+PRINTFLINELEN
+
+/* ----- Per-thread output buffer and current indices into line ---- */
+struct perthread
+{
+  LONG   lineindex;                /* where next char */
+  LONG   tidemark;                 /* rightmost char */
+  int    bell;                     /* TRUE if line has bell */
+  UCHAR  line[PRINTFMAXBUF];       /* accumulator */
+};
+
+/* ----- Local static variables ----- */
+static ULONG  ourpid=0;            /* our process ID */
+static ULONG  servepid=0;          /* process IDs of the server */
+static HQUEUE qhandle=0;           /* handle for the queue */
+static struct perthread *tps[PRINTFTHREADS+1]; /* -> per-thread data */
+
+/* ----- Local subroutine ----- */
+static int printf_(struct perthread *);
+
+/* ----------------------------------------------------------------- */
+/* The "printf" function.  Note this has a variable number of        */
+/* arguments.                                                        */
+/* ----------------------------------------------------------------- */
+int SYSTEM EXPORT WriteLog(char *f, ...)
+{
+  TIB    *ptib;                    /* process/thread id structures */
+  PIB    *ppib;                    /* .. */
+  TID    ourtid;                   /* thread ID */
+  struct perthread *tp;            /* pointer to per-thread data */
+  int    rc;                       /* returncode */
+  ULONG  urc;                      /* returncode */
+
+  urc=DosOpenQueue( &servepid,
+                    &qhandle,
+                    PRINTFQNAME);  /* Open the Q */
+  /* Non-0 RC means Q does not exist or cannot be opened */
+  if (urc==343)
+    return 0;          /* queue does not exist, so quit */
+  if (urc!=0)
+    return -1;         /* report any other error */
+
+  /* First determine our thread ID (and hence get access to the      */
+  /* correct per-thread data.  If the per-thread data has not been   */
+  /* allocated, then allocate it now.  It is never freed, once       */
+  /* allocated, as PRINTF is not notified of end-of-thread.          */
+  DosGetInfoBlocks(&ptib,&ppib);   /* get process/thread info */
+  ourtid=ptib->tib_ptib2->tib2_ultid;   /* .. and copy TID */
+  if (ourtid>PRINTFTHREADS)        /* too many threads .. */
+    return 0;                      /* .. so quit, quietly */
+  tp=tps[ourtid];                  /* copy to local pointer */
+  if (tp==NULL)
+  {
+    /* uninitialized (NULL=0) */
+    /* allocate a per-thread structure */
+    tp=(struct perthread *)malloc(sizeof(struct perthread));
+    if (tp==NULL)
+      return -1;       /* out of memory -- return error */
+    tps[ourtid]=tp;                /* save for future calls */
+    strcpy(tp->line,PRINTFID);     /* initialize: line.. */
+    tp->lineindex=PRINTFIDSIZE-1;  /* ..where next char */
+    tp->tidemark =PRINTFIDSIZE-2;  /* ..rightmost char */
+    tp->bell=FALSE;                /* ..if line has bell */
+    if (ourpid==0)
+      ourpid=ppib->pib_ulpid;   /* save PID for all to use */
+  }
+
+  { /* Block for declarations -- only needed if queue exists, etc. */
+    LONG  count;                   /* count of characters formatted */
+    UCHAR buffer[PRINTFMAXLEN+1];  /* formatting area */
+    LONG  i, newind;               /* work */
+    UCHAR ch;                      /* .. */
+    va_list argptr;                /* -> variable argument list */
+
+    va_start(argptr, f);           /* get pointer to argument list */
+    count=vsprintf(buffer, f, argptr);
+    va_end(argptr);                /* done with variable arguments */
+
+    if (count<0)
+      return count-1000;/* bad start */
+
+    if (count>PRINTFMAXLEN)
+    {
+      /* Disaster -- we are probably "dead", but just in case we */
+      /* are not, carry on with truncated data. */
+      count=PRINTFMAXLEN;
+    }
+    buffer[count]='\0';            /* ensure terminated */
+    /* OK, ready to go with the data now in BUFFER                    */
+    /* We copy from the formatted string to the output (line) buffer, */
+    /* taking note of certain control characters and sending a line   */
+    /* the queue whenever we see a LF control, or when the line       */
+    /* fills (causing a forced break).                                */
+    for (i=0; ; i++)
+    {
+      ch=buffer[i]; if (!ch) break;
+      switch(ch)
+      {
+        case '\r':                 /* carriage return */
+          tp->lineindex=PRINTFIDSIZE-1; /* back to start of line */
+          break;
+        case '\n':                 /* new line */
+        case '\f':                 /* form feed */
+          rc=printf_(tp);          /* print a line */
+          if (rc!=0) return rc;    /* error */
+          break;
+        case '\t':                 /* tab */
+          newind=tp->lineindex-PRINTFIDSIZE+1;   /* offset into data */
+          newind=tp->lineindex+5-newind%5;    /* new index requested */
+          if (newind>=PRINTFMAXBUF)
+            newind=PRINTFMAXBUF;    /* clamp */
+          for (; tp->lineindex<newind; tp->lineindex++)
+          {
+            if (tp->lineindex>tp->tidemark)
+            {  /* beyond current end */
+              tp->line[tp->lineindex]=' ';              /* add space */
+              tp->tidemark=tp->lineindex;
+            }
+          }
+          break;
+        case '\v':                 /* vertical tab */
+          /* ignore it */
+          break;
+        case '\b':                 /* backspace */
+          tp->lineindex=max(tp->lineindex-1,PRINTFIDSIZE);
+          break;
+        case '\a':                 /* alert (bell) */
+          tp->bell=TRUE;
+          break;
+        default:                   /* ordinary character */
+          tp->line[tp->lineindex]=ch;
+          if (tp->lineindex>tp->tidemark)  /* is rightmost.. */
+            tp->tidemark=tp->lineindex;
+          tp->lineindex++;                 /* step for next */
+        } /* switch */
+      if (tp->lineindex>=PRINTFMAXBUF)
+      {
+        rc=printf_(tp);            /* print a line */
+        if (rc!=0)
+          return rc;      /* error */
+      }
+
+    } /* copy loop */
+    return count;                  /* all formatted data processed */
+  } /* block */
+} /* printf */
+
+/* ----- printf_(tp) -- Local subroutine to send a line ------------ */
+/* A line has been completed (or overflowed): write it to the queue. */
+int printf_(struct perthread *tp)  /* pointer to per-thread data */
+{
+  ULONG   urc;                     /* unsigned returncode */
+  PSZ     pszTo, pszFrom;          /* character pointers */
+  PVOID   addr;                    /* address of output data */
+  long    size;                    /* total size of output data */
+  time_t  timenow;                 /* holds current time */
+
+  tp->line[tp->tidemark+1]='\0';   /* add terminator */
+  size=tp->tidemark+2;             /* total length of data */
+
+  /* Get some shared memory that can be given away */
+  urc=DosAllocSharedMem( &addr,
+                         NULL,
+                         (unsigned)size,
+                         OBJ_GIVEABLE|PAG_WRITE|PAG_COMMIT|flAllocMem);
+                                   /*knut: added flAllocMem */
+
+  if (urc!=0)
+    return -2;                     /* error */
+
+  pszTo=addr;                      /* copy for clarity */
+  pszFrom=&(tp->line[0]);          /* pointer to source */
+  strcpy(pszTo,pszFrom);           /* copy the string to shared memory */
+
+  if (ourpid!=servepid)
+  {          /* (no giveaway needed if to self) */
+    urc=DosGiveSharedMem(addr, servepid, PAG_READ); /* give access */
+    if (urc!=0)
+      return -3; /* error */
+  }
+
+  /* Write the selector, size, and timestamp to the queue */
+  if (tp->bell) size=-size;        /* BELL passed by negation */
+  time(&timenow);                  /* optional - else use 0 */
+  urc=DosWriteQueue( qhandle,           /* handle */
+                     (unsigned)timenow, /* 'request' (timestamp) */
+                     (unsigned)size,    /* 'length'  (length/bell) */
+                               addr,    /* 'address' (address) */
+                               0);       /* priority (FIFO if enabled) */
+  if (urc!=0)
+    return -4;           /* error */
+  if (ourpid!=servepid)
+  {          /* if given away.. */
+    urc=DosFreeMem(addr);          /* .. *we* are done with it */
+    if (urc!=0)
+      return -5; /* error */
+  }
+  /* Reset the line buffer and indices */
+  tp->lineindex=PRINTFIDSIZE-1;    /* where next char */
+  tp->tidemark =PRINTFIDSIZE-2;    /* rightmost char */
+  tp->bell     =FALSE;             /* true if line has bell */
+  return 0;                        /* success! */
+} /* printf_ */
+#else
+
+
+#if 1   /*PLF Mon  97-09-08 20:04:28*/
+static FILE *flog = NULL;   /*PLF Mon  97-09-08 20:00:15*/
+static BOOL init = FALSE;
+
+int SYSTEM EXPORT WriteLog(char *tekst, ...)
+{
+  va_list argptr;
+  if(!init)
+  {
+    init = TRUE;
+    if(!getenv("NODDRAWLOG"))
+      flog = fopen("DDRAW.log", "w");
+  }
+
+  if(flog)
+  {
+     va_start(argptr, tekst);
+     vfprintf(flog, tekst, argptr);
+     va_end(argptr);
+     fflush(flog);
+  }
+  return 1;
+}
+#else   /*PLF Mon  97-09-08 20:04:26*/
+/******************************************************************************/
+static BOOL init = FALSE;
+static BOOL fLog = TRUE;
+/******************************************************************************/
+int SYSTEM EXPORT WriteLog(char *tekst, ...)
+{
+  ULONG Action, Wrote;
+  HFILE log;
+  APIRET rc;
+  char message[4096];
+  va_list argptr;
+  ULONG openFlags = OPEN_ACTION_CREATE_IF_NEW;
+
+  if(fLog == FALSE)
+    return(FALSE);
+
+  if(!init)
+  {
+    init = TRUE;
+    openFlags |= OPEN_ACTION_REPLACE_IF_EXISTS;
+    if(getenv("NOWIN32LOG"))
+      fLog = FALSE;
+  }
+  else
+    openFlags |= OPEN_ACTION_OPEN_IF_EXISTS;
+
+  rc = DosOpen( "win32os2.log",
+                &log,           /* file handle returned */
+                &Action,
+                0L,
+                FILE_NORMAL,
+                openFlags,
+                OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYWRITE,
+                (PEAOP2)NULL);
+
+   rc = DosSetFilePtr(log, 0, FILE_END, &Wrote);
+   va_start(argptr, tekst);
+   vsprintf(message, tekst, argptr);
+   va_end(argptr);
+
+   rc = DosWrite(log, message, strlen(message), &Wrote);
+
+   DosClose(log);   /*PLF Mon  97-09-08 20:01:43*/
+   return(TRUE);
+}
+#endif  /*PLF Mon  97-09-08 20:04:23*/
+/******************************************************************************/
+/******************************************************************************/
+
+
+#endif
Index: trunk/src/ddraw/os2DDWindow.cpp
===================================================================
--- trunk/src/ddraw/os2DDWindow.cpp	(revision 210)
+++ trunk/src/ddraw/os2DDWindow.cpp	(revision 210)
@@ -0,0 +1,63 @@
+#define INCL_WIN
+#include <os2wrap.h>
+#include "os2DDWindow.h"
+
+PFNWP pfnOrgClientProc = NULL;
+
+MRESULT EXPENTRY DDOS2WindowProc(HWND hwnd, ULONG ulMsg, MPARAM mp1, MPARAM mp2);
+extern VOID SwitchDisplay(HWND hwnd);
+
+BOOL OS2DdSubClassWindow(HWND hwndClient)
+{
+  HWND hwndParent;
+
+  // only allow subclassing once!
+
+  if(NULL==pfnOrgClientProc)
+  {
+    hwndParent = WinQueryWindow(hwndClient,QW_PARENT);
+
+    if(hwndParent!=HWND_DESKTOP)
+      hwndFrame = hwndParent;
+    else
+      hwndFrame = hwndClient;
+
+    pfnOrgClientProc = WinSubclassWindow(hwndFrame,DDOS2WindowProc);
+
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+
+MRESULT EXPENTRY DDOS2WindowProc(HWND hwnd, ULONG ulMsg, MPARAM mp1, MPARAM mp2)
+{
+  USHORT usFlags;
+  switch(ulMsg)
+  {
+    // capture the mouse
+    case WM_ACTIVATE:
+      if(mp1)
+        WinSetCapture(HWND_DESKTOP,hwnd);
+      else
+        WinSetCapture(HWND_DESKTOP,NULLHANDLE);
+      break;
+    case WM_CHAR:
+      // Check for CTRL+SHIFT+F12 to toggle between stretched (FS) / windowd mode
+      usFlags = SHORT1FROMMP(mp1);
+      if(!(usFlags & KC_KEYUP))
+      {
+        if( (usFlags & KC_VIRTUALKEY) && (usFlags & KC_SHIFT) && (usFlags & KC_CTRL))
+        {
+          if(VK_F12 == SHORT2FROMMP(mp2))
+            SwitchDisplay(hwnd);
+        }
+      }
+      break;
+    default:
+      break;
+  }
+  return pfnOrgClientProc(hwnd, ulMsg, mp1,mp2);
+}
+
