1
0
mirror of https://github.com/DxWnd/DxWnd.reloaded synced 2024-12-30 09:25:35 +01:00
DxWnd.reloaded/dll/ddraw.cpp
gho tik ffbdf3bca0 v2_03_84_src
Former-commit-id: 44f86a910079133c39c744e710ca17f736bf2051
2017-03-06 11:47:08 -05:00

5966 lines
260 KiB
C++

#define _CRT_SECURE_NO_WARNINGS
#define INITGUID
//#define FULLHEXDUMP
#include <windows.h>
#include <ddraw.h>
#include "dxwnd.h"
#include "dxhook.h"
#include "ddrawi.h"
#include "dxwcore.hpp"
#include "stdio.h"
#include "hddraw.h"
#include "dxhelper.h"
#include "syslibs.h"
#define EMULATEZBUFFERATTACH FALSE
#ifdef CHECKMETHODPOINTERS
static void NullMethodPointer(char *s)
{
char msg[80];
sprintf(msg, "NULL %s method", s);
MessageBox(0, msg, "DxWnd", MB_OK);
}
#define CHECKPTR(p, s) if(!p) NullMethodPointer(s)
#else
#define CHECKPTR(p, s)
#endif
extern BOOL IsChangeDisplaySettingsHotPatched;
extern void TextureHandling(LPDIRECTDRAWSURFACE, int);
extern void SetMinimalCaps(LPDDCAPS, LPDDCAPS);
ColorConversion_Type pColorConversion = NULL;
HDC hFlippedDC = NULL;
BOOL bFlippedDC = FALSE;
DWORD dwBackBufferCaps = 0;
// DirectDraw API
HRESULT WINAPI extDirectDrawCreate(GUID FAR *, LPDIRECTDRAW FAR *, IUnknown FAR *);
HRESULT WINAPI extDirectDrawCreateEx(GUID FAR *, LPDIRECTDRAW FAR *, REFIID, IUnknown FAR *);
HRESULT WINAPI extDirectDrawEnumerateA(LPDDENUMCALLBACKA, LPVOID);
HRESULT WINAPI extDirectDrawEnumerateExA(LPDDENUMCALLBACKEXA, LPVOID, DWORD);
HRESULT WINAPI extDirectDrawEnumerateW(LPDDENUMCALLBACKW, LPVOID);
HRESULT WINAPI extDirectDrawEnumerateExW(LPDDENUMCALLBACKEXW, LPVOID, DWORD);
HRESULT WINAPI extDirectDrawCreateClipper(DWORD, LPDIRECTDRAWCLIPPER *, IUnknown *);
// DirectDraw
HRESULT WINAPI extQueryInterfaceD1(void *, REFIID, LPVOID *);
HRESULT WINAPI extQueryInterfaceD2(void *, REFIID, LPVOID *);
HRESULT WINAPI extQueryInterfaceD4(void *, REFIID, LPVOID *);
HRESULT WINAPI extQueryInterfaceD7(void *, REFIID, LPVOID *);
ULONG WINAPI extReleaseD1(LPDIRECTDRAW);
ULONG WINAPI extReleaseD2(LPDIRECTDRAW);
ULONG WINAPI extReleaseD4(LPDIRECTDRAW);
ULONG WINAPI extReleaseD7(LPDIRECTDRAW);
/*** IDirectDraw methods ***/
HRESULT WINAPI extCompact(LPDIRECTDRAW); // unimplemented method ???
HRESULT WINAPI extCreateClipper1(LPDIRECTDRAW, DWORD, LPDIRECTDRAWCLIPPER FAR* , IUnknown FAR*);
HRESULT WINAPI extCreateClipper2(LPDIRECTDRAW, DWORD, LPDIRECTDRAWCLIPPER FAR* , IUnknown FAR*);
HRESULT WINAPI extCreateClipper4(LPDIRECTDRAW, DWORD, LPDIRECTDRAWCLIPPER FAR* , IUnknown FAR*);
HRESULT WINAPI extCreateClipper7(LPDIRECTDRAW, DWORD, LPDIRECTDRAWCLIPPER FAR* , IUnknown FAR*);
HRESULT WINAPI extCreatePalette1(LPDIRECTDRAW, DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE *, IUnknown *);
HRESULT WINAPI extCreatePalette2(LPDIRECTDRAW, DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE *, IUnknown *);
HRESULT WINAPI extCreatePalette4(LPDIRECTDRAW, DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE *, IUnknown *);
HRESULT WINAPI extCreatePalette7(LPDIRECTDRAW, DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE *, IUnknown *);
HRESULT WINAPI extCreateSurface1(LPDIRECTDRAW, DDSURFACEDESC *, LPDIRECTDRAWSURFACE *, void *);
HRESULT WINAPI extCreateSurface2(LPDIRECTDRAW, DDSURFACEDESC *, LPDIRECTDRAWSURFACE *, void *);
HRESULT WINAPI extCreateSurface4(LPDIRECTDRAW, DDSURFACEDESC2 *, LPDIRECTDRAWSURFACE *, void *);
HRESULT WINAPI extCreateSurface7(LPDIRECTDRAW, DDSURFACEDESC2 *, LPDIRECTDRAWSURFACE *, void *);
HRESULT WINAPI extFlipToGDISurface1(LPDIRECTDRAW);
HRESULT WINAPI extFlipToGDISurface2(LPDIRECTDRAW);
HRESULT WINAPI extFlipToGDISurface4(LPDIRECTDRAW);
HRESULT WINAPI extFlipToGDISurface7(LPDIRECTDRAW);
HRESULT WINAPI extGetDisplayMode1(LPDIRECTDRAW, LPDDSURFACEDESC);
HRESULT WINAPI extGetDisplayMode2(LPDIRECTDRAW, LPDDSURFACEDESC);
HRESULT WINAPI extGetDisplayMode4(LPDIRECTDRAW, LPDDSURFACEDESC2);
HRESULT WINAPI extGetDisplayMode7(LPDIRECTDRAW, LPDDSURFACEDESC2);
HRESULT WINAPI extGetGDISurface1(LPDIRECTDRAW, LPDIRECTDRAWSURFACE *);
HRESULT WINAPI extGetGDISurface2(LPDIRECTDRAW, LPDIRECTDRAWSURFACE *);
HRESULT WINAPI extGetGDISurface4(LPDIRECTDRAW, LPDIRECTDRAWSURFACE *);
HRESULT WINAPI extGetGDISurface7(LPDIRECTDRAW, LPDIRECTDRAWSURFACE *);
HRESULT WINAPI extEnumDisplayModes1(LPDIRECTDRAW, DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK);
HRESULT WINAPI extEnumDisplayModes2(LPDIRECTDRAW, DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK);
HRESULT WINAPI extEnumDisplayModes4(LPDIRECTDRAW, DWORD, LPDDSURFACEDESC2, LPVOID, LPDDENUMMODESCALLBACK2);
HRESULT WINAPI extEnumDisplayModes7(LPDIRECTDRAW, DWORD, LPDDSURFACEDESC2, LPVOID, LPDDENUMMODESCALLBACK2);
HRESULT WINAPI extInitialize1(LPDIRECTDRAW, FAR GUID *);
HRESULT WINAPI extInitialize2(LPDIRECTDRAW, FAR GUID *);
HRESULT WINAPI extInitialize4(LPDIRECTDRAW, FAR GUID *);
HRESULT WINAPI extInitialize7(LPDIRECTDRAW, FAR GUID *);
HRESULT WINAPI extSetCooperativeLevel1(LPDIRECTDRAW, HWND, DWORD);
HRESULT WINAPI extSetCooperativeLevel2(LPDIRECTDRAW, HWND, DWORD);
HRESULT WINAPI extSetCooperativeLevel4(LPDIRECTDRAW, HWND, DWORD);
HRESULT WINAPI extSetCooperativeLevel7(LPDIRECTDRAW, HWND, DWORD);
HRESULT WINAPI extSetDisplayMode1(LPDIRECTDRAW, DWORD, DWORD, DWORD);
HRESULT WINAPI extSetDisplayMode2(LPDIRECTDRAW, DWORD, DWORD, DWORD, DWORD, DWORD);
HRESULT WINAPI extSetDisplayMode4(LPDIRECTDRAW, DWORD, DWORD, DWORD, DWORD, DWORD);
HRESULT WINAPI extSetDisplayMode7(LPDIRECTDRAW, DWORD, DWORD, DWORD, DWORD, DWORD);
HRESULT WINAPI extWaitForVerticalBlank1(LPDIRECTDRAW, DWORD, HANDLE);
HRESULT WINAPI extWaitForVerticalBlank2(LPDIRECTDRAW, DWORD, HANDLE);
HRESULT WINAPI extWaitForVerticalBlank4(LPDIRECTDRAW, DWORD, HANDLE);
HRESULT WINAPI extWaitForVerticalBlank7(LPDIRECTDRAW, DWORD, HANDLE);
/*** Added in the V2 Interface ***/
HRESULT WINAPI extGetAvailableVidMem2(LPDIRECTDRAW, LPDDSCAPS, LPDWORD, LPDWORD);
HRESULT WINAPI extGetAvailableVidMem4(LPDIRECTDRAW, LPDDSCAPS2, LPDWORD, LPDWORD);
HRESULT WINAPI extGetAvailableVidMem7(LPDIRECTDRAW, LPDDSCAPS2, LPDWORD, LPDWORD);
/*** Added in the V4 Interface ***/
HRESULT WINAPI extTestCooperativeLevel4(LPDIRECTDRAW);
HRESULT WINAPI extTestCooperativeLevel7(LPDIRECTDRAW);
// STDMETHOD(StartModeTest)(THIS_ LPSIZE, DWORD, DWORD ) PURE;
// STDMETHOD(EvaluateMode)(THIS_ DWORD, DWORD * ) PURE;
HRESULT WINAPI extGetCaps1D(LPDIRECTDRAW, LPDDCAPS, LPDDCAPS);
HRESULT WINAPI extGetCaps2D(LPDIRECTDRAW, LPDDCAPS, LPDDCAPS);
HRESULT WINAPI extGetCaps4D(LPDIRECTDRAW, LPDDCAPS, LPDDCAPS);
HRESULT WINAPI extGetCaps7D(LPDIRECTDRAW, LPDDCAPS, LPDDCAPS);
// DirectDrawSurface
HRESULT WINAPI extQueryInterfaceS1(void *, REFIID, LPVOID *);
HRESULT WINAPI extQueryInterfaceS2(void *, REFIID, LPVOID *);
HRESULT WINAPI extQueryInterfaceS3(void *, REFIID, LPVOID *);
HRESULT WINAPI extQueryInterfaceS4(void *, REFIID, LPVOID *);
HRESULT WINAPI extQueryInterfaceS7(void *, REFIID, LPVOID *);
HRESULT WINAPI extReleaseS1(LPDIRECTDRAWSURFACE);
HRESULT WINAPI extReleaseS2(LPDIRECTDRAWSURFACE);
HRESULT WINAPI extReleaseS3(LPDIRECTDRAWSURFACE);
HRESULT WINAPI extReleaseS4(LPDIRECTDRAWSURFACE);
HRESULT WINAPI extReleaseS7(LPDIRECTDRAWSURFACE);
/*** IDirectDrawSurface methods ***/
HRESULT WINAPI extAddAttachedSurface1(LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE);
HRESULT WINAPI extAddAttachedSurface2(LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE);
HRESULT WINAPI extAddAttachedSurface3(LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE);
HRESULT WINAPI extAddAttachedSurface4(LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE);
HRESULT WINAPI extAddAttachedSurface7(LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE);
HRESULT WINAPI extBlt1(LPDIRECTDRAWSURFACE, LPRECT, LPDIRECTDRAWSURFACE, LPRECT, DWORD, LPDDBLTFX);
HRESULT WINAPI extBlt2(LPDIRECTDRAWSURFACE, LPRECT, LPDIRECTDRAWSURFACE, LPRECT, DWORD, LPDDBLTFX);
HRESULT WINAPI extBlt3(LPDIRECTDRAWSURFACE, LPRECT, LPDIRECTDRAWSURFACE, LPRECT, DWORD, LPDDBLTFX);
HRESULT WINAPI extBlt4(LPDIRECTDRAWSURFACE, LPRECT, LPDIRECTDRAWSURFACE, LPRECT, DWORD, LPDDBLTFX);
HRESULT WINAPI extBlt7(LPDIRECTDRAWSURFACE, LPRECT, LPDIRECTDRAWSURFACE, LPRECT, DWORD, LPDDBLTFX);
HRESULT WINAPI extBltFast1(LPDIRECTDRAWSURFACE, DWORD, DWORD, LPDIRECTDRAWSURFACE, LPRECT, DWORD);
HRESULT WINAPI extBltFast2(LPDIRECTDRAWSURFACE, DWORD, DWORD, LPDIRECTDRAWSURFACE, LPRECT, DWORD);
HRESULT WINAPI extBltFast3(LPDIRECTDRAWSURFACE, DWORD, DWORD, LPDIRECTDRAWSURFACE, LPRECT, DWORD);
HRESULT WINAPI extBltFast4(LPDIRECTDRAWSURFACE, DWORD, DWORD, LPDIRECTDRAWSURFACE, LPRECT, DWORD);
HRESULT WINAPI extBltFast7(LPDIRECTDRAWSURFACE, DWORD, DWORD, LPDIRECTDRAWSURFACE, LPRECT, DWORD);
HRESULT WINAPI extDeleteAttachedSurface1(LPDIRECTDRAWSURFACE, DWORD, LPDIRECTDRAWSURFACE);
HRESULT WINAPI extDeleteAttachedSurface2(LPDIRECTDRAWSURFACE, DWORD, LPDIRECTDRAWSURFACE);
HRESULT WINAPI extDeleteAttachedSurface3(LPDIRECTDRAWSURFACE, DWORD, LPDIRECTDRAWSURFACE);
HRESULT WINAPI extDeleteAttachedSurface4(LPDIRECTDRAWSURFACE, DWORD, LPDIRECTDRAWSURFACE);
HRESULT WINAPI extDeleteAttachedSurface7(LPDIRECTDRAWSURFACE, DWORD, LPDIRECTDRAWSURFACE);
HRESULT WINAPI extEnumAttachedSurfaces1(LPDIRECTDRAWSURFACE, LPVOID, LPDDENUMSURFACESCALLBACK);
HRESULT WINAPI extEnumAttachedSurfaces2(LPDIRECTDRAWSURFACE, LPVOID, LPDDENUMSURFACESCALLBACK);
HRESULT WINAPI extEnumAttachedSurfaces3(LPDIRECTDRAWSURFACE, LPVOID, LPDDENUMSURFACESCALLBACK);
HRESULT WINAPI extEnumAttachedSurfaces4(LPDIRECTDRAWSURFACE, LPVOID, LPDDENUMSURFACESCALLBACK);
HRESULT WINAPI extEnumAttachedSurfaces7(LPDIRECTDRAWSURFACE, LPVOID, LPDDENUMSURFACESCALLBACK);
HRESULT WINAPI extFlip1(LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE, DWORD);
HRESULT WINAPI extFlip2(LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE, DWORD);
HRESULT WINAPI extFlip3(LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE, DWORD);
HRESULT WINAPI extFlip4(LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE, DWORD);
HRESULT WINAPI extFlip7(LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE, DWORD);
HRESULT WINAPI extGetAttachedSurface1(LPDIRECTDRAWSURFACE, DDSCAPS *, LPDIRECTDRAWSURFACE *);
HRESULT WINAPI extGetAttachedSurface2(LPDIRECTDRAWSURFACE, DDSCAPS *, LPDIRECTDRAWSURFACE *);
HRESULT WINAPI extGetAttachedSurface3(LPDIRECTDRAWSURFACE, DDSCAPS *, LPDIRECTDRAWSURFACE *);
HRESULT WINAPI extGetAttachedSurface4(LPDIRECTDRAWSURFACE, DDSCAPS *, LPDIRECTDRAWSURFACE *);
HRESULT WINAPI extGetAttachedSurface7(LPDIRECTDRAWSURFACE, DDSCAPS *, LPDIRECTDRAWSURFACE *);
HRESULT WINAPI extGetCaps1S(LPDIRECTDRAWSURFACE, LPDDSCAPS);
HRESULT WINAPI extGetCaps2S(LPDIRECTDRAWSURFACE, LPDDSCAPS);
HRESULT WINAPI extGetCaps3S(LPDIRECTDRAWSURFACE, LPDDSCAPS);
HRESULT WINAPI extGetCaps4S(LPDIRECTDRAWSURFACE, LPDDSCAPS2);
HRESULT WINAPI extGetCaps7S(LPDIRECTDRAWSURFACE, LPDDSCAPS2);
HRESULT WINAPI extGetColorKey1(LPDIRECTDRAWSURFACE, DWORD, LPDDCOLORKEY);
HRESULT WINAPI extGetColorKey2(LPDIRECTDRAWSURFACE, DWORD, LPDDCOLORKEY);
HRESULT WINAPI extGetColorKey3(LPDIRECTDRAWSURFACE, DWORD, LPDDCOLORKEY);
HRESULT WINAPI extGetColorKey4(LPDIRECTDRAWSURFACE, DWORD, LPDDCOLORKEY);
HRESULT WINAPI extGetColorKey7(LPDIRECTDRAWSURFACE, DWORD, LPDDCOLORKEY);
HRESULT WINAPI extGetDC1(LPDIRECTDRAWSURFACE, HDC FAR *);
HRESULT WINAPI extGetDC2(LPDIRECTDRAWSURFACE, HDC FAR *);
HRESULT WINAPI extGetDC3(LPDIRECTDRAWSURFACE, HDC FAR *);
HRESULT WINAPI extGetDC4(LPDIRECTDRAWSURFACE, HDC FAR *);
HRESULT WINAPI extGetDC7(LPDIRECTDRAWSURFACE, HDC FAR *);
HRESULT WINAPI extGetPalette1(LPDIRECTDRAWSURFACE, LPDIRECTDRAWPALETTE *);
HRESULT WINAPI extGetPalette2(LPDIRECTDRAWSURFACE, LPDIRECTDRAWPALETTE *);
HRESULT WINAPI extGetPalette3(LPDIRECTDRAWSURFACE, LPDIRECTDRAWPALETTE *);
HRESULT WINAPI extGetPalette4(LPDIRECTDRAWSURFACE, LPDIRECTDRAWPALETTE *);
HRESULT WINAPI extGetPalette7(LPDIRECTDRAWSURFACE, LPDIRECTDRAWPALETTE *);
HRESULT WINAPI extGetPixelFormat1(LPDIRECTDRAWSURFACE, LPDDPIXELFORMAT);
HRESULT WINAPI extGetPixelFormat2(LPDIRECTDRAWSURFACE, LPDDPIXELFORMAT);
HRESULT WINAPI extGetPixelFormat3(LPDIRECTDRAWSURFACE, LPDDPIXELFORMAT);
HRESULT WINAPI extGetPixelFormat4(LPDIRECTDRAWSURFACE, LPDDPIXELFORMAT);
HRESULT WINAPI extGetPixelFormat7(LPDIRECTDRAWSURFACE, LPDDPIXELFORMAT);
HRESULT WINAPI extGetSurfaceDesc1(LPDIRECTDRAWSURFACE lpdds, LPDDSURFACEDESC lpddsd);
HRESULT WINAPI extGetSurfaceDesc2(LPDIRECTDRAWSURFACE lpdds, LPDDSURFACEDESC lpddsd);
HRESULT WINAPI extGetSurfaceDesc3(LPDIRECTDRAWSURFACE lpdds, LPDDSURFACEDESC lpddsd);
HRESULT WINAPI extGetSurfaceDesc4(LPDIRECTDRAWSURFACE2 lpdds, LPDDSURFACEDESC2 lpddsd);
HRESULT WINAPI extGetSurfaceDesc7(LPDIRECTDRAWSURFACE2 lpdds, LPDDSURFACEDESC2 lpddsd);
HRESULT WINAPI extLock1(LPDIRECTDRAWSURFACE, LPRECT, LPDDSURFACEDESC, DWORD, HANDLE);
HRESULT WINAPI extLock2(LPDIRECTDRAWSURFACE, LPRECT, LPDDSURFACEDESC, DWORD, HANDLE);
HRESULT WINAPI extLock3(LPDIRECTDRAWSURFACE, LPRECT, LPDDSURFACEDESC, DWORD, HANDLE);
HRESULT WINAPI extLock4(LPDIRECTDRAWSURFACE, LPRECT, LPDDSURFACEDESC, DWORD, HANDLE);
HRESULT WINAPI extLock7(LPDIRECTDRAWSURFACE, LPRECT, LPDDSURFACEDESC, DWORD, HANDLE);
HRESULT WINAPI extLockDir1(LPDIRECTDRAWSURFACE, LPRECT, LPDDSURFACEDESC, DWORD, HANDLE);
HRESULT WINAPI extLockDir2(LPDIRECTDRAWSURFACE, LPRECT, LPDDSURFACEDESC, DWORD, HANDLE);
HRESULT WINAPI extLockDir3(LPDIRECTDRAWSURFACE, LPRECT, LPDDSURFACEDESC, DWORD, HANDLE);
HRESULT WINAPI extLockDir4(LPDIRECTDRAWSURFACE, LPRECT, LPDDSURFACEDESC, DWORD, HANDLE);
HRESULT WINAPI extLockDir7(LPDIRECTDRAWSURFACE, LPRECT, LPDDSURFACEDESC, DWORD, HANDLE);
HRESULT WINAPI extReleaseDC1(LPDIRECTDRAWSURFACE, HDC);
HRESULT WINAPI extReleaseDC2(LPDIRECTDRAWSURFACE, HDC);
HRESULT WINAPI extReleaseDC3(LPDIRECTDRAWSURFACE, HDC);
HRESULT WINAPI extReleaseDC4(LPDIRECTDRAWSURFACE, HDC);
HRESULT WINAPI extReleaseDC7(LPDIRECTDRAWSURFACE, HDC);
HRESULT WINAPI extSetClipper1(LPDIRECTDRAWSURFACE, LPDIRECTDRAWCLIPPER);
HRESULT WINAPI extSetClipper2(LPDIRECTDRAWSURFACE, LPDIRECTDRAWCLIPPER);
HRESULT WINAPI extSetClipper3(LPDIRECTDRAWSURFACE, LPDIRECTDRAWCLIPPER);
HRESULT WINAPI extSetClipper4(LPDIRECTDRAWSURFACE, LPDIRECTDRAWCLIPPER);
HRESULT WINAPI extSetClipper7(LPDIRECTDRAWSURFACE, LPDIRECTDRAWCLIPPER);
HRESULT WINAPI extSetColorKey1(LPDIRECTDRAWSURFACE, DWORD, LPDDCOLORKEY);
HRESULT WINAPI extSetColorKey2(LPDIRECTDRAWSURFACE, DWORD, LPDDCOLORKEY);
HRESULT WINAPI extSetColorKey3(LPDIRECTDRAWSURFACE, DWORD, LPDDCOLORKEY);
HRESULT WINAPI extSetColorKey4(LPDIRECTDRAWSURFACE, DWORD, LPDDCOLORKEY);
HRESULT WINAPI extSetColorKey7(LPDIRECTDRAWSURFACE, DWORD, LPDDCOLORKEY);
HRESULT WINAPI extSetPalette1(LPDIRECTDRAWSURFACE, LPDIRECTDRAWPALETTE);
HRESULT WINAPI extSetPalette2(LPDIRECTDRAWSURFACE, LPDIRECTDRAWPALETTE);
HRESULT WINAPI extSetPalette3(LPDIRECTDRAWSURFACE, LPDIRECTDRAWPALETTE);
HRESULT WINAPI extSetPalette4(LPDIRECTDRAWSURFACE, LPDIRECTDRAWPALETTE);
HRESULT WINAPI extSetPalette7(LPDIRECTDRAWSURFACE, LPDIRECTDRAWPALETTE);
HRESULT WINAPI extUnlock1(LPDIRECTDRAWSURFACE, LPVOID);
HRESULT WINAPI extUnlock2(LPDIRECTDRAWSURFACE, LPVOID);
HRESULT WINAPI extUnlock3(LPDIRECTDRAWSURFACE, LPVOID);
HRESULT WINAPI extUnlock4(LPDIRECTDRAWSURFACE, LPRECT);
HRESULT WINAPI extUnlock7(LPDIRECTDRAWSURFACE, LPRECT);
HRESULT WINAPI extUnlockDir1(LPDIRECTDRAWSURFACE, LPVOID);
HRESULT WINAPI extUnlockDir2(LPDIRECTDRAWSURFACE, LPVOID);
HRESULT WINAPI extUnlockDir3(LPDIRECTDRAWSURFACE, LPVOID);
HRESULT WINAPI extUnlockDir4(LPDIRECTDRAWSURFACE, LPRECT);
HRESULT WINAPI extUnlockDir7(LPDIRECTDRAWSURFACE, LPRECT);
HRESULT WINAPI extEnumOverlayZOrders1(LPDIRECTDRAWSURFACE, DWORD, LPVOID, LPDDENUMSURFACESCALLBACK);
HRESULT WINAPI extEnumOverlayZOrders2(LPDIRECTDRAWSURFACE, DWORD, LPVOID, LPDDENUMSURFACESCALLBACK);
HRESULT WINAPI extEnumOverlayZOrders3(LPDIRECTDRAWSURFACE, DWORD, LPVOID, LPDDENUMSURFACESCALLBACK);
HRESULT WINAPI extEnumOverlayZOrders4(LPDIRECTDRAWSURFACE, DWORD, LPVOID, LPDDENUMSURFACESCALLBACK);
HRESULT WINAPI extEnumOverlayZOrders7(LPDIRECTDRAWSURFACE, DWORD, LPVOID, LPDDENUMSURFACESCALLBACK);
HRESULT WINAPI extAddOverlayDirtyRect1(LPDIRECTDRAWSURFACE, LPRECT);
HRESULT WINAPI extAddOverlayDirtyRect2(LPDIRECTDRAWSURFACE, LPRECT);
HRESULT WINAPI extAddOverlayDirtyRect3(LPDIRECTDRAWSURFACE, LPRECT);
HRESULT WINAPI extAddOverlayDirtyRect4(LPDIRECTDRAWSURFACE, LPRECT);
HRESULT WINAPI extAddOverlayDirtyRect7(LPDIRECTDRAWSURFACE, LPRECT);
HRESULT WINAPI extCreateSurface(int, CreateSurface_Type, LPDIRECTDRAW, DDSURFACEDESC2 *, LPDIRECTDRAWSURFACE *, void *);
HRESULT WINAPI extSetSurfaceDesc3(LPDIRECTDRAWSURFACE, LPDDSURFACEDESC, DWORD);
HRESULT WINAPI extSetSurfaceDesc4(LPDIRECTDRAWSURFACE, LPDDSURFACEDESC, DWORD);
HRESULT WINAPI extSetSurfaceDesc7(LPDIRECTDRAWSURFACE, LPDDSURFACEDESC, DWORD);
// DirectDrawClipper
HRESULT WINAPI extReleaseC(LPDIRECTDRAWCLIPPER);
HRESULT WINAPI extGetClipList(LPDIRECTDRAWCLIPPER, LPRECT, LPRGNDATA, LPDWORD);
HRESULT WINAPI extSetHWnd(LPDIRECTDRAWCLIPPER, DWORD, HWND);
// DirectDrawPalette
HRESULT WINAPI extReleaseP(LPDIRECTDRAWPALETTE);
// STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, DWORD, LPPALETTEENTRY) PURE;
HRESULT WINAPI extSetEntries(LPDIRECTDRAWPALETTE, DWORD, DWORD, DWORD, LPPALETTEENTRY);
// GammaRamp
HRESULT WINAPI extDDSetGammaRamp(LPDIRECTDRAWSURFACE, DWORD, LPDDGAMMARAMP);
HRESULT WINAPI extDDGetGammaRamp(LPDIRECTDRAWSURFACE, DWORD, LPDDGAMMARAMP);
HDC WINAPI extGDIGetDC(HWND);
HDC WINAPI extGDIGetWindowDC(HWND);
int WINAPI extGDIReleaseDC(HWND, HDC);
/* DirectDraw APIs */
DirectDrawCreate_Type pDirectDrawCreate = NULL;
DirectDrawCreateEx_Type pDirectDrawCreateEx = NULL;
DirectDrawEnumerateA_Type pDirectDrawEnumerateA = NULL;
DirectDrawEnumerateW_Type pDirectDrawEnumerateW = NULL;
DirectDrawEnumerateExA_Type pDirectDrawEnumerateExA = NULL;
DirectDrawEnumerateExW_Type pDirectDrawEnumerateExW = NULL;
DirectDrawCreateClipper_Type pDirectDrawCreateClipper = NULL;
HandleDDThreadLock_Type pAcquireDDThreadLock = NULL;
HandleDDThreadLock_Type pReleaseDDThreadLock = NULL;
/* DirectDraw hook pointers */
QueryInterface_Type pQueryInterfaceD1, pQueryInterfaceD2, pQueryInterfaceD4, pQueryInterfaceD7;
AddRefD_Type pAddRefD;
ReleaseD_Type pReleaseD1, pReleaseD2, pReleaseD4, pReleaseD7;
Compact_Type pCompact;
CreateClipper_Type pCreateClipper1, pCreateClipper2, pCreateClipper4, pCreateClipper7;
CreatePalette_Type pCreatePalette1, pCreatePalette2, pCreatePalette4, pCreatePalette7;
CreateSurface1_Type pCreateSurface1, pCreateSurface2, pCreateSurface3, pCreateSurface4, pCreateSurface7;
EnumDisplayModes1_Type pEnumDisplayModes1, pEnumDisplayModes2;
EnumDisplayModes4_Type pEnumDisplayModes4, pEnumDisplayModes7;
EnumSurfaces1_Type pEnumSurfaces1;
EnumSurfaces4_Type pEnumSurfaces4;
FlipToGDISurface_Type pFlipToGDISurface1, pFlipToGDISurface2, pFlipToGDISurface4, pFlipToGDISurface7;
GetCapsD_Type pGetCaps1D, pGetCaps2D, pGetCaps4D, pGetCaps7D;
GetDisplayMode_Type pGetDisplayMode1, pGetDisplayMode2;
GetDisplayMode4_Type pGetDisplayMode4, pGetDisplayMode7;
GetFourCCCodes_Type pGetFourCCCodes;
GetGDISurface_Type pGetGDISurface1, pGetGDISurface2, pGetGDISurface4, pGetGDISurface7;
GetMonitorFrequency_Type pGetMonitorFrequency;
GetScanLine_Type pGetScanLine;
GetVerticalBlankStatus_Type pGetVerticalBlankStatus;
Initialize_Type pInitialize1, pInitialize2, pInitialize4, pInitialize7;
RestoreDisplayMode_Type pRestoreDisplayMode;
SetCooperativeLevel_Type pSetCooperativeLevel1, pSetCooperativeLevel2, pSetCooperativeLevel4, pSetCooperativeLevel7;
SetDisplayMode1_Type pSetDisplayMode1;
SetDisplayMode2_Type pSetDisplayMode2, pSetDisplayMode4, pSetDisplayMode7;
WaitForVerticalBlank_Type pWaitForVerticalBlank1, pWaitForVerticalBlank2, pWaitForVerticalBlank4, pWaitForVerticalBlank7;
GetSurfaceFromDC_Type pGetSurfaceFromDC;
GetAvailableVidMem_Type pGetAvailableVidMem2;
GetAvailableVidMem4_Type pGetAvailableVidMem4, pGetAvailableVidMem7;
RestoreAllSurfaces_Type pRestoreAllSurfaces;
TestCooperativeLevel_Type pTestCooperativeLevel4, pTestCooperativeLevel7;
GetDeviceIdentifier_Type pGetDeviceIdentifier;
/* DirectDrawSurface hook pointers */
QueryInterface_Type pQueryInterfaceS1, pQueryInterfaceS2, pQueryInterfaceS3, pQueryInterfaceS4, pQueryInterfaceS7;
AddRefS_Type pAddRefS;
ReleaseS_Type pReleaseS1, pReleaseS2, pReleaseS3, pReleaseS4, pReleaseS7;
AddAttachedSurface_Type pAddAttachedSurface1, pAddAttachedSurface2, pAddAttachedSurface3, pAddAttachedSurface4, pAddAttachedSurface7;
AddOverlayDirtyRect_Type pAddOverlayDirtyRect;
Blt_Type pBlt1, pBlt2, pBlt3, pBlt4, pBlt7;
//BltBatch_Type pBltBatch;
BltFast_Type pBltFast1, pBltFast2, pBltFast3, pBltFast4, pBltFast7;
DeleteAttachedSurface_Type pDeleteAttachedSurface1, pDeleteAttachedSurface2, pDeleteAttachedSurface3, pDeleteAttachedSurface4, pDeleteAttachedSurface7;
EnumAttachedSurfaces_Type pEnumAttachedSurfaces1, pEnumAttachedSurfaces2, pEnumAttachedSurfaces3, pEnumAttachedSurfaces4, pEnumAttachedSurfaces7;
EnumOverlayZOrders_Type pEnumOverlayZOrders;
Flip_Type pFlip1, pFlip2, pFlip3, pFlip4, pFlip7;
GetAttachedSurface_Type pGetAttachedSurface1, pGetAttachedSurface2, pGetAttachedSurface3, pGetAttachedSurface4, pGetAttachedSurface7;
GetBltStatus_Type pGetBltStatus;
GetCapsS_Type pGetCaps1S, pGetCaps2S, pGetCaps3S, pGetCaps4S, pGetCaps7S;
GetClipper_Type pGetClipper;
GetColorKey_Type pGetColorKey1, pGetColorKey2, pGetColorKey3, pGetColorKey4, pGetColorKey7;
GetDC_Type pGetDC1, pGetDC2, pGetDC3, pGetDC4, pGetDC7;
GetFlipStatus_Type pGetFlipStatus;
GetOverlayPosition_Type pGetOverlayPosition;
GetPalette_Type pGetPalette1, pGetPalette2, pGetPalette3, pGetPalette4, pGetPalette7;
GetPixelFormat_Type pGetPixelFormat1, pGetPixelFormat2, pGetPixelFormat3, pGetPixelFormat4, pGetPixelFormat7;
GetSurfaceDesc_Type pGetSurfaceDesc1, pGetSurfaceDesc2, pGetSurfaceDesc3;
GetSurfaceDesc2_Type pGetSurfaceDesc4, pGetSurfaceDesc7;
Lock_Type pLock1, pLock2, pLock3, pLock4, pLock7;
EnumOverlayZOrders_Type pEnumOverlayZOrders1, pEnumOverlayZOrders2, pEnumOverlayZOrders3, pEnumOverlayZOrders4, pEnumOverlayZOrders7;
AddOverlayDirtyRect_Type pAddOverlayDirtyRect1, pAddOverlayDirtyRect2, pAddOverlayDirtyRect3, pAddOverlayDirtyRect4, pAddOverlayDirtyRect7;
//Initialize
IsLost_Type pIsLost;
ReleaseDC_Type pReleaseDC1, pReleaseDC2, pReleaseDC3, pReleaseDC4, pReleaseDC7;
Restore_Type pRestore;
SetClipper_Type pSetClipper1, pSetClipper2, pSetClipper3, pSetClipper4, pSetClipper7;
SetColorKey_Type pSetColorKey1, pSetColorKey2, pSetColorKey3, pSetColorKey4, pSetColorKey7;
SetOverlayPosition_Type pSetOverlayPosition;
SetPalette_Type pSetPalette1, pSetPalette2, pSetPalette3, pSetPalette4, pSetPalette7;
Unlock1_Type pUnlock1, pUnlock2, pUnlock3;
Unlock4_Type pUnlock4, pUnlock7;
UpdateOverlay_Type pUpdateOverlay;
UpdateOverlayDisplay_Type pUpdateOverlayDisplay;
UpdateOverlayZOrder_Type pUpdateOverlayZOrder;
SetSurfaceDesc_Type pSetSurfaceDesc3, pSetSurfaceDesc4, pSetSurfaceDesc7;
/* DirectDrawClipper hook pointers */
QueryInterface_Type pQueryInterfaceC;
AddRefC_Type pAddRefC;
ReleaseC_Type pReleaseC;
GetClipList_Type pGetClipList;
GetHWnd_Type pGetHWnd;
InitializeC_Type pInitializeC;
IsClipListChanged_Type pIsClipListChanged;
SetClipList_Type pSetClipList;
SetHWnd_Type pSetHWnd;
/* DirectDrawPalette hook pointers */
QueryInterfaceP_Type pQueryInterfaceP;
AddRefP_Type pAddRefP;
ReleaseP_Type pReleaseP;
/*** IDirectDrawPalette methods ***/
GetCapsP_Type pGetCapsP;
GetEntries_Type pGetEntries;
// STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, DWORD, LPPALETTEENTRY) PURE;
SetEntries_Type pSetEntries;
// GammaRamp
GammaRamp_Type pDDGetGammaRamp;
GammaRamp_Type pDDSetGammaRamp;
// ddraw global variables, constants & so on
#define MAXBACKBUFFERS 4
extern PALETTEENTRY DefaultSystemPalette[256];
LPDIRECTDRAWSURFACE lpDDSEmu_Prim=NULL;
LPDIRECTDRAWSURFACE lpDDSEmu_Back=NULL;
LPDIRECTDRAWSURFACE lpDDZBuffer=NULL;
// v2.1.87: lpPrimaryDD is the DIRECTDRAW object to which the primary surface and all
// the service objects (emulated backbuffer, emulater primary, ....) are attached.
LPDIRECTDRAW lpPrimaryDD=NULL;
int iBakBufferVersion;
LPDIRECTDRAWPALETTE lpDDP=NULL;
LPDIRECTDRAWCLIPPER lpddC=NULL;
int iDDPExtraRefCounter=0;
// v2.02.37: globals to store requested main surface capabilities
DDSURFACEDESC2 DDSD_Prim;
DWORD PaletteEntries[256];
DWORD *Palette16BPP = NULL;
void *EmuScreenBuffer = NULL; // to implement pitch bug fix
DWORD rPitch = 0;
LPVOID rSurface = NULL;
static void SetPixFmt(LPDDSURFACEDESC2);
static void GetPixFmt(LPDDSURFACEDESC2);
static HookEntryEx_Type ddHooks[]={
{HOOK_HOT_CANDIDATE, 0x08, "DirectDrawCreate", (FARPROC)NULL, (FARPROC *)&pDirectDrawCreate, (FARPROC)extDirectDrawCreate},
{HOOK_HOT_CANDIDATE, 0x0A, "DirectDrawCreateEx", (FARPROC)NULL, (FARPROC *)&pDirectDrawCreateEx, (FARPROC)extDirectDrawCreateEx},
{HOOK_HOT_CANDIDATE, 0x0B, "DirectDrawEnumerateA", (FARPROC)NULL, (FARPROC *)&pDirectDrawEnumerateA, (FARPROC)extDirectDrawEnumerateA},
{HOOK_HOT_CANDIDATE, 0x0C, "DirectDrawEnumerateExA", (FARPROC)NULL, (FARPROC *)&pDirectDrawEnumerateExA, (FARPROC)extDirectDrawEnumerateExA},
{HOOK_HOT_CANDIDATE, 0x09, "DirectDrawCreateClipper", (FARPROC)NULL, (FARPROC *)&pDirectDrawCreateClipper, (FARPROC)extDirectDrawCreateClipper},
{HOOK_HOT_CANDIDATE, 0x01, "AcquireDDThreadLock", (FARPROC)NULL, (FARPROC *)&pAcquireDDThreadLock, (FARPROC)NULL},
{HOOK_HOT_CANDIDATE, 0x15, "ReleaseDDThreadLock", (FARPROC)NULL, (FARPROC *)&pReleaseDDThreadLock, (FARPROC)NULL},
{HOOK_IAT_CANDIDATE, 0x0E, "DirectDrawEnumerateW", (FARPROC)NULL, (FARPROC *)&pDirectDrawEnumerateW, (FARPROC)extDirectDrawCreate},
{HOOK_IAT_CANDIDATE, 0x0D, "DirectDrawEnumerateExW", (FARPROC)NULL, (FARPROC *)&pDirectDrawEnumerateExW, (FARPROC)extDirectDrawCreate},
{HOOK_IAT_CANDIDATE, 0, 0, NULL, 0, 0} // terminator
};
FARPROC Remap_ddraw_ProcAddress(LPCSTR proc, HMODULE hModule)
{
FARPROC addr;
if (dxw.dwTargetDDVersion == HOOKDDRAWNONE) return NULL;
if (addr=RemapLibraryEx(proc, hModule, ddHooks)) return addr;
return NULL;
}
extern HRESULT WINAPI sBlt(int, Blt_Type pBlt, char *, LPDIRECTDRAWSURFACE, LPRECT, LPDIRECTDRAWSURFACE, LPRECT, DWORD, LPDDBLTFX, BOOL);
/* ------------------------------------------------------------------------------ */
// auxiliary (static) functions
/* ------------------------------------------------------------------------------ */
DWORD gdwRefreshRate;
#define MAXREFRESHDELAYCOUNT 20
int iRefreshDelays[MAXREFRESHDELAYCOUNT]={16, 17};
int iRefreshDelayCount=2;
static HRESULT myGetDisplayMode(int dxversion, LPDIRECTDRAW lpdd, LPDDSURFACEDESC lpdds)
{
HRESULT res;
switch(dxversion){
default:
case 1: res=(*pGetDisplayMode1)(lpdd, lpdds); break;
case 2: res=(*pGetDisplayMode2)(lpdd, lpdds); break;
case 4: res=(*pGetDisplayMode4)(lpdd, (LPDDSURFACEDESC2)lpdds); break;
case 7: res=(*pGetDisplayMode7)(lpdd, (LPDDSURFACEDESC2)lpdds); break;
}
return res;
}
void SetVSyncDelays(int dxversion, LPDIRECTDRAW lpdd)
{
DDSURFACEDESC2 ddsdRefreshRate;
HRESULT res;
memset(&ddsdRefreshRate, 0, sizeof(ddsdRefreshRate));
ddsdRefreshRate.dwSize = sizeof(DDSURFACEDESC);
res=myGetDisplayMode(dxversion, lpdd, (LPDDSURFACEDESC)&ddsdRefreshRate);
if(res) return;
dxw.SetVSyncDelays(ddsdRefreshRate.dwRefreshRate);
}
static void Stopper(char *s, int line)
{
char sMsg[81];
sprintf(sMsg,"break: \"%s\"", s);
MessageBox(0, sMsg, "break", MB_OK | MB_ICONEXCLAMATION);
}
//#define STOPPER_TEST // comment out to eliminate
#ifdef STOPPER_TEST
#define STOPPER(s) Stopper(s, __LINE__)
#else
#define STOPPER(s)
#endif
static char *DumpPixelFormat(LPDDSURFACEDESC2 lpddsd)
{
return ExplainPixelFormat(&(lpddsd->ddpfPixelFormat));
}
static CHAR *LogSurfaceAttributes(LPDDSURFACEDESC lpddsd, char *label, int line)
{
static char sInfo[1024];
sprintf(sInfo, "SurfaceDesc: %s Flags=%x(%s)",
label,
lpddsd->dwFlags, ExplainFlags(lpddsd->dwFlags));
if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) sprintf(sInfo, "%s BackBufferCount=%d", sInfo, lpddsd->dwBackBufferCount);
if (lpddsd->dwFlags & DDSD_WIDTH) sprintf(sInfo, "%s Width=%d", sInfo, lpddsd->dwWidth);
if (lpddsd->dwFlags & DDSD_HEIGHT) sprintf(sInfo, "%s Height=%d", sInfo, lpddsd->dwHeight);
if (lpddsd->dwFlags & DDSD_PITCH) sprintf(sInfo, "%s Pitch=%d", sInfo, lpddsd->lPitch);
if (lpddsd->dwFlags & DDSD_MIPMAPCOUNT) sprintf(sInfo, "%s MipMapCount=%d", sInfo, lpddsd->dwMipMapCount);
if (lpddsd->dwFlags & DDSD_CAPS) {
sprintf(sInfo, "%s Caps=%x(%s)", sInfo, lpddsd->ddsCaps.dwCaps, ExplainDDSCaps(lpddsd->ddsCaps.dwCaps));
if(lpddsd->dwSize==sizeof(DDSURFACEDESC2)){
LPDDSURFACEDESC2 lpddsd2=(LPDDSURFACEDESC2)lpddsd;
sprintf(sInfo, "%s Caps2=%x(%s)", sInfo, lpddsd2->ddsCaps.dwCaps2, ExplainDDSCaps2(lpddsd2->ddsCaps.dwCaps2));
sprintf(sInfo, "%s Caps3=%x(%s)", sInfo, lpddsd2->ddsCaps.dwCaps3, ExplainDDSCaps3(lpddsd2->ddsCaps.dwCaps3));
}
}
if (lpddsd->dwFlags & DDSD_CKDESTBLT ) sprintf(sInfo, "%s CKDestBlt=(%x,%x)", sInfo, lpddsd->ddckCKDestBlt.dwColorSpaceLowValue, lpddsd->ddckCKDestBlt.dwColorSpaceHighValue);
if (lpddsd->dwFlags & DDSD_CKDESTOVERLAY ) sprintf(sInfo, "%s CKDestOverlay=(%x,%x)", sInfo, lpddsd->ddckCKDestOverlay.dwColorSpaceLowValue, lpddsd->ddckCKDestOverlay.dwColorSpaceHighValue);
if (lpddsd->dwFlags & DDSD_CKSRCBLT ) sprintf(sInfo, "%s CKSrcBlt=(%x,%x)", sInfo, lpddsd->ddckCKSrcBlt.dwColorSpaceLowValue, lpddsd->ddckCKSrcBlt.dwColorSpaceHighValue);
if (lpddsd->dwFlags & DDSD_CKSRCOVERLAY ) sprintf(sInfo, "%s CKSrcOverlay=(%x,%x)", sInfo, lpddsd->ddckCKSrcOverlay.dwColorSpaceLowValue, lpddsd->ddckCKSrcOverlay.dwColorSpaceHighValue);
if (lpddsd->dwFlags & DDSD_PIXELFORMAT ) sprintf(sInfo, "%s %s", sInfo, DumpPixelFormat((LPDDSURFACEDESC2)lpddsd));
if (lpddsd->dwFlags & DDSD_LPSURFACE) sprintf(sInfo, "%s Surface=%x", sInfo, lpddsd->lpSurface);
if (lpddsd->dwFlags & DDSD_ZBUFFERBITDEPTH) sprintf(sInfo, "%s ZBufferBitDepth=%d", sInfo, lpddsd->dwZBufferBitDepth);
if (lpddsd->dwFlags & DDSD_ALPHABITDEPTH) sprintf(sInfo, "%s AlphaBitDepth=%d", sInfo, lpddsd->dwAlphaBitDepth);
if (lpddsd->dwFlags & DDSD_REFRESHRATE) sprintf(sInfo, "%s RefreshRate=%d", sInfo, lpddsd->dwRefreshRate);
if (lpddsd->dwFlags & DDSD_LINEARSIZE) sprintf(sInfo, "%s LinearSize=%d", sInfo, lpddsd->dwLinearSize);
if (lpddsd->dwSize == sizeof(DDSURFACEDESC2)){
if (lpddsd->dwFlags & DDSD_TEXTURESTAGE) sprintf(sInfo, "%s TextureStage=%x", sInfo, ((LPDDSURFACEDESC2)lpddsd)->dwTextureStage);
if (lpddsd->dwFlags & DDSD_FVF) sprintf(sInfo, "%s FVF=%x", sInfo, ((LPDDSURFACEDESC2)lpddsd)->dwFVF);
}
return sInfo;
}
static void DumpPixFmt(LPDDSURFACEDESC2 lpdds)
{
OutTrace("PixelFormat: lpdds=%x %s\n", DumpPixelFormat(lpdds));
}
/* ------------------------------------------------------------------------------ */
// auxiliary (static) functions for palette handling
/* ------------------------------------------------------------------------------ */
BOOL isPaletteUpdated;
void mySetPalette(int dwstart, int dwcount, LPPALETTEENTRY lpentries)
{
int i;
extern DXWNDSTATUS *pStatus;
// if has reserved palette entries, recover them
if(dxw.dwFlags5 & LOCKRESERVEDPALETTE){
int nStatCols, nPalEntries;
PALETTEENTRY SysPalEntry[256];
LPPALETTEENTRY lpEntry;
extern GetSystemPaletteEntries_Type pGDIGetSystemPaletteEntries;
extern GetDeviceCaps_Type pGDIGetDeviceCaps;
// The number of static colours should be 20, but inquire it anyway
nStatCols = (*pGDIGetDeviceCaps)(GetDC(0), NUMRESERVED);
// fix the first nStatCols/2 and the last nStatCols/2 entries
nPalEntries=(*pGDIGetSystemPaletteEntries)(GetDC(0), 0, 256, SysPalEntry);
for (i = 0; i < 256; i++){
// skip intermediate un-reserved palette entries
if(i==(nStatCols / 2)) i=256 - (nStatCols / 2);
lpEntry = &lpentries[i];
if(lpEntry->peFlags==0){
lpEntry->peRed = SysPalEntry[i].peRed;
lpEntry->peGreen = SysPalEntry[i].peGreen;
lpEntry->peBlue = SysPalEntry[i].peBlue;
}
}
}
// copy the palette entries on the current system palette
for(int idx=0; idx<dwcount; idx++)
pStatus->Palette[dwstart+idx]= lpentries[idx];
for(i = 0; i < dwcount; i ++){
PALETTEENTRY PalColor;
PalColor = lpentries[i];
if (dxw.dwFlags3 & BLACKWHITE){
// (http://www.codeproject.com/Articles/66253/Converting-Colors-to-Gray-Shades):
// gray = (red * 0.30) + (green * 0.59) + (blue * 0.11)
DWORD grayscale;
//grayscale = ((DWORD)lpentries[i].peRed + (DWORD)lpentries[i].peGreen + (DWORD)lpentries[i].peBlue) / 3;
grayscale = (((DWORD)PalColor.peRed * 30) + ((DWORD)PalColor.peGreen * 59) + ((DWORD)PalColor.peBlue) * 11) / 100;
PalColor.peRed = PalColor.peGreen = PalColor.peBlue = (BYTE)grayscale;
}
switch (dxw.ActualPixelFormat.dwRGBBitCount){
case 32:
PaletteEntries[i + dwstart] =
(((DWORD)PalColor.peRed) << 16) + (((DWORD)PalColor.peGreen) << 8) + ((DWORD)PalColor.peBlue);
break;
case 16:
PaletteEntries[i + dwstart] = (dxw.ActualPixelFormat.dwGBitMask == 0x03E0) ?
(((DWORD)PalColor.peRed & 0xF8) << 8) + (((DWORD)PalColor.peGreen & 0xFC) << 3) + (((DWORD)PalColor.peBlue &0xF8) >> 3)
:
(((DWORD)PalColor.peRed & 0xF8) << 8) + (((DWORD)PalColor.peGreen & 0xF8) << 3) + (((DWORD)PalColor.peBlue &0xF8) >> 3);
break;
default:
OutTraceDW("ASSERT: unsupported Color BPP=%d\n", dxw.ActualPixelFormat.dwRGBBitCount);
break;
}
}
isPaletteUpdated = TRUE;
}
void InitDDScreenParameters(int dxversion, LPDIRECTDRAW lpdd)
{
HRESULT res;
DDSURFACEDESC2 ddsd;
ddsd.dwSize=sizeof(DDSURFACEDESC);
res=myGetDisplayMode(dxversion, lpdd, (LPDDSURFACEDESC)&ddsd);
if(res){
OutTraceE("GetDisplayMode: ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return;
}
OutTraceDW("InitDDScreenParameters: Actual %s\n", DumpPixelFormat((LPDDSURFACEDESC2)&ddsd));
dxw.ActualPixelFormat=ddsd.ddpfPixelFormat;
if(dxw.VirtualPixelFormat.dwRGBBitCount==0) dxw.VirtualPixelFormat=ddsd.ddpfPixelFormat;
SetBltTransformations(dxversion);
return;
}
void InitDSScreenParameters(int dxversion, LPDIRECTDRAWSURFACE lpdds)
{
HRESULT res;
DDPIXELFORMAT p;
DDSURFACEDESC2 ddsd;
GetPixelFormat_Type pGetPixelFormat;
switch(dxversion){
case 1: pGetPixelFormat=pGetPixelFormat1; break;
case 2: pGetPixelFormat=pGetPixelFormat2; break;
case 3: pGetPixelFormat=pGetPixelFormat3; break;
case 4: pGetPixelFormat=pGetPixelFormat4; break;
case 7: pGetPixelFormat=pGetPixelFormat7; break;
}
//OutTrace("dxversion=%d pGetPixelFormat=%x\n", dxversion, pGetPixelFormat);
p.dwSize=sizeof(DDPIXELFORMAT);
if(res=(*pGetPixelFormat)(lpdds, &p)){
OutTraceE("GetPixelFormat: ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return;
}
ddsd.ddpfPixelFormat = p;
OutTraceDW("InitDSScreenParameters: version=%d Actual %s\n", dxversion, DumpPixelFormat(&ddsd));
dxw.ActualPixelFormat = p;
SetBltTransformations(dxversion);
return;
}
void InitScreenParameters(int dxversion)
{
extern void FixPixelFormat(int , DDPIXELFORMAT *);
DEVMODE CurrDevMode;
static int DoOnce = FALSE;
if(DoOnce) return;
DoOnce = TRUE;
// set default VGA mode 800x600
// should I make it configurable ? (640x480, 800x600, 1024x768)
dxw.SetScreenSize(); // 800 x 600 by default
GetHookInfo()->Height=(short)dxw.GetScreenHeight();
GetHookInfo()->Width=(short)dxw.GetScreenWidth();
GetHookInfo()->ColorDepth=0; // unknown
GetHookInfo()->DXVersion=0; // unknown
GetHookInfo()->isLogging=(dxw.dwTFlags & OUTTRACE);
if(!(*pEnumDisplaySettings)(NULL, ENUM_CURRENT_SETTINGS, &CurrDevMode)){
OutTraceE("EnumDisplaySettings: ERROR err=%d at %d\n", GetLastError(), __LINE__);
return;
}
memset(&dxw.ActualPixelFormat, 0, sizeof(DDPIXELFORMAT));
// initialize to default null values, but dwRGBBitCount
dxw.ActualPixelFormat.dwRGBBitCount=CurrDevMode.dmBitsPerPel;
dxw.VirtualPixelFormat.dwRGBBitCount=CurrDevMode.dmBitsPerPel; // until set differently
if(dxw.dwFlags2 & INIT8BPP) FixPixelFormat(8, &dxw.VirtualPixelFormat);
if(dxw.dwFlags2 & INIT16BPP) FixPixelFormat(16, &dxw.VirtualPixelFormat);
if(dxw.dwFlags7 & INIT24BPP) FixPixelFormat(24, &dxw.VirtualPixelFormat);
if(dxw.dwFlags7 & INIT32BPP) FixPixelFormat(32, &dxw.VirtualPixelFormat);
OutTraceDW("InitScreenParameters: dxversion=%d RGBBitCount=%d\n", dxversion, CurrDevMode.dmBitsPerPel);
SetBltTransformations(dxversion);
return;
}
void FixPixelFormat(int ColorDepth, DDPIXELFORMAT *pf)
{
pf->dwFlags = DDPF_RGB;
switch(ColorDepth){
case 8:
pf->dwFlags |= DDPF_PALETTEINDEXED8;
pf->dwRGBBitCount = 8;
pf->dwRBitMask = 0;
pf->dwGBitMask = 0;
pf->dwBBitMask = 0;
pf->dwRGBAlphaBitMask = 0x0000;
break;
case 15: // v2.02.53: Hesperian Wars - so far the only game setting color depth to 15 BPP!
case 16:
pf->dwRGBBitCount = 16;
if (dxw.dwFlags1 & USERGB565){
pf->dwRBitMask = 0xf800;
pf->dwGBitMask = 0x07e0;
pf->dwBBitMask = 0x001f;
pf->dwRGBAlphaBitMask = 0x0000;
}
else {
if(!(dxw.dwFlags4 & NOALPHACHANNEL) && (ColorDepth == 16)) pf->dwFlags |= DDPF_ALPHAPIXELS; // v2.02.33,40,53
pf->dwRBitMask = 0x7c00;
pf->dwGBitMask = 0x03e0;
pf->dwBBitMask = 0x001f;
pf->dwRGBAlphaBitMask = 0x8000;
}
break;
case 24:
pf->dwRGBBitCount = 24;
pf->dwRBitMask = 0x00FF0000;
pf->dwGBitMask = 0x0000FF00;
pf->dwBBitMask = 0x000000FF;
pf->dwRGBAlphaBitMask = 0x00000000;
break;
case 32:
if(!(dxw.dwFlags4 & NOALPHACHANNEL)) pf->dwFlags |= DDPF_ALPHAPIXELS; // v2.02.33
pf->dwRGBBitCount = 32;
pf->dwRBitMask = 0x00FF0000;
pf->dwGBitMask = 0x0000FF00;
pf->dwBBitMask = 0x000000FF;
pf->dwRGBAlphaBitMask = 0xFF000000;
break;
}
}
static void ddSetCompatibility()
{
typedef HRESULT (WINAPI *SetAppCompatData_Type)(DWORD, DWORD);
SetAppCompatData_Type pSetAppCompatData;
HRESULT res;
HINSTANCE hinst;
hinst=LoadLibrary("ddraw.dll");
pSetAppCompatData=(SetAppCompatData_Type)(*pGetProcAddress)(hinst, "SetAppCompatData");
if(pSetAppCompatData) {
if (dxw.dwFlags2 & SETCOMPATIBILITY){
// v2.03.27: set DWM Off for both primary Lock and Blt. Good for Age of Empires intro movie!
res=(*pSetAppCompatData)(1, 0);
res=(*pSetAppCompatData)(2, 0);
OutTraceDW("HookDirectDraw: SetAppCompatData(2,0) ret=%x(%s)\n", res, ExplainDDError(res));
}
if (dxw.dwFlags6 & DISABLEMAXWINMODE){
res=(*pSetAppCompatData)(12, 0);
OutTraceDW("HookDirectDraw: SetAppCompatData(12,0) ret=%x(%s)\n", res, ExplainDDError(res));
}
}
else
OutTraceDW("HookDirectDraw: missing SetAppCompatData call\n");
FreeLibrary(hinst);
}
static void BypassGOGDDrawRedirector()
{
// this procedure bypasses the GOG proxy ddraw.dll that sometimes is found in the GOG game folders.
// This way, there will be no more the need to rename or delete this file.
char sSysLibraryPath[MAX_PATH+10];
HMODULE hinst;
GetSystemDirectory(sSysLibraryPath, MAX_PATH);
strcat(sSysLibraryPath, "\\ddraw.dll");
hinst = LoadLibrary(sSysLibraryPath);
pDirectDrawEnumerateA = (DirectDrawEnumerateA_Type)GetProcAddress(hinst, "DirectDrawEnumerateA");
pDirectDrawEnumerateExA = (DirectDrawEnumerateExA_Type)GetProcAddress(hinst, "DirectDrawEnumerateExA");
pDirectDrawEnumerateW = (DirectDrawEnumerateW_Type)GetProcAddress(hinst, "DirectDrawEnumerateW");
pDirectDrawEnumerateExW = (DirectDrawEnumerateExW_Type)GetProcAddress(hinst, "DirectDrawEnumerateExW");
pDirectDrawCreate = (DirectDrawCreate_Type)GetProcAddress(hinst, "DirectDrawCreate");
pDirectDrawCreateEx = (DirectDrawCreateEx_Type)GetProcAddress(hinst, "DirectDrawCreateEx");
}
int HookDirectDraw(HMODULE module, int version)
{
if(dxw.dwTargetDDVersion == HOOKDDRAWNONE) return 0;
if ((dxw.dwFlags2 & SETCOMPATIBILITY) ||
(dxw.dwFlags6 & DISABLEMAXWINMODE)){
static BOOL AlreadyDone = FALSE;
if(!AlreadyDone){
ddSetCompatibility();
AlreadyDone = TRUE;
}
}
if(dxw.dwFlags6 & BYPASSGOGLIBS) {
BypassGOGDDrawRedirector();
return TRUE;
}
if(dxw.dwFlags4 & HOTPATCH) {
// hot-patch all APIs and that's all folks!
HookLibraryEx(module, ddHooks, "ddraw.dll");
return TRUE;
}
//const GUID dd7 = {0x15e65ec0,0x3b9c,0x11d2,0xb9,0x2f,0x00,0x60,0x97,0x97,0xea,0x5b};
HMODULE hinst;
OutTraceB("HookDirectDraw version=%d\n", version); //GHO
switch(version){
case 0: // automatic
HookLibraryEx(module, ddHooks, "ddraw.dll");
break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
HookLibraryEx(module, ddHooks, "ddraw.dll");
if(!pDirectDrawCreate){ // required for IAT patching
hinst = LoadLibrary("ddraw.dll");
pDirectDrawCreate = (DirectDrawCreate_Type)GetProcAddress(hinst, "DirectDrawCreate");
pDirectDrawEnumerateA = (DirectDrawEnumerateA_Type)GetProcAddress(hinst, "DirectDrawEnumerateA");
}
if(pDirectDrawCreate){
LPDIRECTDRAW lpdd;
BOOL res;
HookLibraryEx(module, ddHooks, "ddraw.dll");
res=extDirectDrawCreate(0, &lpdd, 0);
if (res){
OutTraceE("DirectDrawCreate: ERROR res=%x(%s)\n", res, ExplainDDError(res));
}
lpdd->Release();
}
break;
case 7:
//hinst = LoadLibrary("ddraw.dll");
HookLibraryEx(module, ddHooks, "ddraw.dll");
if(!pDirectDrawCreate){ // required for IAT patching in "Crimson skies"
hinst = LoadLibrary("ddraw.dll");
pDirectDrawEnumerateA = (DirectDrawEnumerateA_Type)GetProcAddress(hinst, "DirectDrawEnumerateA");
pDirectDrawEnumerateExA = (DirectDrawEnumerateExA_Type)GetProcAddress(hinst, "DirectDrawEnumerateExA");
pDirectDrawCreate = (DirectDrawCreate_Type)GetProcAddress(hinst, "DirectDrawCreate");
pDirectDrawCreateEx = (DirectDrawCreateEx_Type)GetProcAddress(hinst, "DirectDrawCreateEx");
}
if(pDirectDrawCreate){
LPDIRECTDRAW lpdd;
BOOL res;
res=extDirectDrawCreate(0, &lpdd, 0);
if (res) OutTraceE("DirectDrawCreate: ERROR res=%x(%s)\n", res, ExplainDDError(res));
lpdd->Release();
}
break;
}
if(pDirectDrawCreate || pDirectDrawCreateEx) return 1;
return 0;
}
CreatePalette_Type pCreatePaletteMethod(int dxversion)
{
CreatePalette_Type pCreatePalette;
switch(dxversion){
case 1: pCreatePalette = pCreatePalette1; break;
case 2: pCreatePalette = pCreatePalette2; break;
case 4: pCreatePalette = pCreatePalette4; break;
case 7: pCreatePalette = pCreatePalette7; break;
}
CHECKPTR(pCreatePalette, "CreatePalette");
return pCreatePalette;
}
SetPalette_Type pSetPaletteMethod(int dxversion)
{
SetPalette_Type pSetPalette;
switch(dxversion){
case 1: pSetPalette=pSetPalette1; break;
case 2: pSetPalette=pSetPalette2; break;
case 4: pSetPalette=pSetPalette4; break;
case 7: pSetPalette=pSetPalette7; break;
}
CHECKPTR(pSetPalette, "SetPalette");
return pSetPalette;
}
ReleaseS_Type pReleaseSMethod(int dxversion)
{
ReleaseS_Type pReleaseS;
switch(dxversion){
case 1: pReleaseS=pReleaseS1; break;
case 2: pReleaseS=pReleaseS2; break;
case 3: pReleaseS=pReleaseS3; break;
case 4: pReleaseS=pReleaseS4; break;
case 7: pReleaseS=pReleaseS7; break;
}
CHECKPTR(pReleaseS, "Surface::Release");
return pReleaseS;
}
ReleaseDC_Type pReleaseDCMethod()
{
ReleaseDC_Type pReleaseDC;
switch(iBakBufferVersion){
case 1: pReleaseDC=pReleaseDC1; break;
case 2: pReleaseDC=pReleaseDC2; break;
case 3: pReleaseDC=pReleaseDC3; break;
case 4: pReleaseDC=pReleaseDC4; break;
case 7: pReleaseDC=pReleaseDC7; break;
}
CHECKPTR(pReleaseDC, "ReleaseDC");
return pReleaseDC;
}
SetClipper_Type pSetClipperMethod(int dxversion)
{
SetClipper_Type pSetClipper;
switch(dxversion){
case 1: pSetClipper=pSetClipper1; break;
case 2: pSetClipper=pSetClipper2; break;
case 3: pSetClipper=pSetClipper3; break;
case 4: pSetClipper=pSetClipper4; break;
case 7: pSetClipper=pSetClipper7; break;
}
CHECKPTR(pSetClipper, "SetClipper");
return pSetClipper;
}
Blt_Type pBltMethod()
{
Blt_Type pBlt;
switch(iBakBufferVersion){
case 1: pBlt=pBlt1; break;
case 2: pBlt=pBlt2; break;
case 3: pBlt=pBlt3; break;
case 4: pBlt=pBlt4; break;
case 7: pBlt=pBlt7; break;
}
CHECKPTR(pBlt, "Blt");
return pBlt;
}
GetDC_Type pGetDCMethod()
{
GetDC_Type pGetDC;
switch(iBakBufferVersion){
case 1: pGetDC=pGetDC1; break;
case 2: pGetDC=pGetDC2; break;
case 3: pGetDC=pGetDC3; break;
case 4: pGetDC=pGetDC4; break;
case 7: pGetDC=pGetDC7; break;
}
CHECKPTR(pGetDC, "GetDC");
return pGetDC;
}
Unlock4_Type pUnlockMethod(int dxversion)
{
Unlock4_Type pUnlock;
switch(dxversion){
case 1: pUnlock=(Unlock4_Type)pUnlock1; break;
case 2: pUnlock=(Unlock4_Type)pUnlock2; break;
case 3: pUnlock=(Unlock4_Type)pUnlock3; break;
case 4: pUnlock=(Unlock4_Type)pUnlock4; break;
case 7: pUnlock=(Unlock4_Type)pUnlock7; break;
}
CHECKPTR(pUnlock, "Unlock");
return pUnlock;
}
Lock_Type pLockMethod(int dxversion)
{
Lock_Type pLock;
switch(dxversion){
case 1: pLock=pLock1; break;
case 2: pLock=pLock2; break;
case 3: pLock=pLock3; break;
case 4: pLock=pLock4; break;
case 7: pLock=pLock7; break;
}
CHECKPTR(pLock, "Lock");
return pLock;
}
CreateSurface2_Type pCreateSurfaceMethod(int dxversion)
{
CreateSurface2_Type pCreateSurface;
switch(dxversion){
case 1: pCreateSurface=(CreateSurface2_Type)pCreateSurface1; break;
case 2: pCreateSurface=(CreateSurface2_Type)pCreateSurface2; break;
case 3: pCreateSurface=(CreateSurface2_Type)pCreateSurface3; break;
case 4: pCreateSurface=(CreateSurface2_Type)pCreateSurface4; break;
case 7: pCreateSurface=(CreateSurface2_Type)pCreateSurface7; break;
}
CHECKPTR(pCreateSurface, "CreateSurface");
return pCreateSurface;
}
GetSurfaceDesc2_Type pGetSurfaceDescMethod()
{
GetSurfaceDesc2_Type pGetSurfaceDesc;
pGetSurfaceDesc = NULL;
switch(iBakBufferVersion){
case 1: pGetSurfaceDesc=(GetSurfaceDesc2_Type)pGetSurfaceDesc1; break;
case 2: pGetSurfaceDesc=(GetSurfaceDesc2_Type)pGetSurfaceDesc2; break;
case 3: pGetSurfaceDesc=(GetSurfaceDesc2_Type)pGetSurfaceDesc3; break;
case 4: pGetSurfaceDesc=(GetSurfaceDesc2_Type)pGetSurfaceDesc4; break;
case 7: pGetSurfaceDesc=(GetSurfaceDesc2_Type)pGetSurfaceDesc7; break;
}
CHECKPTR(pGetSurfaceDesc, "GetSurfaceDesc");
return pGetSurfaceDesc;
}
GetGDISurface_Type pGetGDISurfaceMethod(int dxversion)
{
GetGDISurface_Type pGetGDISurface;
switch(dxversion){
default:
case 1: pGetGDISurface = pGetGDISurface1; break;
case 2: pGetGDISurface = pGetGDISurface2; break;
case 4: pGetGDISurface = pGetGDISurface4; break;
case 7: pGetGDISurface = pGetGDISurface7; break;
}
CHECKPTR(pGetGDISurface, "GetGDISurface");
return pGetGDISurface;
}
int lpddsHookedVersion()
{
return iBakBufferVersion;
}
void DescribeSurface(LPDIRECTDRAWSURFACE lpdds, int dxversion, char *label, int line)
{
DDSURFACEDESC2 ddsd;
HRESULT res;
GetSurfaceDesc2_Type pGetSurfaceDesc = NULL;
int dwSize = (dxversion<4)?sizeof(DDSURFACEDESC):sizeof(DDSURFACEDESC2);
memset(&ddsd, 0, dwSize);
ddsd.dwSize = dwSize;
pGetSurfaceDesc = pGetSurfaceDescMethod();
if(pGetSurfaceDesc==NULL) return;
res=(*pGetSurfaceDescMethod())((LPDIRECTDRAWSURFACE2)lpdds, &ddsd);
if(res)return;
OutTraceDW("Surface %s: ddsd=%x dxversion=%d %s\n",
label, lpdds, dxversion, LogSurfaceAttributes((LPDDSURFACEDESC)&ddsd, label, line));
}
void RegisterPixelFormat(int dxversion, LPDIRECTDRAWSURFACE lpdds)
{
DDSURFACEDESC2 ddsdpix;
memset((void *)&ddsdpix, 0, sizeof(DDSURFACEDESC2));
ddsdpix.dwSize = (dxversion < 4) ? sizeof(DDSURFACEDESC) : sizeof(DDSURFACEDESC2);
ddsdpix.dwFlags = DDSD_PIXELFORMAT;
switch(dxversion){
case 1: if(pGetSurfaceDesc1)(*pGetSurfaceDesc1)((LPDIRECTDRAWSURFACE)lpdds, (LPDDSURFACEDESC)&ddsdpix); break;
case 2: if(pGetSurfaceDesc2)(*pGetSurfaceDesc2)((LPDIRECTDRAWSURFACE)lpdds, (LPDDSURFACEDESC)&ddsdpix); break;
case 3: if(pGetSurfaceDesc3)(*pGetSurfaceDesc3)((LPDIRECTDRAWSURFACE)lpdds, (LPDDSURFACEDESC)&ddsdpix); break;
case 4: if(pGetSurfaceDesc4)(*pGetSurfaceDesc4)((LPDIRECTDRAWSURFACE2)lpdds, &ddsdpix); break;
case 7: if(pGetSurfaceDesc7)(*pGetSurfaceDesc7)((LPDIRECTDRAWSURFACE2)lpdds, &ddsdpix); break;
}
GetHookInfo()->pfd=ddsdpix.ddpfPixelFormat; // v2.02.88
OutTraceB("RegisterPixelFormat: lpdds=%x %s\n", lpdds, DumpPixelFormat(&ddsdpix));
}
/* ------------------------------------------------------------------ */
// SetPixFmt: builds a pixel format descriptor when no one is specified, starting from the color depth, the current
// desktop pixel format (when the color depth is the same) or the config flags
static void SetPixFmt(LPDDSURFACEDESC2 lpdd)
{
OutTraceDW("SetPixFmt: BPP=%d Use565=%d NoAlpha=%d\n",
dxw.VirtualPixelFormat.dwRGBBitCount,
dxw.dwFlags1 & USERGB565 ? 1:0,
dxw.dwFlags4 & NOALPHACHANNEL ? 1:0);
memset(&lpdd->ddpfPixelFormat,0,sizeof(DDPIXELFORMAT));
lpdd->ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
switch (dxw.VirtualPixelFormat.dwRGBBitCount)
{
case 8:
case 15:
case 16:
case 24:
case 32:
FixPixelFormat(dxw.VirtualPixelFormat.dwRGBBitCount, &lpdd->ddpfPixelFormat);
break;
default:
OutTraceE("CreateSurface ERROR: Unsupported resolution ColorBPP=%d\n", dxw.VirtualPixelFormat.dwRGBBitCount);
break;
}
// remember current virtual settings
dxw.VirtualPixelFormat=lpdd->ddpfPixelFormat;
OutTraceDW("SetPixFmt: %s\n", DumpPixelFormat(lpdd));
}
// retrieves the stored pixel format
static void GetPixFmt(LPDDSURFACEDESC2 lpdd)
{
lpdd->ddpfPixelFormat = dxw.VirtualPixelFormat;
OutTraceDW("GetPixFmt: %s\n", DumpPixelFormat(lpdd));
}
/* ------------------------------------------------------------------ */
// hook query functions that determines the object versioning ....
/* ------------------------------------------------------------------ */
int Set_dwSize_From_Surface()
{
int size;
switch(iBakBufferVersion){
case 1: size=sizeof(DDSURFACEDESC); break;
case 2: size=sizeof(DDSURFACEDESC); break;
case 3: size=sizeof(DDSURFACEDESC); break;
case 4: size=sizeof(DDSURFACEDESC2); break;
case 7: size=sizeof(DDSURFACEDESC2); break;
}
return size;
}
void HookDDSession(LPDIRECTDRAW *lplpdd, int dxversion)
{
OutTraceDW("Hooking directdraw session dd=%x dxversion=%d thread_id=%x\n",
*lplpdd, dxversion, GetCurrentThreadId());
SetHook((void *)(**(DWORD **)lplpdd + 12), extCompact, (void **)&pCompact, "Compact");
switch(dxversion) {
case 1:
SetHook((void *)(**(DWORD **)lplpdd), extQueryInterfaceD1, (void **)&pQueryInterfaceD1, "QueryInterface(D1)");
SetHook((void *)(**(DWORD **)lplpdd + 16), extCreateClipper1, (void **)&pCreateClipper1, "CreateClipper(D1)");
SetHook((void *)(**(DWORD **)lplpdd + 8), extReleaseD1, (void **)&pReleaseD1, "Release(D1)");
SetHook((void *)(**(DWORD **)lplpdd + 20), extCreatePalette1, (void **)&pCreatePalette1, "CreatePalette(D1)");
SetHook((void *)(**(DWORD **)lplpdd + 24), extCreateSurface1, (void **)&pCreateSurface1, "CreateSurface(D1)");
SetHook((void *)(**(DWORD **)lplpdd + 32), extEnumDisplayModes1, (void **)&pEnumDisplayModes1, "EnumDisplayModes(D1)");
SetHook((void *)(**(DWORD **)lplpdd + 40), extFlipToGDISurface1, (void **)&pFlipToGDISurface1, "FlipToGDISurface(D1)");
SetHook((void *)(**(DWORD **)lplpdd + 44), extGetCaps1D, (void **)&pGetCaps1D, "GetCaps(D1)");
SetHook((void *)(**(DWORD **)lplpdd + 48), extGetDisplayMode1, (void **)&pGetDisplayMode1, "GetDisplayMode(D1)");
SetHook((void *)(**(DWORD **)lplpdd + 56), extGetGDISurface1, (void **)&pGetGDISurface1, "GetGDISurface(D1)");
SetHook((void *)(**(DWORD **)lplpdd + 72), extInitialize1, (void **)&pInitialize1, "Initialize(D1)");
SetHook((void *)(**(DWORD **)lplpdd + 80), extSetCooperativeLevel1, (void **)&pSetCooperativeLevel1, "SetCooperativeLevel(D1)");
SetHook((void *)(**(DWORD **)lplpdd + 84), extSetDisplayMode1, (void **)&pSetDisplayMode1, "SetDisplayMode(D1)");
SetHook((void *)(**(DWORD **)lplpdd + 88), extWaitForVerticalBlank1, (void **)&pWaitForVerticalBlank1, "WaitForVerticalBlank(D1)");
break;
case 2:
SetHook((void *)(**(DWORD **)lplpdd), extQueryInterfaceD2, (void **)&pQueryInterfaceD2, "QueryInterface(D2)");
SetHook((void *)(**(DWORD **)lplpdd + 16), extCreateClipper2, (void **)&pCreateClipper2, "CreateClipper(D2)");
SetHook((void *)(**(DWORD **)lplpdd + 8), extReleaseD2, (void **)&pReleaseD2, "Release(D2)");
SetHook((void *)(**(DWORD **)lplpdd + 20), extCreatePalette2, (void **)&pCreatePalette2, "CreatePalette(D2)");
SetHook((void *)(**(DWORD **)lplpdd + 24), extCreateSurface2, (void **)&pCreateSurface2, "CreateSurface(D2)");
SetHook((void *)(**(DWORD **)lplpdd + 32), extEnumDisplayModes2, (void **)&pEnumDisplayModes2, "EnumDisplayModes(D1)");
SetHook((void *)(**(DWORD **)lplpdd + 40), extFlipToGDISurface2, (void **)&pFlipToGDISurface2, "FlipToGDISurface(D2)");
SetHook((void *)(**(DWORD **)lplpdd + 44), extGetCaps2D, (void **)&pGetCaps2D, "GetCaps(D2)");
SetHook((void *)(**(DWORD **)lplpdd + 48), extGetDisplayMode2, (void **)&pGetDisplayMode2, "GetDisplayMode(D2)");
SetHook((void *)(**(DWORD **)lplpdd + 56), extGetGDISurface2, (void **)&pGetGDISurface2, "GetGDISurface(D2)");
SetHook((void *)(**(DWORD **)lplpdd + 72), extInitialize2, (void **)&pInitialize2, "Initialize(D2)");
SetHook((void *)(**(DWORD **)lplpdd + 80), extSetCooperativeLevel2, (void **)&pSetCooperativeLevel2, "SetCooperativeLevel(D2)");
SetHook((void *)(**(DWORD **)lplpdd + 84), extSetDisplayMode2, (void **)&pSetDisplayMode2, "SetDisplayMode(D2)");
SetHook((void *)(**(DWORD **)lplpdd + 88), extWaitForVerticalBlank2, (void **)&pWaitForVerticalBlank2, "WaitForVerticalBlank(D2)");
// added in v2 interface
SetHook((void *)(**(DWORD **)lplpdd + 92), extGetAvailableVidMem2, (void **)&pGetAvailableVidMem2, "GetAvailableVidMem(D2)");
break;
case 4:
SetHook((void *)(**(DWORD **)lplpdd), extQueryInterfaceD4, (void **)&pQueryInterfaceD4, "QueryInterface(D4)");
SetHook((void *)(**(DWORD **)lplpdd + 16), extCreateClipper4, (void **)&pCreateClipper4, "CreateClipper(D4)");
SetHook((void *)(**(DWORD **)lplpdd + 8), extReleaseD4, (void **)&pReleaseD4, "Release(D4)");
SetHook((void *)(**(DWORD **)lplpdd + 20), extCreatePalette4, (void **)&pCreatePalette4, "CreatePalette(D4)");
SetHook((void *)(**(DWORD **)lplpdd + 24), extCreateSurface4, (void **)&pCreateSurface4, "CreateSurface(D4)");
SetHook((void *)(**(DWORD **)lplpdd + 32), extEnumDisplayModes4, (void **)&pEnumDisplayModes4, "EnumDisplayModes(D4)");
SetHook((void *)(**(DWORD **)lplpdd + 40), extFlipToGDISurface4, (void **)&pFlipToGDISurface4, "FlipToGDISurface(D4)");
SetHook((void *)(**(DWORD **)lplpdd + 44), extGetCaps4D, (void **)&pGetCaps4D, "GetCaps(D4)");
SetHook((void *)(**(DWORD **)lplpdd + 48), extGetDisplayMode4, (void **)&pGetDisplayMode4, "GetDisplayMode(D4)");
SetHook((void *)(**(DWORD **)lplpdd + 56), extGetGDISurface4, (void **)&pGetGDISurface4, "GetGDISurface(D4)");
SetHook((void *)(**(DWORD **)lplpdd + 72), extInitialize4, (void **)&pInitialize4, "Initialize(D4)");
SetHook((void *)(**(DWORD **)lplpdd + 80), extSetCooperativeLevel4, (void **)&pSetCooperativeLevel4, "SetCooperativeLevel(D4)");
SetHook((void *)(**(DWORD **)lplpdd + 84), extSetDisplayMode4, (void **)&pSetDisplayMode4, "SetDisplayMode(D4)");
SetHook((void *)(**(DWORD **)lplpdd + 88), extWaitForVerticalBlank4, (void **)&pWaitForVerticalBlank4, "WaitForVerticalBlank(D4)");
// added in v2 interface
SetHook((void *)(**(DWORD **)lplpdd + 92), extGetAvailableVidMem4, (void **)&pGetAvailableVidMem4, "GetAvailableVidMem(D4)");
// added in v4 interface
SetHook((void *)(**(DWORD **)lplpdd + 104), extTestCooperativeLevel4, (void **)&pTestCooperativeLevel4, "TestCooperativeLevel(D4)");
break;
case 7:
SetHook((void *)(**(DWORD **)lplpdd), extQueryInterfaceD7, (void **)&pQueryInterfaceD7, "QueryInterface(D7)");
SetHook((void *)(**(DWORD **)lplpdd + 16), extCreateClipper7, (void **)&pCreateClipper7, "CreateClipper(D7)");
SetHook((void *)(**(DWORD **)lplpdd + 8), extReleaseD7, (void **)&pReleaseD7, "Release(D7)");
SetHook((void *)(**(DWORD **)lplpdd + 20), extCreatePalette7, (void **)&pCreatePalette7, "CreatePalette(D7)");
SetHook((void *)(**(DWORD **)lplpdd + 24), extCreateSurface7, (void **)&pCreateSurface7, "CreateSurface(D7)");
SetHook((void *)(**(DWORD **)lplpdd + 32), extEnumDisplayModes7, (void **)&pEnumDisplayModes7, "EnumDisplayModes(D4)");
SetHook((void *)(**(DWORD **)lplpdd + 40), extFlipToGDISurface7, (void **)&pFlipToGDISurface7, "FlipToGDISurface(D7)");
SetHook((void *)(**(DWORD **)lplpdd + 44), extGetCaps7D, (void **)&pGetCaps7D, "GetCaps(D7)");
SetHook((void *)(**(DWORD **)lplpdd + 48), extGetDisplayMode7, (void **)&pGetDisplayMode7, "GetDisplayMode(D7)");
SetHook((void *)(**(DWORD **)lplpdd + 56), extGetGDISurface7, (void **)&pGetGDISurface7, "GetGDISurface(D7)");
SetHook((void *)(**(DWORD **)lplpdd + 72), extInitialize7, (void **)&pInitialize7, "Initialize(D7)");
SetHook((void *)(**(DWORD **)lplpdd + 80), extSetCooperativeLevel7, (void **)&pSetCooperativeLevel7, "SetCooperativeLevel(D7)");
SetHook((void *)(**(DWORD **)lplpdd + 84), extSetDisplayMode7, (void **)&pSetDisplayMode7, "SetDisplayMode(D7)");
SetHook((void *)(**(DWORD **)lplpdd + 88), extWaitForVerticalBlank7, (void **)&pWaitForVerticalBlank7, "WaitForVerticalBlank(D7)");
// added in v2 interface
SetHook((void *)(**(DWORD **)lplpdd + 92), extGetAvailableVidMem7, (void **)&pGetAvailableVidMem7, "GetAvailableVidMem(D7)");
// added in v4 interface
SetHook((void *)(**(DWORD **)lplpdd + 104), extTestCooperativeLevel7, (void **)&pTestCooperativeLevel7, "TestCooperativeLevel(D7)");
break;
}
}
static void HookDDClipper(LPDIRECTDRAWCLIPPER FAR* lplpDDClipper)
{
OutTraceDW("Hooking directdraw clipper dd=%x\n", *lplpDDClipper);
SetHook((void *)(**(DWORD **)lplpDDClipper + 8), extReleaseC, (void **)&pReleaseC, "Release(C)");
SetHook((void *)(**(DWORD **)lplpDDClipper + 12), extGetClipList, (void **)&pGetClipList, "GetClipList(C)");
SetHook((void *)(**(DWORD **)lplpDDClipper + 32), extSetHWnd, (void **)&pSetHWnd, "SetHWnd(C)");
}
static void HookDDPalette(LPDIRECTDRAWPALETTE FAR* lplpDDPalette)
{
OutTraceDW("Hooking directdraw palette dd=%x\n", *lplpDDPalette);
/*** IDirectDrawPalette methods ***/
SetHook((void *)(**(DWORD **)lplpDDPalette + 8), extReleaseP, (void **)&pReleaseP, "Release(P)");
SetHook((void *)(**(DWORD **)lplpDDPalette + 24), extSetEntries, (void **)&pSetEntries, "SetEntries(P)");
}
static void HookDDSurface(LPDIRECTDRAWSURFACE *lplpdds, int dxversion, BOOL isPrim)
{
BOOL bEmu = (dxw.dwFlags1 & (EMULATESURFACE|EMULATEBUFFER));
if(iBakBufferVersion==0) iBakBufferVersion=dxversion; // v2.03.60
OutTraceDW("Hooking surface dds=%x dxversion=%d prim=%x thread_id=%x\n",
*lplpdds, dxversion, isPrim, GetCurrentThreadId());
switch(dxversion) {
case 1:
SetHook((void *)(**(DWORD **)lplpdds), extQueryInterfaceS1, (void **)&pQueryInterfaceS1, "QueryInterface(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 8), extReleaseS1, (void **)&pReleaseS1, "Release(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 12), extAddAttachedSurface1, (void **)&pAddAttachedSurface1, "AddAttachedSurface(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 16), extAddOverlayDirtyRect1, (void **)&pAddOverlayDirtyRect1, "AddOverlayDirtyRect(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 28), extBltFast1, (void **)&pBltFast1, "BltFast(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 20), extBlt1, (void **)&pBlt1, "Blt(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 32), extDeleteAttachedSurface1, (void **)&pDeleteAttachedSurface1, "DeleteAttachedSurface(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 36), extEnumAttachedSurfaces1, (void **)&pEnumAttachedSurfaces1, "EnumAttachedSurfaces(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 40), extEnumOverlayZOrders1, (void **)&pEnumOverlayZOrders1, "EnumOverlayZOrders(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 44), extFlip1, (void **)&pFlip1, "Flip(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 48), extGetAttachedSurface1, (void **)&pGetAttachedSurface1, "GetAttachedSurface(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 56), extGetCaps1S, (void **)&pGetCaps1S, "GetCaps(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 64), extGetColorKey1, (void **)&pGetColorKey1, "GetColorKey(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 68), extGetDC1, (void **)&pGetDC1, "GetDC(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 80), extGetPalette1, (void **)&pGetPalette1, "GetPalette(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 84), extGetPixelFormat1, (void **)&pGetPixelFormat1, "GetPixelFormat(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 88), extGetSurfaceDesc1, (void **)&pGetSurfaceDesc1, "GetSurfaceDesc(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 100), bEmu ? extLock1 : extLockDir1, (void **)&pLock1, "Lock(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 128), bEmu ? extUnlock1 : extUnlockDir1, (void **)&pUnlock1, "Unlock(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 104), extReleaseDC1, (void **)&pReleaseDC1, "ReleaseDC(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 124), extSetPalette1, (void **)&pSetPalette1, "SetPalette(S1)");
break;
case 2:
SetHook((void *)(**(DWORD **)lplpdds), extQueryInterfaceS2, (void **)&pQueryInterfaceS2, "QueryInterface(S2)");
SetHook((void *)(**(DWORD **)lplpdds + 8), extReleaseS2, (void **)&pReleaseS2, "Release(S2)");
SetHook((void *)(**(DWORD **)lplpdds + 12), extAddAttachedSurface2, (void **)&pAddAttachedSurface2, "AddAttachedSurface(S2)");
SetHook((void *)(**(DWORD **)lplpdds + 16), extAddOverlayDirtyRect2, (void **)&pAddOverlayDirtyRect2, "AddOverlayDirtyRect(S2)");
SetHook((void *)(**(DWORD **)lplpdds + 28), extBltFast2, (void **)&pBltFast2, "BltFast(S2)");
SetHook((void *)(**(DWORD **)lplpdds + 20), extBlt2, (void **)&pBlt2, "Blt(S2)");
SetHook((void *)(**(DWORD **)lplpdds + 32), extDeleteAttachedSurface2, (void **)&pDeleteAttachedSurface2, "DeleteAttachedSurface(S2)");
SetHook((void *)(**(DWORD **)lplpdds + 36), extEnumAttachedSurfaces2, (void **)&pEnumAttachedSurfaces2, "EnumAttachedSurfaces(S2)");
SetHook((void *)(**(DWORD **)lplpdds + 40), extEnumOverlayZOrders2, (void **)&pEnumOverlayZOrders2, "EnumOverlayZOrders(S2)");
SetHook((void *)(**(DWORD **)lplpdds + 44), extFlip2, (void **)&pFlip2, "Flip(S2)");
SetHook((void *)(**(DWORD **)lplpdds + 48), extGetAttachedSurface2, (void **)&pGetAttachedSurface2, "GetAttachedSurface(S2)");
SetHook((void *)(**(DWORD **)lplpdds + 56), extGetCaps2S, (void **)&pGetCaps2S, "GetCaps(S2)");
SetHook((void *)(**(DWORD **)lplpdds + 64), extGetColorKey2, (void **)&pGetColorKey2, "GetColorKey(S2)");
SetHook((void *)(**(DWORD **)lplpdds + 68), extGetDC2, (void **)&pGetDC2, "GetDC(S2)");
SetHook((void *)(**(DWORD **)lplpdds + 80), extGetPalette2, (void **)&pGetPalette2, "GetPalette(S2)");
SetHook((void *)(**(DWORD **)lplpdds + 84), extGetPixelFormat2, (void **)&pGetPixelFormat2, "GetPixelFormat(S2)");
SetHook((void *)(**(DWORD **)lplpdds + 88), extGetSurfaceDesc2, (void **)&pGetSurfaceDesc2, "GetSurfaceDesc(S2)");
SetHook((void *)(**(DWORD **)lplpdds + 100), bEmu ? extLock2 : extLockDir2, (void **)&pLock2, "Lock(S2)");
SetHook((void *)(**(DWORD **)lplpdds + 128), bEmu ? extUnlock2 : extUnlockDir2, (void **)&pUnlock2, "Unlock(S2)");
SetHook((void *)(**(DWORD **)lplpdds + 104), extReleaseDC2, (void **)&pReleaseDC2, "ReleaseDC(S2)");
SetHook((void *)(**(DWORD **)lplpdds + 124), extSetPalette2, (void **)&pSetPalette2, "SetPalette(S2)");
break;
case 3:
SetHook((void *)(**(DWORD **)lplpdds), extQueryInterfaceS3, (void **)&pQueryInterfaceS3, "QueryInterface(S3)");
SetHook((void *)(**(DWORD **)lplpdds + 8), extReleaseS3, (void **)&pReleaseS3, "Release(S3)");
SetHook((void *)(**(DWORD **)lplpdds + 12), extAddAttachedSurface3, (void **)&pAddAttachedSurface3, "AddAttachedSurface(S3)");
SetHook((void *)(**(DWORD **)lplpdds + 16), extAddOverlayDirtyRect3, (void **)&pAddOverlayDirtyRect3, "AddOverlayDirtyRect(S3)");
SetHook((void *)(**(DWORD **)lplpdds + 28), extBltFast3, (void **)&pBltFast3, "BltFast(S3)");
SetHook((void *)(**(DWORD **)lplpdds + 20), extBlt3, (void **)&pBlt3, "Blt(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 32), extDeleteAttachedSurface3, (void **)&pDeleteAttachedSurface3, "DeleteAttachedSurface(S3)");
SetHook((void *)(**(DWORD **)lplpdds + 36), extEnumAttachedSurfaces3, (void **)&pEnumAttachedSurfaces3, "EnumAttachedSurfaces(S3)");
SetHook((void *)(**(DWORD **)lplpdds + 40), extEnumOverlayZOrders3, (void **)&pEnumOverlayZOrders3, "EnumOverlayZOrders(S3)");
SetHook((void *)(**(DWORD **)lplpdds + 44), extFlip3, (void **)&pFlip3, "Flip(S3)");
SetHook((void *)(**(DWORD **)lplpdds + 48), extGetAttachedSurface3, (void **)&pGetAttachedSurface3, "GetAttachedSurface(S3)");
SetHook((void *)(**(DWORD **)lplpdds + 56), extGetCaps3S, (void **)&pGetCaps3S, "GetCaps(S3)");
SetHook((void *)(**(DWORD **)lplpdds + 64), extGetColorKey3, (void **)&pGetColorKey3, "GetColorKey(S3)");
SetHook((void *)(**(DWORD **)lplpdds + 68), extGetDC3, (void **)&pGetDC3, "GetDC(S3)");
SetHook((void *)(**(DWORD **)lplpdds + 80), extGetPalette3, (void **)&pGetPalette3, "GetPalette(S3)");
SetHook((void *)(**(DWORD **)lplpdds + 84), extGetPixelFormat3, (void **)&pGetPixelFormat3, "GetPixelFormat(S3)");
SetHook((void *)(**(DWORD **)lplpdds + 88), extGetSurfaceDesc3, (void **)&pGetSurfaceDesc3, "GetSurfaceDesc(S3)");
SetHook((void *)(**(DWORD **)lplpdds + 100), bEmu ? extLock3 : extLockDir3, (void **)&pLock3, "Lock(S3)");
SetHook((void *)(**(DWORD **)lplpdds + 128), bEmu ? extUnlock3 : extUnlockDir3, (void **)&pUnlock3, "Unlock(S3)");
SetHook((void *)(**(DWORD **)lplpdds + 104), extReleaseDC3, (void **)&pReleaseDC3, "ReleaseDC(S3)");
SetHook((void *)(**(DWORD **)lplpdds + 124), extSetPalette3, (void **)&pSetPalette3, "SetPalette(S3)");
// added in interface version 3
SetHook((void *)(**(DWORD **)lplpdds + 156), extSetSurfaceDesc3, (void **)&pSetSurfaceDesc3, "SetSurfaceDesc(S3)");
break;
case 4:
SetHook((void *)(**(DWORD **)lplpdds), extQueryInterfaceS4, (void **)&pQueryInterfaceS4, "QueryInterface(S4)");
SetHook((void *)(**(DWORD **)lplpdds + 8), extReleaseS4, (void **)&pReleaseS4, "Release(S4)");
SetHook((void *)(**(DWORD **)lplpdds + 12), extAddAttachedSurface4, (void **)&pAddAttachedSurface4, "AddAttachedSurface(S4)");
SetHook((void *)(**(DWORD **)lplpdds + 16), extAddOverlayDirtyRect4, (void **)&pAddOverlayDirtyRect4, "AddOverlayDirtyRect(S4)");
SetHook((void *)(**(DWORD **)lplpdds + 28), extBltFast4, (void **)&pBltFast4, "BltFast(S4)");
SetHook((void *)(**(DWORD **)lplpdds + 20), extBlt4, (void **)&pBlt4, "Blt(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 32), extDeleteAttachedSurface4, (void **)&pDeleteAttachedSurface4, "DeleteAttachedSurface(S4)");
SetHook((void *)(**(DWORD **)lplpdds + 36), extEnumAttachedSurfaces4, (void **)&pEnumAttachedSurfaces4, "EnumAttachedSurfaces(S4)");
SetHook((void *)(**(DWORD **)lplpdds + 40), extEnumOverlayZOrders4, (void **)&pEnumOverlayZOrders4, "EnumOverlayZOrders(S4)");
SetHook((void *)(**(DWORD **)lplpdds + 44), extFlip4, (void **)&pFlip4, "Flip(S4)");
SetHook((void *)(**(DWORD **)lplpdds + 48), extGetAttachedSurface4, (void **)&pGetAttachedSurface4, "GetAttachedSurface(S4)");
SetHook((void *)(**(DWORD **)lplpdds + 56), extGetCaps4S, (void **)&pGetCaps4S, "GetCaps(S4)");
SetHook((void *)(**(DWORD **)lplpdds + 64), extGetColorKey4, (void **)&pGetColorKey4, "GetColorKey(S4)");
SetHook((void *)(**(DWORD **)lplpdds + 68), extGetDC4, (void **)&pGetDC4, "GetDC(S4)");
SetHook((void *)(**(DWORD **)lplpdds + 80), extGetPalette4, (void **)&pGetPalette4, "GetPalette(S4)");
SetHook((void *)(**(DWORD **)lplpdds + 84), extGetPixelFormat4, (void **)&pGetPixelFormat4, "GetPixelFormat(S4)");
SetHook((void *)(**(DWORD **)lplpdds + 88), extGetSurfaceDesc4, (void **)&pGetSurfaceDesc4, "GetSurfaceDesc(S4)");
SetHook((void *)(**(DWORD **)lplpdds + 100), bEmu ? extLock4 : extLockDir4, (void **)&pLock4, "Lock(S4)");
SetHook((void *)(**(DWORD **)lplpdds + 128), bEmu ? extUnlock4 : extUnlockDir4, (void **)&pUnlock4, "Unlock(S4)");
SetHook((void *)(**(DWORD **)lplpdds + 104), extReleaseDC4, (void **)&pReleaseDC4, "ReleaseDC(S4)");
SetHook((void *)(**(DWORD **)lplpdds + 124), extSetPalette4, (void **)&pSetPalette4, "SetPalette(S4)");
// added in interface version 3
SetHook((void *)(**(DWORD **)lplpdds + 156), extSetSurfaceDesc4, (void **)&pSetSurfaceDesc4, "SetSurfaceDesc(S4)");
break;
case 7:
SetHook((void *)(**(DWORD **)lplpdds), extQueryInterfaceS7, (void **)&pQueryInterfaceS7, "QueryInterface(S7)");
SetHook((void *)(**(DWORD **)lplpdds + 8), extReleaseS7, (void **)&pReleaseS7, "Release(S7)");
SetHook((void *)(**(DWORD **)lplpdds + 12), extAddAttachedSurface7, (void **)&pAddAttachedSurface7, "AddAttachedSurface(S7)");
SetHook((void *)(**(DWORD **)lplpdds + 16), extAddOverlayDirtyRect7, (void **)&pAddOverlayDirtyRect7, "AddOverlayDirtyRect(S7)");
SetHook((void *)(**(DWORD **)lplpdds + 28), extBltFast7, (void **)&pBltFast7, "BltFast(S7)");
SetHook((void *)(**(DWORD **)lplpdds + 20), extBlt7, (void **)&pBlt7, "Blt(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 32), extDeleteAttachedSurface7, (void **)&pDeleteAttachedSurface7, "DeleteAttachedSurface(S7)");
SetHook((void *)(**(DWORD **)lplpdds + 36), extEnumAttachedSurfaces7, (void **)&pEnumAttachedSurfaces7, "EnumAttachedSurfaces(S7)");
SetHook((void *)(**(DWORD **)lplpdds + 40), extEnumOverlayZOrders7, (void **)&pEnumOverlayZOrders7, "EnumOverlayZOrders(S7)");
SetHook((void *)(**(DWORD **)lplpdds + 44), extFlip7, (void **)&pFlip7, "Flip(S7)");
SetHook((void *)(**(DWORD **)lplpdds + 48), extGetAttachedSurface7, (void **)&pGetAttachedSurface7, "GetAttachedSurface(S7)");
SetHook((void *)(**(DWORD **)lplpdds + 56), extGetCaps7S, (void **)&pGetCaps7S, "GetCaps(S7)");
SetHook((void *)(**(DWORD **)lplpdds + 64), extGetColorKey7, (void **)&pGetColorKey7, "GetColorKey(S7)");
SetHook((void *)(**(DWORD **)lplpdds + 68), extGetDC7, (void **)&pGetDC7, "GetDC(S7)");
SetHook((void *)(**(DWORD **)lplpdds + 80), extGetPalette7, (void **)&pGetPalette7, "GetPalette(S7)");
SetHook((void *)(**(DWORD **)lplpdds + 84), extGetPixelFormat7, (void **)&pGetPixelFormat7, "GetPixelFormat(S7)");
SetHook((void *)(**(DWORD **)lplpdds + 88), extGetSurfaceDesc7, (void **)&pGetSurfaceDesc7, "GetSurfaceDesc(S7)");
SetHook((void *)(**(DWORD **)lplpdds + 100), bEmu ? extLock7 : extLockDir7, (void **)&pLock7, "Lock(S7)");
SetHook((void *)(**(DWORD **)lplpdds + 128), bEmu ? extUnlock7 : extUnlockDir7, (void **)&pUnlock7, "Unlock(S7)");
SetHook((void *)(**(DWORD **)lplpdds + 104), extReleaseDC7, (void **)&pReleaseDC7, "ReleaseDC(S7)");
SetHook((void *)(**(DWORD **)lplpdds + 124), extSetPalette7, (void **)&pSetPalette7, "SetPalette(S7)");
// added in interface version 3
SetHook((void *)(**(DWORD **)lplpdds + 156), extSetSurfaceDesc7, (void **)&pSetSurfaceDesc7, "SetSurfaceDesc(S7)");
break;
}
if (!isPrim) return;
switch(dxversion) {
case 1:
SetHook((void *)(**(DWORD **)lplpdds + 112), extSetClipper1, (void **)&pSetClipper1, "SetClipper(S1)");
SetHook((void *)(**(DWORD **)lplpdds + 116), extSetColorKey1, (void **)&pSetColorKey1, "SetColorKey(S1)");
break;
case 2:
SetHook((void *)(**(DWORD **)lplpdds + 112), extSetClipper2, (void **)&pSetClipper2, "SetClipper(S2)");
SetHook((void *)(**(DWORD **)lplpdds + 116), extSetColorKey2, (void **)&pSetColorKey2, "SetColorKey(S2)");
break;
case 3:
SetHook((void *)(**(DWORD **)lplpdds + 112), extSetClipper3, (void **)&pSetClipper3, "SetClipper(S3)");
SetHook((void *)(**(DWORD **)lplpdds + 116), extSetColorKey3, (void **)&pSetColorKey3, "SetColorKey(S3)");
break;
case 4:
SetHook((void *)(**(DWORD **)lplpdds + 112), extSetClipper4, (void **)&pSetClipper4, "SetClipper(S4)");
SetHook((void *)(**(DWORD **)lplpdds + 116), extSetColorKey4, (void **)&pSetColorKey4, "SetColorKey(S4)");
break;
case 7:
SetHook((void *)(**(DWORD **)lplpdds + 112), extSetClipper7, (void **)&pSetClipper7, "SetClipper(S7)");
SetHook((void *)(**(DWORD **)lplpdds + 116), extSetColorKey7, (void **)&pSetColorKey7, "SetColorKey(S7)");
break;
}
}
static void HookGammaControl(LPVOID *obp)
{
// IDirectDrawGammaControl::GetGammaRamp
SetHook((void *)(**(DWORD **)obp + 12), extDDGetGammaRamp, (void **)&pDDGetGammaRamp, "GetGammaRamp(G)");
// IDirectDrawGammaControl::SetGammaRamp
SetHook((void *)(**(DWORD **)obp + 16), extDDSetGammaRamp, (void **)&pDDSetGammaRamp, "SetGammaRamp(G)");
}
/* ------------------------------------------------------------------------------ */
// CleanRect:
// takes care of a corrupted RECT struct where some elements are not valid pointers.
// In this case, the whole RECT * variable is set to NULL, a value that is interpreted
// by directdraw functions as the whole surface area.
/* ------------------------------------------------------------------------------ */
static void CleanRect(RECT **lprect, int line)
{
__try {
// normally unharmful statements
if(*lprect){
int i;
i=(*lprect)->bottom;
i=(*lprect)->top;
i=(*lprect)->left;
i=(*lprect)->right;
}
}
__except(EXCEPTION_EXECUTE_HANDLER){
OutTraceE("Rectangle exception caught at %d: invalid RECT\n", __LINE__);
if(IsAssertEnabled) MessageBox(0, "Rectangle exception", "CleanRect", MB_OK | MB_ICONEXCLAMATION);
*lprect=NULL;
}
}
static void MaskCapsD(LPDDCAPS c1, LPDDCAPS c2)
{
FILE *capfile;
//char sBuf[80+1];
char token[20+1];
DWORD val;
OutTraceDW("MaskCaps\n");
if(IsDebug){
char CapsBuf[3*sizeof(DDCAPS_DX7)+20];
int i;
unsigned char *p;
if(c1){
p=(unsigned char *)c1;
for(i=0; i<sizeof(DDCAPS_DX7); i++) sprintf(&CapsBuf[3*i], "%02.2X,", p[i]);
OutTrace("CapsDump(c1:HW)=%s\n", CapsBuf);
}
if(c2){
p=(unsigned char *)c2;
for(i=0; i<sizeof(DDCAPS_DX7); i++) sprintf(&CapsBuf[3*i], "%02.2X,", p[i]);
OutTrace("CapsDump(c2:SW)=%s\n", CapsBuf);
}
}
capfile=fopen("dxwnd.cap", "r");
if(!capfile) return;
if(c1) {
while(TRUE){
if(fscanf(capfile, "%s=%x", token, &val)!=2) break;
if(!strcmp(token, "dwCaps")) c1->dwCaps &= val;
if(!strcmp(token, "dwCaps2")) c1->dwCaps2 &= val;
if(!strcmp(token, "dwCKeyCaps")) c1->dwCKeyCaps &= val;
if(!strcmp(token, "dwFXCaps")) c1->dwFXCaps &= val;
}
OutTraceDW("MaskCaps(D-HW): caps=%x(%s) caps2=%x(%s) fxcaps=%x(%s) fxalphacaps=%x(%s) keycaps=%x(%s)\n",
c1->dwCaps, ExplainDDDCaps(c1->dwCaps),
c1->dwCaps2, ExplainDDDCaps2(c1->dwCaps2),
c1->dwFXCaps, ExplainDDFXCaps(c1->dwFXCaps),
c1->dwFXAlphaCaps, ExplainDDFXALPHACaps(c1->dwFXAlphaCaps),
c1->dwCKeyCaps, ExplainDDCKeyCaps(c1->dwCKeyCaps));
}
if(c2) {
while(TRUE){
if(fscanf(capfile, "%s=%x", token, &val)!=2) break;
if(!strcmp(token, "dwCaps")) c2->dwCaps &= val;
if(!strcmp(token, "dwCaps2")) c2->dwCaps2 &= val;
if(!strcmp(token, "dwCKeyCaps")) c2->dwCKeyCaps &= val;
if(!strcmp(token, "dwFXCaps")) c2->dwFXCaps &= val;
}
OutTraceDW("MaskCaps(D-HW): caps=%x(%s) caps2=%x(%s) fxcaps=%x(%s) fxalphacaps=%x(%s) keycaps=%x(%s)\n",
c2->dwCaps, ExplainDDDCaps(c2->dwCaps),
c2->dwCaps2, ExplainDDDCaps2(c2->dwCaps2),
c2->dwFXCaps, ExplainDDFXCaps(c2->dwFXCaps),
c2->dwFXAlphaCaps, ExplainDDFXALPHACaps(c2->dwFXAlphaCaps),
c2->dwCKeyCaps, ExplainDDCKeyCaps(c2->dwCKeyCaps));
}
fclose(capfile);
}
/* ------------------------------------------------------------------------------ */
// directdraw method hooks
/* ------------------------------------------------------------------------------ */
static void HandleCapsD(char *sLabel, LPDDCAPS c)
{
const DWORD dwMaxMem = 0x70000000;
const DWORD dwHugeMem = 0xFFFFFFFF;
OutTraceDDRAW(
"GetCaps(%s): caps=%x(%s) caps2=%x(%s) palcaps=%x(%s) "
"fxcaps=%x(%s) fxalphacaps=%x(%s) keycaps=%x(%s)\n",
sLabel,
c->dwCaps, ExplainDDDCaps(c->dwCaps),
c->dwCaps2, ExplainDDDCaps2(c->dwCaps2),
c->dwPalCaps, ExplainDDPalCaps(c->dwPalCaps),
c->dwFXCaps, ExplainDDFXCaps(c->dwFXCaps),
c->dwFXAlphaCaps, ExplainDDFXALPHACaps(c->dwFXAlphaCaps),
c->dwCKeyCaps, ExplainDDCKeyCaps(c->dwCKeyCaps));
OutTraceDDRAW("GetCaps(%s): VidMemTotal=%x VidMemFree=%x ZBufferBitDepths=%x(%s)\n",
sLabel, c->dwVidMemTotal, c->dwVidMemFree, c->dwZBufferBitDepths, ExplainZBufferBitDepths(c->dwZBufferBitDepths));
OutTraceDDRAW("GetCaps(%s): MaxVisibleOverlays=%x CurrVisibleOverlays=%x\n",
sLabel, c->dwMaxVisibleOverlays, c->dwCurrVisibleOverlays);
if(dxw.bHintActive){
if(c->dwVidMemTotal > dwMaxMem) ShowHint(HINT_LIMITMEM);
if(c->dwVidMemFree > dwMaxMem) ShowHint(HINT_LIMITMEM);
}
if(dxw.dwFlags2 & LIMITRESOURCES){ // check for memory value overflow
if(c->dwVidMemTotal > dwMaxMem) c->dwVidMemTotal = dwMaxMem;
if(c->dwVidMemFree > dwMaxMem) c->dwVidMemFree = dwMaxMem;
}
if(dxw.dwFlags5 & STRESSRESOURCES){
c->dwVidMemTotal = dwHugeMem;
c->dwVidMemFree = dwHugeMem;
}
if(dxw.dwFlags6 & SETZBUFFERBITDEPTHS){
// From MSDN https://msdn.microsoft.com/en-us/library/windows/desktop/gg426101%28v=vs.85%29.aspx :
// dwZBufferBitDepths
// DDBD_8, DDBD_16, DDBD_24, or DDBD_32. (Indicate 8, 16, 24, or 32 bits per pixel.)
// This member is obsolete for DirectX 6.0 and later.
// Use the IDirect3D7::EnumZBufferFormats to retrieve information about supported depth buffer formats.
// v2.03.35: needed to bypass the "Banzai Bug" initial controls
if (c->dwZBufferBitDepths == 0) {
c->dwZBufferBitDepths = (DDBD_8|DDBD_16|DDBD_24|DDBD_32);
OutTraceDDRAW("GetCaps(%s): FIXED ZBufferBitDepths=%x(%s)\n",
sLabel, c->dwZBufferBitDepths, ExplainZBufferBitDepths(c->dwZBufferBitDepths));
}
}
if((dxw.dwFlags5 & STRESSRESOURCES) || (dxw.dwFlags2 & LIMITRESOURCES))
OutTraceDDRAW("GetCaps(%s): FIXED VidMemTotal=%x VidMemFree=%x\n", sLabel, c->dwVidMemTotal, c->dwVidMemFree);
}
static HRESULT WINAPI extGetCapsD(int dxversion, GetCapsD_Type pGetCapsD, LPDIRECTDRAW lpdd, LPDDCAPS c1, LPDDCAPS c2)
{
HRESULT res;
OutTraceDDRAW("GetCaps(D): lpdd=%x %s %s\n", lpdd, c1?"c1":"NULL", c2?"c2":"NULL");
res=(*pGetCapsD)(lpdd, c1, c2);
if(res)
OutTraceE("GetCaps(D): ERROR res=%x(%s)\n", res, ExplainDDError(res));
else {
if (c1) HandleCapsD("D-HW", c1);
if (c2) HandleCapsD("D-SW", c2);
}
if((dxw.dwFlags3 & FORCESHEL) && c1) {
DDCAPS_DX7 swcaps; // DDCAPS_DX7 because it is the bigger in size
int size;
size=c1->dwSize;
if (!c2) {
memset(&swcaps, 0, sizeof(DDCAPS_DX7));
swcaps.dwSize=size;
c2=&swcaps;
res=(*pGetCapsD)(lpdd, NULL, c2);
}
DWORD dwVidMemTotal=c1->dwVidMemTotal;
DWORD dwVidMemFree=c1->dwVidMemFree;
memcpy((void *)c1, (void *)c2, size);
if(c1->dwVidMemTotal == 0) c1->dwVidMemTotal=dwVidMemTotal;
if(c1->dwVidMemFree == 0) c1->dwVidMemFree =dwVidMemFree;
if(c1->dwVidMemTotal == 0) c1->dwVidMemTotal=0x20000000; // 500 MB
if(c1->dwVidMemFree == 0) c1->dwVidMemFree =0x20000000; // 500 MB
if (c1) HandleCapsD("D-HW(fixed)", c1);
if (c2) HandleCapsD("D-SW(fixed)", c2);
}
if((dxw.dwFlags3 & MINIMALCAPS)) SetMinimalCaps(c1, c2);
if(dxw.dwFlags3 & CAPMASK) MaskCapsD(c1, c2);
if(dxw.dwFlags7 & SUPPRESSOVERLAY){
#define OVERLAYLAYERCAPS \
(DDCAPS_OVERLAY|DDCAPS_OVERLAYCANTCLIP|\
DDCAPS_OVERLAYFOURCC|DDCAPS_OVERLAYSTRETCH)
c1->ddsCaps.dwCaps &= ~OVERLAYLAYERCAPS;
c2->ddsCaps.dwCaps &= ~OVERLAYLAYERCAPS;
#define OVERLAYKEYCAPS \
(DDCKEYCAPS_DESTOVERLAY|DDCKEYCAPS_DESTOVERLAYYUV|\
DDCKEYCAPS_SRCOVERLAY|DDCKEYCAPS_SRCOVERLAYYUV|\
DDCKEYCAPS_SRCOVERLAYCLRSPACE|DDCKEYCAPS_SRCOVERLAYCLRSPACEYUV)
c1->dwCKeyCaps &= ~OVERLAYKEYCAPS;
c2->dwCKeyCaps &= ~OVERLAYKEYCAPS;
c1->dwMaxVisibleOverlays = c1->dwCurrVisibleOverlays = 0;
c2->dwMaxVisibleOverlays = c2->dwCurrVisibleOverlays = 0;
}
return res;
}
HRESULT WINAPI extGetCaps1D(LPDIRECTDRAW lpdd, LPDDCAPS c1, LPDDCAPS c2)
{ return extGetCapsD(1, pGetCaps1D, lpdd, c1, c2); }
HRESULT WINAPI extGetCaps2D(LPDIRECTDRAW lpdd, LPDDCAPS c1, LPDDCAPS c2)
{ return extGetCapsD(2, pGetCaps2D, lpdd, c1, c2); }
HRESULT WINAPI extGetCaps4D(LPDIRECTDRAW lpdd, LPDDCAPS c1, LPDDCAPS c2)
{ return extGetCapsD(4, pGetCaps4D, lpdd, c1, c2); }
HRESULT WINAPI extGetCaps7D(LPDIRECTDRAW lpdd, LPDDCAPS_DX7 c1, LPDDCAPS_DX7 c2)
{ return extGetCapsD(7, pGetCaps7D, lpdd, (LPDDCAPS)c1, (LPDDCAPS)c2); }
HRESULT WINAPI extDirectDrawCreate(GUID FAR *lpguid, LPDIRECTDRAW FAR *lplpdd, IUnknown FAR *pu)
{
HRESULT res;
GUID FAR *lpPrivGuid = lpguid;
OutTraceDDRAW("DirectDrawCreate: guid=%x(%s)\n", lpguid, ExplainGUID(lpguid));
if(!pDirectDrawCreate){ // not hooked yet....
HINSTANCE hinst;
hinst = LoadLibrary("ddraw.dll");
if(!hinst){
OutTraceE("LoadLibrary ERROR err=%d at %d\n", GetLastError(), __LINE__);
}
pDirectDrawCreate =
(DirectDrawCreate_Type)GetProcAddress(hinst, "DirectDrawCreate");
if(pDirectDrawCreate)
HookAPI(hinst, "ddraw.dll", pDirectDrawCreate, "DirectDrawCreate", extDirectDrawCreate); // v2.02.52
else{
char sMsg[81];
sprintf_s(sMsg, 80, "DirectDrawCreate hook failed: error=%d\n", GetLastError());
OutTraceDW(sMsg);
if(IsAssertEnabled) MessageBox(0, sMsg, "Hook", MB_OK | MB_ICONEXCLAMATION);
return DDERR_GENERIC; // is there a better one?
}
}
if((dxw.dwFlags3 & FORCESHEL) && (lpguid==NULL)) lpPrivGuid=(GUID FAR *)DDCREATE_EMULATIONONLY;
res = (*pDirectDrawCreate)(lpPrivGuid, lplpdd, pu);
if(res) {
OutTraceE("DirectDrawCreate: ERROR res=%x(%s)\n", res, ExplainDDError(res));
return res;
}
if(dxw.dwFlags3 & COLORFIX) (*((DDRAWI_DIRECTDRAW_INT **)lplpdd))->lpLcl->dwAppHackFlags |= 0x800;
dxw.dwDDVersion=1;
char *mode;
switch ((DWORD)lpPrivGuid){
case 0: mode="NULL"; break;
case DDCREATE_HARDWAREONLY: mode="DDCREATE_HARDWAREONLY"; break;
case DDCREATE_EMULATIONONLY: mode="DDCREATE_EMULATIONONLY"; break;
default:
switch (*(DWORD *)lpguid){
case 0x6C14DB80: dxw.dwDDVersion=1; mode="IID_IDirectDraw"; break;
case 0xB3A6F3E0: dxw.dwDDVersion=2; mode="IID_IDirectDraw2"; break;
case 0x9c59509a: dxw.dwDDVersion=4; mode="IID_IDirectDraw4"; break;
case 0x15e65ec0: dxw.dwDDVersion=7; mode="IID_IDirectDraw7"; break;
default: mode="unknown"; break;
}
break;
}
OutTraceDDRAW("DirectDrawCreate: lpdd=%x guid=%s DDVersion=%d\n", *lplpdd, mode, dxw.dwDDVersion);
HookDDSession(lplpdd, dxw.dwDDVersion);
// beware: old ddraw games seem to reuse a closed ddraw handle. The theory is that maybe whenever
// you created a ddraw session, you got more than one reference count, so that releasing it once
// did not destroy the object.... but why? when (I mean, in which situations? Maybe not always...)
// and for which releases? The fix here assumes that this fact is true and holds always for ddraw 1
// sessions.
// update: this is no good for "Jet Moto" that created a ddraw session and expects to Release it
// with a refcount zero.
//if(dxw.dwDDVersion==1) (*lplpdd)->AddRef(); // seems to fix problems in "Warhammer 40K Rites Of War"
if(IsDebug){
DDCAPS DriverCaps, EmulCaps;
memset(&DriverCaps, 0, sizeof(DriverCaps));
DriverCaps.dwSize=sizeof(DriverCaps);
memset(&EmulCaps, 0, sizeof(EmulCaps));
EmulCaps.dwSize=sizeof(EmulCaps);
(LPDIRECTDRAW)(*lplpdd)->GetCaps(&DriverCaps, &EmulCaps);
//OutTrace("DirectDrawCreate: drivercaps=%x(%s) emulcaps=%x(%s)\n", DriverCaps.ddsCaps, "???", EmulCaps.ddsCaps, "???");
}
if(lpPrimaryDD==NULL) lpPrimaryDD=*lplpdd; // do not override the value set when creating the primary surface!
bFlippedDC = FALSE; // v02.03.30
#ifdef AUTOSETCOOPERATIVELEVEL
OutTrace("Setting cooperative level version=%d hwnd=%x\n", dxw.dwDDVersion, dxw.GethWnd());
switch(dxw.dwDDVersion){
case 1: res=(*pSetCooperativeLevel1)(*lplpdd, dxw.GethWnd(), DDSCL_NORMAL); break;
case 2: res=(*pSetCooperativeLevel2)(*lplpdd, dxw.GethWnd(), DDSCL_NORMAL); break;
case 4: res=(*pSetCooperativeLevel4)(*lplpdd, dxw.GethWnd(), DDSCL_NORMAL); break;
case 7: res=(*pSetCooperativeLevel7)(*lplpdd, dxw.GethWnd(), DDSCL_NORMAL); break;
}
if(res) OutTraceE("SetCooperativeLevel ERROR: err=%x(%s)\n", res, ExplainDDError(res));
#endif
return DD_OK;
}
HRESULT WINAPI extDirectDrawCreateEx(GUID FAR *lpguid,
LPDIRECTDRAW FAR *lplpdd, REFIID iid, IUnknown FAR *pu)
{
HRESULT res;
GUID FAR *lpPrivGuid = lpguid;
OutTraceDDRAW("DirectDrawCreateEx: guid=%x(%s) refiid=%x\n", lpguid, ExplainGUID(lpguid), iid);
// v2.1.70: auto-hooking (just in case...)
if(!pDirectDrawCreateEx){ // not hooked yet....
HINSTANCE hinst;
hinst = LoadLibrary("ddraw.dll");
if(!hinst){
OutTraceE("LoadLibrary ERROR err=%d at %d\n", GetLastError(), __LINE__);
}
pDirectDrawCreateEx =
(DirectDrawCreateEx_Type)GetProcAddress(hinst, "DirectDrawCreateEx");
if(pDirectDrawCreateEx)
HookAPI(hinst, "ddraw.dll", pDirectDrawCreateEx, "DirectDrawCreateEx", extDirectDrawCreateEx); // v2.02.52
else{
char sMsg[81];
sprintf_s(sMsg, 80, "DirectDrawCreateEx hook failed: error=%d\n", GetLastError());
OutTraceDW(sMsg);
if(IsAssertEnabled) MessageBox(0, sMsg, "Hook", MB_OK | MB_ICONEXCLAMATION);
return DDERR_GENERIC; // is there a better one?
}
}
if((dxw.dwFlags3 & FORCESHEL) && (lpguid==NULL)) lpPrivGuid=(GUID FAR *)DDCREATE_EMULATIONONLY;
res = (*pDirectDrawCreateEx)(lpPrivGuid, lplpdd, iid, pu);
if (res){
OutTraceDW("DirectDrawCreateEx: res=%x(%s)\n",res, ExplainDDError(res));
return res;
}
if(dxw.dwFlags3 & COLORFIX) (*((DDRAWI_DIRECTDRAW_INT **)lplpdd))->lpLcl->dwAppHackFlags |= 0x800;
dxw.dwDDVersion=7;
char *mode;
switch ((DWORD)lpPrivGuid){
case 0: mode="NULL"; break;
case DDCREATE_HARDWAREONLY: mode="DDCREATE_HARDWAREONLY"; break;
case DDCREATE_EMULATIONONLY: mode="DDCREATE_EMULATIONONLY"; break;
default:
switch (*(DWORD *)lpguid){
case 0x6C14DB80: dxw.dwDDVersion=1; mode="IID_IDirectDraw"; break;
case 0xB3A6F3E0: dxw.dwDDVersion=2; mode="IID_IDirectDraw2"; break;
case 0x9c59509a: dxw.dwDDVersion=4; mode="IID_IDirectDraw4"; break;
case 0x15e65ec0: dxw.dwDDVersion=7; mode="IID_IDirectDraw7"; break;
default: mode="unknown"; break;
}
break;
}
OutTraceDDRAW("DirectDrawCreateEx: lpdd=%x guid=%s DDVersion=%d\n", *lplpdd, mode, dxw.dwDDVersion);
HookDDSession(lplpdd, dxw.dwDDVersion);
if(IsDebug){
DDCAPS DriverCaps, EmulCaps;
memset(&DriverCaps, 0, sizeof(DriverCaps));
DriverCaps.dwSize=sizeof(DriverCaps);
memset(&EmulCaps, 0, sizeof(EmulCaps));
EmulCaps.dwSize=sizeof(EmulCaps);
(LPDIRECTDRAW)(*lplpdd)->GetCaps(&DriverCaps, &EmulCaps);
//OutTrace("DirectDrawCreate: drivercaps=%x(%s) emulcaps=%x(%s)\n", DriverCaps.ddsCaps, "???", EmulCaps.ddsCaps, "???");
}
if(lpPrimaryDD==NULL) lpPrimaryDD=*lplpdd; // do not override the value set when creating the primary surface!
bFlippedDC = FALSE; // v02.03.30: fix for Powerslide
return DD_OK;
}
static HRESULT WINAPI extInitialize(Initialize_Type pInitialize, LPDIRECTDRAW lpdd, GUID FAR *lpguid)
{
HRESULT res;
GUID FAR *lpPrivGuid = lpguid;
OutTraceDDRAW("Initialize: lpdd=%x guid=%x(%s)\n", lpdd, lpguid, ExplainGUID(lpguid));
if((dxw.dwFlags3 & FORCESHEL) && (lpguid==NULL)) lpPrivGuid=(GUID FAR *)DDCREATE_EMULATIONONLY;
res=(*pInitialize)(lpdd, lpPrivGuid);
if(res == DDERR_ALREADYINITIALIZED) res=DD_OK; // v2.03.18: this error could be caused by the CoCreateInstance implementation
if(dxw.dwFlags3 & COLORFIX) (((DDRAWI_DIRECTDRAW_INT *)lpdd))->lpLcl->dwAppHackFlags |= 0x800;
if(res) OutTraceE("Initialize ERROR: res=%x(%s)\n", res, ExplainDDError(res));
return res;
}
HRESULT WINAPI extInitialize1(LPDIRECTDRAW lpdd, GUID FAR *lpguid)
{ return extInitialize(pInitialize1, lpdd, lpguid); }
HRESULT WINAPI extInitialize2(LPDIRECTDRAW lpdd, GUID FAR *lpguid)
{ return extInitialize(pInitialize2, lpdd, lpguid); }
HRESULT WINAPI extInitialize4(LPDIRECTDRAW lpdd, GUID FAR *lpguid)
{ return extInitialize(pInitialize4, lpdd, lpguid); }
HRESULT WINAPI extInitialize7(LPDIRECTDRAW lpdd, GUID FAR *lpguid)
{ return extInitialize(pInitialize7, lpdd, lpguid); }
static HRESULT WINAPI extQueryInterfaceD(int dxversion, QueryInterface_Type pQueryInterfaceD, void *lpdd, REFIID riid, LPVOID *obp)
{
HRESULT res;
unsigned int dwLocalDDVersion;
unsigned int dwLocalD3DVersion;
res = (*pQueryInterfaceD)(lpdd, riid, obp);
OutTraceDDRAW("QueryInterface(D%d): lpdd=%x REFIID=%x(%s) obp=%x ret=%x at %d\n",
dxversion, lpdd, riid.Data1, ExplainGUID((GUID *)&riid), *obp, res, __LINE__);
if(res) {
OutTraceE("QueryInterface(D) ERROR: res=%x(%s)\n", res, ExplainDDError(res));
return res;
}
dwLocalDDVersion=0;
dwLocalD3DVersion=0;
switch(riid.Data1){
case 0x6C14DB80: //DirectDraw1
dwLocalDDVersion = 1;
break;
case 0xB3A6F3E0: //DirectDraw2
dwLocalDDVersion = 2;
break;
case 0x9c59509a: //DirectDraw4
dwLocalDDVersion = 4;
break;
case 0x15e65ec0: //DirectDraw7
dwLocalDDVersion = 7;
break;
case 0x3BBA0080: //Direct3D
dwLocalD3DVersion = 1;
break;
case 0x6aae1ec1: //Direct3D2
dwLocalD3DVersion = 2;
break;
case 0xbb223240: //Direct3D3
dwLocalD3DVersion = 3;
break;
case 0xf5049e77: //Direct3D7
dwLocalD3DVersion = 7;
break;
}
if (! *obp){
OutTraceDDRAW("QueryInterface(D): Interface for DX version %d not found\n", dwLocalDDVersion);
return(0);
}
if(dwLocalDDVersion) OutTraceDW("QueryInterface(D): Got interface for DX version %d\n", dwLocalDDVersion);
if(dwLocalD3DVersion) OutTraceDW("QueryInterface(D): Got interface for D3D version %d\n", dwLocalD3DVersion);
if (dwLocalDDVersion > dxw.dwMaxDDVersion) {
*obp = NULL;
OutTraceDW("QueryInterface(D): lpdd=%x REFIID=%x obp=(NULL) ret=%x at %d\n",
lpdd, riid.Data1, res, __LINE__);
return(0);
}
switch (dwLocalDDVersion){
case 1: // you never know ....
case 2:
case 4:
// it's not supposed to be written for DDVersion==7, but it works ....
case 7:
dxw.dwDDVersion=dwLocalDDVersion;
HookDDSession((LPDIRECTDRAW *)obp, dxw.dwDDVersion);
break;
}
extern void HookDirect3DSession(LPDIRECTDRAW *, int);
switch (dwLocalD3DVersion){
case 1:
case 2:
case 3:
case 7:
HookDirect3DSession((LPDIRECTDRAW *)obp, dwLocalD3DVersion);
break;
}
OutTraceDDRAW("QueryInterface(D): lpdd=%x REFIID=%x obp=%x DDVersion=%d ret=0\n",
lpdd, riid.Data1, *obp, dxw.dwDDVersion);
return 0;
}
HRESULT WINAPI extQueryInterfaceD1(void *lpdd, REFIID riid, LPVOID *obp)
{ return extQueryInterfaceD(1, pQueryInterfaceD1, lpdd, riid, obp); }
HRESULT WINAPI extQueryInterfaceD2(void *lpdd, REFIID riid, LPVOID *obp)
{ return extQueryInterfaceD(2, pQueryInterfaceD2, lpdd, riid, obp); }
HRESULT WINAPI extQueryInterfaceD4(void *lpdd, REFIID riid, LPVOID *obp)
{ return extQueryInterfaceD(4, pQueryInterfaceD4, lpdd, riid, obp); }
HRESULT WINAPI extQueryInterfaceD7(void *lpdd, REFIID riid, LPVOID *obp)
{ return extQueryInterfaceD(7, pQueryInterfaceD7, lpdd, riid, obp); }
// some unhandled interfaces in emulation mode:
// REFIID={84e63de0-46aa-11cf-816f-0000c020156e}: IID_IDirect3DHALDevice
static HRESULT WINAPI extQueryInterfaceS(int dxversion, QueryInterface_Type pQueryInterfaceS, void *lpdds, REFIID riid, LPVOID *obp)
{
HRESULT res;
BOOL IsPrim;
BOOL IsBack;
BOOL IsGammaRamp;
unsigned int dwLocalDDVersion;
unsigned int dwLocalTexVersion;
unsigned int dwLocalD3DDeviceVersion;
IsPrim=dxwss.IsAPrimarySurface((LPDIRECTDRAWSURFACE)lpdds);
IsBack=dxwss.IsABackBufferSurface((LPDIRECTDRAWSURFACE)lpdds);
OutTraceDDRAW("QueryInterface(S%d): lpdds=%x%s REFIID=%x(%s)\n",
dxversion, lpdds, dxwss.ExplainSurfaceRole((LPDIRECTDRAWSURFACE)lpdds), riid.Data1, ExplainGUID((GUID *)&riid));
IsGammaRamp=FALSE;
dwLocalDDVersion=0;
dwLocalTexVersion=0;
dwLocalD3DDeviceVersion=0;
switch(riid.Data1){
case 0x6C14DB81:
dwLocalDDVersion = 1;
break;
case 0x57805885: //DDSurface2 - WIP (Dark Reign)
dwLocalDDVersion = 2;
break;
case 0xDA044E00: //DDSurface3
dwLocalDDVersion = 3;
break;
case 0x0B2B8630:
dwLocalDDVersion = 4;
break;
case 0x06675a80:
dwLocalDDVersion = 7;
break;
// Direct3DDevice
case 0x84e63de0:
OutTraceDW("QueryInterface: IID_IDirect3DHALDevice\n");
dwLocalD3DDeviceVersion = 1;
break;
case 0xA4665C60: // IID_IDirect3DRGBDevice
OutTraceDW("QueryInterface: IID_IDirect3DRGBDevice\n");
dwLocalD3DDeviceVersion = 1;
break;
case 0xF2086B20: // IID_IDirect3DRampDevice
OutTraceDW("QueryInterface: IID_IDirect3DRampDevice\n");
dwLocalD3DDeviceVersion = 1;
break;
case 0x881949a1: // IID_IDirect3DMMXDevice
OutTraceDW("QueryInterface: IID_IDirect3DMMXDevice\n");
dwLocalD3DDeviceVersion = 1;
break;
case 0x50936643: // IID_IDirect3DRefDevice
OutTraceDW("QueryInterface: IID_IDirect3DRefDevice\n");
dwLocalD3DDeviceVersion = 2;
break;
case 0x8767df22: // IID_IDirect3DNullDevice
OutTraceDW("QueryInterface: IID_IDirect3DNullDevice\n");
dwLocalD3DDeviceVersion = 2;
break;
case 0xf5049e78: // IID_IDirect3DTnLHalDevice,
OutTraceDW("QueryInterface: IID_IDirect3DTnLHalDevice\n");
dwLocalD3DDeviceVersion = 3;
break;
case 0x64108800: // IID_IDirect3DDevice
OutTraceDW("QueryInterface: IID_IDirect3DDevice\n");
dwLocalD3DDeviceVersion = 1;
break;
case 0x93281501: // IID_IDirect3DDevice2
OutTraceDW("QueryInterface: IID_IDirect3DDevice2\n");
dwLocalD3DDeviceVersion = 2;
break;
case 0xb0ab3b60: // IID_IDirect3DDevice3
OutTraceDW("QueryInterface: IID_IDirect3DDevice3\n");
dwLocalD3DDeviceVersion = 3;
break;
case 0xf5049e79: // IID_IDirect3DDevice7
OutTraceDW("QueryInterface: IID_IDirect3DDevice7\n");
dwLocalD3DDeviceVersion = 7;
break;
case 0x4B9F0EE0:
OutTraceDW("QueryInterface: IID_IDirectDrawColorControl\n");
break;
case 0x69C11C3E:
OutTraceDW("QueryInterface: IID_IDirectDrawGammaControl\n");
IsGammaRamp=TRUE;
break;
// textures
case 0x2CDCD9E0:
OutTraceDW("QueryInterface: IID_IDirect3DTexture\n");
dwLocalTexVersion = 1;
break;
case 0x93281502:
OutTraceDW("QueryInterface: IID_IDirect3DTexture2\n");
dwLocalTexVersion = 2;
break;
}
if (dwLocalDDVersion > dxw.dwMaxDDVersion) {
*obp = NULL;
OutTraceDW("QueryInterface(S): DDVersion=%d SUPPRESS lpdds=%x(%s) REFIID=%x obp=(NULL) ret=0 at %d\n",
dwLocalDDVersion, lpdds, IsPrim?"":"(PRIM)", riid.Data1, __LINE__);
return(0);
}
// fix the target for gamma ramp creation: if it is a primary surface, use the real one!!
// v2.03.37: do this just when in esurface emulated mode!!
if( IsGammaRamp &&
(dxw.dwFlags1 & EMULATESURFACE) &&
dxwss.IsAPrimarySurface((LPDIRECTDRAWSURFACE)lpdds))
lpdds = lpDDSEmu_Prim;
res = (*pQueryInterfaceS)(lpdds, riid, obp);
if(res) // added trace
{
OutTraceDW("QueryInterface(S): ERROR lpdds=%x%s REFIID=%x obp=%x ret=%x(%s) at %d\n",
lpdds, IsPrim?"(PRIM)":"", riid.Data1, *obp, res, ExplainDDError(res), __LINE__);
return res;
}
if (! *obp) {
OutTraceDW("QueryInterface(S): Interface for DX version %d not found\n", dwLocalDDVersion);
return 0;
}
// added trace
OutTraceDW("QueryInterface(S): lpdds=%x%s REFIID=%x obp=%x DDVersion=%d TexVersion=%d GammaRamp=%d D3DDevice=%d ret=0\n",
lpdds, IsPrim?"(PRIM)":"", riid.Data1, *obp, dwLocalDDVersion, dwLocalTexVersion, IsGammaRamp, dwLocalD3DDeviceVersion);
if (dwLocalDDVersion) {
switch (dwLocalDDVersion){
case 1: // added for The Sims
case 2:
case 3:
case 4:
case 7:
dxw.dwDDVersion=dwLocalDDVersion;
if(IsPrim){
OutTraceDW("QueryInterface(S): primary=%x new=%x\n", lpdds, *obp);
dxwss.PushPrimarySurface((LPDIRECTDRAWSURFACE)*obp, dwLocalDDVersion);
HookDDSurface((LPDIRECTDRAWSURFACE *)obp, dxw.dwDDVersion, TRUE);
}
else{
if(IsBack) dxwss.PushBackBufferSurface((LPDIRECTDRAWSURFACE)*obp, dwLocalDDVersion);
else dxwss.PopSurface((LPDIRECTDRAWSURFACE)*obp);
// v2.02.13: seems that hooking inconditionally gives troubles. What is the proper safe hook condition?
HookDDSurface((LPDIRECTDRAWSURFACE *)obp, dxw.dwDDVersion, FALSE);
}
break;
}
}
if(dwLocalTexVersion) {
// Texture Handling on QueryInterface
if(dxw.dwFlags5 & TEXTUREMASK) TextureHandling((LPDIRECTDRAWSURFACE)lpdds, dwLocalTexVersion);
HookTexture(obp, dwLocalTexVersion);
}
if(IsGammaRamp) HookGammaControl(obp);
if(dwLocalD3DDeviceVersion) {
extern void HookDirect3DDevice(void **, int);
HookDirect3DDevice(obp, dwLocalD3DDeviceVersion);
}
return 0;
}
HRESULT WINAPI extQueryInterfaceS1(void *lpdds, REFIID riid, LPVOID *obp)
{ return extQueryInterfaceS(1, pQueryInterfaceS1, lpdds, riid, obp); }
HRESULT WINAPI extQueryInterfaceS2(void *lpdds, REFIID riid, LPVOID *obp)
{ return extQueryInterfaceS(2, pQueryInterfaceS2, lpdds, riid, obp); }
HRESULT WINAPI extQueryInterfaceS3(void *lpdds, REFIID riid, LPVOID *obp)
{ return extQueryInterfaceS(3, pQueryInterfaceS3, lpdds, riid, obp); }
HRESULT WINAPI extQueryInterfaceS4(void *lpdds, REFIID riid, LPVOID *obp)
{ return extQueryInterfaceS(4, pQueryInterfaceS4, lpdds, riid, obp); }
HRESULT WINAPI extQueryInterfaceS7(void *lpdds, REFIID riid, LPVOID *obp)
{ return extQueryInterfaceS(7, pQueryInterfaceS7, lpdds, riid, obp); }
HRESULT WINAPI extSetDisplayMode(int dxversion, LPDIRECTDRAW lpdd,
DWORD dwwidth, DWORD dwheight, DWORD dwbpp, DWORD dwrefreshrate, DWORD dwflags)
{
DDSURFACEDESC2 ddsd;
HRESULT res = 0;
if(IsTraceDDRAW){
char sInfo[81];
strcpy(sInfo, "");
if (dxversion>=4) sprintf(sInfo, " dwRefresh=%i dwFlags=%x", dwrefreshrate, dwflags);
OutTrace("SetDisplayMode: version=%d dwWidth=%i dwHeight=%i dwBPP=%i%s\n",
dxversion, dwwidth, dwheight, dwbpp, sInfo);
}
// binkplayer fix
if((int)dwwidth < 0) dwwidth = dxw.GetScreenWidth();
if((int)dwheight < 0) dwheight = dxw.GetScreenHeight();
dxw.SetScreenSize(dwwidth, dwheight);
GetHookInfo()->Height=(short)dxw.GetScreenHeight();
GetHookInfo()->Width=(short)dxw.GetScreenWidth();
GetHookInfo()->ColorDepth=(short)dwbpp;
if(dxw.Windowize) AdjustWindowFrame(dxw.GethWnd(), dwwidth, dwheight);
if(dxw.dwFlags1 & EMULATESURFACE){
// in EMULATESURFACE mode, let SetPixFmt decide upon the PixelFormat
dxw.VirtualPixelFormat.dwRGBBitCount = dwbpp;
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize=sizeof(ddsd);
SetPixFmt(&ddsd);
SetBltTransformations(dxversion);
if(dxw.Windowize) {
OutTraceDW("SetDisplayMode: mode=EMULATE %s ret=OK\n", DumpPixelFormat(&ddsd));
SetVSyncDelays(dxversion, lpdd);
return DD_OK;
}
}
else{
OutTraceDW("SetDisplayMode: mode=STANDARD BPP=%d\n", dwbpp);
dxw.VirtualPixelFormat.dwRGBBitCount = dwbpp;
dxw.ActualPixelFormat.dwRGBBitCount = dwbpp;
}
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_REFRESHRATE;
ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
switch(dxversion){
default:
case 1: ddsd.dwSize=sizeof(LPDDSURFACEDESC); res=(*pGetDisplayMode1)(lpdd, (LPDDSURFACEDESC)&ddsd); break;
case 2: ddsd.dwSize=sizeof(LPDDSURFACEDESC); res=(*pGetDisplayMode2)(lpdd, (LPDDSURFACEDESC)&ddsd); break;
case 4: ddsd.dwSize=sizeof(LPDDSURFACEDESC2); res=(*pGetDisplayMode4)(lpdd, &ddsd); break;
case 7: ddsd.dwSize=sizeof(LPDDSURFACEDESC2); res=(*pGetDisplayMode7)(lpdd, &ddsd); break;
}
if(res){
OutTraceE("SetDisplayMode: GetDisplayMode err=%x(%s)\n", res, ExplainDDError(res));
// fix for Win10 platform returning DDERR_INVALIDPARAMS
RECT desktop;
ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
(*pGetClientRect)((*pGetDesktopWindow)(), &desktop);
ddsd.dwWidth = desktop.right;
ddsd.dwHeight = desktop.bottom;
}
OutTraceB("SetDisplayMode: detected screen size=(%dx%d)\n", ddsd.dwWidth, ddsd.dwHeight);
if(dxw.Windowize){
if(!IsChangeDisplaySettingsHotPatched){
dwwidth = ddsd.dwWidth;
dwheight = ddsd.dwHeight;
}
OutTraceDW("SetDisplayMode: fixing colordepth current=%d required=%d size=(%dx%d)\n",
ddsd.ddpfPixelFormat.dwRGBBitCount, dwbpp, dwwidth, dwheight);
}
if(dxw.dwFlags1 & EMULATESURFACE){
dwbpp = ddsd.ddpfPixelFormat.dwRGBBitCount;
}
switch(dxversion){
default:
case 1: res=(*pSetDisplayMode1)(lpdd, dwwidth, dwheight, dwbpp); break;
case 2: res=(*pSetDisplayMode2)(lpdd, dwwidth, dwheight, dwbpp, ddsd.dwRefreshRate, 0); break;
case 4: res=(*pSetDisplayMode4)(lpdd, dwwidth, dwheight, dwbpp, ddsd.dwRefreshRate, 0); break;
case 7: res=(*pSetDisplayMode7)(lpdd, dwwidth, dwheight, dwbpp, ddsd.dwRefreshRate, 0); break;
}
if(res) OutTraceE("SetDisplayMode: error=%x(%s)\n", res, ExplainDDError(res));
SetVSyncDelays(dxversion, lpdd);
// set a default palette ???
if(dxw.VirtualPixelFormat.dwRGBBitCount == 8)
mySetPalette(0, 256, DefaultSystemPalette);
return DD_OK;
}
HRESULT WINAPI extSetDisplayMode1(LPDIRECTDRAW lpdd, DWORD dwwidth, DWORD dwheight, DWORD dwbpp)
{ return extSetDisplayMode(1, lpdd, dwwidth, dwheight, dwbpp, 0, 0); }
HRESULT WINAPI extSetDisplayMode2(LPDIRECTDRAW lpdd, DWORD dwwidth, DWORD dwheight, DWORD dwbpp, DWORD dwrefreshrate, DWORD dwflags)
{ return extSetDisplayMode(2, lpdd, dwwidth, dwheight, dwbpp, dwrefreshrate, dwflags); }
HRESULT WINAPI extSetDisplayMode4(LPDIRECTDRAW lpdd, DWORD dwwidth, DWORD dwheight, DWORD dwbpp, DWORD dwrefreshrate, DWORD dwflags)
{ return extSetDisplayMode(4, lpdd, dwwidth, dwheight, dwbpp, dwrefreshrate, dwflags); }
HRESULT WINAPI extSetDisplayMode7(LPDIRECTDRAW lpdd, DWORD dwwidth, DWORD dwheight, DWORD dwbpp, DWORD dwrefreshrate, DWORD dwflags)
{ return extSetDisplayMode(7, lpdd, dwwidth, dwheight, dwbpp, dwrefreshrate, dwflags);}
HRESULT WINAPI extGetDisplayMode(GetDisplayMode_Type pGetDisplayMode, LPDIRECTDRAW lpdd, LPDDSURFACEDESC lpddsd)
{
OutTraceDDRAW("GetDisplayMode(D1): lpdd=%x lpddsd=%x\n", lpdd, lpddsd);
(*pGetDisplayMode)(lpdd, lpddsd);
if(dxw.dwFlags1 & EMULATESURFACE) {
GetPixFmt((LPDDSURFACEDESC2)lpddsd);
if(!lpddsd->ddpfPixelFormat.dwFlags) SetPixFmt((LPDDSURFACEDESC2)lpddsd);
}
if(dxw.Windowize){
lpddsd->dwWidth = dxw.GetScreenWidth();
lpddsd->dwHeight = dxw.GetScreenHeight();
// v2.1.96: fake screen color depth
if((dxw.dwFlags2 & (INIT8BPP|INIT16BPP)) || (dxw.dwFlags7 & (INIT24BPP|INIT32BPP))){ // v2.02.32 fix
if(dxw.dwFlags2 & INIT8BPP) FixPixelFormat(8, &lpddsd->ddpfPixelFormat);
if(dxw.dwFlags2 & INIT16BPP) FixPixelFormat(16, &lpddsd->ddpfPixelFormat);
if(dxw.dwFlags7 & INIT24BPP) FixPixelFormat(24, &lpddsd->ddpfPixelFormat);
if(dxw.dwFlags7 & INIT32BPP) FixPixelFormat(32, &lpddsd->ddpfPixelFormat);
OutTraceDW("GetDisplayMode: fix RGBBitCount=%d\n", lpddsd->ddpfPixelFormat.dwRGBBitCount);
}
}
//OutTraceDW("GetDisplayMode: returning WxH=(%dx%d) PixelFormat Flags=%x(%s) RGBBitCount=%d RGBAmask=(%x,%x,%x,%x) Caps=%x(%s)\n",
// lpddsd->dwWidth, lpddsd->dwHeight,
// lpddsd->ddpfPixelFormat.dwFlags, ExplainPixelFormatFlags(lpddsd->ddpfPixelFormat.dwFlags),
// lpddsd->ddpfPixelFormat.dwRGBBitCount,
// lpddsd->ddpfPixelFormat.dwRBitMask, lpddsd->ddpfPixelFormat.dwGBitMask, lpddsd->ddpfPixelFormat.dwBBitMask,
// lpddsd->ddpfPixelFormat.dwRGBAlphaBitMask,
// lpddsd->ddsCaps.dwCaps, ExplainDDSCaps(lpddsd->ddsCaps.dwCaps));
OutTraceDDRAW("GetDisplayMode: returning size=(%dx%d) %s\n", lpddsd->dwWidth, lpddsd->dwHeight, DumpPixelFormat((LPDDSURFACEDESC2)lpddsd));
return DD_OK;
}
HRESULT WINAPI extGetDisplayMode1(LPDIRECTDRAW lpdd, LPDDSURFACEDESC lpddsd)
{ return extGetDisplayMode(pGetDisplayMode1, lpdd, lpddsd); }
HRESULT WINAPI extGetDisplayMode2(LPDIRECTDRAW lpdd, LPDDSURFACEDESC lpddsd)
{ return extGetDisplayMode(pGetDisplayMode2, lpdd, lpddsd); }
HRESULT WINAPI extGetDisplayMode4(LPDIRECTDRAW lpdd, LPDDSURFACEDESC2 lpddsd)
{ return extGetDisplayMode((GetDisplayMode_Type)pGetDisplayMode4, lpdd, (LPDDSURFACEDESC)lpddsd); }
HRESULT WINAPI extGetDisplayMode7(LPDIRECTDRAW lpdd, LPDDSURFACEDESC2 lpddsd)
{ return extGetDisplayMode((GetDisplayMode_Type)pGetDisplayMode7, lpdd, (LPDDSURFACEDESC)lpddsd); }
HRESULT WINAPI extSetCooperativeLevel(int dxversion, SetCooperativeLevel_Type pSetCooperativeLevel, LPDIRECTDRAW lpdd, HWND hwnd, DWORD dwflags)
{
HRESULT res;
BOOL bFixFrame = FALSE;
OutTraceDDRAW("SetCooperativeLevel(D%d): lpdd=%x hwnd=%x dwFlags=%x(%s)\n",
dxversion, lpdd, hwnd, dwflags,ExplainCoopFlags(dwflags));
DDSURFACEDESC2 ddsd;
switch(dxversion){
default:
case 1: ddsd.dwSize=sizeof(DDSURFACEDESC); res=(*pGetDisplayMode1)(lpdd, (LPDDSURFACEDESC)&ddsd); break;
case 2: ddsd.dwSize=sizeof(DDSURFACEDESC); res=(*pGetDisplayMode2)(lpdd, (LPDDSURFACEDESC)&ddsd); break;
case 4: ddsd.dwSize=sizeof(DDSURFACEDESC2); res=(*pGetDisplayMode4)(lpdd, &ddsd); break;
case 7: ddsd.dwSize=sizeof(DDSURFACEDESC2); res=(*pGetDisplayMode7)(lpdd, &ddsd); break;
}
if(res){
OutTraceE("SetCooperativeLevel: GetDisplayMode ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return res;
}
OutTraceDW("InitDDScreenParameters: Actual size=(%dx%d)%s\n", ddsd.dwWidth, ddsd.dwHeight, DumpPixelFormat((LPDDSURFACEDESC2)&ddsd));
dxw.ActualPixelFormat=ddsd.ddpfPixelFormat;
if(dxw.VirtualPixelFormat.dwRGBBitCount==0) dxw.VirtualPixelFormat=ddsd.ddpfPixelFormat;
SetBltTransformations(dxversion);
if(dxw.Windowize){
if (dwflags & DDSCL_FULLSCREEN){
// v2.01.82 fix:
// WARN: Tomb Raider 4 demo is setting cooperative level against hwnd 0 (desktop)
// so in this case better use the registered hWnd value. Same as GP500, who uses
// the desktop window handle.
// v2.02.31 fix:
// Hooligans - Storm over Europe wants to set cooperative level NORMAL to hwnd 0
// that is legitimate, but setting against desktop window gives an error code - so
// the zero hwnd redirection had to be moved within the FULLSCREEN if case.
if(dxw.IsRealDesktop(hwnd)){
OutTraceDW("SetCooperativeLevel: desktop hwnd=%x -> %x\n", hwnd, dxw.GethWnd());
hwnd=dxw.GethWnd();
}
// v2.03.40 fix:
// WARN: "Reah" creates a main window undetected. Setting a FULLSCREEN cooperative level
// against it is a good enough proof that this is the real main window!
if(hwnd != dxw.GethWnd()){
OutTraceDW("SetCooperativeLevel: setting new main hwnd=%x -> %x\n", dxw.GethWnd(), hwnd);
dxw.SethWnd(hwnd);
}
dxw.SetFullScreen(TRUE);
// v2.03.41: added suppression of DDSCL_SETDEVICEWINDOW DDSCL_CREATEDEVICEWINDOW DDSCL_SETFOCUSWINDOW used by "PBA Bowling 2"
dwflags &= ~(DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWMODEX | DDSCL_SETDEVICEWINDOW | DDSCL_CREATEDEVICEWINDOW | DDSCL_SETFOCUSWINDOW);
dwflags |= DDSCL_NORMAL;
bFixFrame = TRUE;
}
else{
// v2.03.77: the game "Portugal 1111" calls SetCooperativeLevel with hwnd=0.
// in such a case, you can get the window size, so better leave the previous
// FullScreen setting unchanged. This is a wise politic also in case of any
// sort of GetClientRect error code.
if(hwnd){
RECT client;
BOOL ret;
ret=(*pGetClientRect)(hwnd, &client);
// v2.02.11:
// Non fullscreen cooperative mode means windowed, unless the window occupies the whole desktop area
if (ret) dxw.SetFullScreen(client.right==dxw.iSizX && client.bottom==dxw.iSizY);
}
}
}
res=(*pSetCooperativeLevel)(lpdd, hwnd, dwflags);
if(res){
if(res == DDERR_INVALIDPARAMS){
//hwnd = GetForegroundWindow();
PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
Sleep(1000);
res=(*pSetCooperativeLevel)(lpdd, hwnd, dwflags);
}
OutTraceE("SetCooperativeLevel: ERROR lpdd=%x hwnd=%x Flags=%x err=%x(%s) at %d\n",
lpdd, hwnd, dwflags, res, ExplainDDError(res), __LINE__);
}
if(bFixFrame){
AdjustWindowFrame(hwnd, dxw.GetScreenWidth(), dxw.GetScreenHeight());
if (dxw.dwFlags1 & FIXWINFRAME) dxw.FixWindowFrame(hwnd);
}
GetHookInfo()->IsFullScreen=dxw.IsFullScreen();
// WARN: GP500 was setting cooperative level against the desktop! This can be partially
// intercepted by hooking the GetDesktopWindow() call, but in windowed mode this can't be
// done, so better repeat the check here.
if ((res==DD_OK) && (hwnd!=NULL)){
if (hwnd==(*pGetDesktopWindow)()){
OutTraceE("SetCooperativeLevel: attempt to work on desktop window\n");
}
else
dxw.SethWnd(hwnd); // save the good one
}
return res;
}
HRESULT WINAPI extSetCooperativeLevel1(LPDIRECTDRAW lpdd, HWND hwnd, DWORD dwflags)
{ return extSetCooperativeLevel(1, pSetCooperativeLevel1, lpdd, hwnd, dwflags); }
HRESULT WINAPI extSetCooperativeLevel2(LPDIRECTDRAW lpdd, HWND hwnd, DWORD dwflags)
{ return extSetCooperativeLevel(2, pSetCooperativeLevel2, lpdd, hwnd, dwflags); }
HRESULT WINAPI extSetCooperativeLevel4(LPDIRECTDRAW lpdd, HWND hwnd, DWORD dwflags)
{ return extSetCooperativeLevel(4, pSetCooperativeLevel4, lpdd, hwnd, dwflags); }
HRESULT WINAPI extSetCooperativeLevel7(LPDIRECTDRAW lpdd, HWND hwnd, DWORD dwflags)
{ return extSetCooperativeLevel(7, pSetCooperativeLevel7, lpdd, hwnd, dwflags); }
static void FixSurfaceCaps(LPDDSURFACEDESC2 lpddsd, int dxversion)
{
// rules of thumb:
// 1) textures should be left untouched (switching to SYSTEMMEMORY when forcing HEL may even fail!)
// 1.1) textures with no DDSD_PIXELFORMAT specification should have one when virtual color depth is not equal to real color depth?
// 2) if a pixel format is specified, if DDSCAPS_SYSTEMMEMORY add DDSCAPS_OFFSCREENPLAY (if pixel formats are different?), otherwise do not touch anything.
// 3) if the surface is used as a buffer (DDSD_WIDTH set, DDSD_HEIGHT unset) do not touch anything.
// 4) zbuffer surfaces (DDSCAPS_ZBUFFER set) must have DDSCAPS_SYSTEMMEMORY
// 5) DDSCAPS_3DDEVICE surfaces should have a defined pixel format
// 6) in all remaining cases, adjust the pixel format and ensure you have DDSCAPS_SYSTEMMEMORY|DDSCAPS_OFFSCREENPLAIN
if(!(lpddsd->dwFlags & DDSD_CAPS)) lpddsd->ddsCaps.dwCaps = 0;
OutTraceDW("FixSurfaceCaps: Flags=%x(%s) Caps=%x(%s)\n",
lpddsd->dwFlags, ExplainFlags(lpddsd->dwFlags), lpddsd->ddsCaps.dwCaps, ExplainDDSCaps(lpddsd->ddsCaps.dwCaps));
// DDSCAPS_TEXTURE surfaces must be left untouched, unless you set FORCESHEL: in this case switch VIDEOMEMORY to SYSTEMMEMORY
if((lpddsd->dwFlags & DDSD_CAPS) && (lpddsd->ddsCaps.dwCaps & DDSCAPS_TEXTURE)){
if (dxw.dwFlags3 & FORCESHEL) {
lpddsd->ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
lpddsd->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
}
if((dxw.dwFlags5 & TEXTUREFORMAT) && !(lpddsd->dwFlags & DDSD_PIXELFORMAT)){
// TEXTURE: enforce PIXELFORMAT on MEMORY
lpddsd->dwFlags |= DDSD_PIXELFORMAT;
GetPixFmt(lpddsd);
}
return;
}
if((lpddsd->dwFlags & DDSD_CAPS) && (lpddsd->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)) { // z-buffer surface - set to memory
lpddsd->ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
return;
}
// this is valid just in case the above block eliminated TEXTURE surfaces....
if (lpddsd->dwFlags & DDSD_PIXELFORMAT){ // pixel format defined
if (lpddsd->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) lpddsd->ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN; // to allow for pixel format conversion (Quest for Glory 5 - GOG version)
return;
}
if ((lpddsd->dwFlags & (DDSD_WIDTH|DDSD_HEIGHT)) == DDSD_WIDTH) { // buffer surface
return;
}
// 3DDEVICE no TEXTURE: enforce PIXELFORMAT
// v2.02.90: added for "Zoo Tycoon" textures
// v2.03.48 - there are two situations
// "Arx fatalis" asks for DDSCAPS_3DDEVICE+DDSCAPS_OFFSCREENPLAIN capability and needs no DDSCAPS_SYSTEMMEMORY capability
// "Bunnies must die" asks for DDSCAPS_3DDEVICE+DDSCAPS_OFFSCREENPLAIN+DDSCAPS_VIDEOMEMORY capability and requires DDSCAPS_SYSTEMMEMORY capability
// we try to manage them by checking for the DDSCAPS_VIDEOMEMORY capability ...
if((lpddsd->dwFlags & DDSD_CAPS) && (lpddsd->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)){
lpddsd->dwFlags |= DDSD_PIXELFORMAT;
if(lpddsd->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
lpddsd->ddsCaps.dwCaps = (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_3DDEVICE|DDSCAPS_SYSTEMMEMORY); // good for "Bunnies must die", NO "Arx Fatalis"
else
lpddsd->ddsCaps.dwCaps = (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_3DDEVICE); // good for "Arx Fatalis", NO "Bunnies must die"
GetPixFmt(lpddsd);
return;
}
// default case: adjust pixel format
OutTraceB("FixSurfaceCaps: suppress DDSCAPS_VIDEOMEMORY case\n");
lpddsd->dwFlags |= (DDSD_CAPS|DDSD_PIXELFORMAT);
lpddsd->ddsCaps.dwCaps &= ~(DDSCAPS_VIDEOMEMORY|DDSCAPS_LOCALVIDMEM); // v2.02.43
lpddsd->ddsCaps.dwCaps |= (DDSCAPS_SYSTEMMEMORY|DDSCAPS_OFFSCREENPLAIN);
if(!(dxw.dwFlags3 & NOPIXELFORMAT)) GetPixFmt(lpddsd);
return;
}
static void ClearSurfaceDesc(void *ddsd, int dxversion)
{
int size;
size = (dxversion < 4) ? sizeof(DDSURFACEDESC) : sizeof(DDSURFACEDESC2);
memset(ddsd, 0, size); // Clean all
((LPDDSURFACEDESC)ddsd)->dwSize = size;
}
static void BuildRealSurfaces(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, int dxversion)
{
HRESULT res;
DDSURFACEDESC2 ddsd;
OutTraceDW("DEBUG: BuildRealSurfaces: lpdd=%x pCreateSurface=%x version=%d\n", lpdd, pCreateSurface, dxversion);
if(lpDDSEmu_Prim==NULL){
ClearSurfaceDesc((void *)&ddsd, dxversion);
ddsd.dwFlags = DDSD_CAPS;
// try DDSCAPS_SYSTEMMEMORY first, then suppress it if not supported
// no, DDSCAPS_SYSTEMMEMORY cause screen flickering while moving the window (and other troubles?)
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
OutTraceDW("CreateSurface: %s\n", LogSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[EmuPrim]", __LINE__));
res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSEmu_Prim, 0);
if(res==DDERR_PRIMARYSURFACEALREADYEXISTS){
OutTraceDW("CreateSurface: ASSERT DDSEmu_Prim already exists\n");
if(dxw.Windowize){
// in Windowize mode, the desktop properties are untouched, then the current primary surface can be recycled
res=(*pGetGDISurfaceMethod(dxversion))(lpdd, &lpDDSEmu_Prim);
}
else {
// in non-Windowized mode, the primary surface must be released and rebuilt with the proper properties
res=(*pGetGDISurfaceMethod(dxversion))(lpdd, &lpDDSEmu_Prim);
if (lpDDSEmu_Prim) while((*pReleaseSMethod(dxversion))(lpDDSEmu_Prim));
res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSEmu_Prim, 0);
}
}
if(res){
OutTraceE("CreateSurface: ERROR on DDSEmu_Prim res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd);
return;
}
OutTraceDW("CreateSurface: created new DDSEmu_Prim=%x\n",lpDDSEmu_Prim);
if(IsDebug) DescribeSurface(lpDDSEmu_Prim, dxversion, "DDSEmu_Prim", __LINE__);
InitDSScreenParameters(dxversion, lpDDSEmu_Prim);
dxwss.PopSurface(lpDDSEmu_Prim);
if (dxw.dwFlags3 & FORCECLIPPER){
OutTraceDW("CreateSurface: FORCE SetClipper on primary hwnd=%x lpdds=%x\n", dxw.GethWnd(), lpDDSEmu_Prim);
res=lpdd->CreateClipper(0, &lpddC, NULL);
if (res) OutTraceE("CreateSurface: CreateClipper ERROR res=%x(%s)\n", res, ExplainDDError(res));
res=lpddC->SetHWnd(0, dxw.GethWnd());
if (res) OutTraceE("CreateSurface: SetHWnd ERROR res=%x(%s)\n", res, ExplainDDError(res));
res=lpDDSEmu_Prim->SetClipper(lpddC);
if (res) OutTraceE("CreateSurface: SetClipper ERROR res=%x(%s)\n", res, ExplainDDError(res));
}
// can't hook lpDDSEmu_Prim as generic, since the Flip method is unimplemented for a PRIMARY surface!
// better avoid it or hook just useful methods.
//if (dxw.dwTFlags & OUTPROXYTRACE) HookDDSurfaceGeneric(&lpDDSEmu_Prim, dxw.dwDDVersion);
}
if(lpDDSEmu_Back==NULL){
ClearSurfaceDesc((void *)&ddsd, dxversion);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = dwBackBufferCaps;
ddsd.dwWidth = dxw.GetScreenWidth();
ddsd.dwHeight = dxw.GetScreenHeight();
if(dxw.dwFlags4 & BILINEAR2XFILTER){
// double backbuffer size
ddsd.dwWidth = dxw.GetScreenWidth() << 1;
ddsd.dwHeight = dxw.GetScreenHeight() << 1;
}
OutTraceDW("CreateSurface: %s\n", LogSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[EmuBack]", __LINE__));
res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSEmu_Back, 0);
if(res) {
ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
OutTraceDW("CreateSurface: %s\n", LogSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[EmuBack]", __LINE__));
res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSEmu_Back, 0);
}
if(res){
OutTraceE("CreateSurface: CreateSurface ERROR on DDSEmuBack : res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd);
return;
}
OutTraceDW("CreateSurface: created new DDSEmu_Back=%x\n", lpDDSEmu_Back);
if(IsDebug) DescribeSurface(lpDDSEmu_Back, dxversion, "DDSEmu_Back", __LINE__);
dxwss.PopSurface(lpDDSEmu_Back);
//if (dxw.dwTFlags & OUTPROXYTRACE) HookDDSurfaceGeneric(&lpDDSEmu_Back, dxversion);
}
}
void RestoreDDrawSurfaces()
{
// if it's a ddraw game ....
if(lpPrimaryDD){
OutTraceDW("RestoreDDrawSurfaces: rebuilding surfaces for dd session %x\n", lpPrimaryDD);
ReleaseS_Type pReleaseS;
CreateSurface_Type pCreateSurface;
switch(iBakBufferVersion){
case 1: pCreateSurface=(CreateSurface_Type)pCreateSurface1; pReleaseS=pReleaseS1; break;
case 2: pCreateSurface=(CreateSurface_Type)pCreateSurface2; pReleaseS=pReleaseS2; break;
case 3: pCreateSurface=(CreateSurface_Type)pCreateSurface3; pReleaseS=pReleaseS3; break;
case 4: pCreateSurface=(CreateSurface_Type)pCreateSurface4; pReleaseS=pReleaseS4; break;
case 7: pCreateSurface=(CreateSurface_Type)pCreateSurface7; pReleaseS=pReleaseS7; break;
}
if(lpDDSEmu_Back) while((*pReleaseS)(lpDDSEmu_Back)); lpDDSEmu_Back=0;
if(lpDDSEmu_Prim) while((*pReleaseS)(lpDDSEmu_Prim)); lpDDSEmu_Prim=0;
BuildRealSurfaces(lpPrimaryDD, pCreateSurface, iBakBufferVersion);
}
}
static HRESULT BuildPrimaryEmu(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
{
DDSURFACEDESC2 ddsd;
HRESULT res;
OutTraceDW("DEBUG: BuildPrimaryEmu: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
// emulated primary surface
memcpy((void *)&ddsd, lpddsd, lpddsd->dwSize);
// handle the surface attributes before the ddsd.dwFlags gets updated:
// if a surface desc is NOT specified, build one
if(!(ddsd.dwFlags & DDSD_PIXELFORMAT)) SetPixFmt((LPDDSURFACEDESC2)&ddsd);
// then save it
dxw.VirtualPixelFormat = ddsd.ddpfPixelFormat;
OutTraceDW("DDSD_PIXELFORMAT: color=%d flags=%x\n", dxw.VirtualPixelFormat.dwRGBBitCount, dxw.VirtualPixelFormat.dwFlags);
ddsd.dwFlags &= ~(DDSD_BACKBUFFERCOUNT|DDSD_REFRESHRATE);
ddsd.dwFlags |= (DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT);
ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX|DDSCAPS_VIDEOMEMORY|DDSCAPS_LOCALVIDMEM);
// DDSCAPS_OFFSCREENPLAIN seems required to support the palette in memory surfaces
ddsd.ddsCaps.dwCaps |= (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY);
// on WinXP Fifa 99 doesn't like DDSCAPS_SYSTEMMEMORY cap, so better to leave a way to unset it....
if(dxw.dwFlags6 & NOSYSMEMPRIMARY) ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
ddsd.dwWidth = dxw.GetScreenWidth();
ddsd.dwHeight = dxw.GetScreenHeight();
// create Primary surface
OutTraceDW("CreateSurface: %s\n", LogSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Primary]" , __LINE__));
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
if(res){
OutTraceE("CreateSurface: ERROR on DDSPrim res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd);
return res;
}
iBakBufferVersion=dxversion; // v2.03.01
OutTraceDW("CreateSurface: created PRIMARY DDSPrim=%x\n", *lplpdds);
if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSPrim", __LINE__);
HookDDSurface(lplpdds, dxversion, TRUE);
// "Hoyle Casino Empire" opens a primary surface and NOT a backbuffer ....
// build a default System palette and apply it to primary surface
if((ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) &&
(dxw.dwFlags6 & SYNCPALETTE)){
if(lpDDP == NULL){
res=(*pCreatePaletteMethod(dxversion))(lpdd, DDPCAPS_8BIT|DDPCAPS_ALLOW256, DefaultSystemPalette, &lpDDP, NULL);
if(res) OutTrace("CreateSurface: CreatePalette ERROR err=%x at %d\n", res, __LINE__);
}
// this must be done after hooking - who knows why?
res=(*pSetPaletteMethod(dxversion))(*lplpdds, lpDDP);
if(res) {
OutTraceE("CreateSurface: SetPalette ERROR err=%x at %d\n", res, __LINE__);
}
else iDDPExtraRefCounter++;
}
// set a global capability value for surfaces that have to blit to primary
// DDSCAPS_OFFSCREENPLAIN seems required to support the palette in memory surfaces
// DDSCAPS_SYSTEMMEMORY makes operations faster, but it is not always good...
dwBackBufferCaps = (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY);
// on WinXP Fifa 99 doesn't like DDSCAPS_SYSTEMMEMORY cap, so better to leave a way to unset it....
// this is important to avoid that certain D3D operations will abort - see "Forsaken" problem
if(dxw.dwFlags6 & NOSYSMEMBACKBUF) dwBackBufferCaps = DDSCAPS_OFFSCREENPLAIN;
if(dxw.dwFlags6 & SHAREDDC) bFlippedDC = TRUE;
if(dxw.dwFlags5 & GDIMODE) return DD_OK;
BuildRealSurfaces(lpdd, pCreateSurface, dxversion);
return DD_OK;
}
static HRESULT BuildPrimaryFlippable(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
{
DDSURFACEDESC2 ddsd;
HRESULT res;
OutTraceDW("DEBUG: BuildPrimaryFlippable: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
// emulated primary surface
memcpy((void *)&ddsd, lpddsd, lpddsd->dwSize);
// handle the surface attributes before the ddsd.dwFlags gets updated:
// if a surface desc is NOT specified, build one
if(!(ddsd.dwFlags & DDSD_PIXELFORMAT)) SetPixFmt((LPDDSURFACEDESC2)&ddsd);
// then save it
dxw.VirtualPixelFormat = ddsd.ddpfPixelFormat;
OutTraceDW("DDSD_PIXELFORMAT: color=%d flags=%x\n", dxw.VirtualPixelFormat.dwRGBBitCount, dxw.VirtualPixelFormat.dwFlags);
// dwFlags
ddsd.dwFlags &= ~(DDSD_REFRESHRATE);
ddsd.dwFlags |= (DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT|DDSD_BACKBUFFERCOUNT);
// dwBackBufferCount: set to at least 1
if(!(lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) || (lpddsd->dwBackBufferCount == 0)) ddsd.dwBackBufferCount = 1;
// dwCaps
ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY|DDSCAPS_LOCALVIDMEM|DDSCAPS_FRONTBUFFER);
ddsd.ddsCaps.dwCaps |= (DDSCAPS_COMPLEX|DDSCAPS_FLIP|DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY);
// on WinXP Fifa 99 doesn't like DDSCAPS_SYSTEMMEMORY cap, so better to leave a way to unset it....
if(dxw.dwFlags6 & NOSYSMEMPRIMARY) ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
// dwWidth & dwHeight
ddsd.dwWidth = dxw.GetScreenWidth();
ddsd.dwHeight = dxw.GetScreenHeight();
// create Primary surface
OutTraceDW("CreateSurface: %s\n", LogSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Primary]" , __LINE__));
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
if(res){
OutTraceE("CreateSurface: ERROR on DDSPrim res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd);
return res;
}
iBakBufferVersion=dxversion; // v2.03.01
OutTraceDW("CreateSurface: created PRIMARY DDSPrim=%x\n", *lplpdds);
if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSPrim", __LINE__);
HookDDSurface(lplpdds, dxversion, TRUE);
// "Hoyle Casino Empire" opens a primary surface and NOT a backbuffer ....
// build a default System palette and apply it to primary surface
if((ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) &&
(dxw.dwFlags6 & SYNCPALETTE)){
if(lpDDP == NULL){
res=(*pCreatePaletteMethod(dxversion))(lpdd, DDPCAPS_8BIT|DDPCAPS_ALLOW256, DefaultSystemPalette, &lpDDP, NULL);
if(res) OutTrace("CreateSurface: CreatePalette ERROR err=%x at %d\n", res, __LINE__);
}
// this must be done after hooking - who knows why?
res=(*pSetPaletteMethod(dxversion))(*lplpdds, lpDDP);
if(res) {
OutTraceE("CreateSurface: SetPalette ERROR err=%x at %d\n", res, __LINE__);
}
else iDDPExtraRefCounter++;
}
// set a global capability value for surfaces that have to blit to primary
dwBackBufferCaps = (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY);
// on WinXP Fifa 99 doesn't like DDSCAPS_SYSTEMMEMORY cap, so better to leave a way to unset it....
// this is important to avoid that certain D3D operations will abort - see "Forsaken" problem
if(dxw.dwFlags6 & NOSYSMEMBACKBUF) dwBackBufferCaps = DDSCAPS_OFFSCREENPLAIN;
if(dxw.dwFlags6 & SHAREDDC) bFlippedDC = TRUE;
if(dxw.dwFlags5 & GDIMODE) return DD_OK;
BuildRealSurfaces(lpdd, pCreateSurface, dxversion);
return DD_OK;
}
static HRESULT BuildPrimaryDir(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
{
DDSURFACEDESC2 ddsd;
HRESULT res;
OutTraceDW("DEBUG: BuildPrimaryDir: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
// genuine primary surface
memcpy((void *)&ddsd, lpddsd, lpddsd->dwSize);
ddsd.dwFlags &= ~(DDSD_WIDTH|DDSD_HEIGHT|DDSD_BACKBUFFERCOUNT|DDSD_REFRESHRATE|DDSD_PIXELFORMAT);
ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_FLIP|DDSCAPS_COMPLEX);
// v2.02.93: don't move primary / backbuf surfaces on systemmemory when 3DDEVICE is requested
// this impact also on capabilities for temporary surfaces for AERO optimized handling
if ((lpddsd->dwFlags & DDSD_CAPS) && (lpddsd->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)) ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
// create Primary surface
OutTraceDW("CreateSurface: %s\n", LogSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Primary]", __LINE__));
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
if(res){
if (res==DDERR_PRIMARYSURFACEALREADYEXISTS){
LPDIRECTDRAWSURFACE lpPrim;
GetGDISurface_Type pGetGDISurface;
switch(dxversion){
default:
case 1: pGetGDISurface = pGetGDISurface1; break;
case 2: pGetGDISurface = pGetGDISurface2; break;
case 4: pGetGDISurface = pGetGDISurface4; break;
case 7: pGetGDISurface = pGetGDISurface7; break;
}
OutTraceE("CreateSurface: CreateSurface DDERR_PRIMARYSURFACEALREADYEXISTS workaround\n");
(*pGetGDISurface)(lpPrimaryDD, &lpPrim);
while ((*pReleaseSMethod(dxversion))(lpPrim));
res = (*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
}
/* fall through */
if(res){
OutTraceE("CreateSurface: ERROR on DDSPrim res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd);
return res;
}
}
OutTraceDW("CreateSurface: created PRIMARY DDSPrim=%x\n", *lplpdds);
if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSPrim", __LINE__);
if(dxw.dwFlags1 & EMULATEBUFFER){
lpDDSEmu_Prim = *lplpdds;
dxwss.PopSurface(lpDDSEmu_Prim);
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
// warning: can't create zero sized backbuffer surface !!!!
ddsd.dwWidth = dxw.GetScreenWidth();
ddsd.dwHeight = dxw.GetScreenHeight();
ddsd.ddsCaps.dwCaps = 0;
if (dxversion >= 4) ddsd.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
OutTraceDW("CreateSurface: %s\n", LogSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Dir FixBuf]", __LINE__));
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
if(res){
OutTraceE("CreateSurface: ERROR on DDSPrim res=%x(%s) at %d\n",res, ExplainDDError(res), __LINE__);
return res;
}
OutTraceDW("CreateSurface: created FIX DDSPrim=%x\n", *lplpdds);
if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSPrim(2)", __LINE__);
}
iBakBufferVersion=dxversion; // v2.03.37
HookDDSurface(lplpdds, dxversion, TRUE);
if(dxw.dwFlags1 & CLIPCURSOR) dxw.SetClipCursor();
return DD_OK;
}
static HRESULT BuildBackBufferEmu(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
{
DDSURFACEDESC2 ddsd;
HRESULT res;
OutTraceDW("DEBUG: BuildBackBufferEmu: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
// create BackBuffer surface
memcpy(&ddsd, lpddsd, lpddsd->dwSize);
ddsd.dwFlags &= ~(DDSD_BACKBUFFERCOUNT|DDSD_REFRESHRATE);
ddsd.dwFlags |= (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT);
ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_BACKBUFFER|DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX|DDSCAPS_VIDEOMEMORY|DDSCAPS_LOCALVIDMEM);
// v2.03.75: if a surface desc is NOT specified, build one. This will allow ZBUF attach.
if(!(lpddsd->dwFlags & DDSD_PIXELFORMAT)) SetPixFmt((LPDDSURFACEDESC2)&ddsd);
// DDSCAPS_OFFSCREENPLAIN seems required to support the palette in memory surfaces
ddsd.ddsCaps.dwCaps |= (DDSCAPS_SYSTEMMEMORY|DDSCAPS_OFFSCREENPLAIN);
if(ddsd.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY; // necessary: Martian Gotic crashes otherwise
// on WinXP Fifa 99 doesn't like DDSCAPS_SYSTEMMEMORY cap, so better to leave a way to unset it....
if(dxw.dwFlags6 & NOSYSMEMBACKBUF) ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
ddsd.dwWidth = dxw.GetScreenWidth();
ddsd.dwHeight = dxw.GetScreenHeight();
GetPixFmt(&ddsd);
OutTraceDW("CreateSurface: %s\n", LogSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Backbuf]", __LINE__));
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
if(res) {
OutTraceE("CreateSurface ERROR: res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd);
return res;
}
OutTraceDW("CreateSurface: created BACK DDSBack=%x\n", *lplpdds);
if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSBack", __LINE__);
HookDDSurface(lplpdds, dxversion, FALSE); // added !!!
iBakBufferVersion=dxversion; // v2.02.31
if((ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) &&
(dxw.dwFlags6 & SYNCPALETTE)){
if(lpDDP == NULL){
res=(*pCreatePaletteMethod(dxversion))(lpdd, DDPCAPS_8BIT|DDPCAPS_ALLOW256, DefaultSystemPalette, &lpDDP, NULL);
if(res) OutTrace("CreateSurface: CreatePalette ERROR err=%x at %d\n", res, __LINE__);
}
// this must be done after hooking - who knows why?
res=(*pSetPaletteMethod(dxversion))(*lplpdds, lpDDP);
if(res) {
OutTraceE("CreateSurface: SetPalette ERROR err=%x at %d\n", res, __LINE__);
}
else iDDPExtraRefCounter++;
}
// V2.1.85/V2.2.34: tricky !!!!
// When a real backbuffer is created, it has a reference to its frontbuffer.
// some games (Monopoly 3D) may depend on this setting - i.e. they could close
// the exceeding references - so this is better be replicated adding an initial
// reference to the zero count. But you don't have to do this if the backbuffer
// is created independently by the primary surface.
(*lplpdds)->AddRef(); // should it be repeated BBCount times????
return DD_OK;
}
static HRESULT BuildBackBufferFlippable(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
{
DDSURFACEDESC2 ddsd;
HRESULT res;
OutTraceDW("DEBUG: BuildBackBufferFlippable: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
//MessageBox(NULL, "BuildBackBufferFlippable", "DxWnd", MB_OK);
// create BackBuffer surface
memcpy(&ddsd, lpddsd, lpddsd->dwSize);
ddsd.dwFlags &= ~(DDSD_BACKBUFFERCOUNT|DDSD_REFRESHRATE);
ddsd.dwFlags |= (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT);
ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_PRIMARYSURFACE|DDSCAPS_FRONTBUFFER|DDSCAPS_BACKBUFFER|DDSCAPS_VIDEOMEMORY|DDSCAPS_LOCALVIDMEM);
ddsd.ddsCaps.dwCaps |= (DDSCAPS_SYSTEMMEMORY|DDSCAPS_OFFSCREENPLAIN);
ddsd.dwWidth = dxw.GetScreenWidth();
ddsd.dwHeight = dxw.GetScreenHeight();
GetPixFmt(&ddsd);
OutTraceDW("CreateSurface: %s\n", LogSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Backbuf]", __LINE__));
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
if(res) {
OutTraceE("CreateSurface ERROR: res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd);
return res;
}
OutTraceDW("CreateSurface: created BACK DDSBack=%x\n", *lplpdds);
if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSBack", __LINE__);
HookDDSurface(lplpdds, dxversion, FALSE); // added !!!
iBakBufferVersion=dxversion; // v2.02.31
if((ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) &&
(dxw.dwFlags6 & SYNCPALETTE)){
if(lpDDP == NULL){
res=(*pCreatePaletteMethod(dxversion))(lpdd, DDPCAPS_8BIT|DDPCAPS_ALLOW256, DefaultSystemPalette, &lpDDP, NULL);
if(res) OutTrace("CreateSurface: CreatePalette ERROR err=%x at %d\n", res, __LINE__);
}
// this must be done after hooking - who knows why?
res=(*pSetPaletteMethod(dxversion))(*lplpdds, lpDDP);
if(res) {
OutTraceE("CreateSurface: SetPalette ERROR err=%x at %d\n", res, __LINE__);
}
else iDDPExtraRefCounter++;
}
return DD_OK;
}
static HRESULT AttachBackBufferFlippable(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
{
HRESULT res;
LPDIRECTDRAWSURFACE lpDDSPrim;
OutTraceDW("DEBUG: AttachBackBufferFlippable: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
// retrieve the attached backbuffer surface and hook it
if(lpddsd->dwBackBufferCount == 0) return DD_OK; // nothing to retrieve
GetAttachedSurface_Type pGetAttachedSurface;
DDSCAPS2 caps;
switch(dxversion){
case 1: pGetAttachedSurface = pGetAttachedSurface1; break;
case 2: pGetAttachedSurface = pGetAttachedSurface2; break;
case 3: pGetAttachedSurface = pGetAttachedSurface3; break;
case 4: pGetAttachedSurface = pGetAttachedSurface4; break;
case 7: pGetAttachedSurface = pGetAttachedSurface7; break;
}
memset(&caps, 0, sizeof(caps));
caps.dwCaps = DDSCAPS_BACKBUFFER;
lpDDSPrim = dxwss.GetPrimarySurface();
res = (*pGetAttachedSurface)(lpDDSPrim, (LPDDSCAPS)&caps, lplpdds);
if(res){
OutTraceE("CreateSurface: GetAttachedSurface ERROR on DDSPrim res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return res;
}
OutTraceDW("CreateSurface: retrieved BACK DDSBack=%x\n", *lplpdds);
if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSBack", __LINE__);
HookDDSurface(lplpdds, dxversion, FALSE); // added !!!
iBakBufferVersion=dxversion; // v2.02.31
return DD_OK;
}
static HRESULT BuildBackBufferDir(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
{
DDSURFACEDESC2 ddsd;
HRESULT res;
OutTraceDW("DEBUG: BuildBackBufferDir: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
// create BackBuffer surface
// ClearSurfaceDesc((void *)&ddsd, dxversion);
memcpy(&ddsd, lpddsd, lpddsd->dwSize);
ddsd.dwFlags &= ~(DDSD_WIDTH|DDSD_HEIGHT|DDSD_BACKBUFFERCOUNT|DDSD_REFRESHRATE|DDSD_PIXELFORMAT);
ddsd.dwFlags |= (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH);
ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX);
// v2.02.93: don't move primary / backbuf surfaces on systemmemory when 3DDEVICE is requested
if(lpddsd->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) {
ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
}
else {
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
if (dxversion >= 4) ddsd.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_VIDEOMEMORY|DDSCAPS_LOCALVIDMEM);
}
if(dxw.dwFlags6 & NOSYSMEMBACKBUF) ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
ddsd.dwWidth = dxw.GetScreenWidth();
ddsd.dwHeight = dxw.GetScreenHeight();
if (dxw.dwFlags2 & BACKBUFATTACH) {
LPDIRECTDRAWSURFACE lpPrim;
DDSURFACEDESC2 prim;
GetGDISurface_Type pGetGDISurface;
switch(dxversion){
default:
case 1: pGetGDISurface = pGetGDISurface1; break;
case 2: pGetGDISurface = pGetGDISurface2; break;
case 4: pGetGDISurface = pGetGDISurface4; break;
case 7: pGetGDISurface = pGetGDISurface7; break;
}
(*pGetGDISurface)(lpPrimaryDD, &lpPrim);
memset(&prim, 0, sizeof(DDSURFACEDESC2));
prim.dwSize = (dxversion >= 4) ? sizeof(DDSURFACEDESC2) : sizeof(DDSURFACEDESC);
res=lpPrim->GetSurfaceDesc((DDSURFACEDESC *)&prim);
(*pReleaseSMethod(dxversion))(lpPrim);
ddsd.dwWidth = prim.dwWidth;
ddsd.dwHeight = prim.dwHeight;
OutTraceDW("BMX FIX: res=%x(%s) wxh=(%dx%d)\n", res, ExplainDDError(res),ddsd.dwWidth, ddsd.dwHeight);
}
OutTraceDW("CreateSurface: %s\n", LogSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Backbuf]", __LINE__));
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
if(res) {
if ((dxw.dwFlags1 & SWITCHVIDEOMEMORY) && (res==DDERR_OUTOFVIDEOMEMORY)){
OutTraceDW("CreateSurface: CreateSurface DDERR_OUTOFVIDEOMEMORY ERROR at %d, retry in SYSTEMMEMORY\n", __LINE__);
ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
}
if(res){
OutTraceE("CreateSurface ERROR: res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return res;
}
}
OutTraceDW("CreateSurface: created BACK DDSBack=%x\n", *lplpdds);
if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSBack", __LINE__);
HookDDSurface(lplpdds, dxversion, FALSE); // added !!!
iBakBufferVersion=dxversion; // v2.02.31
return DD_OK;
}
static HRESULT BuildGenericEmu(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
{
DDSURFACEDESC2 ddsd;
HRESULT res;
OutTraceDW("DEBUG: BuildGenericEmu: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
memcpy(&ddsd, lpddsd, lpddsd->dwSize); // Copy over ....
FixSurfaceCaps(&ddsd, dxversion);
// It looks that DDSCAPS_SYSTEMMEMORY surfaces can perfectly be DDSCAPS_3DDEVICE as well.
// For "Risk II" it is necessary that both the primary surface and the offscreen surfaces are generated
// with the same type, so that assuming an identical lPitch and memcopy-ing from one buffer to the
// other is a legitimate operation.
if(dxw.dwFlags6 & POWER2WIDTH){ // v2.03.28: POWER2WIDTH to fix "Midtown Madness" in surface emulation mode
if(((ddsd.dwFlags & (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH)) == (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH)) &&
(ddsd.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN)
){
DWORD dwWidth;
dwWidth = ((ddsd.dwWidth + 3) >> 2) << 2;
if(dwWidth != ddsd.dwWidth) OutTraceDW("CreateSurface: fixed surface width %d->%d\n", ddsd.dwWidth, dwWidth);
ddsd.dwWidth = dwWidth;
}
}
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, pu);
if ((dxw.dwFlags1 & SWITCHVIDEOMEMORY) && (res!=DD_OK)){
OutTraceDW("CreateSurface ERROR: res=%x(%s) at %d, retry\n", res, ExplainDDError(res), __LINE__);
ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, pu);
}
if (res) {
OutTraceE("CreateSurface: ERROR on Emu_Generic res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return res;
}
OutTraceDW("CreateSurface: CREATED lpddsd=%x version=%d %s\n",
*lplpdds, dxversion, LogSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Emu Generic]", __LINE__));
// v2.02.66: if 8BPP paletized surface and a primary palette exixts, apply.
// fixes "Virtua Fighter PC" palette bug
if(lpDDP && (ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)){
res=(*pSetPaletteMethod(dxversion))(*lplpdds, lpDDP);
if(res)
OutTraceE("SetPalette: ERROR on lpdds=%x(Emu_Generic) res=%x(%s) at %d\n", *lplpdds, res, ExplainDDError(res), __LINE__);
else {
OutTraceDW("CreateSurface: applied lpddp=%x to lpdds=%x\n", lpDDP, *lplpdds);
iDDPExtraRefCounter++;
}
}
// diagnostic hooks ....
HookDDSurface(lplpdds, dxversion, FALSE);
return DD_OK;
}
static HRESULT BuildGenericFlippable(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
{
DDSURFACEDESC2 ddsd;
HRESULT res;
OutTraceDW("DEBUG: BuildGenericFlippable: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
memcpy(&ddsd, lpddsd, lpddsd->dwSize); // Copy over ....
FixSurfaceCaps(&ddsd, dxversion);
if(dxw.dwFlags6 & POWER2WIDTH){ // v2.03.28: POWER2WIDTH to fix "Midtown Madness" in surface emulation mode
if(((ddsd.dwFlags & (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH)) == (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH)) &&
(ddsd.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN)
){
DWORD dwWidth;
dwWidth = ((ddsd.dwWidth + 3) >> 2) << 2;
if(dwWidth != ddsd.dwWidth) OutTraceDW("CreateSurface: fixed surface width %d->%d\n", ddsd.dwWidth, dwWidth);
ddsd.dwWidth = dwWidth;
}
}
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, pu);
if ((dxw.dwFlags1 & SWITCHVIDEOMEMORY) && (res!=DD_OK)){
OutTraceDW("CreateSurface ERROR: res=%x(%s) at %d, retry\n", res, ExplainDDError(res), __LINE__);
ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, pu);
}
if (res) {
OutTraceE("CreateSurface: ERROR on Emu_Generic res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return res;
}
OutTraceDW("CreateSurface: CREATED lpddsd=%x version=%d %s\n",
*lplpdds, dxversion, LogSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Emu Generic]", __LINE__));
// v2.02.66: if 8BPP paletized surface and a primary palette exixts, apply.
// fixes "Virtua Fighter PC" palette bug
if(lpDDP && (ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)){
res=(*pSetPaletteMethod(dxversion))(*lplpdds, lpDDP);
if(res)
OutTraceE("SetPalette: ERROR on lpdds=%x(Emu_Generic) res=%x(%s) at %d\n", *lplpdds, res, ExplainDDError(res), __LINE__);
else {
OutTraceDW("CreateSurface: applied lpddp=%x to lpdds=%x\n", lpDDP, *lplpdds);
iDDPExtraRefCounter++;
}
}
// diagnostic hooks ....
HookDDSurface(lplpdds, dxversion, FALSE);
return DD_OK;
}
static HRESULT BuildGenericDir(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
{
HRESULT res;
OutTraceDW("DEBUG: BuildGenericDir: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
OutTraceDW("CreateSurface: %s\n", LogSurfaceAttributes((LPDDSURFACEDESC)lpddsd, "[Dir Generic]", __LINE__));
res = (*pCreateSurface)(lpdd, lpddsd, lplpdds, 0);
if(res){
// v2.02.60: Ref. game Incoming GOG release, post by Marek, error DDERR_UNSUPPORTED while trying to create ZBUFFER surface
if ((dxw.dwFlags1 & SWITCHVIDEOMEMORY) && ((res==DDERR_OUTOFVIDEOMEMORY)||(res==DDERR_UNSUPPORTED))){
OutTraceDW("CreateSurface ERROR: res=%x(%s) at %d, retry\n", res, ExplainDDError(res), __LINE__);
lpddsd->ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
lpddsd->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
res = (*pCreateSurface)(lpdd, lpddsd, lplpdds, 0);
}
if(res){
OutTraceE("CreateSurface: CreateSurface ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return res;
}
}
OutTraceDW("CreateSurface: CREATED lpddsd=%x version=%d %s\n",
*lplpdds, dxversion, LogSurfaceAttributes((LPDDSURFACEDESC)lpddsd, "[Dir Generic]", __LINE__));
// hooks ....
HookDDSurface(lplpdds, dxversion, FALSE);
return DD_OK;
}
static HRESULT WINAPI extCreateSurface(int dxversion, CreateSurface_Type pCreateSurface, LPDIRECTDRAW lpdd, DDSURFACEDESC2 *lpddsd,
LPDIRECTDRAWSURFACE *lplpdds, void *pu)
{
HRESULT res;
DDSURFACEDESC2 ddsd;
LPDIRECTDRAWSURFACE lpDDSPrim;
LPDIRECTDRAWSURFACE lpDDSBack = NULL;
DWORD CurFlags;
int TargetSize;
typedef HRESULT (*BuildSurface_Type)(LPDIRECTDRAW, CreateSurface_Type, LPDDSURFACEDESC2, int, LPDIRECTDRAWSURFACE *, void *);
BuildSurface_Type BuildPrimary;
BuildSurface_Type BuildBackBuffer;
BuildSurface_Type AttachBackBuffer;
BuildSurface_Type BuildGeneric;
enum {
PRIMARY_DIRECT = 0,
PRIMARY_FLIPPABLE,
PRIMARY_EMULATED
} SurfaceMode;
OutTraceDDRAW("CreateSurface: Version=%d lpdd=%x %s\n",
dxversion, lpdd, LogSurfaceAttributes((LPDDSURFACEDESC)lpddsd, "[CreateSurface]", __LINE__));
lpddsd->ddpfPixelFormat.dwFourCC = 0;
SurfaceMode = (dxw.dwFlags1 & EMULATESURFACE) ? ((dxw.dwFlags6 & FLIPEMULATION) ? PRIMARY_EMULATED : PRIMARY_FLIPPABLE) : PRIMARY_DIRECT;
switch(SurfaceMode) {
case PRIMARY_DIRECT:
BuildPrimary = BuildPrimaryDir;
BuildBackBuffer = BuildBackBufferDir;
AttachBackBuffer = BuildBackBufferDir;
BuildGeneric = BuildGenericDir;
break;
case PRIMARY_FLIPPABLE:
BuildPrimary = BuildPrimaryFlippable;
BuildBackBuffer = BuildBackBufferFlippable;
AttachBackBuffer = AttachBackBufferFlippable;
BuildGeneric = BuildGenericFlippable;
//BuildGeneric = BuildGenericEmu;
break;
case PRIMARY_EMULATED:
BuildPrimary = BuildPrimaryEmu;
BuildBackBuffer = BuildBackBufferEmu;
AttachBackBuffer = BuildBackBufferEmu;
BuildGeneric = BuildGenericEmu;
break;
}
// check for lpddsd->dwSize value
TargetSize=(dxversion<4)?sizeof(DDSURFACEDESC):sizeof(DDSURFACEDESC2);
if(lpddsd->dwSize != TargetSize){
char sMsg[81];
sprintf_s(sMsg,80, "CreateSurface: ASSERT bad dwSize=%d dxversion=%d\n",
lpddsd->dwSize, dxversion);
OutTraceDW(sMsg);
if(IsAssertEnabled) MessageBox(0, sMsg, "CreateSurface", MB_OK | MB_ICONEXCLAMATION);
return DDERR_INVALIDPARAMS;
}
//GHO workaround (needed for WarWind, Rogue Spear):
if (lpddsd->dwFlags && !(lpddsd->dwFlags & 0x1)){
OutTraceDW("CreateSurface: fixing illegal dwFlags value: %x -> %x\n",
lpddsd->dwFlags, (lpddsd->dwFlags | DDSD_CAPS));
lpddsd->dwFlags |= DDSD_CAPS;
}
memcpy(&ddsd, lpddsd, lpddsd->dwSize); // Copy
// v2.02.38: this is odd: in "Star Force Deluxe" there is no PRIMARY surface, but a surface with
// 0 flags and 0 capabilities serves for this purpose. Is it a side-effect of old ddraw releases?
if((dxversion == 1) && ((ddsd.dwFlags & ~DDSD_BACKBUFFERCOUNT) == 0)){ // Star Force Deluxe
ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
//if(dxw.VirtualPixelFormat.dwRGBBitCount == 8) ddsd.ddsCaps.dwCaps |= DDSCAPS_PALETTE;
}
// creation of the primary surface....
if(ddsd.dwFlags & DDSD_CAPS && ddsd.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE){
dxwss.ClearSurfaceList(); // v2.03.83: "Daytona USA" would saturate the list otherwise
SetVSyncDelays(dxversion, lpdd);
GetHookInfo()->Height=(short)dxw.GetScreenHeight();
GetHookInfo()->Width=(short)dxw.GetScreenWidth();
GetHookInfo()->ColorDepth=(short)dxw.VirtualPixelFormat.dwRGBBitCount;
GetHookInfo()->DXVersion=dxversion;
lpPrimaryDD = lpdd; // v2.1.87
memcpy(&DDSD_Prim, lpddsd, sizeof(DDSD_Prim)); // v2.02.37
// beware of the different behaviour between older and newer directdraw releases...
if(dxversion >= 4){
if (lpDDSEmu_Back) while(lpDDSEmu_Back->Release());
if (lpDDSEmu_Prim) while(lpDDSEmu_Prim->Release());
if (ddsd.dwFlags & DDSD_BACKBUFFERCOUNT) { // Praetorians !!!!
lpDDSBack = dxwss.GetBackBufferSurface();
if (lpDDSBack) {
if(dxw.dwFlags6 & FLIPEMULATION) while(lpDDSBack->Release());
dxwss.PopSurface(lpDDSBack);
lpDDSBack = NULL;
}
}
}
lpDDSEmu_Back=NULL;
lpDDSEmu_Prim=NULL;
int BBCount=0; // or 1 ??
if (ddsd.dwFlags & DDSD_BACKBUFFERCOUNT) BBCount=ddsd.dwBackBufferCount;
if ((BBCount > 0) && (iBakBufferVersion < 4)){
lpDDSBack=NULL;
OutTraceDW("CreateSurface: backbuffer cleared - BackBufferCount=%d\n", BBCount);
}
if (BBCount > MAXBACKBUFFERS){
char sMsg[81];
sprintf_s(sMsg, 80, "CreateSurface: BackBufferCount=%d\n", BBCount);
OutTraceDW(sMsg);
if (IsAssertEnabled) MessageBox(0, sMsg, "CreateSurface", MB_OK | MB_ICONEXCLAMATION);
// recover ...
BBCount = MAXBACKBUFFERS;
}
// build emulated primary surface, real primary and backbuffer surfaces
CurFlags=ddsd.dwFlags;
res=BuildPrimary(lpdd, pCreateSurface, lpddsd, dxversion, lplpdds, NULL);
if(res) return res;
lpDDSPrim = *lplpdds;
dxwss.PushPrimarySurface(lpDDSPrim, dxversion);
RegisterPixelFormat(dxversion, lpDDSPrim);
if (BBCount){
// build emulated backbuffer surface
res=AttachBackBuffer(lpdd, pCreateSurface, lpddsd, dxversion, &lpDDSBack, NULL);
if(res) return res;
dxwss.PushBackBufferSurface(lpDDSBack, dxversion);
}
if(IsTraceDDRAW){
char sInfo[256+1];
sprintf(sInfo, "CreateSurface: created DDSPrim=%x DDSBack=%x", lpDDSPrim, lpDDSBack);
if(dxw.dwFlags1 & (EMULATESURFACE|EMULATEBUFFER)) sprintf(sInfo, "%s DDSEmu_Prim=%x", sInfo, lpDDSEmu_Prim);
if(dxw.dwFlags1 & EMULATESURFACE) sprintf(sInfo, "%s DDSEmu_Back=%x", sInfo, lpDDSEmu_Back);
strcat(sInfo, "\n");
OutTrace(sInfo);
}
// rebuild the clipper area
if(dxw.dwFlags1 & CLIPCURSOR) dxw.SetClipCursor();
// v2.2.64: added extra ref needed to preserve ddraw session for later use. Is it a ddraw1 legacy?
// seems to fix problems in "Warhammer 40K Rites Of War" that uses a ddraw session after reaching 0 refcount.
// v2.2.84: avoid the extra referenced in non windowed mode since it causes the window shift reported by gsky916
// for Wind Fantasy SP.
// v2.3.59: same extra reference is needed by "Wahammer Chaos Gate" that uses ddraw interface release 2
// v2.3.72: fixed previous fix: condition is <=2, not >=2 !
// Be aware that it may perhaps become <=3, if we get the same problem elsewhere
if((dxw.dwDDVersion<=2) && dxw.Windowize) lpdd->AddRef();
return DD_OK;
}
// a request for a separate (not complex) backbuffer to attach later on, maybe.
if ((ddsd.dwFlags & DDSD_CAPS) && (ddsd.ddsCaps.dwCaps & DDSCAPS_BACKBUFFER)){
if (lpDDSBack) {
OutTraceDW("CreateSurface: returning current DDSBack=%x\n", lpDDSBack);
*lplpdds = lpDDSBack;
return DD_OK;
}
res=BuildBackBuffer(lpdd, pCreateSurface, lpddsd, dxversion, lplpdds, NULL);
if(res == DD_OK) {
dxwss.PushBackBufferSurface(*lplpdds, dxversion);
dxwcdb.PushCaps(*lplpdds, lpddsd->ddsCaps.dwCaps);
}
return res;
}
// if nothing else, it's a generic/zbuffer surface
res=BuildGeneric(lpdd, pCreateSurface, lpddsd, dxversion, lplpdds, pu);
if(!res) {
dxwss.PopSurface(*lplpdds);
if(lpddsd->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) {
// v2.03.82: save ZBUFFER capabilities for later fix in D3D CreateDevice
if(lpddsd->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) dxwcdb.PushCaps(*lplpdds, lpddsd->ddsCaps.dwCaps);
OutTraceDW("CreateSurface: lpDDZBuffer=%x save ZBUFFER caps=%x(%s)\n", *lplpdds, lpddsd->ddsCaps.dwCaps, ExplainDDSCaps(lpddsd->ddsCaps.dwCaps));
}
}
return res;
}
HRESULT WINAPI extCreateSurface1(LPDIRECTDRAW lpdd, DDSURFACEDESC *lpddsd, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
{ return extCreateSurface(1, (CreateSurface_Type)pCreateSurface1, lpdd, (DDSURFACEDESC2 *)lpddsd, lplpdds, pu); }
HRESULT WINAPI extCreateSurface2(LPDIRECTDRAW lpdd, DDSURFACEDESC *lpddsd, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
{ return extCreateSurface(2, (CreateSurface_Type)pCreateSurface2, lpdd, (DDSURFACEDESC2 *)lpddsd, lplpdds, pu); }
HRESULT WINAPI extCreateSurface4(LPDIRECTDRAW lpdd, DDSURFACEDESC2 *lpddsd, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
{ return extCreateSurface(4, (CreateSurface_Type)pCreateSurface4, lpdd, (DDSURFACEDESC2 *)lpddsd, lplpdds, pu); }
HRESULT WINAPI extCreateSurface7(LPDIRECTDRAW lpdd, DDSURFACEDESC2 *lpddsd, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
{ return extCreateSurface(7, (CreateSurface_Type)pCreateSurface7, lpdd, (DDSURFACEDESC2 *)lpddsd, lplpdds, pu); }
HRESULT WINAPI extGetAttachedSurface(int dxversion, GetAttachedSurface_Type pGetAttachedSurface,
LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS lpddsc, LPDIRECTDRAWSURFACE *lplpddas)
{
HRESULT res;
BOOL IsPrim;
BOOL IsBack;
IsPrim=dxwss.IsAPrimarySurface(lpdds);
IsBack=dxwss.IsABackBufferSurface(lpdds);
OutTraceDDRAW("GetAttachedSurface(%d): lpdds=%x%s caps=%x(%s)\n",
dxversion, lpdds, (IsPrim?"(PRIM)":(IsBack ? "(BACK)":"")), lpddsc->dwCaps, ExplainDDSCaps(lpddsc->dwCaps));
if(dxw.dwFlags1 & EMULATESURFACE){
// v2.1.81: fix to make "Silver" working: if the primary surface was created with
// backbuffercount == 2, the game expects some more surface to be attached to
// the attached backbuffer. Since there would be no use for it, just return
// the attached backbuffer itself. Makes Silver working, anyway....
// beware: "Snowboard Racer" fails if you return an attached surface anyhow! There,
// the primary surface was created with back buffer count == 1.
// v2.2.62 fix: a check to implement doublebuffer emulation only in case of DDSCAPS_BACKBUFFER
// requests. A call to GetAttachedSurface can be made to retrieve DDSCAPS_ZBUFFER surfaces, and in
// this case the BackBuffer surface can't be returned.
// v2.03.56.fix1: the double buffer trick for Silver works in generic EMULATESURFACE mode, but the
// surface is requested also as a DDSCAPS_VIDEOMEMORY one.
if (IsBack && (DDSD_Prim.dwBackBufferCount > 1) && (lpddsc->dwCaps & (DDSCAPS_BACKBUFFER|DDSCAPS_VIDEOMEMORY))){
*lplpddas = lpdds;
OutTraceDW("GetAttachedSurface(%d): DOUBLEBUFFER attached to BACK=%x\n", dxversion, lpdds);
return DD_OK;
}
// on primary surface return the backbuffer surface coming from either an explicit
// AddAttachedSurface, or a primary complex surface creation otherwise....
if(IsPrim && (lpddsc->dwCaps & (DDSCAPS_BACKBUFFER|DDSCAPS_FLIP))) { // v2.02.42 added DDSCAPS_FLIP for Empire Earth
// in "Tomb Raider III" GOG release, the primary surface is queryed and has no attached
// backbuffer, but a backbuffer does exist and has to be retrieved by GetBackBufferSurface.
LPDIRECTDRAWSURFACE lpddsback = dxwss.GetBackBufferSurface();
if (lpddsback) {
*lplpddas = lpddsback;
OutTraceDW("GetAttachedSurface(%d): BACKBUFFER attached=%x\n", dxversion, *lplpddas);
return DD_OK;
}
else {
*lplpddas = NULL;
OutTraceDW("GetAttachedSurface(%d): no attached BACKBUFFER\n", dxversion);
return DDERR_NOTFOUND;
}
}
}
else {
// Virtual primary surfaces are created with no DDSCAPS_3DDEVICE caps, so don't look for it ....
if(IsPrim && (lpddsc->dwCaps & (DDSCAPS_BACKBUFFER|DDSCAPS_FLIP)))
lpddsc->dwCaps &= ~DDSCAPS_3DDEVICE;
}
// proxy the call...
res=(*pGetAttachedSurface)(lpdds, lpddsc, lplpddas);
if(res) {
// if possible, simulate a backbuffer attached to primary surface
if (IsPrim && (DDSD_Prim.dwBackBufferCount > 0) && (lpddsc->dwCaps & (DDSCAPS_BACKBUFFER|DDSCAPS_FLIP))){
LPDIRECTDRAWSURFACE lpBackBuffer;
lpBackBuffer = dxwss.GetBackBufferSurface();
if(lpBackBuffer){
*lplpddas = lpBackBuffer;
OutTraceDW("GetAttachedSurface(%d): SIMULATE BACKBUF attach to PRIM=%x\n", dxversion, lpdds);
return DD_OK;
}
}
// arguable utility ....
// commented out: causes "Arx Fatalis" crash assigning ZBUFFER to the wrong surface?
// would that be necessary on some game?
//if(dxw.dwFlags6 & SETZBUFFERBITDEPTHS){
// if (lpDDZBuffer && (lpddsc->dwCaps & DDSCAPS_ZBUFFER)){
// *lplpddas = lpDDZBuffer;
// OutTraceDW("GetAttachedSurface(%d): SIMULATE ZBUFFER attach to %s=%x\n", dxversion, IsPrim?"PRIM":"BACK", lpdds);
// return DD_OK;
// }
//}
OutTraceE("GetAttachedSurface(%d): ERROR res=%x(%s) at %d\n", dxversion, res, ExplainDDError(res), __LINE__);
}
else {
OutTraceDDRAW("GetAttachedSurface(%d): attached=%x\n", dxversion, *lplpddas);
}
return res;
}
HRESULT WINAPI extGetAttachedSurface1(LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS lpddsc, LPDIRECTDRAWSURFACE *lplpddas)
{ return extGetAttachedSurface(1, pGetAttachedSurface1, lpdds, lpddsc, lplpddas); }
HRESULT WINAPI extGetAttachedSurface2(LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS lpddsc, LPDIRECTDRAWSURFACE *lplpddas)
{ return extGetAttachedSurface(2, pGetAttachedSurface2, lpdds, lpddsc, lplpddas); }
HRESULT WINAPI extGetAttachedSurface3(LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS lpddsc, LPDIRECTDRAWSURFACE *lplpddas)
{ return extGetAttachedSurface(3, pGetAttachedSurface3, lpdds, lpddsc, lplpddas); }
HRESULT WINAPI extGetAttachedSurface4(LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS lpddsc, LPDIRECTDRAWSURFACE *lplpddas)
{ return extGetAttachedSurface(4, pGetAttachedSurface4, lpdds, lpddsc, lplpddas); }
HRESULT WINAPI extGetAttachedSurface7(LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS lpddsc, LPDIRECTDRAWSURFACE *lplpddas)
{ return extGetAttachedSurface(7, pGetAttachedSurface7, lpdds, lpddsc, lplpddas); }
void BlitError(HRESULT res, LPRECT lps, LPRECT lpd, int line)
{
char sInfo[512];
sprintf(sInfo, "Blt: ERROR %x(%s) at %d", res, ExplainDDError(res), line);
if (res==DDERR_INVALIDRECT){
if (lps)
sprintf(sInfo, "%s src=(%d,%d)-(%d,%d)", sInfo, lps->left, lps->top, lps->right, lps->bottom);
else
sprintf(sInfo, "%s src=(NULL)", sInfo);
if (lpd)
sprintf(sInfo, "%s dest=(%d,%d)-(%d,%d)", sInfo, lpd->left, lpd->top, lpd->right, lpd->bottom);
else
sprintf(sInfo, "%s dest=(NULL)", sInfo);
}
strcat(sInfo, "\n");
OutTrace(sInfo);
return;
}
void BlitTrace(char *label, LPRECT lps, LPRECT lpd, int line)
{
char sInfo[512];
sprintf(sInfo, "[%s]", label);
if (lps)
sprintf(sInfo, "%s src=(%d,%d)-(%d,%d)", sInfo, lps->left, lps->top, lps->right, lps->bottom);
else
sprintf(sInfo, "%s src=(NULL)", sInfo);
if (lpd)
sprintf(sInfo, "%s dest=(%d,%d)-(%d,%d)", sInfo, lpd->left, lpd->top, lpd->right, lpd->bottom);
else
sprintf(sInfo, "%s dest=(NULL)", sInfo);
sprintf(sInfo, "%s at %d\n", sInfo, line);
OutTrace(sInfo);
return;
}
HRESULT WINAPI PrimaryBlt(int dxversion, Blt_Type pBlt, LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect, LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect)
{
return (*pBlt)(lpdds, lpdestrect, lpddssrc, lpsrcrect, DDBLT_WAIT, 0);
}
HRESULT WINAPI PrimaryFastBlt(int dxversion, Blt_Type pBlt, LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect, LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect)
{
HRESULT res;
RECT client;
int iXOffset, iYOffset; // offsets to center surface area to window
(*pGetClientRect)(dxw.GethWnd(), &client);
iXOffset = (client.right - dxw.GetScreenWidth()) >> 1;
iYOffset = (client.bottom - dxw.GetScreenHeight()) >> 1;
if(dxw.dwFlags3 & FORCECLIPPER){
RECT destrect;
destrect.left = iXOffset + lpdestrect->left;
destrect.right = iXOffset + lpdestrect->right;
destrect.top = iYOffset + lpdestrect->top;
destrect.bottom = iYOffset + lpdestrect->bottom;
res = (*pBlt)(lpdds, &destrect, lpddssrc, lpsrcrect, DDBLT_WAIT, 0);
}
else {
BltFast_Type pBltFast;
switch(dxversion){
case 1: pBltFast=pBltFast1; break;
case 2: pBltFast=pBltFast2; break;
case 3: pBltFast=pBltFast3; break;
case 4: pBltFast=pBltFast4; break;
case 7: pBltFast=pBltFast7; break;
}
res= (*pBltFast)(lpdds, iXOffset + lpdestrect->left, iYOffset + lpdestrect->top, lpddssrc, lpsrcrect, DDBLTFAST_WAIT);
}
return res;
}
HRESULT WINAPI PrimaryStretchBlt(int dxversion, Blt_Type pBlt, LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect, LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect)
{
HRESULT res;
DDSURFACEDESC2 ddsd;
RECT TmpRect;
LPDIRECTDRAWSURFACE lpddsTmp;
LPDIRECTDRAWSURFACE lpddsBak;
DDSCAPS caps;
CreateSurface1_Type pCreateSurface;
BltFast_Type pBltFast;
int dwSize;
switch(iBakBufferVersion){
default:
case 1: pBltFast=pBltFast1; pCreateSurface=pCreateSurface1; dwSize = sizeof(DDSURFACEDESC); break;
case 2: pBltFast=pBltFast2; pCreateSurface=(CreateSurface1_Type)pCreateSurface2; dwSize = sizeof(DDSURFACEDESC); break;
case 3: pBltFast=pBltFast3; pCreateSurface=(CreateSurface1_Type)pCreateSurface3; dwSize = sizeof(DDSURFACEDESC); break;
case 4: pBltFast=pBltFast4; pCreateSurface=(CreateSurface1_Type)pCreateSurface4; dwSize = sizeof(DDSURFACEDESC2); break;
case 7: pBltFast=pBltFast7; pCreateSurface=(CreateSurface1_Type)pCreateSurface7; dwSize = sizeof(DDSURFACEDESC2); break;
}
caps.dwCaps = DDSCAPS_BACKBUFFER;
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = dwSize;
if(lpddssrc==NULL){
// blit from backbuffer
lpdds->GetAttachedSurface(&caps, &(LPDIRECTDRAWSURFACE)lpddsBak);
if(lpddsBak == NULL) {
OutTraceE("PrimaryStretchBlt: skip - lpddsBak=%x at %d\n", lpddsBak, __LINE__);
return DD_OK; // fake a success ...
}
lpddsBak->GetSurfaceDesc((LPDDSURFACEDESC)&ddsd);
}
else{
// blit from surface
lpddssrc->GetSurfaceDesc((LPDDSURFACEDESC)&ddsd);
}
TmpRect.left = TmpRect.top = 0;
TmpRect.bottom = ddsd.dwHeight = lpdestrect->bottom - lpdestrect->top;
TmpRect.right = ddsd.dwWidth = lpdestrect->right - lpdestrect->left;
if((TmpRect.bottom==0) || (TmpRect.right==0)) return DD_OK; // avoid blitting to null areas (Fifa 2000 D3D)
ddsd.dwFlags = (DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS);
// capabilities must cope with primary / backbuffer surface capabilities to get speedy operations
ddsd.ddsCaps.dwCaps = dwBackBufferCaps;
res=(*pCreateSurface)(lpPrimaryDD, (LPDDSURFACEDESC)&ddsd, &lpddsTmp, NULL);
if(res) {
OutTraceE("PrimaryStretchBlt: CreateSurface ERROR %x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
OutTraceB("PrimaryStretchBlt: CreateSurface %s\n", LogSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Gateway]", __LINE__));
return res;
}
// stretch-blit to target size on OFFSCREENPLAIN temp surface
res= (*pBlt)(lpddsTmp, &TmpRect, lpddssrc, lpsrcrect, DDBLT_WAIT, 0);
if(res) {
OutTraceE("PrimaryStretchBlt: Blt ERROR %x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
}
else {
while(TRUE) {
// fast-blit to primary
if(dxw.dwFlags3 & FORCECLIPPER){
res= (*pBlt)(lpdds, lpdestrect, lpddsTmp, &TmpRect, DDBLT_WAIT, 0);
if(res) OutTraceE("PrimaryStretchBlt: Blt ERROR %x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
}
else{
res= (*pBltFast)(lpdds, lpdestrect->left, lpdestrect->top, lpddsTmp, &TmpRect, DDBLTFAST_WAIT);
if(res) OutTraceE("PrimaryStretchBlt: BltFast ERROR %x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
}
if(res == DDERR_SURFACELOST){
res = lpdds->Restore();
if(res) {
OutTraceE("PrimaryStretchBlt: Restore ERROR %x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
}
else {
OutTraceDW("PrimaryStretchBlt: surface sucessfully recovered, retry\n");
continue;
}
}
break;
}
}
(*pReleaseSMethod(dxversion))(lpddsTmp);
return res;
}
void *LoadFilter(char *apiname)
{
HMODULE filterlib;
#define MAX_FILE_PATH 512
char sSourcePath[MAX_FILE_PATH+1];
char *p;
DWORD dwAttrib;
dwAttrib = GetFileAttributes("dxwnd.dll");
if (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) return NULL;
GetModuleFileName(GetModuleHandle("dxwnd"), sSourcePath, MAX_FILE_PATH);
p=&sSourcePath[strlen(sSourcePath)-strlen("dxwnd.dll")];
*p=0;
SetDllDirectory(sSourcePath);
strcpy(p, "filter.dll");
filterlib=(*pLoadLibraryA)(sSourcePath);
if(!filterlib) {
OutTraceDW("DXWND: Load lib=\"%s\" failed err=%d\n", sSourcePath, GetLastError());
return NULL;
}
return (*pGetProcAddress)(filterlib, apiname);
}
HRESULT WINAPI PrimaryBilinearBlt(int dxversion, Blt_Type pBlt, LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect, LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect)
{
HRESULT res;
typedef void (WINAPI *Resize_HQ_Type)( unsigned char*, RECT *, int, unsigned char*, RECT *, int);
static Resize_HQ_Type pResize_HQ = NULL;
/* to be implemented .... */
DDSURFACEDESC2 ddsd;
RECT TmpRect, SrcRect;
LPDIRECTDRAWSURFACE lpddsTmp;
LPDIRECTDRAWSURFACE lpddsBak;
LPDIRECTDRAWSURFACE lpddsCopy=NULL;
DDSCAPS caps;
BYTE *bSourceBuf, *bDestBuf;
LONG dwWidth, dwHeight;
int SrcPitch, DestPitch;
CreateSurface1_Type pCreateSurface;
BltFast_Type pBltFast;
int dwSize;
switch(dxversion){
default:
case 1: pBltFast=pBltFast1; pCreateSurface=pCreateSurface1; dwSize = sizeof(DDSURFACEDESC); break;
case 2: pBltFast=pBltFast2; pCreateSurface=(CreateSurface1_Type)pCreateSurface2; dwSize = sizeof(DDSURFACEDESC); break;
case 3: pBltFast=pBltFast3; pCreateSurface=(CreateSurface1_Type)pCreateSurface3; dwSize = sizeof(DDSURFACEDESC); break;
case 4: pBltFast=pBltFast4; pCreateSurface=(CreateSurface1_Type)pCreateSurface4; dwSize = sizeof(DDSURFACEDESC2); break;
case 7: pBltFast=pBltFast7; pCreateSurface=(CreateSurface1_Type)pCreateSurface7; dwSize = sizeof(DDSURFACEDESC2); break;
}
caps.dwCaps = DDSCAPS_BACKBUFFER;
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = dwSize;
if(lpddssrc==NULL){
// blit from backbuffer
lpdds->GetAttachedSurface(&caps, &lpddsBak);
if(lpddsBak) lpddsBak->GetSurfaceDesc((LPDDSURFACEDESC)&ddsd);
}
else{
// blit from surface
lpddssrc->GetSurfaceDesc((LPDDSURFACEDESC)&ddsd);
}
// assign source RECT values anyway....
if(!lpsrcrect){
lpsrcrect = &SrcRect;
lpsrcrect->left = lpsrcrect->top = 0;
lpsrcrect->right = dxw.GetScreenWidth();
lpsrcrect->bottom = dxw.GetScreenHeight();
}
dwWidth = lpdestrect->right - lpdestrect->left;
dwHeight = lpdestrect->bottom - lpdestrect->top;
TmpRect.left = TmpRect.top = 0;
TmpRect.bottom = ddsd.dwHeight = dwHeight;
TmpRect.right = ddsd.dwWidth = dwWidth;
ddsd.dwFlags = (DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS);
// capabilities must cope with primary / backbuffer surface capabilities to get speedy operations
ddsd.ddsCaps.dwCaps = dwBackBufferCaps;
res=(*pCreateSurface)(lpPrimaryDD, (LPDDSURFACEDESC)&ddsd, &lpddsTmp, NULL);
if(res) OutTraceE("PrimaryBilinearBlt: CreateSurface ERROR %x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
// get informations
memset(&ddsd,0,dwSize);
ddsd.dwSize = dwSize;
ddsd.dwFlags = DDSD_LPSURFACE | DDSD_PITCH;
res=(*pLockMethod(dxversion))(lpddssrc, 0, (LPDDSURFACEDESC)&ddsd, DDLOCK_SURFACEMEMORYPTR|DDLOCK_READONLY, 0);
if(res) {
OutTraceE("PrimaryBilinearBlt: Lock ERROR %x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return DD_OK;
}
bSourceBuf = (BYTE *)ddsd.lpSurface;
SrcPitch = ddsd.lPitch;
memset(&ddsd,0,dwSize);
ddsd.dwSize = dwSize;
ddsd.dwFlags = DDSD_LPSURFACE | DDSD_PITCH;
res=(*pLockMethod(dxversion))(lpddsTmp, 0, (LPDDSURFACEDESC)&ddsd, DDLOCK_SURFACEMEMORYPTR|DDLOCK_WRITEONLY|DDLOCK_WAIT, 0);
if(res) {
OutTraceE("PrimaryBilinearBlt: Lock ERROR %x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return DD_OK;
}
bDestBuf = (BYTE *)ddsd.lpSurface;
DestPitch = ddsd.lPitch;
// do the filtering
if(!pResize_HQ) {
char *filter;
HMODULE filterlib;
switch(ddsd.ddpfPixelFormat.dwGBitMask)
{
default:
case 0x00FF00:
filter = "Resize_HQ_4ch";
break;
case 0x0007E0: // RGB565
filter = "Resize_HQ_2ch565";
break;
case 0x0003E0: // RGB555
filter = "Resize_HQ_2ch555";
break;
}
filterlib=(*pLoadLibraryA)("filter.dll");
if(!filterlib) {
char sMsg[80+1];
sprintf(sMsg, "DXWND: ERROR can't load lib=\"filter.dll\" err=%x\n", GetLastError());
OutTraceE(sMsg);
MessageBox(0, sMsg, "ERROR", MB_OK | MB_ICONEXCLAMATION);
exit(0);
}
pResize_HQ = (Resize_HQ_Type)(*pGetProcAddress)(filterlib, filter);
if(!pResize_HQ){
char sMsg[80+1];
sprintf(sMsg, "DXWND: ERROR can't load name=\"%s\"\n", filter);
OutTraceE(sMsg);
MessageBox(0, sMsg, "ERROR", MB_OK | MB_ICONEXCLAMATION);
exit(0);
}
}
(*pResize_HQ)(bSourceBuf, lpsrcrect, SrcPitch, bDestBuf, lpdestrect, DestPitch);
// fast-blit to primary
(*pUnlockMethod(dxversion))(lpddssrc, NULL);
(*pUnlockMethod(dxversion))(lpddsTmp, NULL);
if(dxw.dwFlags3 & FORCECLIPPER) {
res= (*pBlt)(lpdds, lpdestrect, lpddsTmp, &TmpRect, DDBLT_WAIT, 0);
if(res) OutTraceE("PrimaryBilinearBlt: Blt ERROR %x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
}
else {
res= (*pBltFast)(lpdds, lpdestrect->left, lpdestrect->top, lpddsTmp, &TmpRect, DDBLTFAST_WAIT);
if(res) OutTraceE("PrimaryBilinearBlt: BltFast ERROR %x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
}
(*pReleaseSMethod(dxversion))(lpddsTmp);
if(lpddsCopy) (*pReleaseSMethod(dxversion))(lpddsCopy);
return res;
}
HRESULT WINAPI PrimaryNoBlt(int dxversion, Blt_Type pBlt, LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect, LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect)
{
return DD_OK;
}
typedef HRESULT (WINAPI *ColorConversion_Type)(int, LPDIRECTDRAWSURFACE, RECT, LPDIRECTDRAWSURFACE *);
HRESULT WINAPI ColorConversionEmulated(int dxversion, LPDIRECTDRAWSURFACE lpdds, RECT emurect, LPDIRECTDRAWSURFACE *lpddssource)
{
HRESULT res;
Blt_Type pBlt;
switch(dxversion){
case 1: pBlt=pBlt1; break;
case 2: pBlt=pBlt2; break;
case 3: pBlt=pBlt3; break;
case 4: pBlt=pBlt4; break;
case 7: pBlt=pBlt7; break;
}
res=(*pEmuBlt)(dxversion, pBlt, lpDDSEmu_Back, &emurect, lpdds, &emurect, DDBLT_WAIT, 0);
if(res==DDERR_SURFACEBUSY){
(*pUnlockMethod(dxversion))(lpdds, NULL);
(*pUnlockMethod(dxversion))(lpDDSEmu_Back, NULL);
res=(*pEmuBlt)(dxversion, pBlt, lpDDSEmu_Back, &emurect, lpdds, &emurect, DDBLT_WAIT, 0);
}
if(res) {
BlitError(res, &emurect, &emurect, __LINE__);
if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=0;
}
*lpddssource = lpDDSEmu_Back;
return res;
}
HRESULT WINAPI ColorConversionGDI(int version, LPDIRECTDRAWSURFACE lpdds, RECT emurect, LPDIRECTDRAWSURFACE *lpddssource)
{
// GDICOLORCONV: use GDI capabilities to convert color depth by BitBlt-ting between different hdc
HRESULT res;
GetDC_Type pGetDC = pGetDCMethod();
ReleaseDC_Type pReleaseDC = pReleaseDCMethod();
do {
HDC hdc_source, hdc_dest;
res=(*pGetDC)(lpdds, &hdc_source);
if(res) {
OutTraceE("GetDC ERROR: err=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
break;
}
res=(*pGetDC)(lpDDSEmu_Back, &hdc_dest);
if(res) {
OutTraceE("GetDC ERROR: err=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
break;
}
if(!BitBlt(hdc_dest, 0, 0, dxw.GetScreenWidth(), dxw.GetScreenHeight(), hdc_source, 0, 0, SRCCOPY)){
OutTraceE("BitBlt ERROR: err=%d at %d\n", GetLastError(), __LINE__);
}
res=(*pReleaseDC)(lpdds, hdc_source);
if(res) {
OutTraceE("ReleaseDC ERROR: err=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
break;
}
res=(*pReleaseDC)(lpDDSEmu_Back, hdc_dest);
if(res) {
OutTraceE("ReleaseDC ERROR: err=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
break;
}
} while(FALSE);
*lpddssource = lpDDSEmu_Back;
return res;
}
HRESULT WINAPI ColorConversionDDRAW(int dxversion, LPDIRECTDRAWSURFACE lpdds, RECT emurect, LPDIRECTDRAWSURFACE *lpddssource)
{
*lpddssource = lpdds;
return DD_OK;
}
HRESULT WINAPI extFlip(int dxversion, Flip_Type pFlip, LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWSURFACE lpddssrc, DWORD dwflags)
{
BOOL IsPrim;
HRESULT res;
DDSURFACEDESC2 ddsd;
LPDIRECTDRAWSURFACE lpddsTmp;
LPDIRECTDRAWSURFACE lpDDSBack;
IsPrim=dxwss.IsAPrimarySurface(lpdds);
OutTraceDDRAW("Flip: lpdds=%x%s, src=%x, flags=%x(%s) version=%d\n",
lpdds, IsPrim?"(PRIM)":"", lpddssrc, dwflags, ExplainFlipFlags(dwflags), dxversion);
Blt_Type pBlt;
switch (dxversion){
case 1: pBlt = pBlt1; break;
case 2: pBlt = pBlt2; break;
case 3: pBlt = pBlt3; break;
case 4: pBlt = pBlt4; break;
case 7: pBlt = pBlt7; break;
}
if (!IsPrim){
if(lpddssrc){
res=(*pFlip)(lpdds, lpddssrc, dwflags);
}
else{
LPDIRECTDRAWSURFACE lpddsAttached;
DDSCAPS ddsc;
DDSURFACEDESC2 sd;
sd.dwSize=Set_dwSize_From_Surface();
res=lpdds->GetSurfaceDesc((DDSURFACEDESC *)&sd);
if (res) OutTraceDW("Flip: GetSurfaceDesc res=%x at %d\n",res, __LINE__);
// replace these CAPS (good for seven kingdoms II) with same as lpdds surface
ddsc.dwCaps=sd.ddsCaps.dwCaps;
res=lpdds->GetAttachedSurface(&ddsc, &lpddsAttached);
if(res){
OutTraceE("Flip: GetAttachedSurface ERROR %x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return res;
}
res=sBlt(dxversion, pBlt, "Flip", lpdds, NULL, lpddsAttached, NULL, DDBLT_WAIT, 0, TRUE);
if(res){
OutTraceE("Flip: Blt ERROR %x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return res;
}
}
if(res) OutTraceE("Flip: ERROR %x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return res;
}
// emulation to primary surface Flip - you can't flip to window surfaces,
// so you have to replace it with Blt operations.
if((dwflags & DDFLIP_WAIT) || (dxw.dwFlags1 & SAVELOAD)) lpPrimaryDD->WaitForVerticalBlank(DDWAITVB_BLOCKEND , 0);
lpDDSBack = dxwss.GetBackBufferSurface();
if(dxw.dwFlags4 & NOFLIPEMULATION){
HRESULT res2;
// create a temporary working surface
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = (dxversion <4) ? sizeof(DDSURFACEDESC) : sizeof(DDSURFACEDESC2); // v2.03.60 insidious bug fix !!!
// v2.02.80: the BackBuffer may not exist? see "HellCopter"
if(lpDDSBack){
(*pGetSurfaceDescMethod())((LPDIRECTDRAWSURFACE2)lpDDSBack, &ddsd);
ddsd.dwFlags &= ~DDSD_PITCH;
}
else{
ddsd.dwFlags = (DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS);
ddsd.ddsCaps.dwCaps = (DDSCAPS_OFFSCREENPLAIN);
ddsd.dwHeight = dxw.GetScreenHeight();
ddsd.dwWidth = dxw.GetScreenWidth();
}
res2=(*pCreateSurfaceMethod(dxversion))(lpPrimaryDD, &ddsd, &lpddsTmp, NULL);
if(res2) {
OutTraceE("CreateSurface: ERROR %x(%s) at %d\n", res2, ExplainDDError(res2), __LINE__);
OutTraceE("Size=%d lpPrimaryDD=%x lpDDSBack=%x %s\n",
ddsd.dwSize, lpPrimaryDD, lpDDSBack, LogSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[FlipBuf]", __LINE__));
}
//OutTrace("DEBUG: copied surface size=(%dx%d)\n", ddsd.dwWidth, ddsd.dwHeight);
// copy front buffer
if(dxw.dwFlags1 & EMULATESURFACE){
// in emulated mode, the primary surface is virtual and you can pick it all
// needed for "Gruntz"
res2= (*pBlt)(lpddsTmp, NULL, lpdds, NULL, DDBLT_WAIT, NULL);
if(res2) BlitError(res2, NULL, NULL, __LINE__);
}
else {
// in no-emulated mode, the primary surface is the whole screen, so you have to pick...
// needed for "Black Thorn"
RECT clip;
if(dxw.dwFlags1 & EMULATEBUFFER)
clip=dxw.GetScreenRect();
else
clip=dxw.GetUnmappedScreenRect();
res2= (*pBlt)(lpddsTmp, NULL, lpdds, &clip, DDBLT_WAIT, NULL);
if(res2) BlitError(res2, &clip, NULL, __LINE__);
}
}
if(lpddssrc){
//res=lpdds->Blt(0, lpddssrc, 0, DDBLT_WAIT, 0);
res=sBlt(dxversion, pBlt, "Flip", lpdds, NULL, lpddssrc, NULL, DDBLT_WAIT, 0, TRUE);
}
else{
if(!lpDDSBack){
OutTraceE("Flip: no backbuffer\n");
return DDERR_INVALIDPARAMS;
}
if (dxw.dwFlags2 & BACKBUFATTACH){
RECT NullArea;
NullArea.left=NullArea.top=0;
NullArea.bottom=dxw.GetScreenHeight();
NullArea.right=dxw.GetScreenWidth();
res=sBlt(dxversion, pBlt, "Flip", lpdds, NULL, lpDDSBack, &NullArea, DDBLT_WAIT, 0, TRUE);
}
else
res=sBlt(dxversion, pBlt, "Flip", lpdds, NULL, lpDDSBack, NULL, DDBLT_WAIT, 0, TRUE);
lpddssrc = lpDDSBack;
}
if(dxw.dwFlags4 & NOFLIPEMULATION){
HRESULT res2;
// restore flipped backbuffer and delete temporary surface
res2= (*pBlt)(lpddssrc, NULL, lpddsTmp, NULL, DDBLT_WAIT, NULL);
if(res2) OutTraceE("Blt: ERROR %x(%s) at %d\n", res2, ExplainDDError(res2), __LINE__);
(*pReleaseSMethod(dxversion))(lpddsTmp);
}
if(res) OutTraceE("Flip: Blt ERROR %x(%s)\n", res, ExplainDDError(res));
return res;
}
HRESULT WINAPI extFlip1(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWSURFACE lpddssrc, DWORD dwflags)
{ return extFlip(1, pFlip1, lpdds, lpddssrc, dwflags); }
HRESULT WINAPI extFlip2(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWSURFACE lpddssrc, DWORD dwflags)
{ return extFlip(2, pFlip2, lpdds, lpddssrc, dwflags); }
HRESULT WINAPI extFlip3(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWSURFACE lpddssrc, DWORD dwflags)
{ return extFlip(3, pFlip3, lpdds, lpddssrc, dwflags); }
HRESULT WINAPI extFlip4(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWSURFACE lpddssrc, DWORD dwflags)
{ return extFlip(4, pFlip4, lpdds, lpddssrc, dwflags); }
HRESULT WINAPI extFlip7(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWSURFACE lpddssrc, DWORD dwflags)
{ return extFlip(7, pFlip7, lpdds, lpddssrc, dwflags); }
HRESULT WINAPI extBlt(int dxversion, Blt_Type pBlt, LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect,
LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwflags, LPDDBLTFX lpddbltfx)
{
if ((dxw.dwFlags2 & FULLRECTBLT) && dxwss.IsAPrimarySurface(lpdds)){
lpsrcrect=NULL;
lpdestrect=NULL;
}
return sBlt(dxversion, pBlt, "Blt", lpdds, lpdestrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx, FALSE);
}
HRESULT WINAPI extBlt1(LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect, LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwflags, LPDDBLTFX lpddbltfx)
{ return extBlt(1, pBlt1, lpdds, lpdestrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx); }
HRESULT WINAPI extBlt2(LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect, LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwflags, LPDDBLTFX lpddbltfx)
{ return extBlt(2, pBlt2, lpdds, lpdestrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx); }
HRESULT WINAPI extBlt3(LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect, LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwflags, LPDDBLTFX lpddbltfx)
{ return extBlt(3, pBlt3, lpdds, lpdestrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx); }
HRESULT WINAPI extBlt4(LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect, LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwflags, LPDDBLTFX lpddbltfx)
{ return extBlt(4, pBlt4, lpdds, lpdestrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx); }
HRESULT WINAPI extBlt7(LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect, LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwflags, LPDDBLTFX lpddbltfx)
{ return extBlt(7, pBlt7, lpdds, lpdestrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx); }
HRESULT WINAPI extBltFast(int dxversion, Blt_Type pBlt, BltFast_Type pBltFast,
LPDIRECTDRAWSURFACE lpdds, DWORD dwx, DWORD dwy,
LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwtrans)
{
// BltFast is supported just on screen surfaces, so it has to be replaced
// by ordinary Blt operation in EMULATESURFACE mode.
// Mind that screen surface doesn't necessarily mean PRIMARY surfaces!
RECT srcrect, destrect;
DWORD flags = 0;
DDSURFACEDESC2 ddsd;
HRESULT ret;
BOOL ToPrim, FromPrim;
ToPrim=dxwss.IsAPrimarySurface(lpdds);
FromPrim=dxwss.IsAPrimarySurface(lpddssrc);
CleanRect(&lpsrcrect,__LINE__);
if(IsTraceDDRAW){
char sRect[81];
if (lpsrcrect) sprintf(sRect, "(%d,%d)-(%d,%d)", lpsrcrect->left, lpsrcrect->top, lpsrcrect->right, lpsrcrect->bottom);
else strcpy(sRect, "(NULL)");
OutTrace("BltFast(%d): dest=%x%s src=%x%s dwTrans=%x(%s) (x,y)=(%d,%d) srcrect=%s\n",
dxversion, lpdds, ToPrim?"(PRIM)":"", lpddssrc, FromPrim?"(PRIM)":"", dwtrans, ExplainBltFastFlags(dwtrans), dwx, dwy, sRect);
}
// try the actual method first, it may work in some corcumstances....
// when ret is DDERR_UNSUPPORTED try the emulated path.
if(!(ToPrim || FromPrim)) {
ret = pBltFast(lpdds, dwx, dwy, lpddssrc, lpsrcrect, dwtrans);
if(ret != DDERR_UNSUPPORTED) {
if(ret) OutTraceE("BltFast ERROR: res=%x(%s)\n", ret, ExplainDDError(ret));
return ret;
}
}
// consistency check ....
if (lpsrcrect)
if((lpsrcrect->left >= lpsrcrect->right) || (lpsrcrect->top >= lpsrcrect->bottom)) {
OutTraceDW("BltFast: ASSERT bad rect at %d\n", __LINE__);
return 0;
}
flags = 0;
if(dwtrans & DDBLTFAST_WAIT) flags = DDBLT_WAIT;
if(dwtrans & DDBLTFAST_DESTCOLORKEY) flags |= DDBLT_KEYDEST;
if(dwtrans & DDBLTFAST_SRCCOLORKEY) flags |= DDBLT_KEYSRC;
if ((dxw.dwFlags2 & FULLRECTBLT) && ToPrim){
return sBlt(dxversion, pBlt, "BltFast", lpdds, NULL, lpddssrc, lpsrcrect, flags, NULL, FALSE);
}
destrect.left = dwx;
destrect.top = dwy;
if(lpsrcrect){
destrect.right = destrect.left + lpsrcrect->right - lpsrcrect->left;
destrect.bottom = destrect.top + lpsrcrect->bottom - lpsrcrect->top;
// avoid altering pointed values....
srcrect=*lpsrcrect;
ret=sBlt(dxversion, pBlt, "BltFast", lpdds, &destrect, lpddssrc, &srcrect, flags, NULL, FALSE);
}
else{
// does it EVER goes through here? NULL is not a valid rect value for BltFast call....
// yes, forced in FULLRECTBLT mode!
// yes, when BltFast on DDBLTFAST_SRCCOLORKEY!! (Pax Corpus)
if(lpddssrc){
ddsd.dwSize=Set_dwSize_From_Surface();
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
ret=lpddssrc->GetSurfaceDesc((LPDDSURFACEDESC)&ddsd);
if (ret){
OutTraceE("BltFast: GetSurfaceDesc ERROR %x at %d\n", ret, __LINE__);
return 0;
}
destrect.right = destrect.left + ddsd.dwWidth;
destrect.bottom = destrect.top + ddsd.dwHeight;
ret=sBlt(dxversion, pBlt, "BltFast", lpdds, &destrect, lpddssrc, NULL, flags, NULL, FALSE);
}
else{
//ret=sBlt("BltFast", lpdds, NULL, lpddssrc, NULL, flags, NULL, FALSE);
ret=DD_OK;
}
}
return ret;
}
HRESULT WINAPI extBltFast1(LPDIRECTDRAWSURFACE lpdds, DWORD dwx, DWORD dwy, LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwtrans)
{ return extBltFast(1, pBlt1, pBltFast1, lpdds, dwx, dwy, lpddssrc, lpsrcrect, dwtrans); }
HRESULT WINAPI extBltFast2(LPDIRECTDRAWSURFACE lpdds, DWORD dwx, DWORD dwy, LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwtrans)
{ return extBltFast(2, pBlt2, pBltFast2, lpdds, dwx, dwy, lpddssrc, lpsrcrect, dwtrans); }
HRESULT WINAPI extBltFast3(LPDIRECTDRAWSURFACE lpdds, DWORD dwx, DWORD dwy, LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwtrans)
{ return extBltFast(3, pBlt3, pBltFast3, lpdds, dwx, dwy, lpddssrc, lpsrcrect, dwtrans); }
HRESULT WINAPI extBltFast4(LPDIRECTDRAWSURFACE lpdds, DWORD dwx, DWORD dwy, LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwtrans)
{ return extBltFast(4, pBlt4, pBltFast4, lpdds, dwx, dwy, lpddssrc, lpsrcrect, dwtrans); }
HRESULT WINAPI extBltFast7(LPDIRECTDRAWSURFACE lpdds, DWORD dwx, DWORD dwy, LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwtrans)
{ return extBltFast(7, pBlt7, pBltFast7, lpdds, dwx, dwy, lpddssrc, lpsrcrect, dwtrans); }
HRESULT WINAPI extWaitForVerticalBlank(WaitForVerticalBlank_Type pWaitForVerticalBlank, LPDIRECTDRAW lpdd, DWORD dwflags, HANDLE hevent)
{
if(dxw.dwFlags1 & SAVELOAD){
dxw.VSyncWait();
return 0;
}
return (*pWaitForVerticalBlank)(lpdd, dwflags, hevent);
}
HRESULT WINAPI extWaitForVerticalBlank1(LPDIRECTDRAW lpdd, DWORD dwflags, HANDLE hevent)
{ return extWaitForVerticalBlank(pWaitForVerticalBlank1, lpdd, dwflags, hevent); }
HRESULT WINAPI extWaitForVerticalBlank2(LPDIRECTDRAW lpdd, DWORD dwflags, HANDLE hevent)
{ return extWaitForVerticalBlank(pWaitForVerticalBlank2, lpdd, dwflags, hevent); }
HRESULT WINAPI extWaitForVerticalBlank4(LPDIRECTDRAW lpdd, DWORD dwflags, HANDLE hevent)
{ return extWaitForVerticalBlank(pWaitForVerticalBlank4, lpdd, dwflags, hevent); }
HRESULT WINAPI extWaitForVerticalBlank7(LPDIRECTDRAW lpdd, DWORD dwflags, HANDLE hevent)
{ return extWaitForVerticalBlank(pWaitForVerticalBlank7, lpdd, dwflags, hevent); }
#define DDPCAPS_INITIALIZE_LEGACY 0x00000008l
HRESULT WINAPI extCreatePalette(int version, CreatePalette_Type pCreatePalette,
LPDIRECTDRAW lpdd, DWORD dwflags, LPPALETTEENTRY lpddpa, LPDIRECTDRAWPALETTE *lplpddp, IUnknown *pu)
{
HRESULT res;
OutTraceDDRAW("CreatePalette: lpdd=%x dwFlags=%x(%s)\n", lpdd, dwflags, ExplainCreatePaletteFlags(dwflags));
if(IsDebug && (dwflags & DDPCAPS_8BIT)) dxw.DumpPalette(256, lpddpa);
if(dxw.dwFlags1 & EMULATESURFACE) dwflags &= ~DDPCAPS_PRIMARYSURFACE;
res = (*pCreatePalette)(lpdd, dwflags, lpddpa, lplpddp, pu);
if (res) {
OutTraceE("CreatePalette: ERROR res=%x(%s)\n", res, ExplainDDError(res));
return res;
}
OutTraceDDRAW("CreatePalette: OK lpddp=%x\n", *lplpddp);
HookDDPalette(lplpddp);
return DD_OK;
}
HRESULT WINAPI extCreatePalette1(LPDIRECTDRAW lpdd, DWORD dwflags, LPPALETTEENTRY lpddpa, LPDIRECTDRAWPALETTE *lplpddp, IUnknown *pu)
{ return extCreatePalette(1, (CreatePalette_Type)pCreatePalette1, lpdd, dwflags, lpddpa, lplpddp, pu); }
HRESULT WINAPI extCreatePalette2(LPDIRECTDRAW lpdd, DWORD dwflags, LPPALETTEENTRY lpddpa, LPDIRECTDRAWPALETTE *lplpddp, IUnknown *pu)
{ return extCreatePalette(2, (CreatePalette_Type)pCreatePalette2, lpdd, dwflags, lpddpa, lplpddp, pu); }
HRESULT WINAPI extCreatePalette4(LPDIRECTDRAW lpdd, DWORD dwflags, LPPALETTEENTRY lpddpa, LPDIRECTDRAWPALETTE *lplpddp, IUnknown *pu)
{ return extCreatePalette(4, (CreatePalette_Type)pCreatePalette4, lpdd, dwflags, lpddpa, lplpddp, pu); }
HRESULT WINAPI extCreatePalette7(LPDIRECTDRAW lpdd, DWORD dwflags, LPPALETTEENTRY lpddpa, LPDIRECTDRAWPALETTE *lplpddp, IUnknown *pu)
{ return extCreatePalette(7, (CreatePalette_Type)pCreatePalette7, lpdd, dwflags, lpddpa, lplpddp, pu); }
HRESULT WINAPI extGetPalette(int dxversion, GetPalette_Type pGetPalette, LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWPALETTE *lplpddp)
{
HRESULT res;
BOOL isPrim, isBack;
isPrim=dxwss.IsAPrimarySurface(lpdds);
isBack=dxwss.IsABackBufferSurface(lpdds);
OutTraceDDRAW("GetPalette(%d): lpdds=%x%s%s\n", dxversion, lpdds, isPrim?"(PRIM)":"", isBack?"(BACK)":"");
res=(*pGetPalette)(lpdds, lplpddp);
// v2.03.07: in "Die Hard Trilogy" the backbuffer surface is queryed for the palette
// v2.03.08: in "Viper Racing" lpDDP is still NULL (how could it be?)
if((dxw.dwFlags1 & EMULATESURFACE) && (res == DDERR_NOPALETTEATTACHED) && (isPrim||isBack) && lpDDP){
OutTraceDW("GetPalette: retrieve PRIMARY palette for emulated surface lpDDP=%x\n", lpDDP);
*lplpddp = lpDDP;
lpDDP->AddRef();
iDDPExtraRefCounter++;
res=DD_OK;
}
if (res) OutTraceE("GetPalette: ERROR res=%x(%s)\n", res, ExplainDDError(res));
else OutTraceDDRAW("GetPalette: OK\n");
return res;
}
HRESULT WINAPI extGetPalette1(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWPALETTE *lplpddp)
{ return extGetPalette(1, pGetPalette1, lpdds, lplpddp); }
HRESULT WINAPI extGetPalette2(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWPALETTE *lplpddp)
{ return extGetPalette(2, pGetPalette2, lpdds, lplpddp); }
HRESULT WINAPI extGetPalette3(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWPALETTE *lplpddp)
{ return extGetPalette(3, pGetPalette3, lpdds, lplpddp); }
HRESULT WINAPI extGetPalette4(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWPALETTE *lplpddp)
{ return extGetPalette(4, pGetPalette4, lpdds, lplpddp); }
HRESULT WINAPI extGetPalette7(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWPALETTE *lplpddp)
{ return extGetPalette(7, pGetPalette7, lpdds, lplpddp); }
HRESULT WINAPI extSetPalette(int dxversion, SetPalette_Type pSetPalette, LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWPALETTE lpddp)
{
PALETTEENTRY *lpentries;
BOOL isPrim;
HRESULT res;
isPrim=dxwss.IsAPrimarySurface(lpdds);
OutTraceDDRAW("SetPalette(%d): lpdds=%x%s lpddp=%x\n", dxversion, lpdds, isPrim?"(PRIM)":"", lpddp);
res=(*pSetPalette)(lpdds, lpddp);
if(res)OutTraceE("SetPalette: ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
else OutTraceDDRAW("SetPalette: OK\n");
res=DD_OK;
if((dxw.dwFlags1 & EMULATESURFACE) && isPrim){
OutTraceDW("SetPalette: register PRIMARY palette lpDDP=%x\n", lpddp);
lpDDP = lpddp;
LPDIRECTDRAWSURFACE lpDDSBack;
if(lpddp){
HRESULT res2;
lpentries = (LPPALETTEENTRY)PaletteEntries;
res2=lpddp->GetEntries(0, 0, 256, lpentries);
if(res2) OutTraceE("SetPalette: GetEntries ERROR res=%x(%s)\n", res2, ExplainDDError(res2));
mySetPalette(0, 256, lpentries); // v2.02.76: necessary for "Requiem Avenging Angel" in SURFACEEMULATION mode
}
// Apply palette to backbuffer surface. This is necessary on some games: "Duckman private dick", "Total Soccer 2000", ...
lpDDSBack = dxwss.GetBackBufferSurface();
if (lpDDSBack){
OutTraceDW("SetPalette: apply PRIMARY palette lpDDP=%x to DDSBack=%x\n", lpddp, lpDDSBack);
res=(*pSetPalette)(lpDDSBack, lpddp);
if(res) OutTraceE("SetPalette: ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
}
// add a reference to simulate what would happen in reality....
lpdds->AddRef();
res=DD_OK;
}
return res;
}
HRESULT WINAPI extSetPalette1(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWPALETTE lpddp)
{ return extSetPalette(1, pSetPalette1, lpdds, lpddp); }
HRESULT WINAPI extSetPalette2(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWPALETTE lpddp)
{ return extSetPalette(2, pSetPalette2, lpdds, lpddp); }
HRESULT WINAPI extSetPalette3(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWPALETTE lpddp)
{ return extSetPalette(3, pSetPalette3, lpdds, lpddp); }
HRESULT WINAPI extSetPalette4(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWPALETTE lpddp)
{ return extSetPalette(4, pSetPalette4, lpdds, lpddp); }
HRESULT WINAPI extSetPalette7(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWPALETTE lpddp)
{ return extSetPalette(7, pSetPalette7, lpdds, lpddp); }
HRESULT WINAPI extSetEntries(LPDIRECTDRAWPALETTE lpddp, DWORD dwflags, DWORD dwstart, DWORD dwcount, LPPALETTEENTRY lpentries)
{
HRESULT res;
OutTraceDDRAW("SetEntries: lpddp=%x dwFlags=%x, start=%d, count=%d entries=%x\n", //GHO: added trace infos
lpddp, dwflags, dwstart, dwcount, lpentries);
if(IsDebug) dxw.DumpPalette(dwcount, &lpentries[dwstart]);
if((dxw.dwFlags1 & EMULATESURFACE) && (lpDDP == lpddp)){
OutTraceDW("SetEntries: update PRIMARY palette lpDDP=%x\n", lpddp);
if ((dwstart + dwcount > 256) || (dwstart<0)){
dwcount=256;
dwstart=0;
OutTraceDW("SetEntries: ASSERT start+count > 256\n");
}
mySetPalette(dwstart, dwcount, lpentries);
// GHO: needed for fixed rect and variable palette animations,
// e.g. dungeon keeper loading screen, Warcraft II splash, ...
// GHO: but refreshing cause flickering when GDI was used without updating the primary surface
// e.g. Tomb Raider 2 intro titles, Virtua Fighter PC, ...
// v2.03.10: do not blit also in case of GDI mode
if ((dxw.dwFlags1 & EMULATESURFACE) && !(dxw.dwFlags2 & NOPALETTEUPDATE) && !(dxw.dwFlags5 & GDIMODE)) dxw.ScreenRefresh();
}
// this part (setentry against all surfaces, including virtual primary) can be necessary whenever the game uses mixed access to the
// screen (like ddraw & GDI) and is necessary on "Road Rash".
res = (*pSetEntries)(lpddp, dwflags, dwstart, dwcount, lpentries);
if(res) OutTraceE("SetEntries: ERROR res=%x(%s)\n", res, ExplainDDError(res));
else OutTraceDDRAW("SetEntries: OK\n");
return res;
}
static HRESULT WINAPI extSetClipper(SetClipper_Type pSetClipper, LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWCLIPPER lpddc)
{
HRESULT res;
BOOL isPrim;
isPrim=dxwss.IsAPrimarySurface(lpdds);
OutTraceDDRAW("SetClipper: lpdds=%x%s lpddc=%x\n", lpdds, isPrim?"(PRIM)":"", lpddc);
// v2.1.84: SUPPRESSCLIPPING flag - improves "Monopoly Edition 3D" where continuous
// clipping ON & OFF affects blitting on primary surface.
// Needed also to avoid "New Yourk Racer" intro movie clipping.
if(dxw.dwFlags1 & SUPPRESSCLIPPING) return 0;
if(dxw.dwFlags1 & (EMULATESURFACE|EMULATEBUFFER)){
if (dxw.dwFlags3 & FORCECLIPPER){
// v2.03.48: FORCECLIPPER ensures that a valid clipper is issued on the real primary surface
// and on the main game window. Then, you won't be able to BltFast any longer....
if ((isPrim || dxwss.IsABackBufferSurface(lpdds)) && lpDDSEmu_Prim){
OutTraceDW("SetClipper: redirect surface to primary hwnd=%x lpdds=%x%s->%x\n",
dxw.GethWnd(), lpdds, isPrim?"(PRIM)":"", lpDDSEmu_Prim);
res=(*pSetHWnd)(lpddc, 0, dxw.GethWnd());
//res=lpddc->SetHWnd(0, dxw.GethWnd());
if (res) OutTraceE("SetClipper: SetHWnd ERROR res=%x(%s)\n", res, ExplainDDError(res));
res=(*pSetClipper)(lpDDSEmu_Prim, lpddc);
if (res) OutTraceE("SetClipper: ERROR res=%x(%s)\n", res, ExplainDDError(res));
return res;
}
}
else {
if ((isPrim && lpDDSEmu_Prim) ||
(dxwss.IsABackBufferSurface(lpdds) && lpDDSEmu_Back)){
OutTraceDW("SetClipper: skip primary/backbuffer lpdds=%x\n", lpdds);
return 0;
}
}
}
res=(*pSetClipper)(lpdds, lpddc);
if (res)
OutTraceE("SetClipper: ERROR res=%x(%s)\n", res, ExplainDDError(res));
return res;
}
HRESULT WINAPI extSetClipper1(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWCLIPPER lpddc)
{ return extSetClipper(pSetClipper1, lpdds, lpddc); }
HRESULT WINAPI extSetClipper2(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWCLIPPER lpddc)
{ return extSetClipper(pSetClipper2, lpdds, lpddc); }
HRESULT WINAPI extSetClipper3(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWCLIPPER lpddc)
{ return extSetClipper(pSetClipper3, lpdds, lpddc); }
HRESULT WINAPI extSetClipper4(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWCLIPPER lpddc)
{ return extSetClipper(pSetClipper4, lpdds, lpddc); }
HRESULT WINAPI extSetClipper7(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWCLIPPER lpddc)
{ return extSetClipper(pSetClipper7, lpdds, lpddc); }
DDSURFACEDESC SaveSurfaceDesc;
LPDIRECTDRAWSURFACE SaveSurface = NULL;
static HRESULT WINAPI extLock(int dxversion, Lock_Type pLock, LPDIRECTDRAWSURFACE lpdds, LPRECT lprect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD flags, HANDLE hEvent)
{
HRESULT res;
CleanRect(&lprect, __LINE__);
if(IsTraceDDRAW){
BOOL IsPrim=dxwss.IsAPrimarySurface(lpdds);
char sRect[81];
if (lprect) sprintf_s(sRect, 80, "(%d,%d)-(%d,%d)", lprect->left, lprect->top, lprect->right, lprect->bottom);
else strcpy(sRect, "(NULL)");
OutTrace("Lock(%d): lpdds=%x%s flags=%x(%s) lpDDSurfaceDesc=%x rect=%s\n",
dxversion, lpdds, (IsPrim ? "(PRIM)":""), flags, ExplainLockFlags(flags), lpDDSurfaceDesc, sRect);
}
res=(*pLock)(lpdds, lprect, lpDDSurfaceDesc, flags, hEvent);
if(res==DDERR_SURFACEBUSY){ // v70: fix for "Ancient Evil"
(*pUnlockMethod(dxversion))(lpdds, NULL);
res = (*pLock)(lpdds, lprect, lpDDSurfaceDesc, flags, hEvent);
OutTraceDW("Lock RETRY: ret=%x(%s)\n", res, ExplainDDError(res));
}
if(res==DDERR_SURFACELOST){
lpdds->Restore();
res = (*pLock)(lpdds, lprect, lpDDSurfaceDesc, flags, hEvent);
OutTraceDW("Lock RETRY: ret=%x(%s)\n", res, ExplainDDError(res));
}
if(res) OutTraceE("Lock ERROR: ret=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
OutTraceB("Lock: lPitch=%d lpSurface=%x ZBufferBitDepth=%d %s\n",
lpDDSurfaceDesc->lPitch, lpDDSurfaceDesc->lpSurface, lpDDSurfaceDesc->dwZBufferBitDepth, LogSurfaceAttributes(lpDDSurfaceDesc, "[Locked]", __LINE__));
// v2.03.60: necessary for "Mech Commander 2"
if(dxw.dwFlags6 & SETZBUFFERBITDEPTHS)
lpDDSurfaceDesc->dwZBufferBitDepth = dxw.VirtualPixelFormat.dwRGBBitCount;
if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=DD_OK;
if((dxw.dwFlags6 & FIXPITCH) || (dxw.dwFlags3 & MARKLOCK)){
SaveSurfaceDesc = *lpDDSurfaceDesc;
SaveSurface = lpdds;
}
return res;
}
HRESULT WINAPI extLock1(LPDIRECTDRAWSURFACE lpdds, LPRECT lprect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD flags, HANDLE hEvent)
{ return extLock(1, pLock1, lpdds, lprect, lpDDSurfaceDesc, flags, hEvent); }
HRESULT WINAPI extLock2(LPDIRECTDRAWSURFACE lpdds, LPRECT lprect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD flags, HANDLE hEvent)
{ return extLock(2, pLock2, lpdds, lprect, lpDDSurfaceDesc, flags, hEvent); }
HRESULT WINAPI extLock3(LPDIRECTDRAWSURFACE lpdds, LPRECT lprect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD flags, HANDLE hEvent)
{ return extLock(3, pLock3, lpdds, lprect, lpDDSurfaceDesc, flags, hEvent); }
HRESULT WINAPI extLock4(LPDIRECTDRAWSURFACE lpdds, LPRECT lprect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD flags, HANDLE hEvent)
{ return extLock(4, pLock4, lpdds, lprect, lpDDSurfaceDesc, flags, hEvent); }
HRESULT WINAPI extLock7(LPDIRECTDRAWSURFACE lpdds, LPRECT lprect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD flags, HANDLE hEvent)
{ return extLock(7, pLock7, lpdds, lprect, lpDDSurfaceDesc, flags, hEvent); }
LPDIRECTDRAWSURFACE2 lpDDSBuffer = NULL;
static HRESULT WINAPI extLockDir(int dxversion, Lock_Type pLock, LPDIRECTDRAWSURFACE lpdds, LPRECT lprect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD flags, HANDLE hEvent)
{
HRESULT res, res2;
static RECT client;
POINT upleft={0,0};
LPDIRECTDRAWSURFACE lpDDSPrim;
Blt_Type pBlt;
GetGDISurface_Type pGetGDISurface;
// this hooker operates on
// Beware!!! for strange reason, the function gets hooked to ANY surface, also non primary ones!!!
// to find out whether it is the primary or not, using lpdds==lpPrimaryDD->GetGDISurface(&lpDDSPrim);
if(IsTraceDDRAW){
BOOL IsPrim=dxwss.IsAPrimarySurface(lpdds);
char sRect[81];
if (lprect) sprintf_s(sRect, 80, "(%d,%d)-(%d,%d)", lprect->left, lprect->top, lprect->right, lprect->bottom);
else strcpy(sRect, "(NULL)");
OutTrace("Lock(%d): lpdds=%x%s flags=%x(%s) lpDDSurfaceDesc=%x rect=%s\n",
dxversion, lpdds, (IsPrim ? "(PRIM)":""), flags, ExplainLockFlags(flags), lpDDSurfaceDesc, sRect);
}
switch(dxversion){
case 1: pBlt=pBlt1; pGetGDISurface=pGetGDISurface1; break;
case 2: pBlt=pBlt2; pGetGDISurface=pGetGDISurface2; break;
case 4: pBlt=pBlt4; pGetGDISurface=pGetGDISurface4; break;
case 7: pBlt=pBlt7; pGetGDISurface=pGetGDISurface7; break;
}
// V2.02.43: Empire Earth does some test Lock operations apparently before the primary surface is created
if(lpPrimaryDD){
lpDDSPrim=0;
res2=(*pGetGDISurface)(lpPrimaryDD, &lpDDSPrim);
if(res2)
OutTraceE("Lock: GetGDISurface ERROR res=%x(%s) at %d\n", res2, ExplainDDError(res2), __LINE__);
else
(*pReleaseSMethod(dxversion))(lpDDSPrim);
if(lpdds==lpDDSPrim){
if(dxw.dwFlags1 & LOCKEDSURFACE){
DDSURFACEDESC2 ddsd;
DDBLTFX fx;
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize=sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
ddsd.dwWidth = dxw.GetScreenWidth();
ddsd.dwHeight = dxw.GetScreenHeight();
ddsd.ddsCaps.dwCaps = 0;
OutTraceB("Lock: %s\n", LogSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Dir FixBuf]" , __LINE__));
res=(*pCreateSurface1)(lpPrimaryDD, (DDSURFACEDESC *)&ddsd, (LPDIRECTDRAWSURFACE *)&lpDDSBuffer, 0);
if(res){
OutTraceE("CreateSurface: ERROR on DDSBuffer res=%x(%s) at %d\n",res, ExplainDDError(res), __LINE__);
return res;
}
memset(&fx, 0, sizeof(fx));
fx.dwSize=sizeof(DDBLTFX);
fx.dwFillColor=0;
res=(*pBlt)((LPDIRECTDRAWSURFACE)lpDDSBuffer, NULL, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
if(res){
OutTraceE("Blt: ERROR on DDSBuffer res=%x(%s) at %d\n",res, ExplainDDError(res), __LINE__);
}
lpdds=(LPDIRECTDRAWSURFACE)lpDDSBuffer;
}
else{
// since it can't scale, at least the updated rect is centered into the window.
HWND hwnd;
hwnd = dxw.GethWnd();
(*pGetClientRect)(hwnd, &client);
(*pClientToScreen)(hwnd, &upleft);
if (!lprect) lprect=&client;
OffsetRect(lprect,
upleft.x+(client.right-dxw.GetScreenWidth())/2,
upleft.y+(client.bottom-dxw.GetScreenHeight())/2);
OutTraceDW("Lock: NULL rect remapped to (%d,%d)-(%d,%d)\n",
lprect->left, lprect->top, lprect->right, lprect->bottom);
}
}
}
res=(*pLock)(lpdds, lprect, lpDDSurfaceDesc, flags, hEvent);
if(res) OutTraceE("Lock ERROR: ret=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
OutTraceB("Lock: lPitch=%d lpSurface=%x ZBufferBitDepth=%d %s\n",
lpDDSurfaceDesc->lPitch, lpDDSurfaceDesc->lpSurface, lpDDSurfaceDesc->dwZBufferBitDepth, LogSurfaceAttributes(lpDDSurfaceDesc, "[Locked]", __LINE__));
// v2.03.60: necessary for "Mech Commander 2"
if(dxw.dwFlags6 & SETZBUFFERBITDEPTHS)
lpDDSurfaceDesc->dwZBufferBitDepth = dxw.VirtualPixelFormat.dwRGBBitCount;
if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=DD_OK;
return res;
}
HRESULT WINAPI extLockDir1(LPDIRECTDRAWSURFACE lpdds, LPRECT lprect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD flags, HANDLE hEvent)
{ return extLockDir(1, pLock1, lpdds, lprect, lpDDSurfaceDesc, flags, hEvent); }
HRESULT WINAPI extLockDir2(LPDIRECTDRAWSURFACE lpdds, LPRECT lprect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD flags, HANDLE hEvent)
{ return extLockDir(2, pLock2, lpdds, lprect, lpDDSurfaceDesc, flags, hEvent); }
HRESULT WINAPI extLockDir3(LPDIRECTDRAWSURFACE lpdds, LPRECT lprect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD flags, HANDLE hEvent)
{ return extLockDir(3, pLock3, lpdds, lprect, lpDDSurfaceDesc, flags, hEvent); }
HRESULT WINAPI extLockDir4(LPDIRECTDRAWSURFACE lpdds, LPRECT lprect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD flags, HANDLE hEvent)
{ return extLockDir(4, pLock4, lpdds, lprect, lpDDSurfaceDesc, flags, hEvent); }
HRESULT WINAPI extLockDir7(LPDIRECTDRAWSURFACE lpdds, LPRECT lprect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD flags, HANDLE hEvent)
{ return extLockDir(7, pLock7, lpdds, lprect, lpDDSurfaceDesc, flags, hEvent); }
#define MARK16COLOR 0x7C1F
#define MARK32COLOR 0x00FF00FF
static HRESULT WINAPI extUnlock(int dxversion, Unlock4_Type pUnlock, LPDIRECTDRAWSURFACE lpdds, LPRECT lprect)
{
HRESULT res;
BOOL IsPrim;
BOOL IsBack;
RECT rect;
Blt_Type pBlt;
IsPrim=dxwss.IsAPrimarySurface(lpdds);
IsBack=dxwss.IsABackBufferSurface(lpdds);
if(IsTraceDDRAW){
char sRect[81];
switch(dxversion){
case 1:
case 2:
case 3:
sprintf_s(sRect, 80, "lpvoid=%x", lprect);
break;
case 4:
case 7:
if (lprect) sprintf_s(sRect, 80, "rect=(%d,%d)-(%d,%d)", lprect->left, lprect->top, lprect->right, lprect->bottom);
else strcpy(sRect, "rect=(NULL)");
break;
}
OutTrace("Unlock(%d): lpdds=%x%s %s\n", dxversion, lpdds, (IsPrim ? "(PRIM)": (IsBack ? "(BACK)" : "")), sRect);
}
switch(dxversion){
case 1: pBlt=pBlt1; break;
case 2: pBlt=pBlt2; break;
case 3: pBlt=pBlt3; break;
case 4: pBlt=pBlt4; break;
case 7: pBlt=pBlt7; break;
}
if(dxversion >= 4){
// make lprect point elsewhere, so that the original values are not altered
if(lprect){
CleanRect(&lprect,__LINE__);
rect = *lprect;
lprect = &rect;
// v2.03.20: apparently, it seems that in ddraw 7 you can set an empty rectangle to mean the whole area ....
// this fixes the black screen otherwise present in "Arcanum".
if(IsPrim && ((lprect->right - lprect->left) == 0) && ((lprect->bottom - lprect->top) == 0)) lprect = NULL;
}
}
if((dxw.dwFlags6 & FIXPITCH) && !(IsPrim||IsBack) && (lpdds == SaveSurface)){
OutTrace("DEBUG: fixing lpdds=%x size=(%dx%d) surface=%x pitch=%d bpp=%d\n",
lpdds, SaveSurfaceDesc.dwWidth, SaveSurfaceDesc.dwHeight, SaveSurfaceDesc.lpSurface, SaveSurfaceDesc.lPitch, SaveSurfaceDesc.ddpfPixelFormat.dwRGBBitCount);
int y;
LONG lVirtualPitch;
LPVOID p1, p2;
lVirtualPitch = (((SaveSurfaceDesc.dwWidth+1)>>1) * SaveSurfaceDesc.ddpfPixelFormat.dwRGBBitCount) >> 2;
if(lVirtualPitch != SaveSurfaceDesc.lPitch){ // do just if necessary ...
for (y=SaveSurfaceDesc.dwHeight-1; y; y--){ // for each scan line ...
p1 = (LPVOID)((DWORD)SaveSurfaceDesc.lpSurface + (y * lVirtualPitch));
p2 = (LPVOID)((DWORD)SaveSurfaceDesc.lpSurface + (y * SaveSurfaceDesc.lPitch));
memcpy(p2, p1, SaveSurfaceDesc.lPitch); // copy line to correct offset
}
}
}
if((dxw.dwFlags3 & MARKLOCK) && !(IsPrim||IsBack) && (lpdds == SaveSurface)){
switch(SaveSurfaceDesc.ddpfPixelFormat.dwRGBBitCount){
case 16:
for (UINT y=0; y<SaveSurfaceDesc.dwHeight; y++){ // for each scan line ...
USHORT *p;
p = (USHORT *)((DWORD)SaveSurfaceDesc.lpSurface + (y * SaveSurfaceDesc.lPitch));
p[0] = MARK16COLOR;
p[SaveSurfaceDesc.dwWidth-1] = MARK16COLOR;
if((y==0) || (y==(SaveSurfaceDesc.dwHeight-1)))
for (UINT x=0; x<SaveSurfaceDesc.dwWidth; x++) p[x] = MARK16COLOR;
}
break;
case 32:
for (UINT y=0; y<SaveSurfaceDesc.dwHeight; y++){ // for each scan line ...
ULONG *p;
p = (ULONG *)((DWORD)SaveSurfaceDesc.lpSurface + (y * SaveSurfaceDesc.lPitch));
p[0] = MARK32COLOR;
p[SaveSurfaceDesc.dwWidth-1] = MARK32COLOR;
if((y==0) || (y==(SaveSurfaceDesc.dwHeight-1)))
for (UINT x=0; x<SaveSurfaceDesc.dwWidth; x++) p[x] = MARK32COLOR;
}
break;
}
}
res=(*pUnlock)(lpdds, lprect);
if (IsPrim && res==DD_OK) {
if(dxversion < 4) lprect=NULL; // v2.03.60
res=sBlt(dxversion, pBlt, "Unlock", lpdds, lprect, lpdds, lprect, NULL, 0, FALSE);
}
if(res==DDERR_NOTLOCKED) res=DD_OK; // ignore not locked error
if (res) OutTraceE("Unlock ERROR res=%x(%s) at %d\n",res, ExplainDDError(res), __LINE__);
if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=DD_OK;
if((dxw.dwFlags5 & TEXTUREMASK) && (!IsPrim)) {
// Texture Handling on Unlock
TextureHandling(lpdds, dxversion);
}
return res;
}
HRESULT WINAPI extUnlock1(LPDIRECTDRAWSURFACE lpdds, LPVOID lpvoid)
{ return extUnlock(1, (Unlock4_Type)pUnlock1, lpdds, (LPRECT)lpvoid); }
HRESULT WINAPI extUnlock2(LPDIRECTDRAWSURFACE lpdds, LPVOID lpvoid)
{ return extUnlock(2, (Unlock4_Type)pUnlock2, lpdds, (LPRECT)lpvoid); }
HRESULT WINAPI extUnlock3(LPDIRECTDRAWSURFACE lpdds, LPVOID lpvoid)
{ return extUnlock(3, (Unlock4_Type)pUnlock3, lpdds, (LPRECT)lpvoid); }
HRESULT WINAPI extUnlock4(LPDIRECTDRAWSURFACE lpdds, LPRECT lprect)
{ return extUnlock(4, pUnlock4, lpdds, lprect); }
HRESULT WINAPI extUnlock7(LPDIRECTDRAWSURFACE lpdds, LPRECT lprect)
{ return extUnlock(7, pUnlock7, lpdds, lprect); }
static HRESULT WINAPI extUnlockDir(int dxversion, Unlock4_Type pUnlock, LPDIRECTDRAWSURFACE lpdds, LPRECT lprect)
{
HRESULT res;
//RECT screen, rect;
BOOL IsPrim;
BOOL IsBack;
LPDIRECTDRAWSURFACE lpDDSPrim;
GetGDISurface_Type pGetGDISurface;
Blt_Type pBlt;
IsPrim=dxwss.IsAPrimarySurface(lpdds);
IsBack=dxwss.IsABackBufferSurface(lpdds);
if ((dxversion >= 4) && lprect) CleanRect(&lprect,__LINE__);
if(IsTraceDDRAW){
char sRect[81];
switch(dxversion){
case 1:
case 2:
case 3:
sprintf_s(sRect, 80, "lpvoid=%x", lprect);
break;
case 4:
case 7:
if (lprect) sprintf_s(sRect, 80, "rect=(%d,%d)-(%d,%d)", lprect->left, lprect->top, lprect->right, lprect->bottom);
else strcpy(sRect, "rect=(NULL)");
break;
}
OutTrace("Unlock(%d): lpdds=%x%s %s\n", dxversion, lpdds, (IsPrim ? "(PRIM)": (IsBack ? "(BACK)" : "")), sRect);
}
switch(dxversion){
default:
case 1: pGetGDISurface = pGetGDISurface1; pBlt = pBlt1; break;
case 2: pGetGDISurface = pGetGDISurface2; pBlt = pBlt2; break;
case 3: pGetGDISurface = pGetGDISurface2; pBlt = pBlt3; break;
case 4: pGetGDISurface = pGetGDISurface4; pBlt = pBlt4; break;
case 7: pGetGDISurface = pGetGDISurface7; pBlt = pBlt7; break;
}
if(dxw.dwFlags1 & LOCKEDSURFACE){
(*pGetGDISurface)(lpPrimaryDD, &lpDDSPrim);
if(lpdds==lpDDSPrim && lpDDSBuffer){
RECT client;
POINT upleft={0,0};
(*pGetClientRect)(dxw.GethWnd(), &client);
(*pClientToScreen)(dxw.GethWnd(), &upleft);
if (!lprect) lprect=&client;
OffsetRect(lprect, upleft.x, upleft.y);
res=(*pUnlock)((LPDIRECTDRAWSURFACE)lpDDSBuffer, lprect);
(*pBlt)(lpdds, lprect, (LPDIRECTDRAWSURFACE)lpDDSBuffer, NULL, DDBLT_WAIT, 0);
(*pReleaseSMethod(dxversion))((LPDIRECTDRAWSURFACE)lpDDSBuffer);
lpDDSBuffer = NULL;
}
(*pReleaseSMethod(dxversion))(lpDDSPrim); // to leave a correct refcount
}
res=(*pUnlock)(lpdds, lprect);
if(res==DDERR_NOTLOCKED) res=DD_OK; // ignore not locked error
if (res) OutTraceE("Unlock ERROR res=%x(%s) at %d\n",res, ExplainDDError(res), __LINE__);
if (IsPrim && res==DD_OK) sBlt(dxversion, pBlt, "Unlock", lpdds, NULL, lpdds, NULL, NULL, 0, FALSE);
if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=DD_OK;
return res;
}
HRESULT WINAPI extUnlockDir1(LPDIRECTDRAWSURFACE lpdds, LPVOID lpvoid)
{ return extUnlockDir(1, (Unlock4_Type)pUnlock1, lpdds, (LPRECT)lpvoid); }
HRESULT WINAPI extUnlockDir2(LPDIRECTDRAWSURFACE lpdds, LPVOID lpvoid)
{ return extUnlockDir(2, (Unlock4_Type)pUnlock2, lpdds, (LPRECT)lpvoid); }
HRESULT WINAPI extUnlockDir3(LPDIRECTDRAWSURFACE lpdds, LPVOID lpvoid)
{ return extUnlockDir(3, (Unlock4_Type)pUnlock3, lpdds, (LPRECT)lpvoid); }
HRESULT WINAPI extUnlockDir4(LPDIRECTDRAWSURFACE lpdds, LPRECT lprect)
{ return extUnlockDir(4, pUnlock4, lpdds, lprect); }
HRESULT WINAPI extUnlockDir7(LPDIRECTDRAWSURFACE lpdds, LPRECT lprect)
{ return extUnlockDir(7, pUnlock7, lpdds, lprect); }
/* to do: instead of calling GDI GetDC, try to map GetDC with Lock and
ReleaseDC with Unlock, returning the surface memory ptr (???) as HDC
and avoiding the consistency check performed by surface::GetDC (why
should it bother if the screen is 32BPP and the surface is not??? */
static HRESULT WINAPI extGetDC(int dxversion, GetDC_Type pGetDC, LPDIRECTDRAWSURFACE lpdds, HDC FAR *pHDC)
{
HRESULT res;
BOOL IsPrim;
IsPrim=dxwss.IsAPrimarySurface(lpdds);
OutTraceDDRAW("GetDC: lpdss=%x%s\n",lpdds, IsPrim?"(PRIM)":"");
// In non-emulated mode, better return the window DC rather than the actual primary surfce DC,
// because that would refer to the whole desktop
if (!(dxw.dwFlags1 & EMULATESURFACE) && IsPrim) {
*pHDC = (*pGDIGetDC)(dxw.GethWnd());
return DD_OK;
}
res=(*pGetDC)(lpdds, pHDC);
if (res==DDERR_CANTCREATEDC &&
(dxw.dwFlags1 & EMULATESURFACE) &&
dxw.VirtualPixelFormat.dwRGBBitCount==8) {
// for 8BPP palettized surfaces, connect them to either the ddraw emulated palette or the GDI emulated palette
OutTraceDW("GetDC: adding 8BPP palette to surface lpdds=%x\n", lpdds);
if(lpDDP==NULL){
// should link here to the GDI palette? See Hyperblade....
dxw.palNumEntries=256;
res=(*pCreatePaletteMethod(dxversion))(lpPrimaryDD, DDPCAPS_ALLOW256|DDPCAPS_8BIT|DDPCAPS_INITIALIZE, dxw.palPalEntry, &lpDDP, NULL);
if (res) {
OutTraceE("GetDC: CreatePalette ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return res;
}
}
res=(*pSetPaletteMethod(dxversion))(lpdds, lpDDP);
if (res) {
OutTraceE("GetDC: SetPalette ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return res;
}
iDDPExtraRefCounter++;
// retry ....
res=(*pGetDC)(lpdds, pHDC);
}
OutTraceDDRAW("GetDC: res=%x hdc=%x\n",res, *pHDC);
return res;
}
HRESULT WINAPI extGetDC1(LPDIRECTDRAWSURFACE lpdds, HDC FAR *pHDC)
{ return extGetDC(1, pGetDC1, lpdds, pHDC); }
HRESULT WINAPI extGetDC2(LPDIRECTDRAWSURFACE lpdds, HDC FAR *pHDC)
{ return extGetDC(2, pGetDC2, lpdds, pHDC); }
HRESULT WINAPI extGetDC3(LPDIRECTDRAWSURFACE lpdds, HDC FAR *pHDC)
{ return extGetDC(3, pGetDC3, lpdds, pHDC); }
HRESULT WINAPI extGetDC4(LPDIRECTDRAWSURFACE lpdds, HDC FAR *pHDC)
{ return extGetDC(4, pGetDC4, lpdds, pHDC); }
HRESULT WINAPI extGetDC7(LPDIRECTDRAWSURFACE lpdds, HDC FAR *pHDC)
{ return extGetDC(7, pGetDC7, lpdds, pHDC); }
HRESULT WINAPI extReleaseDC(int dxversion, ReleaseDC_Type pReleaseDC, LPDIRECTDRAWSURFACE lpdds, HDC FAR hdc)
{
HRESULT res;
BOOL IsPrim;
IsPrim=dxwss.IsAPrimarySurface(lpdds);
OutTraceDDRAW("ReleaseDC: lpdss=%x%s hdc=%x\n",lpdds, IsPrim?"(PRIM)":"", hdc);
res=(*pReleaseDC)(lpdds, hdc);
if((IsPrim) && (dxw.dwFlags1 & EMULATESURFACE)) {\
Blt_Type pBlt;
GetGDISurface_Type pGetGDISurface;
switch(dxversion){
default:
case 1: pGetGDISurface = pGetGDISurface1; pBlt = pBlt1; break;
case 2: pGetGDISurface = pGetGDISurface2; pBlt = pBlt2; break;
case 3: pGetGDISurface = pGetGDISurface2; pBlt = pBlt3; break;
case 4: pGetGDISurface = pGetGDISurface4; pBlt = pBlt4; break;
case 7: pGetGDISurface = pGetGDISurface7; pBlt = pBlt7; break;
}
sBlt(dxversion, pBlt, "ReleaseDC", lpdds, NULL, lpdds, NULL, 0, NULL, FALSE);
}
if (res) OutTraceE("ReleaseDC: ERROR res=%x(%s)\n", res, ExplainDDError(res));
if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=DD_OK;
return res;
}
HRESULT WINAPI extReleaseDC1(LPDIRECTDRAWSURFACE lpdds, HDC FAR hdc)
{ return extReleaseDC(1, pReleaseDC1, lpdds, hdc); }
HRESULT WINAPI extReleaseDC2(LPDIRECTDRAWSURFACE lpdds, HDC FAR hdc)
{ return extReleaseDC(2, pReleaseDC2, lpdds, hdc); }
HRESULT WINAPI extReleaseDC3(LPDIRECTDRAWSURFACE lpdds, HDC FAR hdc)
{ return extReleaseDC(3, pReleaseDC3, lpdds, hdc); }
HRESULT WINAPI extReleaseDC4(LPDIRECTDRAWSURFACE lpdds, HDC FAR hdc)
{ return extReleaseDC(4, pReleaseDC4, lpdds, hdc); }
HRESULT WINAPI extReleaseDC7(LPDIRECTDRAWSURFACE lpdds, HDC FAR hdc)
{ return extReleaseDC(7, pReleaseDC7, lpdds, hdc); }
HRESULT WINAPI extFlipToGDISurface(FlipToGDISurface_Type pFlipToGDISurface, LPDIRECTDRAW lpdd)
{
// HRESULT res;
OutTraceDDRAW("FlipToGDISurface: lpdd=%x\n", lpdd);
// to revise: so far, it seems the best thing to do is NOTHING, just return 0.
// res=(*pFlipToGDISurface)(lpdd);
// if (res) OutTraceE("FlipToGDISurface: ERROR res=%x(%s), skipping\n", res, ExplainDDError(res));
// pretend you flipped anyway....
if(dxw.dwFlags6 & SHAREDDC) bFlippedDC = TRUE;
return DD_OK;
}
HRESULT WINAPI extFlipToGDISurface1(LPDIRECTDRAW lpdd)
{ return extFlipToGDISurface(pFlipToGDISurface1, lpdd); }
HRESULT WINAPI extFlipToGDISurface2(LPDIRECTDRAW lpdd)
{ return extFlipToGDISurface(pFlipToGDISurface2, lpdd); }
HRESULT WINAPI extFlipToGDISurface4(LPDIRECTDRAW lpdd)
{ return extFlipToGDISurface(pFlipToGDISurface4, lpdd); }
HRESULT WINAPI extFlipToGDISurface7(LPDIRECTDRAW lpdd)
{ return extFlipToGDISurface(pFlipToGDISurface7, lpdd); }
HRESULT WINAPI extGetGDISurface(GetGDISurface_Type pGetGDISurface, LPDIRECTDRAW lpdd, LPDIRECTDRAWSURFACE *w)
{
int res;
// v2.02.31:
// in EMULATED mode, should not return the actual ddraw primary surface, but the virtual one.
if(dxw.dwFlags1 & EMULATESURFACE){
*w=dxwss.GetPrimarySurface();
OutTraceDW("GetGDISurface: EMULATED lpdd=%x w=%x\n", lpdd, *w);
return DD_OK;
}
res=(*pGetGDISurface)(lpdd, w);
if (res) {
OutTraceE("GetGDISurface: ERROR lpdd=%x res=%x(%s)\n", lpdd, res, ExplainDDError(res));
}
else {
OutTraceDDRAW("GetGDISurface: lpdd=%x w=%x\n", lpdd, *w);
}
return res;
}
HRESULT WINAPI extGetGDISurface1(LPDIRECTDRAW lpdd, LPDIRECTDRAWSURFACE *w)
{ return extGetGDISurface(pGetGDISurface1, lpdd, w); }
HRESULT WINAPI extGetGDISurface2(LPDIRECTDRAW lpdd, LPDIRECTDRAWSURFACE *w)
{ return extGetGDISurface(pGetGDISurface2, lpdd, w); }
HRESULT WINAPI extGetGDISurface4(LPDIRECTDRAW lpdd, LPDIRECTDRAWSURFACE *w)
{ return extGetGDISurface(pGetGDISurface4, lpdd, w); }
HRESULT WINAPI extGetGDISurface7(LPDIRECTDRAW lpdd, LPDIRECTDRAWSURFACE *w)
{ return extGetGDISurface(pGetGDISurface7, lpdd, w); }
// debug function to dump all video modes queried by the DirectDrav::EnumDisplayModes method
HRESULT WINAPI EnumModesCallbackDumper(LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext)
{
OutTrace("EnumModesCallback:\n");
OutTrace("\tdwSize=%d\n", lpDDSurfaceDesc->dwSize);
OutTrace("\tdwFlags=%x(%s)\n", lpDDSurfaceDesc->dwFlags, ExplainFlags(lpDDSurfaceDesc->dwFlags));
OutTrace("\tdwWidth x dwHeight=(%d,%d)\n", lpDDSurfaceDesc->dwWidth, lpDDSurfaceDesc->dwHeight);
OutTrace("\tlPitch=%d\n", lpDDSurfaceDesc->lPitch);
OutTrace("\tdwBackBufferCount=%d\n", lpDDSurfaceDesc->dwBackBufferCount);
OutTrace("\tdwRefreshRate=%d\n", lpDDSurfaceDesc->dwRefreshRate);
OutTrace("\tlpSurface=%x\n", lpDDSurfaceDesc->lpSurface);
OutTrace("\tCaps=%x(%s)\n", lpDDSurfaceDesc->ddsCaps.dwCaps, ExplainDDSCaps(lpDDSurfaceDesc->ddsCaps.dwCaps));
//if ((NewContext_Type *)lpContext->dxversion >= 4) {
// OutTrace("\tddpfPixelFormat %s\n", DumpPixelFormat((LPDDSURFACEDESC2)lpDDSurfaceDesc));
//}
#ifdef FULLHEXDUMP
OutTrace("DDSurfaceDesc=");
OutTraceHex((BYTE *)lpDDSurfaceDesc, sizeof(DDSURFACEDESC));
#endif
return DDENUMRET_OK;
}
typedef HRESULT (WINAPI *EnumModesCallback_Type)(LPDDSURFACEDESC, LPVOID);
typedef struct {
LPVOID lpContext;
EnumModesCallback_Type lpCallback;
DWORD dwWidth;
DWORD dwHeight;
int dxversion;
} NewContext_Type;
static BOOL CheckResolutionLimit(LPDDSURFACEDESC lpDDSurfaceDesc)
{
#define HUGE 100000
DWORD maxw, maxh;
maxw=HUGE; maxh=HUGE;
switch(dxw.MaxScreenRes){
case DXW_LIMIT_320x200: maxw=320; maxh=200; break;
case DXW_LIMIT_640x480: maxw=640; maxh=480; break;
case DXW_LIMIT_800x600: maxw=800; maxh=600; break;
case DXW_LIMIT_1024x768: maxw=1024; maxh=768; break;
case DXW_LIMIT_1280x960: maxw=1280; maxh=960; break;
}
if((lpDDSurfaceDesc->dwWidth > maxw) || (lpDDSurfaceDesc->dwHeight > maxh)){
OutTraceDW("EnumDisplaySettings: hide device mode=(%d,%d)\n", maxw, maxh);
return TRUE;
}
return FALSE;
}
HRESULT WINAPI myEnumModesFilterDirect(LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext)
{
HRESULT res;
SupportedRes_Type *SupportedRes;
if ((((NewContext_Type *)lpContext)->dwHeight != lpDDSurfaceDesc->dwHeight) ||
(((NewContext_Type *)lpContext)->dwWidth != lpDDSurfaceDesc->dwWidth)) return DDENUMRET_OK;
if (IsDebug) EnumModesCallbackDumper(lpDDSurfaceDesc, NULL);
// tricky part: for each color depth related to current video resolution, fake each of the
// supported resolutions, unless is greater than maximum allowed
SupportedRes = (dxw.dwFlags4 & SUPPORTHDTV) ? &SupportedHDTVRes[0] : &SupportedSVGARes[0];
for (int ResIdx=0; SupportedRes[ResIdx].h; ResIdx++){
lpDDSurfaceDesc->dwHeight=SupportedRes[ResIdx].h;
lpDDSurfaceDesc->dwWidth=SupportedRes[ResIdx].w;
if((dxw.dwFlags4 & LIMITSCREENRES) && CheckResolutionLimit(lpDDSurfaceDesc)) return DDENUMRET_OK;
if (dxw.dwFlags1 & PREVENTMAXIMIZE){
// if PREVENTMAXIMIZE is set, don't let the caller know about forbidden screen settings.
if((lpDDSurfaceDesc->dwHeight > dxw.GetScreenHeight()) ||
(lpDDSurfaceDesc->dwWidth > dxw.GetScreenWidth())){
OutTraceDW("EnumDisplayModes: skipping screen size=(%d,%d)\n", lpDDSurfaceDesc->dwHeight, lpDDSurfaceDesc->dwWidth);
return DDENUMRET_OK;
}
}
res=(*((NewContext_Type *)lpContext)->lpCallback)(lpDDSurfaceDesc, ((NewContext_Type *)lpContext)->lpContext);
OutTraceDW("EnumDisplayModes(D): proposed size[%d]=(%d,%d) res=%x\n", ResIdx, SupportedRes[ResIdx].w, SupportedRes[ResIdx].h, res);
if(res==DDENUMRET_CANCEL) break;
}
return res;
}
HRESULT WINAPI myEnumModesFilterNative(LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext)
{
HRESULT res;
if (IsDebug) EnumModesCallbackDumper(lpDDSurfaceDesc, NULL);
if (dxw.dwFlags1 & PREVENTMAXIMIZE){
// if PREVENTMAXIMIZE is set, don't let the caller know about forbidden screen settings.
if((lpDDSurfaceDesc->dwHeight > dxw.GetScreenHeight()) ||
(lpDDSurfaceDesc->dwWidth > dxw.GetScreenWidth())){
OutTraceDW("EnumDisplayModes: skipping screen size=(%d,%d)\n", lpDDSurfaceDesc->dwHeight, lpDDSurfaceDesc->dwWidth);
return DDENUMRET_OK;
}
}
if((dxw.dwFlags4 & LIMITSCREENRES) && CheckResolutionLimit(lpDDSurfaceDesc)) return DDENUMRET_OK;
res=(*((NewContext_Type *)lpContext)->lpCallback)(lpDDSurfaceDesc, ((NewContext_Type *)lpContext)->lpContext);
OutTraceDW("EnumDisplayModes(D): native size=(%d,%d) res=%x\n", lpDDSurfaceDesc->dwWidth, lpDDSurfaceDesc->dwHeight, res);
return res;
}
HRESULT WINAPI extEnumDisplayModes(int dxversion, EnumDisplayModes1_Type pEnumDisplayModes, LPDIRECTDRAW lpdd, DWORD dwflags, LPDDSURFACEDESC lpddsd, LPVOID lpContext, LPDDENUMMODESCALLBACK cb)
{
HRESULT res;
SupportedRes_Type *SupportedRes;
NewContext_Type NewContext;
OutTraceDDRAW("EnumDisplayModes(D%d): lpdd=%x flags=%x lpddsd=%x callback=%x\n", dxversion, lpdd, dwflags, lpddsd, cb);
if(lpddsd) OutTraceDDRAW("EnumDisplayModes(D): %s\n", LogSurfaceAttributes(lpddsd, "EnumDisplayModes", __LINE__));
if(dxw.dwFlags4 & NATIVERES){
NewContext.dwWidth = 0;
NewContext.dwHeight = 0;
NewContext.lpContext = lpContext;
NewContext.lpCallback = cb;
NewContext.dxversion = dxversion;
res=(*pEnumDisplayModes)(lpdd, dwflags, lpddsd, &NewContext, myEnumModesFilterNative);
if(res) OutTraceE("EnumDisplayModes(D): ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return res;
}
// note: extEnumDisplayModes serves both the EnumDisplayModes and EnumDisplayModes2 interfaces:
// they differ for the lpddsd argument that should point to either DDSURFACEDESC or DDSURFACEDESC2
// structures, but unification is possible if the lpddsd->dwSize is properly set and is left untouched.
if((dxw.dwFlags1 & EMULATESURFACE)){
int SupportedDepths[5]={8,16,24,32,0};
int ResIdx, DepthIdx;
DDSURFACEDESC2 EmuDesc;
DWORD dwSize;
EmuDesc.dwRefreshRate = 0;
EmuDesc.ddpfPixelFormat.dwFlags = DDPF_RGB;
if (lpddsd) dwSize=lpddsd->dwSize; // sizeof either DDSURFACEDESC or DDSURFACEDESC2 !!!
else dwSize= (dxversion < 4) ? sizeof(DDSURFACEDESC) : sizeof(DDSURFACEDESC2);
memset(&EmuDesc, 0, dwSize);
EmuDesc.dwSize=dwSize;
EmuDesc.dwFlags=DDSD_PIXELFORMAT|DDSD_REFRESHRATE|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH;
SupportedRes = (dxw.dwFlags4 & SUPPORTHDTV) ? &SupportedHDTVRes[0] : &SupportedSVGARes[0];
res=DD_OK;
for (ResIdx=0; SupportedRes[ResIdx].h; ResIdx++){
EmuDesc.dwHeight=SupportedRes[ResIdx].h;
EmuDesc.dwWidth=SupportedRes[ResIdx].w;
if((dxw.dwFlags4 & LIMITSCREENRES) &&
CheckResolutionLimit((LPDDSURFACEDESC)&EmuDesc)) break;
EmuDesc.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT);
EmuDesc.ddpfPixelFormat.dwFlags=DDPF_RGB;
for (DepthIdx=0; SupportedDepths[DepthIdx]; DepthIdx++) {
// v2.03.24: if lpddsd is not null, compatible colr depth must be selected. Skip incompatible ones.
// Fixes "Total Annihilation Kingdoms" crash
if(lpddsd && (lpddsd->dwFlags & DDSD_PIXELFORMAT) && (lpddsd->ddpfPixelFormat.dwRGBBitCount != SupportedDepths[DepthIdx])) continue;
EmuDesc.ddpfPixelFormat.dwRGBBitCount=SupportedDepths[DepthIdx];
EmuDesc.lPitch=SupportedRes[ResIdx].w * SupportedDepths[DepthIdx] / 8;
FixPixelFormat(EmuDesc.ddpfPixelFormat.dwRGBBitCount, &(EmuDesc.ddpfPixelFormat));
if(IsDebug) EnumModesCallbackDumper((LPDDSURFACEDESC)&EmuDesc, lpContext);
res=(*cb)((LPDDSURFACEDESC)&EmuDesc, lpContext);
if(res==DDENUMRET_CANCEL) break;
}
if(res==DDENUMRET_CANCEL) break;
}
res=DD_OK;
}
else{
DDSURFACEDESC2 EmuDesc;
memset(&EmuDesc, 0, sizeof(EmuDesc));
EmuDesc.dwSize = sizeof(DDSURFACEDESC); // using release 1 type ....
res=myGetDisplayMode(dxversion, lpdd, (LPDDSURFACEDESC)&EmuDesc);
if(res){
OutTraceE("EnumDisplayModes(D): GetDisplayMode ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return res;
}
NewContext_Type NewContext;
NewContext.dwWidth = EmuDesc.dwWidth;
NewContext.dwHeight = EmuDesc.dwHeight;
NewContext.lpContext=lpContext;
NewContext.lpCallback=cb;
res=(*pEnumDisplayModes)(lpdd, dwflags, lpddsd, &NewContext, myEnumModesFilterDirect);
}
if(res) OutTraceE("EnumDisplayModes(D): ERROR res=%x(%s)\n", res, ExplainDDError(res));
return res;
}
HRESULT WINAPI extEnumDisplayModes1(LPDIRECTDRAW lpdd, DWORD dwflags, LPDDSURFACEDESC lpddsd, LPVOID lpContext, LPDDENUMMODESCALLBACK cb)
{ return extEnumDisplayModes(1, pEnumDisplayModes1, lpdd, dwflags, lpddsd, lpContext, cb); }
HRESULT WINAPI extEnumDisplayModes2(LPDIRECTDRAW lpdd, DWORD dwflags, LPDDSURFACEDESC lpddsd, LPVOID lpContext, LPDDENUMMODESCALLBACK cb)
{ return extEnumDisplayModes(2, pEnumDisplayModes2, lpdd, dwflags, lpddsd, lpContext, cb); }
HRESULT WINAPI extEnumDisplayModes4(LPDIRECTDRAW lpdd, DWORD dwflags, LPDDSURFACEDESC2 lpddsd, LPVOID lpContext, LPDDENUMMODESCALLBACK2 cb)
{ return extEnumDisplayModes(4, (EnumDisplayModes1_Type)pEnumDisplayModes4, lpdd, dwflags, (LPDDSURFACEDESC)lpddsd, lpContext, (LPDDENUMMODESCALLBACK)cb); }
HRESULT WINAPI extEnumDisplayModes7(LPDIRECTDRAW lpdd, DWORD dwflags, LPDDSURFACEDESC2 lpddsd, LPVOID lpContext, LPDDENUMMODESCALLBACK2 cb)
{ return extEnumDisplayModes(7, (EnumDisplayModes1_Type)pEnumDisplayModes7, lpdd, dwflags, (LPDDSURFACEDESC)lpddsd, lpContext, (LPDDENUMMODESCALLBACK)cb); }
HRESULT WINAPI extGetPixelFormat(GetPixelFormat_Type pGetPixelFormat, LPDIRECTDRAWSURFACE lpdds, LPDDPIXELFORMAT p)
{
DWORD res;
BOOL IsPrim;
IsPrim=dxwss.IsAPrimarySurface(lpdds);
OutTraceDDRAW("GetPixelFormat: lpdds=%x%s\n", lpdds, IsPrim?"(PRIM)":"");
res=(*pGetPixelFormat)(lpdds, p);
if(res){
OutTraceE("GetPixelFormat: ERROR res=%x(%s)\n", res, ExplainDDError(res));
}
else{
OutTraceDDRAW("GetPixelFormat: Flags=%x(%s) FourCC=%x BitCount=%d RGBA=(%x,%x,%x,%x)\n",
p->dwFlags, ExplainPixelFormatFlags(p->dwFlags), p->dwFourCC, p->dwRGBBitCount,
p->dwRBitMask, p->dwGBitMask, p->dwBBitMask, p->dwRGBAlphaBitMask );
}
// fix: virtual pixel definition is helpful not only on promary surfaces, but more in general
// on every surface that returns an error. It fixes "Arx Fatalis" crash.
if ((dxw.dwFlags1 & EMULATESURFACE) && res){
p->dwFlags = dxw.VirtualPixelFormat.dwFlags;
p->dwRGBBitCount= dxw.VirtualPixelFormat.dwRGBBitCount;
p->dwRBitMask = dxw.VirtualPixelFormat.dwRBitMask;
p->dwGBitMask = dxw.VirtualPixelFormat.dwGBitMask;
p->dwBBitMask = dxw.VirtualPixelFormat.dwBBitMask;
p->dwRGBAlphaBitMask = dxw.VirtualPixelFormat.dwRGBAlphaBitMask;
OutTraceDW("GetPixelFormat: EMULATED BitCount=%d RGBA=(%x,%x,%x,%x)\n",
p->dwRGBBitCount, p->dwRBitMask, p->dwGBitMask, p->dwBBitMask, p->dwRGBAlphaBitMask );
res = DD_OK;
}
return res;
}
HRESULT WINAPI extGetPixelFormat1(LPDIRECTDRAWSURFACE lpdds, LPDDPIXELFORMAT p)
{ return extGetPixelFormat(pGetPixelFormat1, lpdds, p); }
HRESULT WINAPI extGetPixelFormat2(LPDIRECTDRAWSURFACE lpdds, LPDDPIXELFORMAT p)
{ return extGetPixelFormat(pGetPixelFormat2, lpdds, p); }
HRESULT WINAPI extGetPixelFormat3(LPDIRECTDRAWSURFACE lpdds, LPDDPIXELFORMAT p)
{ return extGetPixelFormat(pGetPixelFormat3, lpdds, p); }
HRESULT WINAPI extGetPixelFormat4(LPDIRECTDRAWSURFACE lpdds, LPDDPIXELFORMAT p)
{ return extGetPixelFormat(pGetPixelFormat4, lpdds, p); }
HRESULT WINAPI extGetPixelFormat7(LPDIRECTDRAWSURFACE lpdds, LPDDPIXELFORMAT p)
{ return extGetPixelFormat(pGetPixelFormat7, lpdds, p); }
HRESULT WINAPI extTestCooperativeLevel(TestCooperativeLevel_Type pTestCooperativeLevel, LPDIRECTDRAW lpdd)
{
HRESULT res;
res=(*pTestCooperativeLevel)(lpdd);
OutTraceB("TestCooperativeLevel: lpdd=%x res=%x(%s)\n", lpdd, res, ExplainDDError(res));
if(res==DDERR_WRONGMODE) {
res=((LPDIRECTDRAW7)lpdd)->RestoreAllSurfaces();
if(res) OutTraceE("TestCooperativeLevel: RestoreAllSurfaces ERROR res=%x(%s)\n", res, ExplainDDError(res));
}
if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=DD_OK;
return res;
}
HRESULT WINAPI extTestCooperativeLevel4(LPDIRECTDRAW lpdd)
{ return extTestCooperativeLevel(pTestCooperativeLevel4, lpdd); }
HRESULT WINAPI extTestCooperativeLevel7(LPDIRECTDRAW lpdd)
{ return extTestCooperativeLevel(pTestCooperativeLevel7, lpdd); }
HRESULT WINAPI extReleaseS(ReleaseS_Type pReleaseS, LPDIRECTDRAWSURFACE lpdds)
{
HRESULT res;
BOOL IsPrim;
BOOL IsBack;
IsPrim=dxwss.IsAPrimarySurface(lpdds);
IsBack=dxwss.IsABackBufferSurface(lpdds);
// fix for Tetris World .... ???
if (IsBack && (dxw.dwFlags6 & SUPPRESSRELEASE)) {
OutTraceDDRAW("Release(S): SUPPRESS lpdds=%x%s res=0\n", lpdds, dxwss.ExplainSurfaceRole(lpdds));
return 0;
}
res = (*pReleaseS)(lpdds);
OutTraceDDRAW("Release(S): lpdds=%x%s refcount=%d\n", lpdds, dxwss.ExplainSurfaceRole(lpdds), res);
if (res==0) { // common precondition
// erase surface from primary or backbuffer list
// v2-03-20: d3d 1-7 play a dirty trick: it Release the surface passed as argument until refcount == 0,
// but then rebuilds it with the original attributes! So, better not forget them.
if(IsPrim || IsBack) dxwss.UnrefSurface(lpdds);
// when releasing primary surface, erase clipping region
if(IsPrim && (dxw.dwFlags1 & CLIPCURSOR)) dxw.EraseClipCursor();
// clear service surface pointers
if (dxw.dwFlags1 & EMULATESURFACE) {
if(lpdds==lpDDSEmu_Prim) {
OutTraceDW("Release(S): Clearing lpDDSEmu_Prim pointer\n");
lpDDSEmu_Prim=NULL;
}
if(lpdds==lpDDSEmu_Back) {
OutTraceDW("Release(S): Clearing lpDDSEmu_Back pointer\n");
lpDDSEmu_Back=NULL;
}
}
}
if(dxw.dwFlags4 & RETURNNULLREF) return 0;
return res;
}
HRESULT WINAPI extReleaseS1(LPDIRECTDRAWSURFACE lpdds)
{ return extReleaseS(pReleaseS1, lpdds); }
HRESULT WINAPI extReleaseS2(LPDIRECTDRAWSURFACE lpdds)
{ return extReleaseS(pReleaseS2, lpdds); }
HRESULT WINAPI extReleaseS3(LPDIRECTDRAWSURFACE lpdds)
{ return extReleaseS(pReleaseS3, lpdds); }
HRESULT WINAPI extReleaseS4(LPDIRECTDRAWSURFACE lpdds)
{ return extReleaseS(pReleaseS4, lpdds); }
HRESULT WINAPI extReleaseS7(LPDIRECTDRAWSURFACE lpdds)
{ return extReleaseS(pReleaseS7, lpdds); }
static HRESULT WINAPI extSetColorKey(SetColorKey_Type pSetColorKey, LPDIRECTDRAWSURFACE lpdds, DWORD flags, LPDDCOLORKEY lpDDColorKey)
{
HRESULT res;
BOOL IsPrim;
IsPrim=dxwss.IsAPrimarySurface(lpdds);
if(IsTraceDDRAW){
char sInfo[81];
if (lpDDColorKey) sprintf(sInfo, "(L:%x,H:%x)",lpDDColorKey->dwColorSpaceLowValue, lpDDColorKey->dwColorSpaceHighValue);
else strcpy(sInfo, "(NULL)");
OutTrace("SetColorKey: lpdds=%x%s flags=%x(%s) colors=%s\n",
lpdds, (IsPrim ? "(PRIM)" : ""), flags, ExplainColorKeyFlag(flags), sInfo);
}
res=(*pSetColorKey)(lpdds, flags, lpDDColorKey);
if(res) OutTraceE("SetColorKey: ERROR flags=%x lpdds=%x res=%x(%s)\n",
flags, lpdds, res, ExplainDDError(res));
return res;
}
HRESULT WINAPI extSetColorKey1(LPDIRECTDRAWSURFACE lpdds, DWORD flags, LPDDCOLORKEY lpDDColorKey)
{ return extSetColorKey(pSetColorKey1, lpdds, flags, lpDDColorKey); }
HRESULT WINAPI extSetColorKey2(LPDIRECTDRAWSURFACE lpdds, DWORD flags, LPDDCOLORKEY lpDDColorKey)
{ return extSetColorKey(pSetColorKey2, lpdds, flags, lpDDColorKey); }
HRESULT WINAPI extSetColorKey3(LPDIRECTDRAWSURFACE lpdds, DWORD flags, LPDDCOLORKEY lpDDColorKey)
{ return extSetColorKey(pSetColorKey3, lpdds, flags, lpDDColorKey); }
HRESULT WINAPI extSetColorKey4(LPDIRECTDRAWSURFACE lpdds, DWORD flags, LPDDCOLORKEY lpDDColorKey)
{ return extSetColorKey(pSetColorKey4, lpdds, flags, lpDDColorKey); }
HRESULT WINAPI extSetColorKey7(LPDIRECTDRAWSURFACE lpdds, DWORD flags, LPDDCOLORKEY lpDDColorKey)
{ return extSetColorKey(pSetColorKey7, lpdds, flags, lpDDColorKey); }
static HRESULT WINAPI extGetColorKey(GetColorKey_Type pGetColorKey, LPDIRECTDRAWSURFACE lpdds, DWORD flags, LPDDCOLORKEY lpDDColorKey)
{
HRESULT res;
BOOL IsPrim;
IsPrim=dxwss.IsAPrimarySurface(lpdds);
OutTraceDDRAW("GetColorKey(S): lpdds=%x%s flags=%x(%s)\n",
lpdds, (IsPrim ? "(PRIM)" : ""), flags, ExplainColorKeyFlag(flags));
res=(*pGetColorKey)(lpdds, flags, lpDDColorKey);
if(res)
OutTraceE("GetColorKey: ERROR lpdds=%x flags=%x res=%x(%s)\n", lpdds, flags, res, ExplainDDError(res));
else
OutTraceDDRAW("GetColorKey: colors=(L:%x,H:%x)\n",
lpDDColorKey->dwColorSpaceLowValue, lpDDColorKey->dwColorSpaceHighValue);
return res;
}
HRESULT WINAPI extGetColorKey1(LPDIRECTDRAWSURFACE lpdds, DWORD flags, LPDDCOLORKEY lpDDColorKey)
{ return extGetColorKey(pGetColorKey1, lpdds, flags, lpDDColorKey); }
HRESULT WINAPI extGetColorKey2(LPDIRECTDRAWSURFACE lpdds, DWORD flags, LPDDCOLORKEY lpDDColorKey)
{ return extGetColorKey(pGetColorKey2, lpdds, flags, lpDDColorKey); }
HRESULT WINAPI extGetColorKey3(LPDIRECTDRAWSURFACE lpdds, DWORD flags, LPDDCOLORKEY lpDDColorKey)
{ return extGetColorKey(pGetColorKey3, lpdds, flags, lpDDColorKey); }
HRESULT WINAPI extGetColorKey4(LPDIRECTDRAWSURFACE lpdds, DWORD flags, LPDDCOLORKEY lpDDColorKey)
{ return extGetColorKey(pGetColorKey4, lpdds, flags, lpDDColorKey); }
HRESULT WINAPI extGetColorKey7(LPDIRECTDRAWSURFACE lpdds, DWORD flags, LPDDCOLORKEY lpDDColorKey)
{ return extGetColorKey(pGetColorKey7, lpdds, flags, lpDDColorKey); }
static HRESULT WINAPI extEnumAttachedSurfaces(EnumAttachedSurfaces_Type pEnumAttachedSurfaces, LPDIRECTDRAWSURFACE lpdds, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback)
{
HRESULT res;
BOOL IsPrim;
IsPrim=dxwss.IsAPrimarySurface(lpdds);
OutTraceDDRAW("EnumAttachedSurfaces: lpdds=%x%s Context=%x Callback=%x\n",
lpdds, (IsPrim ? "(PRIM)":""), lpContext, lpEnumSurfacesCallback);
if (IsPrim){
LPDIRECTDRAWSURFACE lpDDSBack;
// A Primary surface has not backbuffer attached surfaces actually,
// so don't rely on ddraw and call the callback function directly.
// Needed to make Nox working.
DDSURFACEDESC2 ddsd;
// first, call hooked function
res=(*pEnumAttachedSurfaces)(lpdds, lpContext, lpEnumSurfacesCallback);
if (res)
OutTraceE("EnumAttachedSurfaces: ERROR %x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
if(lpDDSBack = dxwss.GetBackBufferSurface()){
ddsd.dwSize=Set_dwSize_From_Surface();
res=lpDDSBack->GetSurfaceDesc((LPDDSURFACEDESC)&ddsd);
if(res){
OutTraceE("EnumAttachedSurfaces: GetSurfaceDesc ERROR %x(%s)\n",
res, ExplainDDError(res));
return res;
}
res=(lpEnumSurfacesCallback)(lpDDSBack, (LPDDSURFACEDESC)&ddsd, lpContext);
OutTraceDW("EnumSurfacesCallback: on DDSBack res=%x(%s)\n", res, ExplainDDError(res));
}
res=DD_OK; // for Black Dahlia
}
else {
res=(*pEnumAttachedSurfaces)(lpdds, lpContext, lpEnumSurfacesCallback);
if (res)
OutTraceE("EnumAttachedSurfaces: ERROR %x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
}
return res;
}
HRESULT WINAPI extEnumAttachedSurfaces1(LPDIRECTDRAWSURFACE lpdds, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback)
{ return extEnumAttachedSurfaces(pEnumAttachedSurfaces1, lpdds, lpContext, lpEnumSurfacesCallback); }
HRESULT WINAPI extEnumAttachedSurfaces2(LPDIRECTDRAWSURFACE lpdds, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback)
{ return extEnumAttachedSurfaces(pEnumAttachedSurfaces2, lpdds, lpContext, lpEnumSurfacesCallback); }
HRESULT WINAPI extEnumAttachedSurfaces3(LPDIRECTDRAWSURFACE lpdds, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback)
{ return extEnumAttachedSurfaces(pEnumAttachedSurfaces3, lpdds, lpContext, lpEnumSurfacesCallback); }
HRESULT WINAPI extEnumAttachedSurfaces4(LPDIRECTDRAWSURFACE lpdds, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback)
{ return extEnumAttachedSurfaces(pEnumAttachedSurfaces4, lpdds, lpContext, lpEnumSurfacesCallback); }
HRESULT WINAPI extEnumAttachedSurfaces7(LPDIRECTDRAWSURFACE lpdds, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback)
{ return extEnumAttachedSurfaces(pEnumAttachedSurfaces7, lpdds, lpContext, lpEnumSurfacesCallback); }
static HRESULT WINAPI extAddAttachedSurface(AddAttachedSurface_Type pAddAttachedSurface, LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWSURFACE lpddsadd)
{
HRESULT res;
BOOL IsPrim, IsBack;
// You can add backbuffers to primary surfaces to join the flipping chain, but you can't do that
// to an emulated primary surface, and you receive a DDERR_CANNOTATTACHSURFACE error code.
// In that case, it's worth to try to emulate the attach, and since the Flip method is emulated,
// just remember this for further handling in the Flip operation.
// But beware: this holds to BACKBUFFER surfaces only, and NOT for attached ZBUFFERS or similar!
IsPrim=dxwss.IsAPrimarySurface(lpdds);
IsBack=dxwss.IsABackBufferSurface(lpdds);
OutTraceDDRAW("AddAttachedSurface: lpdds=%x%s lpddsadd=%x%s\n", lpdds, IsPrim?"(PRIM)":(IsBack?"(BACK)":""), lpddsadd, (lpddsadd==lpDDZBuffer)?"(ZBUF)":"");
//if(!lpddsadd) return DDERR_CANNOTATTACHSURFACE; // to avoid a crash...
res=(*pAddAttachedSurface)(lpdds, lpddsadd);
if (res) {
HRESULT sdres;
DDSURFACEDESC2 sd;
if (res) OutTraceE("AddAttachedSurface: ERROR %x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
sd.dwSize=Set_dwSize_From_Surface();
sdres=lpddsadd->GetSurfaceDesc((DDSURFACEDESC *)&sd);
if (sdres)
OutTraceE("AddAttachedSurface: GetSurfaceDesc ERROR res=%x at %d\n", sdres, __LINE__);
else
OutTraceDW("AddAttachedSurface: GetSurfaceDesc dwCaps=%x(%s)\n",
sd.ddsCaps.dwCaps, ExplainDDSCaps(sd.ddsCaps.dwCaps));
if (IsPrim){
if (sd.ddsCaps.dwCaps & DDSCAPS_BACKBUFFER)
if ((dxw.dwFlags1 & EMULATESURFACE) && (res==DDERR_CANNOTATTACHSURFACE) ||
(res==DDERR_NOEXCLUSIVEMODE))
OutTraceDW("AddAttachedSurface: emulating BACKBUFFER attach on PRIMARY\n");
dxwss.PushBackBufferSurface(lpddsadd, 1);
if (pAddRefS) (*pAddRefS)(lpdds);
res=DD_OK;
}
//else if (IsBack) {
else {
// v2.02.13: emulate ZBUFFER attach to backbuffer: do nothing and return OK
// this trick makes at least "Nocturne" work also in emulated mode when hardware acceleration
// is set in the game "Options" menu.
if (sd.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) // DDSCAPS_BACKBUFFER for double buffering ???
if ((dxw.dwFlags1 & EMULATESURFACE) && (res==DDERR_CANNOTATTACHSURFACE)){
OutTraceDW("AddAttachedSurface: emulating ZBUFFER attach on BACKBUFFER\n");
if (pAddRefS) (*pAddRefS)(lpdds);
res=DD_OK;
}
}
}
if (res) OutTraceE("AddAttachedSurface: ERROR %x(%s)\n", res, ExplainDDError(res));
return res;
}
HRESULT WINAPI extAddAttachedSurface1(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWSURFACE lpddsadd)
{ return extAddAttachedSurface(pAddAttachedSurface1, lpdds, lpddsadd); }
HRESULT WINAPI extAddAttachedSurface2(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWSURFACE lpddsadd)
{ return extAddAttachedSurface(pAddAttachedSurface2, lpdds, lpddsadd); }
HRESULT WINAPI extAddAttachedSurface3(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWSURFACE lpddsadd)
{ return extAddAttachedSurface(pAddAttachedSurface3, lpdds, lpddsadd); }
HRESULT WINAPI extAddAttachedSurface4(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWSURFACE lpddsadd)
{ return extAddAttachedSurface(pAddAttachedSurface4, lpdds, lpddsadd); }
HRESULT WINAPI extAddAttachedSurface7(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWSURFACE lpddsadd)
{ return extAddAttachedSurface(pAddAttachedSurface7, lpdds, lpddsadd); }
static HRESULT WINAPI extDeleteAttachedSurface(DeleteAttachedSurface_Type pDeleteAttachedSurface, LPDIRECTDRAWSURFACE lpdds, DWORD dwflags, LPDIRECTDRAWSURFACE lpddsdel)
{
HRESULT res;
OutTraceDDRAW("DeleteAttachedSurface: lpdds=%x flags=%x lpddsdel=%x\n", lpdds, dwflags, lpddsdel);
res=(*pDeleteAttachedSurface)(lpdds, dwflags, lpddsdel);
if(res) OutTraceE("DeleteAttachedSurface: ERROR %x(%s)\n", res, ExplainDDError(res));
if (res && dxwss.IsABackBufferSurface(lpddsdel)){
OutTraceDW("DeleteAttachedSurface: emulating surface detach lpdds=%x\n", lpddsdel);
res = DD_OK;
}
if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=DD_OK;
return res;
}
HRESULT WINAPI extDeleteAttachedSurface1(LPDIRECTDRAWSURFACE lpdds, DWORD dwflags, LPDIRECTDRAWSURFACE lpddsdel)
{ return extDeleteAttachedSurface(pDeleteAttachedSurface1, lpdds, dwflags, lpddsdel); }
HRESULT WINAPI extDeleteAttachedSurface2(LPDIRECTDRAWSURFACE lpdds, DWORD dwflags, LPDIRECTDRAWSURFACE lpddsdel)
{ return extDeleteAttachedSurface(pDeleteAttachedSurface2, lpdds, dwflags, lpddsdel); }
HRESULT WINAPI extDeleteAttachedSurface3(LPDIRECTDRAWSURFACE lpdds, DWORD dwflags, LPDIRECTDRAWSURFACE lpddsdel)
{ return extDeleteAttachedSurface(pDeleteAttachedSurface3, lpdds, dwflags, lpddsdel); }
HRESULT WINAPI extDeleteAttachedSurface4(LPDIRECTDRAWSURFACE lpdds, DWORD dwflags, LPDIRECTDRAWSURFACE lpddsdel)
{ return extDeleteAttachedSurface(pDeleteAttachedSurface4, lpdds, dwflags, lpddsdel); }
HRESULT WINAPI extDeleteAttachedSurface7(LPDIRECTDRAWSURFACE lpdds, DWORD dwflags, LPDIRECTDRAWSURFACE lpddsdel)
{ return extDeleteAttachedSurface(pDeleteAttachedSurface7, lpdds, dwflags, lpddsdel); }
HRESULT WINAPI cbDump(LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext)
{
OutTraceDW("EnumDisplayModes: CALLBACK lpdds=%x Context=%x Caps=%x(%s)\n",
lpDDSurfaceDesc, lpContext,
lpDDSurfaceDesc->ddsCaps.dwCaps, ExplainDDSCaps(lpDDSurfaceDesc->ddsCaps.dwCaps));
return 1;
}
static HRESULT WINAPI extGetCapsS(int dxInterface, GetCapsS_Type pGetCapsS, LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS caps)
{
HRESULT res;
BOOL IsPrim, IsBack, IsFixed;
IsPrim=dxwss.IsAPrimarySurface(lpdds);
IsBack=dxwss.IsABackBufferSurface(lpdds);
IsFixed=FALSE;
char *sLabel;
sLabel = IsPrim?"(PRIM)":(IsBack ? "(BACK)" : "");
res=(*pGetCapsS)(lpdds, caps);
if(res)
OutTraceE("GetCaps(S%d): ERROR lpdds=%x%s err=%x(%s)\n", dxInterface, lpdds, sLabel, res, ExplainDDError(res));
else
OutTraceDDRAW("GetCaps(S%d): lpdds=%x%s caps=%x(%s)\n", dxInterface, lpdds, sLabel, caps->dwCaps, ExplainDDSCaps(caps->dwCaps));
if (IsPrim) {
IsFixed=TRUE;
sLabel="PRIMARYSURFACE";
caps->dwCaps |= DDSD_Prim.ddsCaps.dwCaps;
caps->dwCaps |= DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER|DDSCAPS_VIDEOMEMORY|DDSCAPS_VISIBLE; // primary surfaces must be this way
caps->dwCaps &= ~(DDSCAPS_SYSTEMMEMORY|DDSCAPS_OFFSCREENPLAIN); // primary surfaces can't be this way
if(caps->dwCaps & DDSCAPS_3DDEVICE) caps->dwCaps |= DDSCAPS_LOCALVIDMEM;
}
if (IsBack) {
IsFixed=TRUE;
sLabel="BACKBUFFER";
// v2.03.11: added DDSCAPS_FLIP capability to backbuffer surface: "Ignition" checks for it before Flip-ping to primary
caps->dwCaps |= (DDSCAPS_BACKBUFFER|DDSCAPS_VIDEOMEMORY|DDSCAPS_FLIP|DDSCAPS_LOCALVIDMEM); // you never know....
caps->dwCaps &= ~(DDSCAPS_SYSTEMMEMORY|DDSCAPS_OFFSCREENPLAIN); // backbuffer surfaces can't be this way
if(caps->dwCaps & DDSCAPS_3DDEVICE) caps->dwCaps |= DDSCAPS_LOCALVIDMEM;
}
// v2.03.82: fixed logic for ZBUFFER capabilities: "The Creed" may have two, in SYSTEMMEMORY or in VIDEOMEMORY ...
if(caps->dwCaps & DDSCAPS_ZBUFFER) {
DWORD dwCaps;
dwCaps = dxwcdb.GetCaps(lpdds);
// beware! the ZBUFFER surface could have never been registered!
// in this case better keep the original capabilities (or adapt to the primary/backbuffer ones?)
if(dwCaps) {
caps->dwCaps = dwCaps;
OutTraceDW("GetCaps: FIXED ZBUFFER caps=%x(%s)\n", caps->dwCaps, ExplainDDSCaps(caps->dwCaps));
}
else {
OutTraceDW("GetCaps: UNREGISTERED ZBUFFER caps=%x(%s)\n", caps->dwCaps, ExplainDDSCaps(caps->dwCaps));
}
}
// v2.03.78: fix for "Gothik 2": pretend that 3DDEVICE surface are ALWAYS in video memory
if (caps->dwCaps & DDSCAPS_3DDEVICE){
caps->dwCaps |= (DDSCAPS_VIDEOMEMORY|DDSCAPS_LOCALVIDMEM);
caps->dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
}
if(IsFixed) OutTraceDW("GetCaps(S%d): lpdds=%x FIXED %s caps=%x(%s)\n", dxInterface, lpdds, sLabel, caps->dwCaps, ExplainDDSCaps(caps->dwCaps));
return res;
}
HRESULT WINAPI extGetCaps1S(LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS caps)
{ return extGetCapsS(1, pGetCaps1S, lpdds, caps); }
HRESULT WINAPI extGetCaps2S(LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS caps)
{ return extGetCapsS(2, pGetCaps2S, lpdds, caps); }
HRESULT WINAPI extGetCaps3S(LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS caps)
{ return extGetCapsS(3, pGetCaps3S, lpdds, caps); }
HRESULT WINAPI extGetCaps4S(LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS2 caps)
{ return extGetCapsS(4, (GetCapsS_Type)pGetCaps4S, lpdds, (LPDDSCAPS)caps); }
HRESULT WINAPI extGetCaps7S(LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS2 caps)
{ return extGetCapsS(7, (GetCapsS_Type)pGetCaps7S, lpdds, (LPDDSCAPS)caps); }
static ULONG WINAPI extReleaseD(int dxversion, ReleaseD_Type pReleaseD, LPDIRECTDRAW lpdd)
{
ULONG ActualRef;
LONG VirtualRef;
OutTraceDDRAW("Release(D%d): lpdd=%x\n", dxversion, lpdd);
if((ReleaseD_Type)extReleaseD == pReleaseD) {
OutTraceE("Release(D) ERROR: bad hooker pReleaseD=%x\n", pReleaseD);
return 0;
}
ActualRef=(*pReleaseD)(lpdd);
VirtualRef=(LONG)ActualRef;
OutTraceDW("Release(D): lpdd=%x service_lpdd=%x ref=%d\n", lpdd, lpPrimaryDD, ActualRef);
if (lpdd == lpPrimaryDD) { // v2.1.87: fix for Dungeon Keeper II
if(dxw.dwFlags4 & FIXREFCOUNTER){
// v2.02.41: fix the ref counter to sumulate the unwindowed original situation
--VirtualRef; // why ????
if(dxwss.GetBackBufferSurface()) --VirtualRef;
if(dxw.dwFlags1 & EMULATESURFACE){
if(lpDDSEmu_Prim) --VirtualRef;
if(lpDDSEmu_Back) --VirtualRef;
}
if(VirtualRef<0) VirtualRef=0;
OutTraceDW("Release(D): fixed ref counter %d->%d\n", ActualRef, VirtualRef);
}
if((dxversion<4) && (ActualRef==0)){
// directdraw old versions automatically free all linked objects when the parent session is closed.
OutTraceDW("Release(D): RefCount=0 - service object RESET condition\n");
lpDDSEmu_Prim=NULL;
lpDDSEmu_Back=NULL;
lpDDP=NULL;
iDDPExtraRefCounter = 0;
}
if(ActualRef==0) lpPrimaryDD=NULL; // v2.03.61
}
// when lpdd session is closed (ref==0) the system restores the default color depth
// so if FORCE16BPP is set, dxwnd must restore the 16BPP value
//extern void SwitchTo16BPP();
//if((ActualRef==0) && (dxw.dwFlags3 & FORCE16BPP)) SwitchTo16BPP();
OutTraceDDRAW("Release(D): lpdd=%x ref=%x\n", lpdd, VirtualRef);
if(dxw.dwFlags4 & RETURNNULLREF) return 0;
return (ULONG)VirtualRef;
}
ULONG WINAPI extReleaseD1(LPDIRECTDRAW lpdd)
{ return extReleaseD(1, pReleaseD1, lpdd); }
ULONG WINAPI extReleaseD2(LPDIRECTDRAW lpdd)
{ return extReleaseD(2, pReleaseD2, lpdd); }
ULONG WINAPI extReleaseD4(LPDIRECTDRAW lpdd)
{ return extReleaseD(4, pReleaseD4, lpdd); }
ULONG WINAPI extReleaseD7(LPDIRECTDRAW lpdd)
{ return extReleaseD(7, pReleaseD7, lpdd); }
static HRESULT WINAPI extCreateClipper(CreateClipper_Type pCreateClipper, LPDIRECTDRAW lpdd, DWORD dwflags,
LPDIRECTDRAWCLIPPER FAR* lplpDDClipper, IUnknown FAR* pUnkOuter)
{
HRESULT res;
OutTraceDDRAW("CreateClipper: lpdd=%x flags=%x\n", lpdd, dwflags);
res=(*pCreateClipper)(lpdd, dwflags, lplpDDClipper, pUnkOuter);
if(res) {
OutTraceE("CreateClipper: ERROR res=%x(%s)\n", lpdd, res, ExplainDDError(res));
return res;
}
HookDDClipper(lplpDDClipper); // there is a single Clipper intrface!
return res;
}
HRESULT WINAPI extCreateClipper1(LPDIRECTDRAW lpdd, DWORD dwflags, LPDIRECTDRAWCLIPPER FAR* lplpDDClipper, IUnknown FAR* pUnkOuter)
{ return extCreateClipper(pCreateClipper1, lpdd, dwflags, lplpDDClipper, pUnkOuter); }
HRESULT WINAPI extCreateClipper2(LPDIRECTDRAW lpdd, DWORD dwflags, LPDIRECTDRAWCLIPPER FAR* lplpDDClipper, IUnknown FAR* pUnkOuter)
{ return extCreateClipper(pCreateClipper2, lpdd, dwflags, lplpDDClipper, pUnkOuter); }
HRESULT WINAPI extCreateClipper4(LPDIRECTDRAW lpdd, DWORD dwflags, LPDIRECTDRAWCLIPPER FAR* lplpDDClipper, IUnknown FAR* pUnkOuter)
{ return extCreateClipper(pCreateClipper4, lpdd, dwflags, lplpDDClipper, pUnkOuter); }
HRESULT WINAPI extCreateClipper7(LPDIRECTDRAW lpdd, DWORD dwflags, LPDIRECTDRAWCLIPPER FAR* lplpDDClipper, IUnknown FAR* pUnkOuter)
{ return extCreateClipper(pCreateClipper7, lpdd, dwflags, lplpDDClipper, pUnkOuter); }
HRESULT WINAPI extReleaseC(LPDIRECTDRAWCLIPPER lpddClip)
{
ULONG ref;
ref = (*pReleaseC)(lpddClip);
OutTraceDDRAW("Release(C): PROXED lpddClip=%x ref=%x\n", lpddClip, ref);
return ref;
}
HRESULT WINAPI extGetClipList(LPDIRECTDRAWCLIPPER lpddClip, LPRECT lpRect, LPRGNDATA lpRgnData, LPDWORD lpw)
{
HRESULT res;
// returned clip region (both RgnData and single RECT array) should be relocated in window mode
// an easy way to do that, though not accurate, is to consider the clip region as the whole virtual screen
// a better way is to use the dxw.UnmapWindow(RECT *) method
// this makes "Full Pipe" working without clipping problems.
if(IsTraceDDRAW){
char sInfo[81];
if (lpRect) sprintf(sInfo, "rect=(%d,%d)-(%d,%d) ", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
else sprintf(sInfo, "rect=(NULL) ");
OutTrace("GetClipList(C): lpddClip=%x %s\n", lpddClip, sInfo);
}
res=(*pGetClipList)(lpddClip, lpRect, lpRgnData, lpw);
if(IsTraceDDRAW){
if(res) OutTrace("GetClipList(C): ERROR err=%x(%s)\n", res, ExplainDDError(res));
else{
if(lpRgnData){
OutTrace("GetClipList(C): w=%x rgndataheader{size=%d type=%x count=%d RgnSize=%d bound=(%d,%d)-(%d,%d)}\n",
*lpw, lpRgnData->rdh.dwSize, lpRgnData->rdh.iType, lpRgnData->rdh.nCount, lpRgnData->rdh.nRgnSize,
lpRgnData->rdh.rcBound.left, lpRgnData->rdh.rcBound.top, lpRgnData->rdh.rcBound.right, lpRgnData->rdh.rcBound.bottom);
if(dxw.Windowize && (dxw.dwFlags1 & CLIENTREMAPPING)){
dxw.UnmapWindow(&lpRgnData->rdh.rcBound);
//lpRgnData->rdh.rcBound = dxw.GetScreenRect();
OutTraceDW("GetClipList(C): w=%x rgndataheader{size=%d type=%x count=%d RgnSize=%d REMAPPED bound=(%d,%d)-(%d,%d)}\n",
*lpw, lpRgnData->rdh.dwSize, lpRgnData->rdh.iType, lpRgnData->rdh.nCount, lpRgnData->rdh.nRgnSize,
lpRgnData->rdh.rcBound.left, lpRgnData->rdh.rcBound.top, lpRgnData->rdh.rcBound.right, lpRgnData->rdh.rcBound.bottom);
}
if(IsDebug){
RECT *rgns;
rgns = (RECT *)lpRgnData->Buffer;
for(DWORD i=0; i<lpRgnData->rdh.nCount; i++){
OutTrace("GetClipList(C): rect[%d]=(%d,%d)-(%d,%d)\n",
i, rgns[i].left, rgns[i].top, rgns[i].right, rgns[i].bottom);
if(dxw.Windowize && (dxw.dwFlags1 & CLIENTREMAPPING)){
dxw.UnmapWindow(&rgns[i]);
//rgns[i] = dxw.GetScreenRect();
OutTrace("GetClipList(C): REMAPPED rect[%d]=(%d,%d)-(%d,%d)\n",
i, rgns[i].left, rgns[i].top, rgns[i].right, rgns[i].bottom);
}
}
}
}
else{
OutTrace("GetClipList(C): w=%x\n", *lpw);
}
}
}
return res;
}
HRESULT WINAPI extSetHWnd(LPDIRECTDRAWCLIPPER lpddClip, DWORD w, HWND hwnd)
{
HRESULT res;
OutTraceP("SetHWnd(C): lpddClip=%x w=%x hwnd=%x\n", lpddClip, w, hwnd);
res=(*pSetHWnd)(lpddClip, w, hwnd);
if(res) OutTraceP("SetHWnd(C): ERROR err=%x(%s)\n", res, ExplainDDError(res));
return res;
}
static HRESULT WINAPI extGetSurfaceDesc(int dxversion, GetSurfaceDesc_Type pGetSurfaceDesc, LPDIRECTDRAWSURFACE lpdds, LPDDSURFACEDESC lpddsd)
{
HRESULT res;
BOOL IsPrim, IsBack, IsFixed;
IsPrim=dxwss.IsAPrimarySurface(lpdds);
IsBack=dxwss.IsABackBufferSurface(lpdds);
IsFixed=FALSE;
if (!pGetSurfaceDesc) {
OutTraceE("GetSurfaceDesc: ERROR no hooked function\n");
return DDERR_INVALIDPARAMS;
}
#define FIXSURFACEDESCSIZE TRUE
if(FIXSURFACEDESCSIZE){
switch(dxversion){
case 1:
case 2:
case 3:
lpddsd->dwSize = sizeof(DDSURFACEDESC);
break;
case 4:
case 7:
lpddsd->dwSize = sizeof(DDSURFACEDESC2);
break;
}
}
res=(*pGetSurfaceDesc)(lpdds, lpddsd);
OutTraceDDRAW("GetSurfaceDesc: %slpdds=%x%s res=%x(%s)\n",
res?"ERROR ":"", lpdds, IsPrim?"(PRIM)":(IsBack?"(BACK)":""), res, ExplainDDError(res));
if(res) {
OutTraceE("GetSurfaceDesc: ERROR err=%x(%s) dxversion=%d s->len=%d at %d\n", res, ExplainDDError(res), dxversion, lpddsd->dwSize, __LINE__);
return res;
}
OutTraceDDRAW("GetSurfaceDesc: lpdds=%x %s\n", lpdds, LogSurfaceAttributes(lpddsd, "GetSurfaceDesc", __LINE__));
if (IsPrim) {
OutTraceDW("GetSurfaceDesc: fixing PRIMARY surface\n");
IsFixed=TRUE;
if (dxw.dwFlags1 & EMULATESURFACE) lpddsd->ddpfPixelFormat = dxw.VirtualPixelFormat;
lpddsd->ddsCaps.dwCaps |= DDSD_Prim.ddsCaps.dwCaps;
lpddsd->ddsCaps.dwCaps |= (DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER|DDSCAPS_VIDEOMEMORY|DDSCAPS_VISIBLE); // primary surfaces must be this way
lpddsd->ddsCaps.dwCaps &= ~(DDSCAPS_SYSTEMMEMORY|DDSCAPS_OFFSCREENPLAIN); // primary surfaces can't be this way
if(lpddsd->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) lpddsd->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
lpddsd->dwBackBufferCount=DDSD_Prim.dwBackBufferCount;
lpddsd->dwHeight=dxw.GetScreenHeight();
lpddsd->dwWidth=dxw.GetScreenWidth();
}
if (IsBack) {
OutTraceDW("GetSurfaceDesc: fixing BACKBUFFER surface\n");
IsFixed=TRUE;
// flags that backbuffer surfaces must have set
lpddsd->ddsCaps.dwCaps |= (DDSCAPS_3DDEVICE|DDSCAPS_BACKBUFFER|DDSCAPS_VIDEOMEMORY|DDSCAPS_LOCALVIDMEM);
// flags that backbuffer surfaces can't have set
lpddsd->ddsCaps.dwCaps &= ~(DDSCAPS_SYSTEMMEMORY|DDSCAPS_OFFSCREENPLAIN|DDSCAPS_COMPLEX|DDSCAPS_FLIP);
}
// v2.03.82: fixed logic for ZBUFFER capabilities: "The Creed" may have two, in SYSTEMMEMORY or in VIDEOMEMORY ...
if(lpddsd->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) {
lpddsd->ddsCaps.dwCaps = dxwcdb.GetCaps(lpdds);
OutTraceDW("GetSurfaceDesc: lpdds=%x %s\n", lpdds, LogSurfaceAttributes(lpddsd, "GetSurfaceDesc [FIXED]", __LINE__));
}
return DD_OK;
}
// Beware: despite the surface version, some game (The Sims!!!) intentionally uses a different dwSize, so that
// you shouldn't reset the value
HRESULT WINAPI extGetSurfaceDesc1(LPDIRECTDRAWSURFACE lpdds, LPDDSURFACEDESC lpddsd)
{ return extGetSurfaceDesc(1, pGetSurfaceDesc1, lpdds, lpddsd); }
HRESULT WINAPI extGetSurfaceDesc2(LPDIRECTDRAWSURFACE lpdds, LPDDSURFACEDESC lpddsd)
{ return extGetSurfaceDesc(2, pGetSurfaceDesc2, lpdds, lpddsd); }
HRESULT WINAPI extGetSurfaceDesc3(LPDIRECTDRAWSURFACE lpdds, LPDDSURFACEDESC lpddsd)
{ return extGetSurfaceDesc(3, pGetSurfaceDesc3, lpdds, lpddsd); }
HRESULT WINAPI extGetSurfaceDesc4(LPDIRECTDRAWSURFACE2 lpdds, LPDDSURFACEDESC2 lpddsd)
{ return extGetSurfaceDesc(4, (GetSurfaceDesc_Type)pGetSurfaceDesc4, (LPDIRECTDRAWSURFACE)lpdds, (LPDDSURFACEDESC)lpddsd); }
HRESULT WINAPI extGetSurfaceDesc7(LPDIRECTDRAWSURFACE2 lpdds, LPDDSURFACEDESC2 lpddsd)
{ return extGetSurfaceDesc(7, (GetSurfaceDesc_Type)pGetSurfaceDesc7, (LPDIRECTDRAWSURFACE)lpdds, (LPDDSURFACEDESC)lpddsd); }
HRESULT WINAPI extReleaseP(LPDIRECTDRAWPALETTE lpddPalette)
{
ULONG ref;
ref = (*pReleaseP)(lpddPalette);
OutTraceDDRAW("Release(P): lpddPalette=%x ref=%x\n", lpddPalette, ref);
if (lpddPalette == lpDDP) {
if(dxw.dwFlags4 & FIXREFCOUNTER) {
OutTraceDW("Release(P): lpDDP extrarefcount=%d\n", iDDPExtraRefCounter);
if((ULONG)iDDPExtraRefCounter >= ref){
while(ref) ref = (*pReleaseP)(lpddPalette);
lpDDP=NULL;
iDDPExtraRefCounter = 0;
return 0;
}
ref -= iDDPExtraRefCounter;
}
if (ref <= 0) {
ref = 0;
OutTraceDW("Release(P): clearing lpDDP=%x->NULL\n", lpDDP);
lpDDP=NULL;
}
if(dxw.dwFlags4 & RETURNNULLREF) ref = 0;
}
return ref;
}
BOOL FAR PASCAL DDEnumerateCallbackFilterW(GUID FAR *lpGuid, LPWSTR lpDriverDescription, LPWSTR lpDriverName, LPVOID lpContext)
{
BOOL res;
typedef struct {LPDDENUMCALLBACKW lpCallback; LPVOID lpContext;} Context_Type;
Context_Type *p=(Context_Type *)lpContext;
OutTraceDW("DDEnumerateCallback: guid=%x DriverDescription=\"%ls\" DriverName=\"%ls\" Context=%x\n",
lpGuid, lpDriverDescription, lpDriverName, p->lpContext);
if((lpGuid==NULL) || !(dxw.dwFlags2 & HIDEMULTIMONITOR)) res=(*p->lpCallback)(lpGuid, lpDriverDescription, lpDriverName, p->lpContext);
if((lpGuid==NULL) && (dxw.dwFlags2 & HIDEMULTIMONITOR)) res=FALSE;
OutTraceDW("DDEnumerateCallback: res=%x(%s)\n", res, res?"continue":"break");
return res;
}
BOOL FAR PASCAL DDEnumerateCallbackExFilterW(GUID FAR *lpGuid, LPWSTR lpDriverDescription, LPWSTR lpDriverName, LPVOID lpContext, HMONITOR hm)
{
BOOL res;
typedef struct {LPDDENUMCALLBACKEXW lpCallback; LPVOID lpContext;} Context_Type;
Context_Type *p=(Context_Type *)lpContext;
OutTraceDW("DDEnumerateCallbackEx: guid=%x DriverDescription=\"%ls\" DriverName=\"%ls\" Context=%x hm=%x\n",
lpGuid, lpDriverDescription, lpDriverName, lpContext, hm);
res=TRUE;
if((lpGuid==NULL) || !(dxw.dwFlags2 & HIDEMULTIMONITOR)) res=(*p->lpCallback)(lpGuid, lpDriverDescription, lpDriverName, p->lpContext, hm);
if((lpGuid==NULL) && (dxw.dwFlags2 & HIDEMULTIMONITOR)) res=FALSE;
OutTraceDW("DDEnumerateCallbackEx: res=%x(%s)\n", res, res?"continue":"break");
return res;
}
BOOL FAR PASCAL DDEnumerateCallbackFilterA(GUID FAR *lpGuid, LPSTR lpDriverDescription, LPSTR lpDriverName, LPVOID lpContext)
{
BOOL res;
typedef struct {LPDDENUMCALLBACK lpCallback; LPVOID lpContext;} Context_Type;
Context_Type *p=(Context_Type *)lpContext;
OutTraceDW("DDEnumerateCallback: guid=%x DriverDescription=\"%s\" DriverName=\"%s\" Context=%x\n",
lpGuid, lpDriverDescription, lpDriverName, p->lpContext);
if((lpGuid==NULL) || !(dxw.dwFlags2 & HIDEMULTIMONITOR)) res=(*p->lpCallback)(lpGuid, lpDriverDescription, lpDriverName, p->lpContext);
if((lpGuid==NULL) && (dxw.dwFlags2 & HIDEMULTIMONITOR)) res=FALSE;
OutTraceDW("DDEnumerateCallback: res=%x(%s)\n", res, res?"continue":"break");
return res;
}
BOOL FAR PASCAL DDEnumerateCallbackExFilterA(GUID FAR *lpGuid, LPSTR lpDriverDescription, LPSTR lpDriverName, LPVOID lpContext, HMONITOR hm)
{
BOOL res;
typedef struct {LPDDENUMCALLBACKEX lpCallback; LPVOID lpContext;} Context_Type;
Context_Type *p=(Context_Type *)lpContext;
OutTraceDW("DDEnumerateCallbackEx: guid=%x DriverDescription=\"%s\" DriverName=\"%s\" Context=%x hm=%x\n",
lpGuid, lpDriverDescription, lpDriverName, lpContext, hm);
res=TRUE;
if((lpGuid==NULL) || !(dxw.dwFlags2 & HIDEMULTIMONITOR)) res=(*p->lpCallback)(lpGuid, lpDriverDescription, lpDriverName, p->lpContext, hm);
if((lpGuid==NULL) && (dxw.dwFlags2 & HIDEMULTIMONITOR)) res=FALSE;
OutTraceDW("DDEnumerateCallbackEx: res=%x(%s)\n", res, res?"continue":"break");
return res;
}
HRESULT WINAPI extDirectDrawEnumerateA(LPDDENUMCALLBACKA lpCallback, LPVOID lpContext)
{
HRESULT ret;
OutTraceDDRAW("DirectDrawEnumerate: lpCallback=%x lpContext=%x\n", lpCallback, lpContext);
if((dxw.dwFlags2 & HIDEMULTIMONITOR) || (dxw.dwTFlags & OUTDEBUG)){
struct {LPDDENUMCALLBACKA lpCallback; LPVOID lpContext;} myContext;
myContext.lpCallback=lpCallback;
myContext.lpContext=lpContext;
ret=(*pDirectDrawEnumerateA)(DDEnumerateCallbackFilterA, (LPVOID)&myContext);
}
else
ret=(*pDirectDrawEnumerateA)(lpCallback, lpContext);
if(ret) OutTraceE("DirectDrawEnumerate: ERROR res=%x(%s)\n", ret, ExplainDDError(ret));
return ret;
}
HRESULT WINAPI extDirectDrawEnumerateW(LPDDENUMCALLBACKW lpCallback, LPVOID lpContext)
{
HRESULT ret;
OutTraceDDRAW("DirectDrawEnumerate: lpCallback=%x lpContext=%x\n", lpCallback, lpContext);
if((dxw.dwFlags2 & HIDEMULTIMONITOR) || (dxw.dwTFlags & OUTDEBUG)){
struct {LPDDENUMCALLBACKW lpCallback; LPVOID lpContext;} myContext;
myContext.lpCallback=lpCallback;
myContext.lpContext=lpContext;
ret=(*pDirectDrawEnumerateW)(DDEnumerateCallbackFilterW, (LPVOID)&myContext);
}
else
ret=(*pDirectDrawEnumerateW)(lpCallback, lpContext);
if(ret) OutTraceE("DirectDrawEnumerate: ERROR res=%x(%s)\n", ret, ExplainDDError(ret));
return ret;
}
HRESULT WINAPI extDirectDrawEnumerateExA(LPDDENUMCALLBACKEXA lpCallback, LPVOID lpContext, DWORD dwFlags)
{
HRESULT ret;
OutTraceDDRAW("DirectDrawEnumerateEx: lpCallback=%x lpContext=%x Flags=%x(%s)\n",
lpCallback, lpContext, dwFlags, ExplainDDEnumerateFlags(dwFlags));
if((dxw.dwFlags2 & HIDEMULTIMONITOR) || (dxw.dwTFlags & OUTDEBUG)){
struct {LPDDENUMCALLBACKEXA lpCallback; LPVOID lpContext;} myContext;
myContext.lpCallback=lpCallback;
myContext.lpContext=lpContext;
ret=(*pDirectDrawEnumerateExA)(DDEnumerateCallbackExFilterA, (LPVOID)&myContext, dwFlags);
}
else{
ret=(*pDirectDrawEnumerateExA)(lpCallback, lpContext, dwFlags);
}
if(ret) OutTraceE("DirectDrawEnumerateEx: ERROR res=%x(%s)\n", ret, ExplainDDError(ret));
if(dxw.dwFlags1 & SUPPRESSDXERRORS) ret=DD_OK;
return ret;
}
HRESULT WINAPI extDirectDrawEnumerateExW(LPDDENUMCALLBACKEXW lpCallback, LPVOID lpContext, DWORD dwFlags)
{
HRESULT ret;
OutTraceDDRAW("DirectDrawEnumerateEx: lpCallback=%x lpContext=%x Flags=%x(%s)\n",
lpCallback, lpContext, dwFlags, ExplainDDEnumerateFlags(dwFlags));
if((dxw.dwFlags2 & HIDEMULTIMONITOR) || (dxw.dwTFlags & OUTDEBUG)){
struct {LPDDENUMCALLBACKEXW lpCallback; LPVOID lpContext;} myContext;
myContext.lpCallback=lpCallback;
myContext.lpContext=lpContext;
ret=(*pDirectDrawEnumerateExW)(DDEnumerateCallbackExFilterW, (LPVOID)&myContext, dwFlags);
}
else{
ret=(*pDirectDrawEnumerateExW)(lpCallback, lpContext, dwFlags);
}
if(ret) OutTraceE("DirectDrawEnumerateEx: ERROR res=%x(%s)\n", ret, ExplainDDError(ret));
if(dxw.dwFlags1 & SUPPRESSDXERRORS) ret=DD_OK;
return ret;
}
HRESULT WINAPI extDDGetGammaRamp(LPDIRECTDRAWSURFACE lpdds, DWORD dwFlags, LPDDGAMMARAMP lpgr)
{
HRESULT ret;
OutTraceDDRAW("GetGammaRamp: dds=%x dwFlags=%x\n", lpdds, dwFlags);
if(dxwss.IsAPrimarySurface(lpdds)) lpdds=lpDDSEmu_Prim;
ret=(*pDDGetGammaRamp)(lpdds, dwFlags, lpgr);
if(ret) {
OutTraceE("GetGammaRamp: ERROR res=%x(%s)\n", ret, ExplainDDError(ret));
if(dxw.dwFlags1 & SUPPRESSDXERRORS) {
// clear the error code, and provide a reasonable gamma ramp array
for(int i=0; i<256; i++) lpgr->red[i]=lpgr->green[i]=lpgr->blue[i]=(i * 0x100);
ret=0;
}
}
else{
if(IsDebug){
OutTrace("GetGammaRamp: RGB=");
for(int i=0; i<256; i++) OutTrace("(%x,%x,%x)", lpgr->red[i], lpgr->green[i], lpgr->blue[i]);
OutTrace("\n");
}
}
return ret;
}
HRESULT WINAPI extDDSetGammaRamp(LPDIRECTDRAWSURFACE lpdds, DWORD dwFlags, LPDDGAMMARAMP lpgr)
{
HRESULT ret;
OutTraceDDRAW("SetGammaRamp: dds=%x dwFlags=%x\n", lpdds, dwFlags);
if(IsDebug){
OutTrace("GetGammaRamp: RGB=");
for(int i=0; i<256; i++) OutTrace("(%x,%x,%x)", lpgr->red[i], lpgr->green[i], lpgr->blue[i]);
OutTrace("\n");
}
if (dxw.dwFlags2 & DISABLEGAMMARAMP) return DD_OK;
ret=(*pDDSetGammaRamp)(lpdds, dwFlags, lpgr);
if(ret) OutTraceE("SetGammaRamp: ERROR res=%x(%s)\n", ret, ExplainDDError(ret));
if(dxw.dwFlags1 & SUPPRESSDXERRORS) ret = DD_OK;
return ret;
}
static HRESULT WINAPI extGetAvailableVidMem(int dxversion, GetAvailableVidMem4_Type pGetAvailableVidMem, LPDIRECTDRAW lpdd, LPDDSCAPS2 lpDDSCaps, LPDWORD lpdwTotal, LPDWORD lpdwFree)
{
HRESULT res;
//const DWORD dwMaxMem = 0x7FFFF000;
// v03.01.01: limit to smaller value to allow "Breath of Fire IV" card detection
const DWORD dwMaxMem = 0x70000000;
const DWORD dwHugeMem = 0xF0000000;
OutTraceDDRAW("GetAvailableVidMem(D%d): lpdd=%x\n", dxversion, lpdd);
res=(*pGetAvailableVidMem)(lpdd, lpDDSCaps, lpdwTotal, lpdwFree);
if(res){
if((dxw.dwFlags3 & FORCESHEL) && (res==DDERR_NODIRECTDRAWHW)){
// fake some video memory....
OutTraceDW("GetAvailableVidMem(D): FORCESHEL mode Total=Free=%x\n", dwMaxMem);
if(lpdwTotal) *lpdwTotal = dwMaxMem;
if(lpdwFree) *lpdwFree = dwMaxMem;
return DD_OK;
}
OutTraceE("GetAvailableVidMem(D): ERROR res=%x(%s)\n", res, ExplainDDError(res));
return res;
}
if(dxversion == 2){
OutTraceDW("GetAvailableVidMem(D2): DDSCaps=%x(%s) Total=%x Free=%x\n",
lpDDSCaps->dwCaps, ExplainDDSCaps(lpDDSCaps->dwCaps), lpdwTotal?*lpdwTotal:0, lpdwFree?*lpdwFree:0);
}
else{
OutTraceDW("GetAvailableVidMem(D%d): DDSCaps=%x(%s).%x.%x.%x volumedepth=%d Total=%x Free=%x\n",
dxversion,
lpDDSCaps->dwCaps, ExplainDDSCaps(lpDDSCaps->dwCaps),
lpDDSCaps->dwCaps2, lpDDSCaps->dwCaps3, lpDDSCaps->dwCaps4, lpDDSCaps->dwVolumeDepth,
lpdwTotal?*lpdwTotal:0, lpdwFree?*lpdwFree:0);
}
if(!(dxw.dwFlags2 & LIMITRESOURCES)) return res;
// may need hints ....
if(dxw.bHintActive){
if(lpdwTotal && (*lpdwTotal > dwMaxMem)) ShowHint(HINT_LIMITMEM);
if(lpdwFree && (*lpdwFree > dwMaxMem)) ShowHint(HINT_LIMITMEM);
}
// simulate a value overflow condition
if(dxw.dwFlags5 & STRESSRESOURCES){
if(lpdwTotal) *lpdwTotal = dwHugeMem;
if(lpdwFree) *lpdwFree = dwHugeMem;
return DD_OK;
}
// check for memory value overflow - see "Mageslayer" and "Take no Prisoners"
DWORD dwLocalTotal;
if(lpdwTotal == NULL) {
lpdwTotal = &dwLocalTotal; // point to usable memory....
res=(*pGetAvailableVidMem)(lpdd, lpDDSCaps, lpdwTotal, lpdwFree); // do it again to get total memory
}
if(*lpdwTotal > dwMaxMem){
if(lpdwFree != NULL){
DWORD dwDiff = *lpdwTotal - *lpdwFree;
if(dwDiff > dwMaxMem){
*lpdwFree = dwMaxMem;
}
else{
*lpdwFree = dwMaxMem - dwDiff;
}
}
*lpdwTotal = dwMaxMem;
OutTraceDW("GetAvailableVidMem(D): FIXED Total=%x Free=%x\n", *lpdwTotal, *lpdwFree);
}
return res;
}
HRESULT WINAPI extGetAvailableVidMem2(LPDIRECTDRAW lpdd, LPDDSCAPS lpDDSCaps, LPDWORD lpdwTotal, LPDWORD lpdwFree)
{ return extGetAvailableVidMem(2, (GetAvailableVidMem4_Type)pGetAvailableVidMem2, lpdd, (LPDDSCAPS2)lpDDSCaps, lpdwTotal, lpdwFree); }
HRESULT WINAPI extGetAvailableVidMem4(LPDIRECTDRAW lpdd, LPDDSCAPS2 lpDDSCaps, LPDWORD lpdwTotal, LPDWORD lpdwFree)
{ return extGetAvailableVidMem(4, pGetAvailableVidMem4, lpdd, lpDDSCaps, lpdwTotal, lpdwFree); }
HRESULT WINAPI extGetAvailableVidMem7(LPDIRECTDRAW lpdd, LPDDSCAPS2 lpDDSCaps, LPDWORD lpdwTotal, LPDWORD lpdwFree)
{ return extGetAvailableVidMem(7, pGetAvailableVidMem7, lpdd, lpDDSCaps, lpdwTotal, lpdwFree); }
HRESULT WINAPI extSetSurfaceDesc(SetSurfaceDesc_Type pSetSurfaceDesc, LPDIRECTDRAWSURFACE lpdds, LPDDSURFACEDESC lpDDsd2, DWORD dwFlags)
{
HRESULT res;
OutTrace("SetSurfaceDesc: REACHED\n");
res = (*pSetSurfaceDesc)(lpdds, lpDDsd2, dwFlags);
if(res) OutTraceE("SetSurfaceDesc: ERROR res=%x(%s)\n", res, ExplainDDError(res));
return res;
}
HRESULT WINAPI extSetSurfaceDesc3(LPDIRECTDRAWSURFACE lpdds, LPDDSURFACEDESC lpDDsd2, DWORD dwFlags)
{ return extSetSurfaceDesc(pSetSurfaceDesc3, lpdds, lpDDsd2, dwFlags); }
HRESULT WINAPI extSetSurfaceDesc4(LPDIRECTDRAWSURFACE lpdds, LPDDSURFACEDESC lpDDsd2, DWORD dwFlags)
{ return extSetSurfaceDesc(pSetSurfaceDesc4, lpdds, lpDDsd2, dwFlags); }
HRESULT WINAPI extSetSurfaceDesc7(LPDIRECTDRAWSURFACE lpdds, LPDDSURFACEDESC lpDDsd2, DWORD dwFlags)
{ return extSetSurfaceDesc(pSetSurfaceDesc7, lpdds, lpDDsd2, dwFlags); }
HRESULT WINAPI extDirectDrawCreateClipper(DWORD dwFlags, LPDIRECTDRAWCLIPPER *lplpDDClipper, IUnknown *pUnkOuter)
{
HRESULT res;
OutTraceDW("DirectDrawCreateClipper: flags=%x\n", dwFlags);
res = (*pDirectDrawCreateClipper)(dwFlags, lplpDDClipper, pUnkOuter);
if(res) {
OutTraceE("DirectDrawCreateClipper: ERROR res=%x(%s)\n", res, ExplainDDError(res));
return res;
}
HookDDClipper(lplpDDClipper);
return res;
}
HRESULT WINAPI extEnumOverlayZOrders(int dxversion, EnumOverlayZOrders_Type pEnumOverlayZOrders, LPDIRECTDRAWSURFACE lpdds, DWORD dwFlags, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpfnCallback)
{
HRESULT res;
OutTrace("EnumOverlayZOrders(%d): lpdds=%x flags=%x(%s)\n", dxversion, lpdds, dwFlags, dwFlags?"FRONTTOBACK":"BACKTOFRONT");
res = (*pEnumOverlayZOrders)(lpdds, dwFlags, lpContext, lpfnCallback);
OutTrace("EnumOverlayZOrders: res=%x(%s)\n", res, ExplainDDError(res));
return res;
}
HRESULT WINAPI extEnumOverlayZOrders1(LPDIRECTDRAWSURFACE lpdds, DWORD dwFlags, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpfnCallback)
{ return extEnumOverlayZOrders(1, pEnumOverlayZOrders1, lpdds, dwFlags, lpContext, lpfnCallback); }
HRESULT WINAPI extEnumOverlayZOrders2(LPDIRECTDRAWSURFACE lpdds, DWORD dwFlags, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpfnCallback)
{ return extEnumOverlayZOrders(2, pEnumOverlayZOrders2, lpdds, dwFlags, lpContext, lpfnCallback); }
HRESULT WINAPI extEnumOverlayZOrders3(LPDIRECTDRAWSURFACE lpdds, DWORD dwFlags, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpfnCallback)
{ return extEnumOverlayZOrders(3, pEnumOverlayZOrders3, lpdds, dwFlags, lpContext, lpfnCallback); }
HRESULT WINAPI extEnumOverlayZOrders4(LPDIRECTDRAWSURFACE lpdds, DWORD dwFlags, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpfnCallback)
{ return extEnumOverlayZOrders(4, pEnumOverlayZOrders4, lpdds, dwFlags, lpContext, lpfnCallback); }
HRESULT WINAPI extEnumOverlayZOrders7(LPDIRECTDRAWSURFACE lpdds, DWORD dwFlags, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpfnCallback)
{ return extEnumOverlayZOrders(7, pEnumOverlayZOrders7, lpdds, dwFlags, lpContext, lpfnCallback); }
HRESULT WINAPI extAddOverlayDirtyRect(int dxversion, AddOverlayDirtyRect_Type pAddOverlayDirtyRect, LPDIRECTDRAWSURFACE lpdds, LPRECT lpRect)
{
HRESULT res;
char sInfo[128];
if (lpRect)
sprintf(sInfo, "(%d,%d)-(%d,%d)", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
else
sprintf(sInfo, "(NULL)");
OutTrace("AddOverlayDirtyRect(%d): lpdds=%x rect=%s\n", dxversion, lpdds, sInfo);
res=(*pAddOverlayDirtyRect)(lpdds, lpRect);
OutTrace("AddOverlayDirtyRect: res=%x(%s)\n", res, ExplainDDError(res));
return res;
}
HRESULT WINAPI extAddOverlayDirtyRect1(LPDIRECTDRAWSURFACE lpdds, LPRECT lpRect)
{ return extAddOverlayDirtyRect(1, pAddOverlayDirtyRect1, lpdds, lpRect); }
HRESULT WINAPI extAddOverlayDirtyRect2(LPDIRECTDRAWSURFACE lpdds, LPRECT lpRect)
{ return extAddOverlayDirtyRect(2, pAddOverlayDirtyRect2, lpdds, lpRect); }
HRESULT WINAPI extAddOverlayDirtyRect3(LPDIRECTDRAWSURFACE lpdds, LPRECT lpRect)
{ return extAddOverlayDirtyRect(3, pAddOverlayDirtyRect3, lpdds, lpRect); }
HRESULT WINAPI extAddOverlayDirtyRect4(LPDIRECTDRAWSURFACE lpdds, LPRECT lpRect)
{ return extAddOverlayDirtyRect(4, pAddOverlayDirtyRect4, lpdds, lpRect); }
HRESULT WINAPI extAddOverlayDirtyRect7(LPDIRECTDRAWSURFACE lpdds, LPRECT lpRect)
{ return extAddOverlayDirtyRect(7, pAddOverlayDirtyRect7, lpdds, lpRect); }
HRESULT WINAPI extCompact(LPDIRECTDRAW lpdd)
{
OutTraceDW("Compact: lpdd=%x\n", lpdd);
return DD_OK;
}