refactoring

This commit is contained in:
FunkyFr3sh 2020-10-13 09:20:52 +02:00
parent 95afd87656
commit baaa87b18f
62 changed files with 7231 additions and 6636 deletions

View file

@ -6,20 +6,28 @@ CFLAGS = -std=c99
LIBS = -lgdi32 -lwinmm
FILES = src/debug.c \
src/main.c \
src/mouse.c \
src/palette.c \
src/surface.c \
src/clipper.c \
src/render.c \
src/render_soft.c \
src/dd.c \
src/ddpalette.c \
src/ddsurface.c \
src/ddclipper.c \
src/IDirectDraw/IDirectDraw.c \
src/IDirectDraw/IDirectDrawPalette.c \
src/IDirectDraw/IDirectDrawClipper.c \
src/IDirectDraw/IDirectDrawSurface.c \
src/render_ogl.c \
src/render_gdi.c \
src/render_d3d9.c \
src/mouse.c \
src/winapi_hooks.c \
src/screenshot.c \
src/settings.c \
src/config.c \
src/lodepng.c \
src/dinput.c \
src/directinput.c \
src/hook.c \
src/opengl.c
src/dllmain.c \
src/wndproc.c \
src/utils.c \
src/opengl_utils.c
all:
$(WINDRES) -J rc ddraw.rc ddraw.rc.o

View file

@ -11,7 +11,7 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\clipper.c" />
<ClCompile Include="src\ddclipper.c" />
<ClCompile Include="src\debug.c" />
<ClCompile Include="src\detours\creatwth.cpp" />
<ClCompile Include="src\detours\detours.cpp" />
@ -26,37 +26,58 @@
<ClCompile Include="src\detours\uimports.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="src\dinput.c" />
<ClCompile Include="src\directinput.c" />
<ClCompile Include="src\dllmain.c" />
<ClCompile Include="src\utils.c" />
<ClCompile Include="src\hook.c" />
<ClCompile Include="src\IDirectDraw\IDirectDraw.c" />
<ClCompile Include="src\IDirectDraw\IDirectDrawClipper.c" />
<ClCompile Include="src\IDirectDraw\IDirectDrawPalette.c" />
<ClCompile Include="src\IDirectDraw\IDirectDrawSurface.c" />
<ClCompile Include="src\lodepng.c" />
<ClCompile Include="src\main.c" />
<ClCompile Include="src\dd.c" />
<ClCompile Include="src\mouse.c" />
<ClCompile Include="src\opengl.c" />
<ClCompile Include="src\palette.c" />
<ClCompile Include="src\render.c" />
<ClCompile Include="src\opengl_utils.c" />
<ClCompile Include="src\ddpalette.c" />
<ClCompile Include="src\render_ogl.c" />
<ClCompile Include="src\render_d3d9.c" />
<ClCompile Include="src\render_soft.c" />
<ClCompile Include="src\render_gdi.c" />
<ClCompile Include="src\screenshot.c" />
<ClCompile Include="src\settings.c" />
<ClCompile Include="src\surface.c" />
<ClCompile Include="src\config.c" />
<ClCompile Include="src\ddsurface.c" />
<ClCompile Include="src\winapi_hooks.c" />
<ClCompile Include="src\wndproc.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="inc\clipper.h" />
<ClInclude Include="inc\d3d9shader.h" />
<ClInclude Include="inc\ddclipper.h" />
<ClInclude Include="inc\directinput.h" />
<ClInclude Include="inc\dllmain.h" />
<ClInclude Include="inc\glcorearb.h" />
<ClInclude Include="inc\utils.h" />
<ClInclude Include="inc\hook.h" />
<ClInclude Include="inc\IDirectDraw.h" />
<ClInclude Include="inc\IDirectDrawClipper.h" />
<ClInclude Include="inc\IDirectDrawPalette.h" />
<ClInclude Include="inc\IDirectDrawSurface.h" />
<ClInclude Include="inc\KHR\khrplatform.h" />
<ClInclude Include="inc\lodepng.h" />
<ClInclude Include="inc\mouse.h" />
<ClInclude Include="inc\render_d3d9.h" />
<ClInclude Include="inc\ddraw.h" />
<ClInclude Include="inc\debug.h" />
<ClInclude Include="inc\main.h" />
<ClInclude Include="inc\opengl.h" />
<ClInclude Include="inc\palette.h" />
<ClInclude Include="inc\dd.h" />
<ClInclude Include="inc\opengl_utils.h" />
<ClInclude Include="inc\ddpalette.h" />
<ClInclude Include="inc\openglshader.h" />
<ClInclude Include="inc\d3d9shader.h" />
<ClInclude Include="inc\render_ogl.h" />
<ClInclude Include="inc\render_gdi.h" />
<ClInclude Include="inc\scale_pattern.h" />
<ClInclude Include="inc\surface.h" />
<ClInclude Include="inc\screenshot.h" />
<ClInclude Include="inc\config.h" />
<ClInclude Include="inc\ddsurface.h" />
<ClInclude Include="inc\winapi_hooks.h" />
<ClInclude Include="inc\wndproc.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ddraw.rc" />

View file

@ -16,53 +16,26 @@
<Filter Include="Source Files\detours">
<UniqueIdentifier>{af194dd7-3316-4887-93d6-9f2af2135f94}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\IDirectDraw">
<UniqueIdentifier>{37ee5b88-e57f-4c55-a43e-e475cf4e8920}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\clipper.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\debug.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\main.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\mouse.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\palette.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\render.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\render_soft.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\screenshot.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\surface.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\opengl.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\render_d3d9.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\settings.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\lodepng.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\dinput.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\hook.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\detours\disolx64.cpp">
<Filter>Source Files\detours</Filter>
</ClCompile>
@ -96,35 +69,71 @@
<ClCompile Include="src\detours\disolia64.cpp">
<Filter>Source Files\detours</Filter>
</ClCompile>
<ClCompile Include="src\hook.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\IDirectDraw\IDirectDraw.c">
<Filter>Source Files\IDirectDraw</Filter>
</ClCompile>
<ClCompile Include="src\dllmain.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\wndproc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\utils.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\render_ogl.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\dd.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\IDirectDraw\IDirectDrawPalette.c">
<Filter>Source Files\IDirectDraw</Filter>
</ClCompile>
<ClCompile Include="src\ddpalette.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\IDirectDraw\IDirectDrawClipper.c">
<Filter>Source Files\IDirectDraw</Filter>
</ClCompile>
<ClCompile Include="src\ddclipper.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\IDirectDraw\IDirectDrawSurface.c">
<Filter>Source Files\IDirectDraw</Filter>
</ClCompile>
<ClCompile Include="src\ddsurface.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\winapi_hooks.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\directinput.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\render_gdi.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\config.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\opengl_utils.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="inc\clipper.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\ddraw.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\debug.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\main.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\palette.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\surface.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\opengl.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\openglshader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\d3d9shader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\render_d3d9.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -146,6 +155,63 @@
<ClInclude Include="inc\hook.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\IDirectDraw.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\directinput.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\wndproc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\screenshot.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\render_ogl.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\dd.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\IDirectDrawPalette.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\ddpalette.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\IDirectDrawClipper.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\ddclipper.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\IDirectDrawSurface.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\ddsurface.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\winapi_hooks.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\d3d9shader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\dllmain.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\utils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\render_gdi.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\config.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\opengl_utils.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ddraw.rc">

View file

@ -1,10 +1,10 @@
LIBRARY ddraw.dll
EXPORTS
DirectDrawCreate @1
DirectDrawEnumerateA @2
DirectDrawCreateClipper @10
GameHandlesClose DATA
NvOptimusEnablement DATA
AmdPowerXpressRequestHighPerformance DATA
pvBmpBits DATA
DirectDrawCreate @8
DirectDrawCreateClipper @9
DirectDrawEnumerateA @11
GameHandlesClose DATA
NvOptimusEnablement DATA
AmdPowerXpressRequestHighPerformance DATA
pvBmpBits = g_fake_primary_surface_export DATA

View file

@ -4,7 +4,7 @@
#define VERSION_MAJOR 1
#define VERSION_MINOR 3
#define VERSION_BUILD 7
#define VERSION_REVISION 1
#define VERSION_REVISION 2
#define VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION
#define VERSION_STRING ver_str(VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION)

71
inc/IDirectDraw.h Normal file
View file

@ -0,0 +1,71 @@
#ifndef IDIRECTDRAW_H
#define IDIRECTDRAW_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "ddraw.h"
DEFINE_GUID(IID_IDirectDraw4, 0x9c59509a, 0x39bd, 0x11d1, 0x8c, 0x4a, 0x00, 0xc0, 0x4f, 0xd9, 0x30, 0xc5);
DEFINE_GUID(IID_IDirectDraw7, 0x15e65ec0, 0x3b9c, 0x11d2, 0xb9, 0x2f, 0x00, 0x60, 0x97, 0x97, 0xea, 0x5b);
extern struct IDirectDrawImplVtbl g_dd_vtbl1;
extern struct IDirectDrawImplVtbl g_dd_vtblx;
struct IDirectDrawImpl;
struct IDirectDrawImplVtbl;
typedef struct IDirectDrawImpl
{
struct IDirectDrawImplVtbl* lpVtbl;
ULONG ref;
} IDirectDrawImpl;
typedef struct IDirectDrawImplVtbl IDirectDrawImplVtbl;
struct IDirectDrawImplVtbl
{
HRESULT(__stdcall* QueryInterface) (IDirectDrawImpl*, const IID* const riid, LPVOID* ppvObj);
ULONG(__stdcall* AddRef) (IDirectDrawImpl*);
ULONG(__stdcall* Release) (IDirectDrawImpl*);
HRESULT(__stdcall* Compact)(IDirectDrawImpl*);
HRESULT(__stdcall* CreateClipper)(IDirectDrawImpl*, DWORD, LPDIRECTDRAWCLIPPER*, IUnknown*);
HRESULT(__stdcall* CreatePalette)(IDirectDrawImpl*, DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE*, IUnknown*);
HRESULT(__stdcall* CreateSurface)(IDirectDrawImpl*, LPDDSURFACEDESC, LPDIRECTDRAWSURFACE*, IUnknown*);
HRESULT(__stdcall* DuplicateSurface)(IDirectDrawImpl*, LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE*);
HRESULT(__stdcall* EnumDisplayModes)(IDirectDrawImpl*, DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK);
HRESULT(__stdcall* EnumSurfaces)(IDirectDrawImpl*, DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMSURFACESCALLBACK);
HRESULT(__stdcall* FlipToGDISurface)(IDirectDrawImpl*);
HRESULT(__stdcall* GetCaps)(IDirectDrawImpl*, LPDDCAPS, LPDDCAPS);
HRESULT(__stdcall* GetDisplayMode)(IDirectDrawImpl*, LPDDSURFACEDESC);
HRESULT(__stdcall* GetFourCCCodes)(IDirectDrawImpl*, LPDWORD, LPDWORD);
HRESULT(__stdcall* GetGDISurface)(IDirectDrawImpl*, LPDIRECTDRAWSURFACE*);
HRESULT(__stdcall* GetMonitorFrequency)(IDirectDrawImpl*, LPDWORD);
HRESULT(__stdcall* GetScanLine)(IDirectDrawImpl*, LPDWORD);
HRESULT(__stdcall* GetVerticalBlankStatus)(IDirectDrawImpl*, LPBOOL);
HRESULT(__stdcall* Initialize)(IDirectDrawImpl*, GUID*);
HRESULT(__stdcall* RestoreDisplayMode)(IDirectDrawImpl*);
HRESULT(__stdcall* SetCooperativeLevel)(IDirectDrawImpl*, HWND, DWORD);
union
{
LPVOID d;
HRESULT(__stdcall* SetDisplayMode)(IDirectDrawImpl*, DWORD, DWORD, DWORD);
HRESULT(__stdcall* SetDisplayModeX)(IDirectDrawImpl*, DWORD, DWORD, DWORD, DWORD, DWORD);
};
HRESULT(__stdcall* WaitForVerticalBlank)(IDirectDrawImpl*, DWORD, HANDLE);
// v2
HRESULT(__stdcall* GetAvailableVidMem)(IDirectDrawImpl*, void*, LPDWORD, LPDWORD);
// v4
HRESULT(__stdcall* GetSurfaceFromDC)(IDirectDrawImpl*, HDC, void*);
HRESULT(__stdcall* RestoreAllSurfaces)(IDirectDrawImpl*);
HRESULT(__stdcall* TestCooperativeLevel)(IDirectDrawImpl*);
HRESULT(__stdcall* GetDeviceIdentifier)(IDirectDrawImpl*, void*, DWORD);
// v7
HRESULT(__stdcall* StartModeTest)(IDirectDrawImpl*, LPSIZE, DWORD, DWORD);
HRESULT(__stdcall* EvaluateMode)(IDirectDrawImpl*, DWORD, DWORD*);
};
#endif

40
inc/IDirectDrawClipper.h Normal file
View file

@ -0,0 +1,40 @@
#ifndef IDIRECTDRAWCLIPPER_H
#define IDIRECTDRAWCLIPPER_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "ddraw.h"
struct IDirectDrawClipperImpl;
struct IDirectDrawClipperImplVtbl;
typedef struct IDirectDrawClipperImpl
{
struct IDirectDrawClipperImplVtbl *lpVtbl;
ULONG ref;
} IDirectDrawClipperImpl;
typedef struct IDirectDrawClipperImplVtbl IDirectDrawClipperImplVtbl;
struct IDirectDrawClipperImplVtbl
{
/* IUnknown */
HRESULT (__stdcall *QueryInterface)(IDirectDrawClipperImpl *, REFIID, void **);
ULONG (__stdcall *AddRef)(IDirectDrawClipperImpl *);
ULONG (__stdcall *Release)(IDirectDrawClipperImpl *);
/* IDirectDrawClipper */
HRESULT (__stdcall *GetClipList)(IDirectDrawClipperImpl *, LPRECT, LPRGNDATA, LPDWORD);
HRESULT (__stdcall *GetHWnd)(IDirectDrawClipperImpl *, HWND FAR *);
HRESULT (__stdcall *Initialize)(IDirectDrawClipperImpl *, LPDIRECTDRAW, DWORD);
HRESULT (__stdcall *IsClipListChanged)(IDirectDrawClipperImpl *, BOOL FAR *);
HRESULT (__stdcall *SetClipList)(IDirectDrawClipperImpl *, LPRGNDATA,DWORD);
HRESULT (__stdcall *SetHWnd)(IDirectDrawClipperImpl *, DWORD, HWND );
};
extern struct IDirectDrawClipperImplVtbl g_ddc_vtbl;
#endif

42
inc/IDirectDrawPalette.h Normal file
View file

@ -0,0 +1,42 @@
#ifndef IDIRECTDRAWPALETTE_H
#define IDIRECTDRAWPALETTE_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "ddraw.h"
struct IDirectDrawPaletteImpl;
struct IDirectDrawPaletteImplVtbl;
typedef struct IDirectDrawPaletteImpl
{
struct IDirectDrawPaletteImplVtbl* lpVtbl;
ULONG ref;
int data_bgr[256];
RGBQUAD* data_rgb;
} IDirectDrawPaletteImpl;
typedef struct IDirectDrawPaletteImplVtbl IDirectDrawPaletteImplVtbl;
struct IDirectDrawPaletteImplVtbl
{
/* IUnknown */
HRESULT(__stdcall* QueryInterface)(IDirectDrawPaletteImpl*, REFIID, void**);
ULONG(__stdcall* AddRef)(IDirectDrawPaletteImpl*);
ULONG(__stdcall* Release)(IDirectDrawPaletteImpl*);
/* IDirectDrawPalette */
HRESULT(__stdcall* GetCaps)(IDirectDrawPaletteImpl*, LPDWORD);
HRESULT(__stdcall* GetEntries)(IDirectDrawPaletteImpl*, DWORD, DWORD, DWORD, LPPALETTEENTRY);
HRESULT(__stdcall* Initialize)(IDirectDrawPaletteImpl*, LPDIRECTDRAW, DWORD, LPPALETTEENTRY);
HRESULT(__stdcall* SetEntries)(IDirectDrawPaletteImpl*, DWORD, DWORD, DWORD, LPPALETTEENTRY);
};
extern struct IDirectDrawPaletteImplVtbl g_ddp_vtbl;
#endif

View file

@ -1,38 +1,20 @@
/*
* Copyright (c) 2010 Toni Spets <toni.spets@iki.fi>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef SURFACE_H
#define SURFACE_H
#ifndef IDIRECTDRAWSURFACE_H
#define IDIRECTDRAWSURFACE_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "IDirectDrawPalette.h"
#include "ddraw.h"
#include "palette.h"
HRESULT __stdcall ddraw_CreateSurface(IDirectDrawImpl *This, LPDDSURFACEDESC DDSurfaceDesc, LPDIRECTDRAWSURFACE FAR *DDSurface, IUnknown FAR * unkOuter);
struct IDirectDrawSurfaceImpl;
struct IDirectDrawSurfaceImplVtbl;
extern struct IDirectDrawSurfaceImpl *ddraw_primary;
typedef struct IDirectDrawSurfaceImpl
{
struct IDirectDrawSurfaceImplVtbl *lpVtbl;
ULONG Ref;
ULONG ref;
DWORD width;
DWORD height;
@ -43,18 +25,20 @@ typedef struct IDirectDrawSurfaceImpl
IDirectDrawPaletteImpl *palette;
void *surface;
DWORD lPitch;
DWORD lXPitch;
DWORD l_pitch;
DWORD lx_pitch;
PBITMAPINFO bmi;
HBITMAP bitmap;
HDC hDC;
DDCOLORKEY colorKey;
DWORD lastFlipTick;
DWORD lastBltTick;
HDC hdc;
DDCOLORKEY color_key;
DWORD last_flip_tick;
DWORD last_blt_tick;
} IDirectDrawSurfaceImpl;
typedef struct IDirectDrawSurfaceImplVtbl IDirectDrawSurfaceImplVtbl;
struct IDirectDrawSurfaceImplVtbl
{
/* IUnknown */
@ -96,7 +80,8 @@ struct IDirectDrawSurfaceImplVtbl
HRESULT (__stdcall *UpdateOverlay)(IDirectDrawSurfaceImpl*, LPRECT, LPDIRECTDRAWSURFACE,LPRECT,DWORD, LPDDOVERLAYFX);
HRESULT (__stdcall *UpdateOverlayDisplay)(IDirectDrawSurfaceImpl*, DWORD);
HRESULT (__stdcall *UpdateOverlayZOrder)(IDirectDrawSurfaceImpl*, DWORD, LPDIRECTDRAWSURFACE);
} IDirectDrawSurfaceImplVtbl;
};
extern struct IDirectDrawSurfaceImplVtbl g_dds_vtbl;
#endif

View file

@ -1,53 +0,0 @@
/*
* Copyright (c) 2010 Toni Spets <toni.spets@iki.fi>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef CLIPPER_H
#define CLIPPER_H
#include <windows.h>
#include "ddraw.h"
#include "main.h"
HRESULT __stdcall ddraw_CreateClipper(IDirectDrawImpl *This, DWORD dwFlags, LPDIRECTDRAWCLIPPER FAR *lplpDDClipper, IUnknown FAR *pUnkOuter );
struct IDirectDrawClipperImpl;
struct IDirectDrawClipperImplVtbl;
typedef struct IDirectDrawClipperImpl
{
struct IDirectDrawClipperImplVtbl *lpVtbl;
ULONG Ref;
} IDirectDrawClipperImpl;
struct IDirectDrawClipperImplVtbl
{
/* IUnknown */
HRESULT (__stdcall *QueryInterface)(IDirectDrawClipperImpl *, REFIID, void **);
ULONG (__stdcall *AddRef)(IDirectDrawClipperImpl *);
ULONG (__stdcall *Release)(IDirectDrawClipperImpl *);
/* IDirectDrawClipper */
HRESULT (__stdcall *GetClipList)(IDirectDrawClipperImpl *, LPRECT, LPRGNDATA, LPDWORD);
HRESULT (__stdcall *GetHWnd)(IDirectDrawClipperImpl *, HWND FAR *);
HRESULT (__stdcall *Initialize)(IDirectDrawClipperImpl *, LPDIRECTDRAW, DWORD);
HRESULT (__stdcall *IsClipListChanged)(IDirectDrawClipperImpl *, BOOL FAR *);
HRESULT (__stdcall *SetClipList)(IDirectDrawClipperImpl *, LPRGNDATA,DWORD);
HRESULT (__stdcall *SetHWnd)(IDirectDrawClipperImpl *, DWORD, HWND );
} IDirectDrawClipperImplVtbl;
#endif

23
inc/config.h Normal file
View file

@ -0,0 +1,23 @@
#ifndef CONFIG_H
#define CONFIG_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
typedef struct cnc_ddraw_config
{
RECT window_rect;
int window_state;
char ini_path[MAX_PATH];
char process_file_name[96];
int save_settings;
} cnc_ddraw_config;
extern cnc_ddraw_config g_config;
void cfg_load();
void cfg_save();
#endif

View file

@ -1,3 +1,6 @@
#ifndef D3D9SHADER_H
#define D3D9SHADER_H
#if 0
//
// Generated by Microsoft (R) HLSL Shader Compiler 10.1
@ -42,7 +45,7 @@ float4 main(float2 texCoords : TEXCOORD) : COLOR
*/
#endif
const BYTE PalettePixelShaderSrc[] =
const BYTE D3D9_PALETTE_SHADER[] =
{
0, 2, 255, 255, 254, 255,
44, 0, 67, 84, 65, 66,
@ -99,3 +102,5 @@ const BYTE PalettePixelShaderSrc[] =
0, 8, 15, 128, 0, 0,
228, 128, 255, 255, 0, 0
};
#endif

118
inc/dd.h Normal file
View file

@ -0,0 +1,118 @@
#ifndef DD_H
#define DD_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "ddraw.h"
ULONG dd_AddRef();
ULONG dd_Release();
HRESULT dd_EnumDisplayModes(DWORD dwFlags, LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext, LPDDENUMMODESCALLBACK lpEnumModesCallback);
HRESULT dd_WaitForVerticalBlank(DWORD dwFlags, HANDLE h);
HRESULT dd_SetDisplayMode(DWORD width, DWORD height, DWORD bpp);
HRESULT dd_SetCooperativeLevel(HWND hwnd, DWORD dwFlags);
HRESULT dd_RestoreDisplayMode();
HRESULT dd_GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDEmulCaps);
HRESULT dd_GetAvailableVidMem(void* lpDDCaps, LPDWORD lpdwTotal, LPDWORD lpdwFree);
HRESULT dd_GetVerticalBlankStatus(LPBOOL lpbIsInVB);
typedef struct speed_limiter
{
DWORD tick_length;
LONGLONG tick_length_ns;
HANDLE htimer;
LARGE_INTEGER due_time;
BOOL use_blt_or_flip;
} speed_limiter;
struct IDirectDrawSurfaceImpl;
extern struct cnc_ddraw *g_ddraw;
typedef struct cnc_ddraw
{
ULONG ref;
DWORD width;
DWORD height;
DWORD bpp;
BOOL windowed;
BOOL border;
BOOL boxing;
DEVMODE mode;
struct IDirectDrawSurfaceImpl *primary;
char title[128];
HMODULE real_dll;
/* real export from system32\ddraw.dll */
HRESULT (WINAPI *DirectDrawCreate)(GUID FAR*, LPDIRECTDRAW FAR*, IUnknown FAR*);
CRITICAL_SECTION cs;
struct
{
int maxfps;
BOOL forcefps;
int width;
int height;
int bpp;
HDC hdc;
int *tex;
HANDLE thread;
BOOL run;
HANDLE sem;
DEVMODE mode;
struct { int width; int height; int x; int y; } viewport;
LONG palette_updated;
LONG surface_updated;
float scale_w;
float scale_h;
float unscale_w;
float unscale_h;
} render;
HWND hwnd;
LRESULT (CALLBACK *wndproc)(HWND, UINT, WPARAM, LPARAM);
struct { float x; float y; } cursor;
BOOL locked;
BOOL adjmouse;
BOOL devmode;
BOOL vsync;
BOOL vhack;
BOOL isredalert;
BOOL iscnc1;
LONG incutscene;
DWORD (WINAPI *renderer)(void);
BOOL fullscreen;
BOOL maintas;
BOOL noactivateapp;
BOOL handlemouse;
char shader[MAX_PATH];
BOOL wine;
BOOL altenter;
BOOL hidecursor;
BOOL accurate_timers;
BOOL resizable;
BOOL sierrahack;
BOOL nonexclusive;
BOOL bnet_active;
BOOL bnet_was_fullscreen;
BOOL bnet_was_upscaled;
RECT bnet_win_rect;
POINT bnet_pos;
int mouse_y_adjust;
void* last_freed_palette; // Dungeon Keeper hack
BOOL child_window_exists;
DWORD last_set_window_pos_tick; // WINE hack
BOOL show_driver_warning;
speed_limiter ticks_limiter;
speed_limiter flip_limiter;
speed_limiter fps_limiter;
} cnc_ddraw;
#endif

11
inc/ddclipper.h Normal file
View file

@ -0,0 +1,11 @@
#ifndef DDCLIPPER_H
#define DDCLIPPER_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "ddraw.h"
HRESULT dd_CreateClipper(DWORD dwFlags, LPDIRECTDRAWCLIPPER FAR* lplpDDClipper, IUnknown FAR* pUnkOuter);
#endif

14
inc/ddpalette.h Normal file
View file

@ -0,0 +1,14 @@
#ifndef DDPALETTE_H
#define DDPALETTE_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "ddraw.h"
#include "IDirectDrawPalette.h"
#include "dd.h"
HRESULT ddp_GetEntries(IDirectDrawPaletteImpl* This, DWORD dwFlags, DWORD dwBase, DWORD dwNumEntries, LPPALETTEENTRY lpEntries);
HRESULT ddp_SetEntries(IDirectDrawPaletteImpl* This, DWORD dwFlags, DWORD dwStartingEntry, DWORD dwCount, LPPALETTEENTRY lpEntries);
HRESULT dd_CreatePalette(DWORD dwFlags, LPPALETTEENTRY lpDDColorArray, LPDIRECTDRAWPALETTE FAR* lpDDPalette, IUnknown FAR* unkOuter);
#endif

View file

@ -422,7 +422,7 @@ typedef DDBLTBATCH FAR * LPDDBLTBATCH;
/*
* callbacks
*/
typedef DWORD (FAR PASCAL *LPCLIPPERCALLBACK)(LPDIRECTDRAWCLIPPER lpDDClipper, HWND hWnd, DWORD code, LPVOID lpContext );
typedef DWORD (FAR PASCAL *LPCLIPPERCALLBACK)(LPDIRECTDRAWCLIPPER lpDDClipper, HWND hwnd, DWORD code, LPVOID lpContext );
#ifdef STREAMING
typedef DWORD (FAR PASCAL *LPSURFACESTREAMINGCALLBACK)(DWORD);
#endif

32
inc/ddsurface.h Normal file
View file

@ -0,0 +1,32 @@
#ifndef DDSURFACE_H
#define DDSURFACE_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "ddraw.h"
#include "IDirectDrawSurface.h"
// enables redraw via blt/unlock if there wasn't any flip for X ms
#define FLIP_REDRAW_TIMEOUT 1000 / 10
HRESULT dds_AddAttachedSurface(IDirectDrawSurfaceImpl* This, LPDIRECTDRAWSURFACE lpDDSurface);
HRESULT dds_Blt(IDirectDrawSurfaceImpl* This, LPRECT lpDestRect, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx);
HRESULT dds_BltFast(IDirectDrawSurfaceImpl* This, DWORD dst_x, DWORD dst_y, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DWORD flags);
HRESULT dds_DeleteAttachedSurface(IDirectDrawSurfaceImpl* This, DWORD dwFlags, LPDIRECTDRAWSURFACE lpDDSurface);
HRESULT dds_GetSurfaceDesc(IDirectDrawSurfaceImpl* This, LPDDSURFACEDESC lpDDSurfaceDesc);
HRESULT dds_EnumAttachedSurfaces(IDirectDrawSurfaceImpl* This, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback);
HRESULT dds_Flip(IDirectDrawSurfaceImpl* This, LPDIRECTDRAWSURFACE surface, DWORD flags);
HRESULT dds_GetAttachedSurface(IDirectDrawSurfaceImpl* This, LPDDSCAPS lpDdsCaps, LPDIRECTDRAWSURFACE FAR* surface);
HRESULT dds_GetCaps(IDirectDrawSurfaceImpl* This, LPDDSCAPS lpDDSCaps);
HRESULT dds_GetColorKey(IDirectDrawSurfaceImpl* This, DWORD flags, LPDDCOLORKEY colorKey);
HRESULT dds_GetDC(IDirectDrawSurfaceImpl* This, HDC FAR* a);
HRESULT dds_GetPalette(IDirectDrawSurfaceImpl* This, LPDIRECTDRAWPALETTE FAR* lplpDDPalette);
HRESULT dds_GetPixelFormat(IDirectDrawSurfaceImpl* This, LPDDPIXELFORMAT ddpfPixelFormat);
HRESULT dds_Lock(IDirectDrawSurfaceImpl* This, LPRECT lpDestRect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD dwFlags, HANDLE hEvent);
HRESULT dds_SetColorKey(IDirectDrawSurfaceImpl* This, DWORD flags, LPDDCOLORKEY colorKey);
HRESULT dds_SetPalette(IDirectDrawSurfaceImpl* This, LPDIRECTDRAWPALETTE lpDDPalette);
HRESULT dds_Unlock(IDirectDrawSurfaceImpl* This, LPVOID lpRect);
HRESULT dd_CreateSurface(LPDDSURFACEDESC lpDDSurfaceDesc, LPDIRECTDRAWSURFACE FAR* lpDDSurface, IUnknown FAR* unkOuter);
#endif

View file

@ -1,17 +1,25 @@
#pragma once
#ifndef DEBUG_H
#define DEBUG_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
void CounterStart();
double CounterStop();
void DebugPrint(const char *format, ...);
void DrawFrameInfoStart();
void DrawFrameInfoEnd();
int dprintf(const char *fmt, ...);
extern double DebugFrameTime;
extern DWORD DebugFrameCount;
void dbg_counter_start();
double dbg_counter_stop();
void dbg_debug_string(const char *format, ...);
void dbg_draw_frame_info_start();
void dbg_draw_frame_info_end();
int dbg_printf(const char *fmt, ...);
void dbg_init();
void dbg_dump_dds_blt_flags(DWORD flags);
void dbg_dump_dds_caps(DWORD caps);
void dbg_dump_dds_flags(DWORD flags);
void dbg_dump_dds_blt_fast_flags(DWORD flags);
void dbg_dump_dds_lock_flags(DWORD flags);
extern double g_dbg_frame_time;
extern DWORD g_dbg_frame_count;
//#define _DEBUG 1
@ -21,14 +29,35 @@ extern DWORD DebugFrameCount;
//log everything (slow)
//#define _DEBUG_X 1
#ifdef _DEBUG
#ifdef _DEBUG_S
#define printf(format, ...) DebugPrint("xDBG " format, ##__VA_ARGS__)
#define dprintf(format, ...) dbg_debug_string("xDBG " format, ##__VA_ARGS__)
#ifdef _DEBUG_X
#define dprintfex(format, ...) dbg_debug_string("xDBG " format, ##__VA_ARGS__)
#else
#define printf(format, ...) dprintf(format, ##__VA_ARGS__)
#define dprintfex(format, ...)
#endif
#else
#define dprintf(format, ...) dbg_printf(format, ##__VA_ARGS__)
#ifdef _DEBUG_X
#define dprintfex(format, ...) dbg_printf(format, ##__VA_ARGS__)
#else
#define dprintfex(format, ...)
#endif
#endif
#else
#define printf(format, ...)
#endif
#define dprintf(format, ...)
#define dprintfex(format, ...)
#endif
#endif

7
inc/directinput.h Normal file
View file

@ -0,0 +1,7 @@
#ifndef DINPUTINPUT_H
#define DINPUTINPUT_H
void dinput_hook();
void dinput_unhook();
#endif

16
inc/dllmain.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef DLLMAIN_H
#define DLLMAIN_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
extern BOOL GameHandlesClose;
extern HMODULE g_ddraw_module;
typedef enum PROCESS_DPI_AWARENESS {
PROCESS_DPI_UNAWARE = 0,
PROCESS_SYSTEM_DPI_AWARE = 1,
PROCESS_PER_MONITOR_DPI_AWARE = 2
} PROCESS_DPI_AWARENESS;
#endif

View file

@ -1,8 +1,10 @@
#ifndef HOOK_H
#define HOOK_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
typedef BOOL (WINAPI* GETCURSORPOSPROC)(LPPOINT);
typedef BOOL(WINAPI* CLIPCURSORPROC)(const RECT*);
typedef int (WINAPI* SHOWCURSORPROC)(BOOL);
@ -55,13 +57,13 @@ extern LOADLIBRARYWPROC real_LoadLibraryW;
extern LOADLIBRARYEXAPROC real_LoadLibraryExA;
extern LOADLIBRARYEXWPROC real_LoadLibraryExW;
extern int HookingMethod;
extern BOOL Hook_Active;
extern int g_hook_method;
extern BOOL g_hook_active;
void Hook_Init();
void Hook_Exit();
void Hook_PatchIAT(HMODULE hMod, char *moduleName, char *functionName, PROC newFunction);
void Hook_Create(char *moduleName, char *functionName, PROC newFunction, PROC *function);
void Hook_Revert(char *moduleName, char *functionName, PROC newFunction, PROC *function);
void hook_init();
void hook_exit();
void hook_patch_iat(HMODULE hMod, char *moduleName, char *functionName, PROC newFunction);
void hook_create(char *moduleName, char *functionName, PROC newFunction, PROC *function);
void hook_revert(char *moduleName, char *functionName, PROC newFunction, PROC *function);
#endif

View file

@ -1,190 +0,0 @@
/*
* Copyright (c) 2010 Toni Spets <toni.spets@iki.fi>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef MAIN_H
#define MAIN_H
#include <windows.h>
#include "ddraw.h"
#include "debug.h"
#define CUTSCENE_WIDTH 640
#define CUTSCENE_HEIGHT 400
#define WM_AUTORENDERER WM_USER+111
#define WM_WINEFULLSCREEN WM_USER+112
#define WM_D3D9DEVICELOST WM_USER+113
#define IDT_TIMER_LEAVE_BNET 541287654
DEFINE_GUID(IID_IMediaStream, 0xb502d1bd, 0x9a57, 0x11d0, 0x8f, 0xde, 0x00, 0xc0, 0x4f, 0xd9, 0x18, 0x9d);
DEFINE_GUID(IID_IAMMediaStream, 0xbebe595d, 0x9a6f, 0x11d0, 0x8f, 0xde, 0x00, 0xc0, 0x4f, 0xd9, 0x18, 0x9d);
extern BOOL ShowDriverWarning;
extern RECT WindowRect;
extern int WindowState;
extern BOOL ChildWindowExists;
extern HMODULE DDrawModule;
BOOL detect_cutscene();
void LimitGameTicks();
void ToggleFullscreen();
void SetWindowRect(int x, int y, int width, int height, UINT flags);
DWORD WINAPI render_main(void);
DWORD WINAPI render_soft_main(void);
BOOL CALLBACK EnumChildProc(HWND hWnd, LPARAM lParam);
struct IDirectDrawImpl;
struct IDirectDrawImplVtbl;
struct IDirectDrawSurfaceImpl;
extern struct IDirectDrawImpl *ddraw;
typedef struct SpeedLimiter
{
DWORD ticklength;
LONGLONG tickLengthNs;
HANDLE hTimer;
LARGE_INTEGER dueTime;
BOOL useBltOrFlip;
} SpeedLimiter;
typedef struct IDirectDrawImpl
{
struct IDirectDrawImplVtbl *lpVtbl;
ULONG Ref;
DWORD width;
DWORD height;
DWORD bpp;
BOOL windowed;
BOOL border;
BOOL boxing;
DEVMODE mode;
struct IDirectDrawSurfaceImpl *primary;
char title[128];
HMODULE real_dll;
/* real export from system32\ddraw.dll */
HRESULT (WINAPI *DirectDrawCreate)(GUID FAR*, LPDIRECTDRAW FAR*, IUnknown FAR*);
CRITICAL_SECTION cs;
struct
{
int maxfps;
BOOL forcefps;
int width;
int height;
int bpp;
HDC hDC;
int *tex;
HANDLE thread;
BOOL run;
HANDLE sem;
DEVMODE mode;
struct { int width; int height; int x; int y; } viewport;
LONG paletteUpdated;
LONG surfaceUpdated;
float scaleW;
float scaleH;
float unScaleW;
float unScaleH;
} render;
HWND hWnd;
LRESULT (CALLBACK *WndProc)(HWND, UINT, WPARAM, LPARAM);
struct { float x; float y; } cursor;
BOOL locked;
BOOL adjmouse;
BOOL devmode;
BOOL vsync;
BOOL vhack;
BOOL isredalert;
BOOL iscnc1;
LONG incutscene;
DWORD (WINAPI *renderer)(void);
BOOL fullscreen;
BOOL maintas;
BOOL noactivateapp;
BOOL handlemouse;
char shader[MAX_PATH];
BOOL wine;
BOOL altenter;
BOOL hidecursor;
BOOL accurateTimers;
BOOL resizable;
BOOL tm2hack;
BOOL sierrahack;
BOOL nonexclusive;
BOOL bnetActive;
BOOL bnetWasFullscreen;
BOOL bnetWasUpscaled;
RECT bnetWinRect;
POINT bnetPos;
SpeedLimiter ticksLimiter;
SpeedLimiter flipLimiter;
SpeedLimiter fpsLimiter;
} IDirectDrawImpl;
typedef struct IDirectDrawImplVtbl IDirectDrawImplVtbl;
struct IDirectDrawImplVtbl
{
HRESULT(__stdcall *QueryInterface) (IDirectDrawImpl *, const IID* const riid, LPVOID * ppvObj);
ULONG(__stdcall *AddRef) (IDirectDrawImpl *);
ULONG(__stdcall *Release) (IDirectDrawImpl *);
HRESULT(__stdcall *Compact)(IDirectDrawImpl *);
HRESULT(__stdcall *CreateClipper)(IDirectDrawImpl *, DWORD, LPDIRECTDRAWCLIPPER *, IUnknown *);
HRESULT(__stdcall *CreatePalette)(IDirectDrawImpl *, DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE *, IUnknown *);
HRESULT(__stdcall *CreateSurface)(IDirectDrawImpl *, LPDDSURFACEDESC, LPDIRECTDRAWSURFACE *, IUnknown *);
HRESULT(__stdcall *DuplicateSurface)( IDirectDrawImpl *, LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE *);
HRESULT(__stdcall *EnumDisplayModes)( IDirectDrawImpl *, DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK);
HRESULT(__stdcall *EnumSurfaces)(IDirectDrawImpl *, DWORD, LPDDSURFACEDESC, LPVOID,LPDDENUMSURFACESCALLBACK);
HRESULT(__stdcall *FlipToGDISurface)(IDirectDrawImpl *);
HRESULT(__stdcall *GetCaps)(IDirectDrawImpl *, LPDDCAPS, LPDDCAPS);
HRESULT(__stdcall *GetDisplayMode)(IDirectDrawImpl *, LPDDSURFACEDESC);
HRESULT(__stdcall *GetFourCCCodes)(IDirectDrawImpl *, LPDWORD, LPDWORD);
HRESULT(__stdcall *GetGDISurface)(IDirectDrawImpl *, LPDIRECTDRAWSURFACE *);
HRESULT(__stdcall *GetMonitorFrequency)(IDirectDrawImpl *, LPDWORD);
HRESULT(__stdcall *GetScanLine)(IDirectDrawImpl *, LPDWORD);
HRESULT(__stdcall *GetVerticalBlankStatus)(IDirectDrawImpl *, LPBOOL);
HRESULT(__stdcall *Initialize)(IDirectDrawImpl *, GUID *);
HRESULT(__stdcall *RestoreDisplayMode)(IDirectDrawImpl *);
HRESULT(__stdcall *SetCooperativeLevel)(IDirectDrawImpl *, HWND, DWORD);
union
{
HRESULT(__stdcall *SetDisplayMode1)(IDirectDrawImpl *, DWORD, DWORD, DWORD);
HRESULT(__stdcall *SetDisplayMode2)(IDirectDrawImpl *, DWORD, DWORD, DWORD, DWORD, DWORD);
};
HRESULT(__stdcall *WaitForVerticalBlank)(IDirectDrawImpl *, DWORD, HANDLE);
HRESULT(__stdcall *GetAvailableVidMem)(IDirectDrawImpl *, LPDDSCAPS, LPDWORD, LPDWORD);
};
typedef enum PROCESS_DPI_AWARENESS {
PROCESS_DPI_UNAWARE = 0,
PROCESS_SYSTEM_DPI_AWARE = 1,
PROCESS_PER_MONITOR_DPI_AWARE = 2
} PROCESS_DPI_AWARENESS;
#endif

View file

@ -1,37 +1,8 @@
#ifndef MOUSE_H
#define MOUSE_H
#include <windows.h>
void mouse_lock();
void mouse_unlock();
BOOL WINAPI fake_GetCursorPos(LPPOINT lpPoint);
BOOL WINAPI fake_ClipCursor(const RECT *lpRect);
int WINAPI fake_ShowCursor(BOOL bShow);
HCURSOR WINAPI fake_SetCursor(HCURSOR hCursor);
BOOL WINAPI fake_GetWindowRect(HWND hWnd, LPRECT lpRect);
BOOL WINAPI fake_GetClientRect(HWND hWnd, LPRECT lpRect);
BOOL WINAPI fake_ClientToScreen(HWND hWnd, LPPOINT lpPoint);
BOOL WINAPI fake_ScreenToClient(HWND hWnd, LPPOINT lpPoint);
BOOL WINAPI fake_SetCursorPos(int X, int Y);
HWND WINAPI fake_WindowFromPoint(POINT Point);
BOOL WINAPI fake_GetClipCursor(LPRECT lpRect);
BOOL WINAPI fake_GetCursorInfo(PCURSORINFO pci);
int WINAPI fake_GetSystemMetrics(int nIndex);
BOOL WINAPI fake_SetWindowPos(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags);
BOOL WINAPI fake_MoveWindow(HWND hWnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint);
LRESULT WINAPI fake_SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
LONG WINAPI fake_SetWindowLongA(HWND hWnd, int nIndex, LONG dwNewLong);
BOOL WINAPI fake_EnableWindow(HWND hWnd, BOOL bEnable);
BOOL WINAPI fake_DestroyWindow(HWND hWnd);
int WINAPI fake_GetDeviceCaps(HDC hdc, int index);
HMODULE WINAPI fake_LoadLibraryA(LPCSTR lpLibFileName);
HMODULE WINAPI fake_LoadLibraryW(LPCWSTR lpLibFileName);
HMODULE WINAPI fake_LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
HMODULE WINAPI fake_LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
HWND WINAPI fake_CreateWindowExA(
DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y,
int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam);
#endif

View file

@ -1,4 +1,5 @@
#pragma once
#ifndef OPENGL_UTILS_H
#define OPENGL_UTILS_H
#include "glcorearb.h"
// wgl
@ -32,11 +33,11 @@ extern PFNGLVERTEX2FPROC glVertex2f;
// <--- compat profile only
BOOL OpenGL_LoadDll();
void OpenGL_Init();
BOOL OpenGL_ExtExists(char *ext, HDC hdc);
GLuint OpenGL_BuildProgram(const GLchar *vertSource, const GLchar *fragSource);
GLuint OpenGL_BuildProgramFromFile(const char *filePath);
BOOL oglu_load_dll();
void oglu_init();
BOOL oglu_ext_exists(char *ext, HDC hdc);
GLuint oglu_build_program(const GLchar *vertSource, const GLchar *fragSource);
GLuint oglu_build_program_from_file(const char *filePath);
extern PFNGLVIEWPORTPROC glViewport;
extern PFNGLBINDTEXTUREPROC glBindTexture;
@ -52,7 +53,6 @@ extern PFNGLGETTEXIMAGEPROC glGetTexImage;
extern PFNGLPIXELSTOREIPROC glPixelStorei;
extern PFNGLENABLEPROC glEnable;
extern PFNGLCLEARPROC glClear;
extern PFNGLCREATEPROGRAMPROC glCreateProgram;
extern PFNGLDELETEPROGRAMPROC glDeleteProgram;
extern PFNGLUSEPROGRAMPROC glUseProgram;
@ -84,13 +84,11 @@ extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
extern PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
extern PFNGLGETACTIVEUNIFORMPROC glGetActiveUniform;
extern PFNGLCREATESHADERPROC glCreateShader;
extern PFNGLDELETESHADERPROC glDeleteShader;
extern PFNGLSHADERSOURCEPROC glShaderSource;
extern PFNGLCOMPILESHADERPROC glCompileShader;
extern PFNGLGETSHADERIVPROC glGetShaderiv;
extern PFNGLGENBUFFERSPROC glGenBuffers;
extern PFNGLBINDBUFFERPROC glBindBuffer;
extern PFNGLBUFFERDATAPROC glBufferData;
@ -102,21 +100,18 @@ extern PFNGLDELETEBUFFERSPROC glDeleteBuffers;
extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
extern PFNGLACTIVETEXTUREPROC glActiveTexture;
extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
extern PFNGLDRAWBUFFERSPROC glDrawBuffers;
extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;
extern PFNGLTEXBUFFERPROC glTexBuffer;
extern HMODULE OpenGL_hModule;
extern HMODULE g_oglu_hmodule;
extern BOOL g_oglu_got_version2;
extern BOOL g_oglu_got_version3;
extern char g_oglu_version[];
extern BOOL OpenGL_GotVersion2;
extern BOOL OpenGL_GotVersion3;
extern char OpenGL_Version[];
#endif

View file

@ -1,6 +1,9 @@
#ifndef OPENGLSHADER_H
#define OPENGLSHADER_H
// old
const char PassthroughVertShader110Src[] =
const char PASSTHROUGH_VERT_SHADER_110[] =
"#version 110\n"
"varying vec2 TEX0; \n"
"\n"
@ -10,7 +13,7 @@ const char PassthroughVertShader110Src[] =
" TEX0 = gl_MultiTexCoord0.xy; \n"
"}\n";
const char PaletteFragShader110Src[] =
const char PALETTE_FRAG_SHADER_110[] =
"#version 110\n"
"uniform sampler2D SurfaceTex; \n"
"uniform sampler2D PaletteTex; \n"
@ -23,7 +26,7 @@ const char PaletteFragShader110Src[] =
"}\n";
const char PassthroughFragShader110Src[] =
const char PASSTHROUGH_FRAG_SHADER_110[] =
"#version 110\n"
"uniform sampler2D SurfaceTex; \n"
"varying vec2 TEX0; \n"
@ -36,7 +39,7 @@ const char PassthroughFragShader110Src[] =
// new
const char PassthroughVertShaderSrc[] =
const char PASSTHROUGH_VERT_SHADER[] =
"#version 130\n"
"in vec4 VertexCoord;\n"
"in vec4 COLOR;\n"
@ -53,7 +56,7 @@ const char PassthroughVertShaderSrc[] =
"}\n";
const char PaletteFragShaderSrc[] =
const char PALETTE_FRAG_SHADER[] =
"#version 130\n"
"out vec4 FragColor;\n"
"uniform sampler2D SurfaceTex;\n"
@ -67,7 +70,7 @@ const char PaletteFragShaderSrc[] =
"}\n";
const char PassthroughFragShaderSrc[] =
const char PASSTHROUGH_FRAG_SHADER[] =
"#version 130\n"
"out vec4 FragColor;\n"
"uniform sampler2D SurfaceTex;\n"
@ -78,3 +81,5 @@ const char PassthroughFragShaderSrc[] =
" vec4 texel = texture(SurfaceTex, TEX0.xy);\n"
" FragColor = texel;\n"
"}\n";
#endif

View file

@ -1,56 +0,0 @@
/*
* Copyright (c) 2010 Toni Spets <toni.spets@iki.fi>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef PALETTE_H
#define PALETTE_H
#include <windows.h>
#include "ddraw.h"
#include "main.h"
struct IDirectDrawPaletteImpl;
struct IDirectDrawPaletteImplVtbl;
typedef struct IDirectDrawPaletteImpl
{
struct IDirectDrawPaletteImplVtbl *lpVtbl;
ULONG Ref;
int data_bgr[256];
RGBQUAD *data_rgb;
} IDirectDrawPaletteImpl;
struct IDirectDrawPaletteImplVtbl
{
/* IUnknown */
HRESULT (__stdcall *QueryInterface)(IDirectDrawPaletteImpl*, REFIID, void**);
ULONG (__stdcall *AddRef)(IDirectDrawPaletteImpl*);
ULONG (__stdcall *Release)(IDirectDrawPaletteImpl*);
/* IDirectDrawPalette */
HRESULT (__stdcall *GetCaps)(IDirectDrawPaletteImpl*, LPDWORD);
HRESULT (__stdcall *GetEntries)(IDirectDrawPaletteImpl*, DWORD, DWORD, DWORD, LPPALETTEENTRY);
HRESULT (__stdcall *Initialize)(IDirectDrawPaletteImpl*, LPDIRECTDRAW, DWORD, LPPALETTEENTRY);
HRESULT (__stdcall *SetEntries)(IDirectDrawPaletteImpl*, DWORD, DWORD, DWORD, LPPALETTEENTRY);
} IDirectDrawPaletteImplVtbl;
HRESULT __stdcall ddraw_CreatePalette(IDirectDrawImpl *This, DWORD dwFlags, LPPALETTEENTRY DDColorArray, LPDIRECTDRAWPALETTE FAR * DDPalette, IUnknown FAR * unkOuter);
extern IDirectDrawPaletteImpl *LastFreedPalette;
#endif

View file

@ -1,11 +1,35 @@
#pragma once
#ifndef RENDER_D3D9_H
#define RENDER_D3D9_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <d3d9.h>
#define D3D9_TEXTURE_COUNT 2
typedef struct CUSTOMVERTEX { float x, y, z, rhw, u, v; } CUSTOMVERTEX;
DWORD WINAPI render_d3d9_main(void);
BOOL Direct3D9_Create();
BOOL Direct3D9_Reset();
BOOL Direct3D9_Release();
BOOL Direct3D9_OnDeviceLost();
typedef struct d3d9_renderer
{
HMODULE hmodule;
D3DPRESENT_PARAMETERS params;
LPDIRECT3D9 instance;
LPDIRECT3DDEVICE9 device;
LPDIRECT3DVERTEXBUFFER9 vertex_buf;
IDirect3DTexture9* surface_tex[D3D9_TEXTURE_COUNT];
IDirect3DTexture9* palette_tex[D3D9_TEXTURE_COUNT];
IDirect3DPixelShader9* pixel_shader;
float scale_w;
float scale_h;
int bits_per_pixel;
} d3d9_renderer;
extern HMODULE Direct3D9_hModule;
BOOL d3d9_is_available();
DWORD WINAPI d3d9_render_main(void);
BOOL d3d9_create();
BOOL d3d9_reset();
BOOL d3d9_release();
BOOL d3d9_on_device_lost();
#endif

10
inc/render_gdi.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef RENDER_GDI_H
#define RENDER_GDI_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
DWORD WINAPI gdi_render_main(void);
#endif

40
inc/render_ogl.h Normal file
View file

@ -0,0 +1,40 @@
#ifndef RENDER_OGL_H
#define RENDER_OGL_H
#include <windows.h>
#include "opengl_utils.h"
#define TEXTURE_COUNT 4
typedef struct ogl_renderer
{
HGLRC context;
GLuint main_program;
GLuint scale_program;
BOOL got_error;
int surface_tex_width;
int surface_tex_height;
int* surface_tex;
GLenum surface_format;
GLenum surface_type;
GLuint surface_tex_ids[TEXTURE_COUNT];
GLuint palette_tex_ids[TEXTURE_COUNT];
float scale_w;
float scale_h;
GLint main_tex_coord_attr_loc;
GLint main_vertex_coord_attr_loc;
GLuint main_vbos[3];
GLuint main_vao;
GLint frame_count_uni_loc;
GLuint frame_buffer_id;
GLuint frame_buffer_tex_id;
GLuint scale_vbos[3];
GLuint scale_vao;
BOOL use_opengl;
BOOL adjust_alignment;
BOOL filter_bilinear;
} ogl_renderer;
DWORD WINAPI ogl_render_main(void);
#endif

10
inc/screenshot.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef SCREENSHOT_H
#define SCREENSHOT_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "ddsurface.h"
BOOL ss_take_screenshot(struct IDirectDrawSurfaceImpl* src);
#endif

20
inc/utils.h Normal file
View file

@ -0,0 +1,20 @@
#ifndef UTILS_H
#define UTILS_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define CUTSCENE_WIDTH 640
#define CUTSCENE_HEIGHT 400
void util_limit_game_ticks();
void util_update_bnet_pos(int newX, int newY);
BOOL util_get_lowest_resolution(float ratio, SIZE* outRes, DWORD minWidth, DWORD minHeight, DWORD maxWidth, DWORD maxHeight);
void util_toggle_fullscreen();
BOOL util_unadjust_window_rect(LPRECT prc, DWORD dwStyle, BOOL fMenu, DWORD dwExStyle);
void util_set_window_rect(int x, int y, int width, int height, UINT flags);
BOOL CALLBACK util_enum_child_proc(HWND hwnd, LPARAM lParam);
BOOL util_detect_cutscene();
#endif

36
inc/winapi_hooks.h Normal file
View file

@ -0,0 +1,36 @@
#ifndef WINAPI_HOOKS_H
#define WINAPI_HOOKS_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
BOOL WINAPI fake_GetCursorPos(LPPOINT lpPoint);
BOOL WINAPI fake_ClipCursor(const RECT *lpRect);
int WINAPI fake_ShowCursor(BOOL bShow);
HCURSOR WINAPI fake_SetCursor(HCURSOR hCursor);
BOOL WINAPI fake_GetWindowRect(HWND hWnd, LPRECT lpRect);
BOOL WINAPI fake_GetClientRect(HWND hWnd, LPRECT lpRect);
BOOL WINAPI fake_ClientToScreen(HWND hWnd, LPPOINT lpPoint);
BOOL WINAPI fake_ScreenToClient(HWND hWnd, LPPOINT lpPoint);
BOOL WINAPI fake_SetCursorPos(int X, int Y);
HWND WINAPI fake_WindowFromPoint(POINT Point);
BOOL WINAPI fake_GetClipCursor(LPRECT lpRect);
BOOL WINAPI fake_GetCursorInfo(PCURSORINFO pci);
int WINAPI fake_GetSystemMetrics(int nIndex);
BOOL WINAPI fake_SetWindowPos(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags);
BOOL WINAPI fake_MoveWindow(HWND hWnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint);
LRESULT WINAPI fake_SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
LONG WINAPI fake_SetWindowLongA(HWND hWnd, int nIndex, LONG dwNewLong);
BOOL WINAPI fake_EnableWindow(HWND hWnd, BOOL bEnable);
BOOL WINAPI fake_DestroyWindow(HWND hWnd);
int WINAPI fake_GetDeviceCaps(HDC hdc, int index);
HMODULE WINAPI fake_LoadLibraryA(LPCSTR lpLibFileName);
HMODULE WINAPI fake_LoadLibraryW(LPCWSTR lpLibFileName);
HMODULE WINAPI fake_LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
HMODULE WINAPI fake_LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
HWND WINAPI fake_CreateWindowExA(
DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y,
int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam);
#endif

12
inc/wndproc.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef WNDPROC_H
#define WNDPROC_H
#define WM_AUTORENDERER WM_USER+111
#define WM_WINEFULLSCREEN WM_USER+112
#define WM_D3D9DEVICELOST WM_USER+113
#define IDT_TIMER_LEAVE_BNET 541287654
LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
#endif

View file

@ -0,0 +1,369 @@
#include <initguid.h>
#include "IDirectDraw.h"
#include "dd.h"
#include "ddclipper.h"
#include "ddpalette.h"
#include "ddsurface.h"
#include "debug.h"
HRESULT __stdcall IDirectDraw__QueryInterface(IDirectDrawImpl* This, REFIID riid, void** obj)
{
dprintf("-> %s(This=%p, riid=%08X, obj=%p)\n", __FUNCTION__, This, (unsigned int)riid, obj);
HRESULT ret = DDERR_UNSUPPORTED;
if (riid)
{
if (IsEqualGUID(&IID_IDirectDraw2, riid) ||
IsEqualGUID(&IID_IDirectDraw4, riid) ||
IsEqualGUID(&IID_IDirectDraw7, riid))
{
dprintf(" GUID = %08X (IID_IDirectDrawX)\n", ((GUID*)riid)->Data1);
IDirectDrawImpl* dd = (IDirectDrawImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawImpl));
dd->lpVtbl = &g_dd_vtblx;
*obj = dd;
IDirectDraw_AddRef(dd);
ret = S_OK;
}
else
{
dprintf(" GUID = %08X\n", ((GUID*)riid)->Data1);
}
ret = S_OK;
}
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
ULONG __stdcall IDirectDraw__AddRef(IDirectDrawImpl* This)
{
dprintf("-> %s(This=%p)\n", __FUNCTION__, This);
ULONG ret = ++This->ref;
ULONG glob_ref = dd_AddRef();
dprintf("<- %s(This ref=%u, global ref=%u)\n", __FUNCTION__, ret, glob_ref);
return ret;
}
ULONG __stdcall IDirectDraw__Release(IDirectDrawImpl* This)
{
dprintf("-> %s(This=%p)\n", __FUNCTION__, This);
ULONG ret = --This->ref;
if (This->ref == 0)
{
dprintf(" Released (%p)\n", This);
HeapFree(GetProcessHeap(), 0, This);
}
ULONG glob_ref = dd_Release();
dprintf("<- %s(This ref=%u, global ref=%u)\n", __FUNCTION__, ret, glob_ref);
return ret;
}
HRESULT __stdcall IDirectDraw__Compact(IDirectDrawImpl* This)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__CreateClipper(IDirectDrawImpl* This, DWORD dwFlags, LPDIRECTDRAWCLIPPER FAR* lplpDDClipper, IUnknown FAR* pUnkOuter)
{
dprintf("-> %s(This=%p, dwFlags=%08X, DDClipper=%p, unkOuter=%p)\n", __FUNCTION__, This, (int)dwFlags, lplpDDClipper, pUnkOuter);
HRESULT ret = dd_CreateClipper(dwFlags, lplpDDClipper, pUnkOuter);
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__CreatePalette(IDirectDrawImpl* This, DWORD dwFlags, LPPALETTEENTRY lpDDColorArray, LPDIRECTDRAWPALETTE FAR* lpDDPalette, IUnknown FAR* unkOuter)
{
dprintf("-> %s(This=%p, dwFlags=%08X, DDColorArray=%p, DDPalette=%p, unkOuter=%p)\n", __FUNCTION__, This, (int)dwFlags, lpDDColorArray, lpDDPalette, unkOuter);
HRESULT ret = dd_CreatePalette(dwFlags, lpDDColorArray, lpDDPalette, unkOuter);
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__CreateSurface(IDirectDrawImpl* This, LPDDSURFACEDESC lpDDSurfaceDesc, LPDIRECTDRAWSURFACE FAR* lpDDSurface, IUnknown FAR* unkOuter)
{
dprintf("-> %s(This=%p, lpDDSurfaceDesc=%p, lpDDSurface=%p, unkOuter=%p)\n", __FUNCTION__, This, lpDDSurfaceDesc, lpDDSurface, unkOuter);
HRESULT ret = dd_CreateSurface(lpDDSurfaceDesc, lpDDSurface, unkOuter);
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__DuplicateSurface(IDirectDrawImpl* This, LPDIRECTDRAWSURFACE src, LPDIRECTDRAWSURFACE* dest)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__EnumDisplayModes(IDirectDrawImpl* This, DWORD dwFlags, LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext, LPDDENUMMODESCALLBACK lpEnumModesCallback)
{
dprintf("-> %s(This=%p, dwFlags=%08X, lpDDSurfaceDesc=%p, lpContext=%p, lpEnumModesCallback=%p)\n", __FUNCTION__, This, (unsigned int)dwFlags, lpDDSurfaceDesc, lpContext, lpEnumModesCallback);
HRESULT ret = dd_EnumDisplayModes(dwFlags, lpDDSurfaceDesc, lpContext, lpEnumModesCallback);
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__EnumSurfaces(IDirectDrawImpl* This, DWORD a, LPDDSURFACEDESC b, LPVOID c, LPDDENUMSURFACESCALLBACK d)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__FlipToGDISurface(IDirectDrawImpl* This)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__GetCaps(IDirectDrawImpl* This, LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDEmulCaps)
{
dprintf("-> %s(This=%p, lpDDDriverCaps=%p, lpDDEmulCaps=%p)\n", __FUNCTION__, This, lpDDDriverCaps, lpDDEmulCaps);
HRESULT ret = dd_GetCaps(lpDDDriverCaps, lpDDEmulCaps);
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__GetDisplayMode(IDirectDrawImpl* This, LPDDSURFACEDESC a)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DDERR_UNSUPPORTEDMODE;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__GetFourCCCodes(IDirectDrawImpl* This, LPDWORD a, LPDWORD b)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__GetGDISurface(IDirectDrawImpl* This, LPDIRECTDRAWSURFACE* a)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__GetMonitorFrequency(IDirectDrawImpl* This, LPDWORD a)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__GetScanLine(IDirectDrawImpl* This, LPDWORD a)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__GetVerticalBlankStatus(IDirectDrawImpl* This, LPBOOL lpbIsInVB)
{
dprintf("-> %s(This=%p, lpbIsInVB=%p)\n", __FUNCTION__, This, lpbIsInVB);
HRESULT ret = dd_GetVerticalBlankStatus(lpbIsInVB);
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__Initialize(IDirectDrawImpl* This, GUID* a)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__RestoreDisplayMode(IDirectDrawImpl* This)
{
dprintf("-> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = dd_RestoreDisplayMode();
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__SetCooperativeLevel(IDirectDrawImpl* This, HWND hwnd, DWORD dwFlags)
{
dprintf("-> %s(This=%p, hwnd=0x%08X, dwFlags=0x%08X)\n", __FUNCTION__, This, (unsigned int)hwnd, (unsigned int)dwFlags);
HRESULT ret = dd_SetCooperativeLevel(hwnd, dwFlags);
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__SetDisplayMode(IDirectDrawImpl* This, DWORD width, DWORD height, DWORD bpp)
{
dprintf("-> %s(This=%p, width=%d, height=%d, bpp=%d)\n", __FUNCTION__, This, (unsigned int)width, (unsigned int)height, (unsigned int)bpp);
HRESULT ret = dd_SetDisplayMode(width, height, bpp);
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__SetDisplayModeX(IDirectDrawImpl* This, DWORD width, DWORD height, DWORD bpp, DWORD refreshRate, DWORD flags)
{
dprintf("-> %s(This=%p, width=%d, height=%d, bpp=%d, refreshRate=%d, flags=%d)\n", __FUNCTION__, This, (unsigned int)width, (unsigned int)height, (unsigned int)bpp, (unsigned int)refreshRate, (unsigned int)flags);
HRESULT ret = dd_SetDisplayMode(width, height, bpp);
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__WaitForVerticalBlank(IDirectDrawImpl* This, DWORD dwFlags, HANDLE h)
{
dprintfex("-> %s(This=%p, flags=%08X, handle=%p)\n", __FUNCTION__, This, dwFlags, h);
HRESULT ret = dd_WaitForVerticalBlank(dwFlags, h);
dprintfex("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__GetAvailableVidMem(IDirectDrawImpl* This, void* lpDDCaps, LPDWORD lpdwTotal, LPDWORD lpdwFree)
{
dprintf("-> %s(This=%p, lpDDCaps=%p, lpdwTotal=%p, lpdwFree=%p)\n", __FUNCTION__, This, lpDDCaps, lpdwTotal, lpdwFree);
HRESULT ret = dd_GetAvailableVidMem(lpDDCaps, lpdwTotal, lpdwFree);
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__GetSurfaceFromDC(IDirectDrawImpl* This, HDC hdc, void* lplpDDSurface)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DDERR_GENERIC;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__RestoreAllSurfaces(IDirectDrawImpl* This)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DDERR_INVALIDOBJECT;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__TestCooperativeLevel(IDirectDrawImpl* This)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DDERR_INVALIDOBJECT;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__GetDeviceIdentifier(IDirectDrawImpl* This, void* pDDDI, DWORD dwFlags)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DDERR_INVALIDPARAMS;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__StartModeTest(IDirectDrawImpl* This, LPSIZE pModes, DWORD dwNumModes, DWORD dwFlags)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DDERR_CURRENTLYNOTAVAIL;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDraw__EvaluateMode(IDirectDrawImpl* This, DWORD dwFlags, DWORD* pTimeout)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DDERR_INVALIDOBJECT;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
struct IDirectDrawImplVtbl g_dd_vtbl1 =
{
/* IUnknown */
IDirectDraw__QueryInterface,
IDirectDraw__AddRef,
IDirectDraw__Release,
/* IDirectDrawImpl */
IDirectDraw__Compact,
IDirectDraw__CreateClipper,
IDirectDraw__CreatePalette,
IDirectDraw__CreateSurface,
IDirectDraw__DuplicateSurface,
IDirectDraw__EnumDisplayModes,
IDirectDraw__EnumSurfaces,
IDirectDraw__FlipToGDISurface,
IDirectDraw__GetCaps,
IDirectDraw__GetDisplayMode,
IDirectDraw__GetFourCCCodes,
IDirectDraw__GetGDISurface,
IDirectDraw__GetMonitorFrequency,
IDirectDraw__GetScanLine,
IDirectDraw__GetVerticalBlankStatus,
IDirectDraw__Initialize,
IDirectDraw__RestoreDisplayMode,
IDirectDraw__SetCooperativeLevel,
{IDirectDraw__SetDisplayMode},
IDirectDraw__WaitForVerticalBlank,
// v2
IDirectDraw__GetAvailableVidMem,
// v4
IDirectDraw__GetSurfaceFromDC,
IDirectDraw__RestoreAllSurfaces,
IDirectDraw__TestCooperativeLevel,
IDirectDraw__GetDeviceIdentifier,
// v7
IDirectDraw__StartModeTest,
IDirectDraw__EvaluateMode,
};
struct IDirectDrawImplVtbl g_dd_vtblx =
{
/* IUnknown */
IDirectDraw__QueryInterface,
IDirectDraw__AddRef,
IDirectDraw__Release,
/* IDirectDrawImpl */
IDirectDraw__Compact,
IDirectDraw__CreateClipper,
IDirectDraw__CreatePalette,
IDirectDraw__CreateSurface,
IDirectDraw__DuplicateSurface,
IDirectDraw__EnumDisplayModes,
IDirectDraw__EnumSurfaces,
IDirectDraw__FlipToGDISurface,
IDirectDraw__GetCaps,
IDirectDraw__GetDisplayMode,
IDirectDraw__GetFourCCCodes,
IDirectDraw__GetGDISurface,
IDirectDraw__GetMonitorFrequency,
IDirectDraw__GetScanLine,
IDirectDraw__GetVerticalBlankStatus,
IDirectDraw__Initialize,
IDirectDraw__RestoreDisplayMode,
IDirectDraw__SetCooperativeLevel,
{IDirectDraw__SetDisplayModeX},
IDirectDraw__WaitForVerticalBlank,
// v2
IDirectDraw__GetAvailableVidMem,
// v4
IDirectDraw__GetSurfaceFromDC,
IDirectDraw__RestoreAllSurfaces,
IDirectDraw__TestCooperativeLevel,
IDirectDraw__GetDeviceIdentifier,
// v7
IDirectDraw__StartModeTest,
IDirectDraw__EvaluateMode,
};

View file

@ -0,0 +1,99 @@
#include "IDirectDrawClipper.h"
#include "ddclipper.h"
#include "debug.h"
HRESULT __stdcall IDirectDrawClipper__QueryInterface(IDirectDrawClipperImpl *This, REFIID riid, void **obj)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p, riid=%08X, obj=%p)\n", __FUNCTION__, This, (unsigned int)riid, obj);
HRESULT ret = S_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
ULONG __stdcall IDirectDrawClipper__AddRef(IDirectDrawClipperImpl *This)
{
dprintf("-> %s(This=%p)\n", __FUNCTION__, This);
ULONG ret = ++This->ref;
dprintf("<- %s(This ref=%u)\n", __FUNCTION__, ret);
return ret;
}
ULONG __stdcall IDirectDrawClipper__Release(IDirectDrawClipperImpl *This)
{
dprintf("-> %s(This=%p)\n", __FUNCTION__, This);
ULONG ret = --This->ref;
if (This->ref == 0)
{
dprintf(" Released (%p)\n", This);
HeapFree(GetProcessHeap(), 0, This);
}
dprintf("<- %s(This ref=%u)\n", __FUNCTION__, ret);
return ret;
}
HRESULT __stdcall IDirectDrawClipper__GetClipList(IDirectDrawClipperImpl *This, LPRECT a, LPRGNDATA b, LPDWORD c)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawClipper__GetHWnd(IDirectDrawClipperImpl *This, HWND FAR *a)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawClipper__Initialize(IDirectDrawClipperImpl *This, LPDIRECTDRAW a, DWORD b)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawClipper__IsClipListChanged(IDirectDrawClipperImpl *This, BOOL FAR *a)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawClipper__SetClipList(IDirectDrawClipperImpl *This, LPRGNDATA a, DWORD b)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawClipper__SetHWnd(IDirectDrawClipperImpl *This, DWORD a, HWND b)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
struct IDirectDrawClipperImplVtbl g_ddc_vtbl =
{
/* IUnknown */
IDirectDrawClipper__QueryInterface,
IDirectDrawClipper__AddRef,
IDirectDrawClipper__Release,
/* IDirectDrawClipper */
IDirectDrawClipper__GetClipList,
IDirectDrawClipper__GetHWnd,
IDirectDrawClipper__Initialize,
IDirectDrawClipper__IsClipListChanged,
IDirectDrawClipper__SetClipList,
IDirectDrawClipper__SetHWnd
};

View file

@ -0,0 +1,84 @@
#include "IDirectDrawPalette.h"
#include "ddpalette.h"
#include "ddsurface.h"
#include "debug.h"
HRESULT __stdcall IDirectDrawPalette__QueryInterface(IDirectDrawPaletteImpl* This, REFIID riid, void** obj)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p, riid=%08X, obj=%p)\n", __FUNCTION__, This, (unsigned int)riid, obj);
HRESULT ret = S_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
ULONG __stdcall IDirectDrawPalette__AddRef(IDirectDrawPaletteImpl* This)
{
dprintf("-> %s(This=%p)\n", __FUNCTION__, This);
ULONG ret = ++This->ref;
dprintf("<- %s(This ref=%u)\n", __FUNCTION__, ret);
return ret;
}
ULONG __stdcall IDirectDrawPalette__Release(IDirectDrawPaletteImpl* This)
{
dprintf("-> %s(This=%p)\n", __FUNCTION__, This);
ULONG ret = --This->ref;
if (This->ref == 0)
{
dprintf(" Released (%p)\n", This);
if (g_ddraw)
g_ddraw->last_freed_palette = This;
HeapFree(GetProcessHeap(), 0, This);
}
dprintf("<- %s(This ref=%u)\n", __FUNCTION__, ret);
return ret;
}
HRESULT __stdcall IDirectDrawPalette__GetCaps(IDirectDrawPaletteImpl* This, LPDWORD caps)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p, caps=%p)\n", __FUNCTION__, This, caps);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawPalette__GetEntries(IDirectDrawPaletteImpl *This, DWORD dwFlags, DWORD dwBase, DWORD dwNumEntries, LPPALETTEENTRY lpEntries)
{
dprintf("-> %s(This=%p, dwFlags=%08X, dwBase=%d, dwNumEntries=%d, lpEntries=%p)\n", __FUNCTION__, This, (int)dwFlags, (int)dwBase, (int)dwNumEntries, lpEntries);
HRESULT ret = ddp_GetEntries(This, dwFlags, dwBase, dwNumEntries, lpEntries);
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawPalette__Initialize(IDirectDrawPaletteImpl* This, LPDIRECTDRAW lpDD, DWORD dw, LPPALETTEENTRY paent)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawPalette__SetEntries(IDirectDrawPaletteImpl *This, DWORD dwFlags, DWORD dwStartingEntry, DWORD dwCount, LPPALETTEENTRY lpEntries)
{
dprintfex("-> %s(This=%p, dwFlags=%08X, dwStartingEntry=%d, dwCount=%d, lpEntries=%p)\n", __FUNCTION__, This, (int)dwFlags, (int)dwStartingEntry, (int)dwCount, lpEntries);
HRESULT ret = ddp_SetEntries(This, dwFlags, dwStartingEntry, dwCount, lpEntries);
dprintfex("<- %s\n", __FUNCTION__);
return ret;
}
struct IDirectDrawPaletteImplVtbl g_ddp_vtbl =
{
/* IUnknown */
IDirectDrawPalette__QueryInterface,
IDirectDrawPalette__AddRef,
IDirectDrawPalette__Release,
/* IDirectDrawPalette */
IDirectDrawPalette__GetCaps,
IDirectDrawPalette__GetEntries,
IDirectDrawPalette__Initialize,
IDirectDrawPalette__SetEntries
};

View file

@ -0,0 +1,377 @@
#include "IDirectDrawSurface.h"
#include "ddsurface.h"
#include "dd.h"
#include "debug.h"
HRESULT __stdcall IDirectDrawSurface__QueryInterface(IDirectDrawSurfaceImpl *This, REFIID riid, void **obj)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p, riid=%08X, obj=%p)\n", __FUNCTION__, This, (unsigned int)riid, obj);
HRESULT ret = S_OK;
if (riid && !IsEqualGUID(&IID_IDirectDrawSurface, riid))
{
dprintf(" GUID = %08X\n", ((GUID *)riid)->Data1);
IDirectDrawSurface_AddRef(This);
}
*obj = This;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
ULONG __stdcall IDirectDrawSurface__AddRef(IDirectDrawSurfaceImpl *This)
{
dprintf("-> %s(This=%p)\n", __FUNCTION__, This);
ULONG ret = ++This->ref;
dprintf("<- %s(This ref=%u)\n", __FUNCTION__, ret);
return ret;
}
ULONG __stdcall IDirectDrawSurface__Release(IDirectDrawSurfaceImpl *This)
{
dprintf("-> %s(This=%p)\n", __FUNCTION__, This);
ULONG ret = --This->ref;
if(This->ref == 0)
{
dprintf(" Released (%p)\n", This);
if ((This->caps & DDSCAPS_PRIMARYSURFACE))
{
EnterCriticalSection(&g_ddraw->cs);
g_ddraw->primary = NULL;
LeaveCriticalSection(&g_ddraw->cs);
}
if (This->bitmap)
DeleteObject(This->bitmap);
else if (This->surface)
HeapFree(GetProcessHeap(), 0, This->surface);
if (This->hdc)
DeleteDC(This->hdc);
if (This->bmi)
HeapFree(GetProcessHeap(), 0, This->bmi);
if(This->palette && (!g_ddraw || (void*)This->palette != g_ddraw->last_freed_palette))
{
IDirectDrawPalette_Release(This->palette);
}
HeapFree(GetProcessHeap(), 0, This);
}
dprintf("<- %s(This ref=%u)\n", __FUNCTION__, ret);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__AddAttachedSurface(IDirectDrawSurfaceImpl *This, LPDIRECTDRAWSURFACE lpDDSurface)
{
dprintf("-> %s(This=%p, lpDDSurface=%p)\n", __FUNCTION__, This, lpDDSurface);
HRESULT ret = dds_AddAttachedSurface(This, lpDDSurface);
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__AddOverlayDirtyRect(IDirectDrawSurfaceImpl *This, LPRECT a)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__Blt(IDirectDrawSurfaceImpl *This, LPRECT lpDestRect, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx)
{
dprintfex("-> %s(This=%p, lpDestRect=%p, lpDDSrcSurface=%p, lpSrcRect=%p, dwFlags=%08X, lpDDBltFx=%p)\n", __FUNCTION__, This, lpDestRect, lpDDSrcSurface, lpSrcRect, (int)dwFlags, lpDDBltFx);
HRESULT ret = dds_Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx);
dprintfex("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__BltBatch(IDirectDrawSurfaceImpl *This, LPDDBLTBATCH a, DWORD b, DWORD c)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__BltFast(IDirectDrawSurfaceImpl *This, DWORD dst_x, DWORD dst_y, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DWORD flags)
{
dprintfex("-> %s(This=%p, x=%d, y=%d, lpDDSrcSurface=%p, lpSrcRect=%p, flags=%08X)\n", __FUNCTION__, This, dst_x, dst_y, lpDDSrcSurface, lpSrcRect, flags);
HRESULT ret = dds_BltFast(This, dst_x, dst_y, lpDDSrcSurface, lpSrcRect, flags);
dprintfex("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__DeleteAttachedSurface(IDirectDrawSurfaceImpl *This, DWORD dwFlags, LPDIRECTDRAWSURFACE lpDDSurface)
{
dprintf("-> %s(This=%p, dwFlags=%08X, lpDDSurface=%p)\n", __FUNCTION__, This, (int)dwFlags, lpDDSurface);
HRESULT ret = dds_DeleteAttachedSurface(This, dwFlags, lpDDSurface);
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__GetSurfaceDesc(IDirectDrawSurfaceImpl *This, LPDDSURFACEDESC lpDDSurfaceDesc)
{
dprintfex("-> %s(This=%p, lpDDSurfaceDesc=%p)\n", __FUNCTION__, This, lpDDSurfaceDesc);
HRESULT ret = dds_GetSurfaceDesc(This, lpDDSurfaceDesc);
dprintfex("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__EnumAttachedSurfaces(IDirectDrawSurfaceImpl *This, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback)
{
dprintf("-> %s(This=%p, lpContext=%p, lpEnumSurfacesCallback=%p)\n", __FUNCTION__, This, lpContext, lpEnumSurfacesCallback);
HRESULT ret = dds_EnumAttachedSurfaces(This, lpContext, lpEnumSurfacesCallback);
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__EnumOverlayZOrders(IDirectDrawSurfaceImpl *This, DWORD a, LPVOID b, LPDDENUMSURFACESCALLBACK c)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__Flip(IDirectDrawSurfaceImpl *This, LPDIRECTDRAWSURFACE surface, DWORD flags)
{
dprintfex("-> %s(This=%p, surface=%p, flags=%08X)\n", __FUNCTION__, This, surface, flags);
HRESULT ret = dds_Flip(This, surface, flags);
dprintfex("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__GetAttachedSurface(IDirectDrawSurfaceImpl *This, LPDDSCAPS lpDdsCaps, LPDIRECTDRAWSURFACE FAR *surface)
{
dprintf("-> %s(This=%p, dwCaps=%08X, surface=%p)\n", __FUNCTION__, This, lpDdsCaps->dwCaps, surface);
HRESULT ret = dds_GetAttachedSurface(This, lpDdsCaps, surface);
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__GetBltStatus(IDirectDrawSurfaceImpl *This, DWORD a)
{
dprintfex("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintfex("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__GetCaps(IDirectDrawSurfaceImpl *This, LPDDSCAPS lpDDSCaps)
{
dprintf("-> %s(This=%p, lpDDSCaps=%p)\n", __FUNCTION__, This, lpDDSCaps);
HRESULT ret = dds_GetCaps(This, lpDDSCaps);
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__GetClipper(IDirectDrawSurfaceImpl *This, LPDIRECTDRAWCLIPPER FAR *a)
{
dprintfex("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintfex("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__GetColorKey(IDirectDrawSurfaceImpl *This, DWORD flags, LPDDCOLORKEY colorKey)
{
dprintfex("-> %s(This=%p, flags=0x%08X, color_key=%p)\n", __FUNCTION__, This, flags, colorKey);
HRESULT ret = dds_GetColorKey(This, flags, colorKey);
dprintfex("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__GetDC(IDirectDrawSurfaceImpl *This, HDC FAR *a)
{
dprintfex("-> %s(This=%p, ...)\n", __FUNCTION__, This);
HRESULT ret = dds_GetDC(This, a);
dprintfex("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__GetFlipStatus(IDirectDrawSurfaceImpl *This, DWORD a)
{
dprintfex("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintfex("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__GetOverlayPosition(IDirectDrawSurfaceImpl *This, LPLONG a, LPLONG b)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__GetPalette(IDirectDrawSurfaceImpl *This, LPDIRECTDRAWPALETTE FAR *lplpDDPalette)
{
dprintf("-> %s(This=%p, lplpDDPalette=%p)\n", __FUNCTION__, This, lplpDDPalette);
HRESULT ret = dds_GetPalette(This, lplpDDPalette);
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__GetPixelFormat(IDirectDrawSurfaceImpl *This, LPDDPIXELFORMAT ddpfPixelFormat)
{
dprintf("-> %s(This=%p, ...)\n", __FUNCTION__, This);
HRESULT ret = dds_GetPixelFormat(This, ddpfPixelFormat);
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__Initialize(IDirectDrawSurfaceImpl *This, LPDIRECTDRAW a, LPDDSURFACEDESC b)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__IsLost(IDirectDrawSurfaceImpl *This)
{
dprintfex("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintfex("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__Lock(IDirectDrawSurfaceImpl *This, LPRECT lpDestRect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD dwFlags, HANDLE hEvent)
{
dprintfex("-> %s(This=%p, lpDestRect=%p, lpDDSurfaceDesc=%p, dwFlags=%08X, hEvent=%p)\n", __FUNCTION__, This, lpDestRect, lpDDSurfaceDesc, (int)dwFlags, hEvent);
HRESULT ret = dds_Lock(This, lpDestRect, lpDDSurfaceDesc, dwFlags, hEvent);
dprintfex("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__ReleaseDC(IDirectDrawSurfaceImpl *This, HDC a)
{
dprintfex("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintfex("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__Restore(IDirectDrawSurfaceImpl *This)
{
dprintfex("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintfex("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__SetClipper(IDirectDrawSurfaceImpl *This, LPDIRECTDRAWCLIPPER a)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__SetColorKey(IDirectDrawSurfaceImpl *This, DWORD flags, LPDDCOLORKEY colorKey)
{
dprintfex("-> %s(This=%p, flags=0x%08X, color_key=%p)\n", __FUNCTION__, This, flags, colorKey);
HRESULT ret = dds_SetColorKey(This, flags, colorKey);
dprintfex("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__SetOverlayPosition(IDirectDrawSurfaceImpl *This, LONG a, LONG b)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__SetPalette(IDirectDrawSurfaceImpl *This, LPDIRECTDRAWPALETTE lpDDPalette)
{
dprintf("-> %s(This=%p, lpDDPalette=%p)\n", __FUNCTION__, This, lpDDPalette);
HRESULT ret = dds_SetPalette(This, lpDDPalette);
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__Unlock(IDirectDrawSurfaceImpl *This, LPVOID lpRect)
{
dprintfex("-> %s(This=%p, lpRect=%p)\n", __FUNCTION__, This, lpRect);
HRESULT ret = dds_Unlock(This, lpRect);
dprintfex("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__UpdateOverlay(IDirectDrawSurfaceImpl *This, LPRECT a, LPDIRECTDRAWSURFACE b, LPRECT c, DWORD d, LPDDOVERLAYFX e)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__UpdateOverlayDisplay(IDirectDrawSurfaceImpl *This, DWORD a)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
HRESULT __stdcall IDirectDrawSurface__UpdateOverlayZOrder(IDirectDrawSurfaceImpl *This, DWORD a, LPDIRECTDRAWSURFACE b)
{
dprintf("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
HRESULT ret = DD_OK;
dprintf("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
return ret;
}
struct IDirectDrawSurfaceImplVtbl g_dds_vtbl =
{
/* IUnknown */
IDirectDrawSurface__QueryInterface,
IDirectDrawSurface__AddRef,
IDirectDrawSurface__Release,
/* IDirectDrawSurface */
IDirectDrawSurface__AddAttachedSurface,
IDirectDrawSurface__AddOverlayDirtyRect,
IDirectDrawSurface__Blt,
IDirectDrawSurface__BltBatch,
IDirectDrawSurface__BltFast,
IDirectDrawSurface__DeleteAttachedSurface,
IDirectDrawSurface__EnumAttachedSurfaces,
IDirectDrawSurface__EnumOverlayZOrders,
IDirectDrawSurface__Flip,
IDirectDrawSurface__GetAttachedSurface,
IDirectDrawSurface__GetBltStatus,
IDirectDrawSurface__GetCaps,
IDirectDrawSurface__GetClipper,
IDirectDrawSurface__GetColorKey,
IDirectDrawSurface__GetDC,
IDirectDrawSurface__GetFlipStatus,
IDirectDrawSurface__GetOverlayPosition,
IDirectDrawSurface__GetPalette,
IDirectDrawSurface__GetPixelFormat,
IDirectDrawSurface__GetSurfaceDesc,
IDirectDrawSurface__Initialize,
IDirectDrawSurface__IsLost,
IDirectDrawSurface__Lock,
IDirectDrawSurface__ReleaseDC,
IDirectDrawSurface__Restore,
IDirectDrawSurface__SetClipper,
IDirectDrawSurface__SetColorKey,
IDirectDrawSurface__SetOverlayPosition,
IDirectDrawSurface__SetPalette,
IDirectDrawSurface__Unlock,
IDirectDrawSurface__UpdateOverlay,
IDirectDrawSurface__UpdateOverlayDisplay,
IDirectDrawSurface__UpdateOverlayZOrder
};

View file

@ -1,119 +0,0 @@
/*
* Copyright (c) 2010 Toni Spets <toni.spets@iki.fi>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <windows.h>
#include <stdio.h>
#include "clipper.h"
HRESULT __stdcall ddraw_clipper_QueryInterface(IDirectDrawClipperImpl *This, REFIID riid, void **obj)
{
printf("??? DirectDrawClipper::QueryInterface(This=%p, riid=%08X, obj=%p)\n", This, (unsigned int)riid, obj);
return S_OK;
}
ULONG __stdcall ddraw_clipper_AddRef(IDirectDrawClipperImpl *This)
{
printf("DirectDrawClipper::AddRef(This=%p)\n", This);
This->Ref++;
return This->Ref;
}
ULONG __stdcall ddraw_clipper_Release(IDirectDrawClipperImpl *This)
{
printf("DirectDrawClipper::Release(This=%p)\n", This);
This->Ref--;
if(This->Ref == 0)
{
printf(" Released (%p)\n", This);
HeapFree(GetProcessHeap(), 0, This);
return 0;
}
return This->Ref;
}
HRESULT __stdcall ddraw_clipper_GetClipList(IDirectDrawClipperImpl *This, LPRECT a, LPRGNDATA b, LPDWORD c)
{
printf("??? IDirectDrawClipper::GetClipList(This=%p, ...)\n", This);
return DD_OK;
}
HRESULT __stdcall ddraw_clipper_GetHWnd(IDirectDrawClipperImpl *This, HWND FAR *a)
{
printf("??? IDirectDrawClipper::GetHWnd(This=%p, ...)\n", This);
return DD_OK;
}
HRESULT __stdcall ddraw_clipper_Initialize(IDirectDrawClipperImpl *This, LPDIRECTDRAW a, DWORD b)
{
printf("??? IDirectDrawClipper::Initialize(This=%p, ...)\n", This);
return DD_OK;
}
HRESULT __stdcall ddraw_clipper_IsClipListChanged(IDirectDrawClipperImpl *This, BOOL FAR *a)
{
printf("??? IDirectDrawClipper::IsClipListChanged(This=%p, ...)\n", This);
return DD_OK;
}
HRESULT __stdcall ddraw_clipper_SetClipList(IDirectDrawClipperImpl *This, LPRGNDATA a, DWORD b)
{
printf("??? IDirectDrawClipper::SetClipList(This=%p, ...)\n", This);
return DD_OK;
}
HRESULT __stdcall ddraw_clipper_SetHWnd(IDirectDrawClipperImpl *This, DWORD a, HWND b)
{
printf("??? IDirectDrawClipper::SetHWnd(This=%p, ...)\n", This);
return DD_OK;
}
struct IDirectDrawClipperImplVtbl ciface =
{
/* IUnknown */
ddraw_clipper_QueryInterface,
ddraw_clipper_AddRef,
ddraw_clipper_Release,
/* IDirectDrawClipper */
ddraw_clipper_GetClipList,
ddraw_clipper_GetHWnd,
ddraw_clipper_Initialize,
ddraw_clipper_IsClipListChanged,
ddraw_clipper_SetClipList,
ddraw_clipper_SetHWnd
};
HRESULT __stdcall ddraw_CreateClipper(IDirectDrawImpl *This, DWORD dwFlags, LPDIRECTDRAWCLIPPER FAR *lplpDDClipper, IUnknown FAR *pUnkOuter )
{
printf("DirectDraw::CreateClipper(This=%p, dwFlags=%08X, DDClipper=%p, unkOuter=%p)\n", This, (int)dwFlags, lplpDDClipper, pUnkOuter);
if (!lplpDDClipper)
return DDERR_INVALIDPARAMS;
IDirectDrawClipperImpl *Clipper = (IDirectDrawClipperImpl *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawClipperImpl));
Clipper->lpVtbl = &ciface;
printf(" Clipper = %p\n", Clipper);
*lplpDDClipper = (LPDIRECTDRAWCLIPPER)Clipper;
ddraw_clipper_AddRef(Clipper);
return DD_OK;
}

View file

@ -2,214 +2,205 @@
#include <windows.h>
#include <stdio.h>
#include <d3d9.h>
#include "main.h"
#include "opengl.h"
#include "config.h"
#include "dd.h"
#include "render_d3d9.h"
#include "render_gdi.h"
#include "render_ogl.h"
#include "hook.h"
#include "debug.h"
static char SettingsIniPath[MAX_PATH];
static char ProcessFileName[96];
static int SaveSettings;
static BOOL GetBool(LPCSTR key, BOOL defaultValue);
static int GetInt(LPCSTR key, int defaultValue);
static DWORD GetString(LPCSTR key, LPCSTR defaultValue, LPSTR outString, DWORD outSize);
static void CreateSettingsIni();
static BOOL cfg_get_bool(LPCSTR key, BOOL defaultValue);
static int cfg_get_int(LPCSTR key, int defaultValue);
static DWORD cfg_get_string(LPCSTR key, LPCSTR defaultValue, LPSTR outString, DWORD outSize);
static void cfg_create_ini();
void Settings_Load()
cnc_ddraw_config g_config =
{ .window_rect = { .left = -32000, .top = -32000, .right = 0, .bottom = 0 }, .window_state = -1 };
void cfg_load()
{
//set up settings ini
char cwd[MAX_PATH];
char tmp[256];
GetCurrentDirectoryA(sizeof(cwd), cwd);
_snprintf(SettingsIniPath, sizeof(SettingsIniPath), "%s\\ddraw.ini", cwd);
_snprintf(g_config.ini_path, sizeof(g_config.ini_path), "%s\\ddraw.ini", cwd);
if (GetFileAttributes(SettingsIniPath) == INVALID_FILE_ATTRIBUTES)
CreateSettingsIni();
if (GetFileAttributes(g_config.ini_path) == INVALID_FILE_ATTRIBUTES)
cfg_create_ini();
//get process filename
char ProcessFilePath[MAX_PATH] = { 0 };
GetModuleFileNameA(NULL, ProcessFilePath, MAX_PATH);
_splitpath(ProcessFilePath, NULL, NULL, ProcessFileName, NULL);
char process_file_path[MAX_PATH] = { 0 };
GetModuleFileNameA(NULL, process_file_path, MAX_PATH);
_splitpath(process_file_path, NULL, NULL, g_config.process_file_name, NULL);
//load settings from ini
ddraw->windowed = GetBool("windowed", FALSE);
ddraw->border = GetBool("border", TRUE);
ddraw->boxing = GetBool("boxing", FALSE);
ddraw->maintas = GetBool("maintas", FALSE);
ddraw->adjmouse = GetBool("adjmouse", FALSE);
ddraw->devmode = GetBool("devmode", FALSE);
ddraw->vsync = GetBool("vsync", FALSE);
ddraw->noactivateapp = GetBool("noactivateapp", FALSE);
ddraw->vhack = GetBool("vhack", FALSE);
ddraw->accurateTimers = GetBool("accuratetimers", FALSE);
ddraw->resizable = GetBool("resizable", TRUE);
ddraw->nonexclusive = GetBool("nonexclusive", FALSE);
ddraw->tm2hack = GetBool("tm2hack", FALSE); // Twisted Metal 2 hack
ddraw->sierrahack = GetBool("sierrahack", FALSE); // Sierra Caesar III, Pharaoh, and Zeus hack
g_ddraw->windowed = cfg_get_bool("windowed", FALSE);
g_ddraw->border = cfg_get_bool("border", TRUE);
g_ddraw->boxing = cfg_get_bool("boxing", FALSE);
g_ddraw->maintas = cfg_get_bool("maintas", FALSE);
g_ddraw->adjmouse = cfg_get_bool("adjmouse", FALSE);
g_ddraw->devmode = cfg_get_bool("devmode", FALSE);
g_ddraw->vsync = cfg_get_bool("vsync", FALSE);
g_ddraw->noactivateapp = cfg_get_bool("noactivateapp", FALSE);
g_ddraw->vhack = cfg_get_bool("vhack", FALSE);
g_ddraw->accurate_timers = cfg_get_bool("accuratetimers", FALSE);
g_ddraw->resizable = cfg_get_bool("resizable", TRUE);
g_ddraw->nonexclusive = cfg_get_bool("nonexclusive", FALSE);
g_ddraw->sierrahack = cfg_get_bool("sierrahack", FALSE); // Sierra Caesar III, Pharaoh, and Zeus hack
WindowRect.right = GetInt("width", 0);
WindowRect.bottom = GetInt("height", 0);
WindowRect.left = GetInt("posX", -32000);
WindowRect.top = GetInt("posY", -32000);
g_config.window_rect.right = cfg_get_int("width", 0);
g_config.window_rect.bottom = cfg_get_int("height", 0);
g_config.window_rect.left = cfg_get_int("posX", -32000);
g_config.window_rect.top = cfg_get_int("posY", -32000);
SaveSettings = GetInt("savesettings", 2);
g_config.save_settings = cfg_get_int("savesettings", 2);
#ifdef _MSC_VER
HookingMethod = GetInt("hook", 4);
g_hook_method = cfg_get_int("hook", 4);
#endif
ddraw->render.maxfps = GetInt("maxfps", 60);
g_ddraw->render.maxfps = cfg_get_int("maxfps", 60);
if (ddraw->render.maxfps)
ddraw->render.forcefps = GetBool("forcefps", FALSE);
if (g_ddraw->render.maxfps)
g_ddraw->render.forcefps = cfg_get_bool("forcefps", FALSE);
if (ddraw->accurateTimers || ddraw->vsync)
ddraw->fpsLimiter.hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
//can't fully set it up here due to missing ddraw->mode.dmDisplayFrequency
if (g_ddraw->accurate_timers || g_ddraw->vsync)
g_ddraw->fps_limiter.htimer = CreateWaitableTimer(NULL, TRUE, NULL);
//can't fully set it up here due to missing g_ddraw->mode.dmDisplayFrequency
int maxTicks = GetInt("maxgameticks", 0);
if (maxTicks > 0 && maxTicks <= 1000)
int max_ticks = cfg_get_int("maxgameticks", 0);
if (max_ticks > 0 && max_ticks <= 1000)
{
if (ddraw->accurateTimers)
ddraw->ticksLimiter.hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
if (g_ddraw->accurate_timers)
g_ddraw->ticks_limiter.htimer = CreateWaitableTimer(NULL, TRUE, NULL);
float len = 1000.0f / maxTicks;
ddraw->ticksLimiter.tickLengthNs = len * 10000;
ddraw->ticksLimiter.ticklength = len + 0.5f;
float len = 1000.0f / max_ticks;
g_ddraw->ticks_limiter.tick_length_ns = len * 10000;
g_ddraw->ticks_limiter.tick_length = len + 0.5f;
}
if (maxTicks >= 0)
if (max_ticks >= 0)
{
//always using 60 fps for flip...
if (ddraw->accurateTimers)
ddraw->flipLimiter.hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
if (g_ddraw->accurate_timers)
g_ddraw->flip_limiter.htimer = CreateWaitableTimer(NULL, TRUE, NULL);
float flipLen = 1000.0f / 60;
ddraw->flipLimiter.tickLengthNs = flipLen * 10000;
ddraw->flipLimiter.ticklength = flipLen + 0.5f;
float flip_len = 1000.0f / 60;
g_ddraw->flip_limiter.tick_length_ns = flip_len * 10000;
g_ddraw->flip_limiter.tick_length = flip_len + 0.5f;
}
if ((ddraw->fullscreen = GetBool("fullscreen", FALSE)))
WindowRect.left = WindowRect.top = -32000;
if ((g_ddraw->fullscreen = cfg_get_bool("fullscreen", FALSE)))
g_config.window_rect.left = g_config.window_rect.top = -32000;
if (!(ddraw->handlemouse = GetBool("handlemouse", TRUE)))
ddraw->adjmouse = TRUE;
if (!(g_ddraw->handlemouse = cfg_get_bool("handlemouse", TRUE)))
g_ddraw->adjmouse = TRUE;
if (GetBool("singlecpu", TRUE))
if (cfg_get_bool("singlecpu", TRUE))
{
SetProcessAffinityMask(GetCurrentProcess(), 1);
}
else
{
DWORD systemAffinity;
DWORD procAffinity;
DWORD system_affinity;
DWORD proc_affinity;
HANDLE proc = GetCurrentProcess();
if (GetProcessAffinityMask(proc, &procAffinity, &systemAffinity))
SetProcessAffinityMask(proc, systemAffinity);
if (GetProcessAffinityMask(proc, &proc_affinity, &system_affinity))
SetProcessAffinityMask(proc, system_affinity);
}
ddraw->render.bpp = GetInt("bpp", 0);
if (ddraw->render.bpp != 16 && ddraw->render.bpp != 24 && ddraw->render.bpp != 32)
ddraw->render.bpp = 0;
g_ddraw->render.bpp = cfg_get_int("bpp", 0);
if (g_ddraw->render.bpp != 16 && g_ddraw->render.bpp != 24 && g_ddraw->render.bpp != 32)
g_ddraw->render.bpp = 0;
// to do: read .glslp config file instead of the shader and apply the correct settings
GetString("shader", "", ddraw->shader, sizeof(ddraw->shader));
cfg_get_string("shader", "", g_ddraw->shader, sizeof(g_ddraw->shader));
GetString("renderer", "auto", tmp, sizeof(tmp));
printf("Using %s renderer\n", tmp);
cfg_get_string("renderer", "auto", tmp, sizeof(tmp));
dprintf(" Using %s renderer\n", tmp);
if (tolower(tmp[0]) == 's' || tolower(tmp[0]) == 'g') //gdi
{
ddraw->renderer = render_soft_main;
g_ddraw->renderer = gdi_render_main;
}
else if (tolower(tmp[0]) == 'd') //direct3d9
{
ddraw->renderer = render_d3d9_main;
g_ddraw->renderer = d3d9_render_main;
}
else if (tolower(tmp[0]) == 'o') //opengl
{
if (OpenGL_LoadDll())
if (oglu_load_dll())
{
ddraw->renderer = render_main;
g_ddraw->renderer = ogl_render_main;
}
else
{
ShowDriverWarning = TRUE;
ddraw->renderer = render_soft_main;
g_ddraw->show_driver_warning = TRUE;
g_ddraw->renderer = gdi_render_main;
}
}
else //auto
{
LPDIRECT3D9 d3d = NULL;
// Windows = Direct3D 9, Wine = OpenGL
if (!ddraw->wine && (Direct3D9_hModule = LoadLibrary("d3d9.dll")))
if (!g_ddraw->wine && d3d9_is_available())
{
IDirect3D9 *(WINAPI *D3DCreate9)(UINT) =
(IDirect3D9 *(WINAPI *)(UINT))GetProcAddress(Direct3D9_hModule, "Direct3DCreate9");
if (D3DCreate9 && (d3d = D3DCreate9(D3D_SDK_VERSION)))
IDirect3D9_Release(d3d);
g_ddraw->renderer = d3d9_render_main;
}
if (d3d)
else if (oglu_load_dll())
{
ddraw->renderer = render_d3d9_main;
}
else if (OpenGL_LoadDll())
{
ddraw->renderer = render_main;
g_ddraw->renderer = ogl_render_main;
}
else
{
ShowDriverWarning = TRUE;
ddraw->renderer = render_soft_main;
g_ddraw->show_driver_warning = TRUE;
g_ddraw->renderer = gdi_render_main;
}
}
}
void Settings_Save(RECT *lpRect, int windowState)
void cfg_save()
{
if (!SaveSettings)
if (!g_config.save_settings)
return;
char buf[16];
char *section = SaveSettings == 1 ? "ddraw" : ProcessFileName;
char *section = g_config.save_settings == 1 ? "ddraw" : g_config.process_file_name;
if (lpRect->right)
if (g_config.window_rect.right)
{
sprintf(buf, "%ld", lpRect->right);
WritePrivateProfileString(section, "width", buf, SettingsIniPath);
sprintf(buf, "%ld", g_config.window_rect.right);
WritePrivateProfileString(section, "width", buf, g_config.ini_path);
}
if (lpRect->bottom)
if (g_config.window_rect.bottom)
{
sprintf(buf, "%ld", lpRect->bottom);
WritePrivateProfileString(section, "height", buf, SettingsIniPath);
sprintf(buf, "%ld", g_config.window_rect.bottom);
WritePrivateProfileString(section, "height", buf, g_config.ini_path);
}
if (lpRect->left != -32000)
if (g_config.window_rect.left != -32000)
{
sprintf(buf, "%ld", lpRect->left);
WritePrivateProfileString(section, "posX", buf, SettingsIniPath);
sprintf(buf, "%ld", g_config.window_rect.left);
WritePrivateProfileString(section, "posX", buf, g_config.ini_path);
}
if (lpRect->top != -32000)
if (g_config.window_rect.top != -32000)
{
sprintf(buf, "%ld", lpRect->top);
WritePrivateProfileString(section, "posY", buf, SettingsIniPath);
sprintf(buf, "%ld", g_config.window_rect.top);
WritePrivateProfileString(section, "posY", buf, g_config.ini_path);
}
if (windowState != -1)
if (g_config.window_state != -1)
{
WritePrivateProfileString(section, "windowed", windowState ? "true" : "false", SettingsIniPath);
WritePrivateProfileString(section, "windowed", g_config.window_state ? "true" : "false", g_config.ini_path);
}
}
static void CreateSettingsIni()
static void cfg_create_ini()
{
FILE *fh = fopen(SettingsIniPath, "w");
FILE *fh = fopen(g_config.ini_path, "w");
if (fh)
{
fputs(
@ -483,7 +474,6 @@ static void CreateSettingsIni()
"nonexclusive=true\n"
"maxgameticks=60\n"
"handlemouse=false\n"
"tm2hack=true\n"
"\n"
"; Caesar III\n"
"[c3]\n"
@ -508,14 +498,17 @@ static void CreateSettingsIni()
}
}
static DWORD GetString(LPCSTR key, LPCSTR defaultValue, LPSTR outString, DWORD outSize)
static DWORD cfg_get_string(LPCSTR key, LPCSTR defaultValue, LPSTR outString, DWORD outSize)
{
DWORD s = GetPrivateProfileStringA(ProcessFileName, key, "", outString, outSize, SettingsIniPath);
DWORD s = GetPrivateProfileStringA(
g_config.process_file_name, key, "", outString, outSize, g_config.ini_path);
if (s > 0)
{
char buf[MAX_PATH] = { 0 };
if (GetPrivateProfileStringA(ProcessFileName, "checkfile", "", buf, sizeof(buf), SettingsIniPath) > 0)
if (GetPrivateProfileStringA(
g_config.process_file_name, "checkfile", "", buf, sizeof(buf), g_config.ini_path) > 0)
{
if (GetFileAttributes(buf) != INVALID_FILE_ATTRIBUTES)
return s;
@ -524,24 +517,24 @@ static DWORD GetString(LPCSTR key, LPCSTR defaultValue, LPSTR outString, DWORD o
return s;
}
return GetPrivateProfileStringA("ddraw", key, defaultValue, outString, outSize, SettingsIniPath);
return GetPrivateProfileStringA("ddraw", key, defaultValue, outString, outSize, g_config.ini_path);
}
static BOOL GetBool(LPCSTR key, BOOL defaultValue)
static BOOL cfg_get_bool(LPCSTR key, BOOL defaultValue)
{
char value[8];
GetString(key, defaultValue ? "Yes" : "No", value, sizeof(value));
cfg_get_string(key, defaultValue ? "Yes" : "No", value, sizeof(value));
return (_stricmp(value, "yes") == 0 || _stricmp(value, "true") == 0 || _stricmp(value, "1") == 0);
}
static int GetInt(LPCSTR key, int defaultValue)
static int cfg_get_int(LPCSTR key, int defaultValue)
{
char defvalue[16];
_snprintf(defvalue, sizeof(defvalue), "%d", defaultValue);
char def_value[16];
_snprintf(def_value, sizeof(def_value), "%d", defaultValue);
char value[16];
GetString(key, defvalue, value, sizeof(value));
cfg_get_string(key, def_value, value, sizeof(value));
return atoi(value);
}

776
src/dd.c Normal file
View file

@ -0,0 +1,776 @@
#include <windows.h>
#include "ddraw.h"
#include "dd.h"
#include "hook.h"
#include "config.h"
#include "mouse.h"
#include "wndproc.h"
#include "render_d3d9.h"
#include "render_gdi.h"
#include "render_ogl.h"
#include "debug.h"
#include "utils.h"
cnc_ddraw *g_ddraw = NULL;
HRESULT dd_EnumDisplayModes(DWORD dwFlags, LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext, LPDDENUMMODESCALLBACK lpEnumModesCallback)
{
DWORD i = 0;
DDSURFACEDESC s;
// Some games crash when you feed them with too many resolutions...
if (g_ddraw->bpp)
{
dprintf(" g_ddraw->bpp=%u\n", g_ddraw->bpp);
//set up some filters to keep the list short
DWORD refresh_rate = 0;
DWORD bpp = 0;
DWORD flags = 99998;
DWORD fixed_output = 99998;
DEVMODE m;
memset(&m, 0, sizeof(DEVMODE));
m.dmSize = sizeof(DEVMODE);
while (EnumDisplaySettings(NULL, i, &m))
{
if (refresh_rate != 60 && m.dmDisplayFrequency >= 50)
refresh_rate = m.dmDisplayFrequency;
if (bpp != 32 && m.dmBitsPerPel >= 16)
bpp = m.dmBitsPerPel;
if (flags != 0)
flags = m.dmDisplayFlags;
if (fixed_output != DMDFO_DEFAULT)
fixed_output = m.dmDisplayFixedOutput;
memset(&m, 0, sizeof(DEVMODE));
m.dmSize = sizeof(DEVMODE);
i++;
}
memset(&m, 0, sizeof(DEVMODE));
m.dmSize = sizeof(DEVMODE);
i = 0;
while (EnumDisplaySettings(NULL, i, &m))
{
if (refresh_rate == m.dmDisplayFrequency &&
bpp == m.dmBitsPerPel &&
flags == m.dmDisplayFlags &&
fixed_output == m.dmDisplayFixedOutput)
{
dprintfex(" %d: %dx%d@%d %d bpp\n", (int)i, (int)m.dmPelsWidth, (int)m.dmPelsHeight, (int)m.dmDisplayFrequency, (int)m.dmBitsPerPel);
memset(&s, 0, sizeof(DDSURFACEDESC));
s.dwSize = sizeof(DDSURFACEDESC);
s.dwFlags = DDSD_HEIGHT | DDSD_REFRESHRATE | DDSD_WIDTH | DDSD_PIXELFORMAT;
s.dwHeight = m.dmPelsHeight;
s.dwWidth = m.dmPelsWidth;
s.dwRefreshRate = 60;
s.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
s.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
s.ddpfPixelFormat.dwRGBBitCount = 8;
if (g_ddraw->bpp == 16)
{
s.ddpfPixelFormat.dwFlags = DDPF_RGB;
s.ddpfPixelFormat.dwRGBBitCount = 16;
s.ddpfPixelFormat.dwRBitMask = 0xF800;
s.ddpfPixelFormat.dwGBitMask = 0x07E0;
s.ddpfPixelFormat.dwBBitMask = 0x001F;
}
if (lpEnumModesCallback(&s, lpContext) == DDENUMRET_CANCEL)
{
dprintf(" DDENUMRET_CANCEL returned, stopping\n");
break;
}
}
memset(&m, 0, sizeof(DEVMODE));
m.dmSize = sizeof(DEVMODE);
i++;
}
}
else
{
SIZE resolutions[] =
{
{ 320, 200 },
{ 320, 240 },
{ 640, 400 },
{ 640, 480 },
{ 800, 600 },
{ 1024, 768 },
{ 1280, 1024 },
{ 1280, 720 },
{ 1920, 1080 },
};
for (i = 0; i < sizeof(resolutions) / sizeof(resolutions[0]); i++)
{
memset(&s, 0, sizeof(DDSURFACEDESC));
s.dwSize = sizeof(DDSURFACEDESC);
s.dwFlags = DDSD_HEIGHT | DDSD_REFRESHRATE | DDSD_WIDTH | DDSD_PIXELFORMAT;
s.dwHeight = resolutions[i].cy;
s.dwWidth = resolutions[i].cx;
s.dwRefreshRate = 60;
s.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
s.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
s.ddpfPixelFormat.dwRGBBitCount = 8;
if (lpEnumModesCallback(&s, lpContext) == DDENUMRET_CANCEL)
{
dprintf(" DDENUMRET_CANCEL returned, stopping\n");
break;
}
s.ddpfPixelFormat.dwFlags = DDPF_RGB;
s.ddpfPixelFormat.dwRGBBitCount = 16;
s.ddpfPixelFormat.dwRBitMask = 0xF800;
s.ddpfPixelFormat.dwGBitMask = 0x07E0;
s.ddpfPixelFormat.dwBBitMask = 0x001F;
if (lpEnumModesCallback(&s, lpContext) == DDENUMRET_CANCEL)
{
dprintf(" DDENUMRET_CANCEL returned, stopping\n");
break;
}
}
}
return DD_OK;
}
HRESULT dd_GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDEmulCaps)
{
if(lpDDDriverCaps)
{
lpDDDriverCaps->dwSize = sizeof(DDCAPS);
lpDDDriverCaps->dwCaps = DDCAPS_BLT | DDCAPS_PALETTE | DDCAPS_BLTCOLORFILL | DDCAPS_BLTSTRETCH | DDCAPS_CANCLIP;
lpDDDriverCaps->dwCKeyCaps = 0;
lpDDDriverCaps->dwPalCaps = DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE;
lpDDDriverCaps->dwVidMemTotal = 16777216;
lpDDDriverCaps->dwVidMemFree = 16777216;
lpDDDriverCaps->dwMaxVisibleOverlays = 0;
lpDDDriverCaps->dwCurrVisibleOverlays = 0;
lpDDDriverCaps->dwNumFourCCCodes = 0;
lpDDDriverCaps->dwAlignBoundarySrc = 0;
lpDDDriverCaps->dwAlignSizeSrc = 0;
lpDDDriverCaps->dwAlignBoundaryDest = 0;
lpDDDriverCaps->dwAlignSizeDest = 0;
lpDDDriverCaps->ddsCaps.dwCaps = DDSCAPS_FLIP;
}
if(lpDDEmulCaps)
{
lpDDEmulCaps->dwSize = 0;
}
return DD_OK;
}
HRESULT dd_RestoreDisplayMode()
{
if(!g_ddraw->render.run)
{
return DD_OK;
}
/* only stop drawing in GL mode when minimized */
if (g_ddraw->renderer != gdi_render_main)
{
EnterCriticalSection(&g_ddraw->cs);
g_ddraw->render.run = FALSE;
ReleaseSemaphore(g_ddraw->render.sem, 1, NULL);
LeaveCriticalSection(&g_ddraw->cs);
if (g_ddraw->render.thread)
{
WaitForSingleObject(g_ddraw->render.thread, INFINITE);
g_ddraw->render.thread = NULL;
}
if (g_ddraw->renderer == d3d9_render_main)
d3d9_release();
}
if(!g_ddraw->windowed)
{
if (g_ddraw->renderer != d3d9_render_main)
ChangeDisplaySettings(NULL, 0);
}
return DD_OK;
}
HRESULT dd_SetDisplayMode(DWORD width, DWORD height, DWORD bpp)
{
if (bpp != 8 && bpp != 16)
return DDERR_INVALIDMODE;
if (g_ddraw->render.thread)
{
EnterCriticalSection(&g_ddraw->cs);
g_ddraw->render.run = FALSE;
ReleaseSemaphore(g_ddraw->render.sem, 1, NULL);
LeaveCriticalSection(&g_ddraw->cs);
WaitForSingleObject(g_ddraw->render.thread, INFINITE);
g_ddraw->render.thread = NULL;
}
if (!g_ddraw->mode.dmPelsWidth)
{
g_ddraw->mode.dmSize = sizeof(DEVMODE);
g_ddraw->mode.dmDriverExtra = 0;
if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &g_ddraw->mode) == FALSE)
{
g_ddraw->mode.dmSize = sizeof(DEVMODE);
g_ddraw->mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
g_ddraw->mode.dmPelsWidth = real_GetSystemMetrics(SM_CXSCREEN);
g_ddraw->mode.dmPelsHeight = real_GetSystemMetrics(SM_CYSCREEN);
g_ddraw->mode.dmDisplayFrequency = 60;
g_ddraw->mode.dmBitsPerPel = 32;
if (!g_ddraw->mode.dmPelsWidth || !g_ddraw->mode.dmPelsHeight)
{
g_ddraw->fullscreen = FALSE;
}
}
const int IDR_MYMENU = 93;
const HANDLE hbicon = LoadImage(GetModuleHandle(0), MAKEINTRESOURCE(IDR_MYMENU), IMAGE_ICON, real_GetSystemMetrics(SM_CXICON), real_GetSystemMetrics(SM_CYICON), 0);
if (hbicon)
real_SendMessageA(g_ddraw->hwnd, WM_SETICON, ICON_BIG, (LPARAM)hbicon);
const HANDLE hsicon = LoadImage(GetModuleHandle(0), MAKEINTRESOURCE(IDR_MYMENU), IMAGE_ICON, real_GetSystemMetrics(SM_CXSMICON), real_GetSystemMetrics(SM_CYSMICON), 0);
if (hsicon)
real_SendMessageA(g_ddraw->hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hsicon);
}
if (g_ddraw->altenter)
{
g_ddraw->altenter = FALSE;
memset(&g_ddraw->render.mode, 0, sizeof(DEVMODE));
g_ddraw->render.mode.dmSize = sizeof(DEVMODE);
g_ddraw->render.mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
g_ddraw->render.mode.dmPelsWidth = g_ddraw->render.width;
g_ddraw->render.mode.dmPelsHeight = g_ddraw->render.height;
if (g_ddraw->render.bpp)
{
g_ddraw->render.mode.dmFields |= DM_BITSPERPEL;
g_ddraw->render.mode.dmBitsPerPel = g_ddraw->render.bpp;
}
if (ChangeDisplaySettings(&g_ddraw->render.mode, CDS_TEST) != DISP_CHANGE_SUCCESSFUL)
{
g_ddraw->render.width = g_ddraw->width;
g_ddraw->render.height = g_ddraw->height;
}
}
else
{
g_ddraw->render.width = g_config.window_rect.right;
g_ddraw->render.height = g_config.window_rect.bottom;
}
//temporary fix: center window for games that keep changing their resolution
if (g_ddraw->width &&
(g_ddraw->width != width || g_ddraw->height != height) &&
(width > g_config.window_rect.right || height > g_config.window_rect.bottom))
{
g_config.window_rect.left = -32000;
g_config.window_rect.top = -32000;
}
g_ddraw->width = width;
g_ddraw->height = height;
g_ddraw->bpp = bpp;
g_ddraw->cursor.x = width / 2;
g_ddraw->cursor.y = height / 2;
BOOL border = g_ddraw->border;
if(g_ddraw->fullscreen)
{
g_ddraw->render.width = g_ddraw->mode.dmPelsWidth;
g_ddraw->render.height = g_ddraw->mode.dmPelsHeight;
if (g_ddraw->windowed) //windowed-fullscreen aka borderless
{
border = FALSE;
g_config.window_rect.left = -32000;
g_config.window_rect.top = -32000;
// prevent OpenGL from going automatically into fullscreen exclusive mode
if (g_ddraw->renderer == ogl_render_main)
g_ddraw->render.height++;
}
}
if(g_ddraw->render.width < g_ddraw->width)
{
g_ddraw->render.width = g_ddraw->width;
}
if(g_ddraw->render.height < g_ddraw->height)
{
g_ddraw->render.height = g_ddraw->height;
}
g_ddraw->render.run = TRUE;
BOOL lock_mouse = g_ddraw->locked || g_ddraw->fullscreen;
mouse_unlock();
memset(&g_ddraw->render.mode, 0, sizeof(DEVMODE));
g_ddraw->render.mode.dmSize = sizeof(DEVMODE);
g_ddraw->render.mode.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT;
g_ddraw->render.mode.dmPelsWidth = g_ddraw->render.width;
g_ddraw->render.mode.dmPelsHeight = g_ddraw->render.height;
if(g_ddraw->render.bpp)
{
g_ddraw->render.mode.dmFields |= DM_BITSPERPEL;
g_ddraw->render.mode.dmBitsPerPel = g_ddraw->render.bpp;
}
BOOL maintas = g_ddraw->maintas;
if (!g_ddraw->windowed)
{
// Making sure the chosen resolution is valid
int old_width = g_ddraw->render.width;
int old_height = g_ddraw->render.height;
if (ChangeDisplaySettings(&g_ddraw->render.mode, CDS_TEST) != DISP_CHANGE_SUCCESSFUL)
{
// fail... compare resolutions
if (g_ddraw->render.width > g_ddraw->mode.dmPelsWidth || g_ddraw->render.height > g_ddraw->mode.dmPelsHeight)
{
// chosen game resolution higher than current resolution, use windowed mode for this case
g_ddraw->windowed = TRUE;
}
else
{
// Try 2x scaling
g_ddraw->render.width *= 2;
g_ddraw->render.height *= 2;
g_ddraw->render.mode.dmPelsWidth = g_ddraw->render.width;
g_ddraw->render.mode.dmPelsHeight = g_ddraw->render.height;
if ((g_ddraw->render.width > g_ddraw->mode.dmPelsWidth || g_ddraw->render.height > g_ddraw->mode.dmPelsHeight) ||
ChangeDisplaySettings(&g_ddraw->render.mode, CDS_TEST) != DISP_CHANGE_SUCCESSFUL)
{
SIZE res = {0};
//try to get a resolution with the same aspect ratio as the requested resolution
BOOL found_res = util_get_lowest_resolution(
(float)old_width / old_height,
&res,
old_width + 1, //don't return the original resolution since we tested that one already
old_height + 1,
g_ddraw->mode.dmPelsWidth,
g_ddraw->mode.dmPelsHeight);
if (!found_res)
{
//try to get a resolution with the same aspect ratio as the current display mode
found_res = util_get_lowest_resolution(
(float)g_ddraw->mode.dmPelsWidth / g_ddraw->mode.dmPelsHeight,
&res,
old_width,
old_height,
g_ddraw->mode.dmPelsWidth,
g_ddraw->mode.dmPelsHeight);
if (found_res)
maintas = TRUE;
}
g_ddraw->render.width = res.cx;
g_ddraw->render.height = res.cy;
g_ddraw->render.mode.dmPelsWidth = g_ddraw->render.width;
g_ddraw->render.mode.dmPelsHeight = g_ddraw->render.height;
if (!found_res || ChangeDisplaySettings(&g_ddraw->render.mode, CDS_TEST) != DISP_CHANGE_SUCCESSFUL)
{
// try current display settings
g_ddraw->render.width = g_ddraw->mode.dmPelsWidth;
g_ddraw->render.height = g_ddraw->mode.dmPelsHeight;
g_ddraw->render.mode.dmPelsWidth = g_ddraw->render.width;
g_ddraw->render.mode.dmPelsHeight = g_ddraw->render.height;
if (ChangeDisplaySettings(&g_ddraw->render.mode, CDS_TEST) != DISP_CHANGE_SUCCESSFUL)
{
// everything failed, use windowed mode instead
g_ddraw->render.width = old_width;
g_ddraw->render.height = old_height;
g_ddraw->render.mode.dmPelsWidth = g_ddraw->render.width;
g_ddraw->render.mode.dmPelsHeight = g_ddraw->render.height;
g_ddraw->windowed = TRUE;
}
else
maintas = TRUE;
}
}
}
}
}
if (g_ddraw->nonexclusive && !g_ddraw->windowed && g_ddraw->renderer == ogl_render_main)
g_ddraw->render.height++;
if (!g_ddraw->handlemouse)
g_ddraw->boxing = maintas = FALSE;
g_ddraw->render.viewport.width = g_ddraw->render.width;
g_ddraw->render.viewport.height = g_ddraw->render.height;
g_ddraw->render.viewport.x = 0;
g_ddraw->render.viewport.y = 0;
if (g_ddraw->boxing)
{
g_ddraw->render.viewport.width = g_ddraw->width;
g_ddraw->render.viewport.height = g_ddraw->height;
int i;
for (i = 20; i-- > 1;)
{
if (g_ddraw->width * i <= g_ddraw->render.width && g_ddraw->height * i <= g_ddraw->render.height)
{
g_ddraw->render.viewport.width *= i;
g_ddraw->render.viewport.height *= i;
break;
}
}
g_ddraw->render.viewport.y = g_ddraw->render.height / 2 - g_ddraw->render.viewport.height / 2;
g_ddraw->render.viewport.x = g_ddraw->render.width / 2 - g_ddraw->render.viewport.width / 2;
}
else if (maintas)
{
g_ddraw->render.viewport.width = g_ddraw->render.width;
g_ddraw->render.viewport.height = ((float)g_ddraw->height / g_ddraw->width) * g_ddraw->render.viewport.width;
if (g_ddraw->render.viewport.height > g_ddraw->render.height)
{
g_ddraw->render.viewport.width =
((float)g_ddraw->render.viewport.width / g_ddraw->render.viewport.height) * g_ddraw->render.height;
g_ddraw->render.viewport.height = g_ddraw->render.height;
}
g_ddraw->render.viewport.y = g_ddraw->render.height / 2 - g_ddraw->render.viewport.height / 2;
g_ddraw->render.viewport.x = g_ddraw->render.width / 2 - g_ddraw->render.viewport.width / 2;
}
g_ddraw->render.scale_w = ((float)g_ddraw->render.viewport.width / g_ddraw->width);
g_ddraw->render.scale_h = ((float)g_ddraw->render.viewport.height / g_ddraw->height);
g_ddraw->render.unscale_w = ((float)g_ddraw->width / g_ddraw->render.viewport.width);
g_ddraw->render.unscale_h = ((float)g_ddraw->height / g_ddraw->render.viewport.height);
if (g_ddraw->windowed)
{
MSG msg; // workaround for "Not Responding" window problem in cnc games
PeekMessage(&msg, g_ddraw->hwnd, 0, 0, PM_NOREMOVE);
if (!border)
{
real_SetWindowLongA(g_ddraw->hwnd, GWL_STYLE, GetWindowLong(g_ddraw->hwnd, GWL_STYLE) & ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU));
}
else
{
real_SetWindowLongA(g_ddraw->hwnd, GWL_STYLE, (GetWindowLong(g_ddraw->hwnd, GWL_STYLE) | WS_OVERLAPPEDWINDOW) & ~WS_MAXIMIZEBOX);
}
if (g_ddraw->wine)
real_SetWindowLongA(g_ddraw->hwnd, GWL_STYLE, (GetWindowLong(g_ddraw->hwnd, GWL_STYLE) | WS_MINIMIZEBOX) & ~(WS_MAXIMIZEBOX | WS_THICKFRAME));
/* center the window with correct dimensions */
int cy = g_ddraw->mode.dmPelsWidth ? g_ddraw->mode.dmPelsWidth : g_ddraw->render.width;
int cx = g_ddraw->mode.dmPelsHeight ? g_ddraw->mode.dmPelsHeight : g_ddraw->render.height;
int x = (g_config.window_rect.left != -32000) ? g_config.window_rect.left : (cy / 2) - (g_ddraw->render.width / 2);
int y = (g_config.window_rect.top != -32000) ? g_config.window_rect.top : (cx / 2) - (g_ddraw->render.height / 2);
RECT dst = { x, y, g_ddraw->render.width + x, g_ddraw->render.height + y };
AdjustWindowRect(&dst, GetWindowLong(g_ddraw->hwnd, GWL_STYLE), FALSE);
real_SetWindowPos(g_ddraw->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
real_MoveWindow(g_ddraw->hwnd, dst.left, dst.top, (dst.right - dst.left), (dst.bottom - dst.top), TRUE);
BOOL d3d9_active = FALSE;
if (g_ddraw->renderer == d3d9_render_main)
{
d3d9_active = d3d9_create();
if (!d3d9_active)
{
d3d9_release();
g_ddraw->show_driver_warning = TRUE;
g_ddraw->renderer = gdi_render_main;
}
}
if (lock_mouse)
mouse_lock();
}
else
{
LONG style = GetWindowLong(g_ddraw->hwnd, GWL_STYLE);
if ((style & WS_CAPTION))
{
real_SetWindowLongA(g_ddraw->hwnd, GWL_STYLE, style & ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU));
}
BOOL d3d9_active = FALSE;
if (g_ddraw->renderer == d3d9_render_main)
{
d3d9_active = d3d9_create();
if (!d3d9_active)
{
d3d9_release();
g_ddraw->show_driver_warning = TRUE;
g_ddraw->renderer = gdi_render_main;
}
}
if (!d3d9_active && ChangeDisplaySettings(&g_ddraw->render.mode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
g_ddraw->render.run = FALSE;
g_ddraw->windowed = TRUE;
return dd_SetDisplayMode(width, height, bpp);
}
if (g_ddraw->wine)
real_SetWindowLongA(g_ddraw->hwnd, GWL_STYLE, GetWindowLong(g_ddraw->hwnd, GWL_STYLE) | WS_MINIMIZEBOX);
real_SetWindowPos(g_ddraw->hwnd, HWND_TOPMOST, 0, 0, g_ddraw->render.width, g_ddraw->render.height, SWP_SHOWWINDOW);
g_ddraw->last_set_window_pos_tick = timeGetTime();
mouse_lock();
}
if(g_ddraw->render.viewport.x != 0 || g_ddraw->render.viewport.y != 0)
{
RedrawWindow(g_ddraw->hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE);
}
if(g_ddraw->render.thread == NULL)
{
InterlockedExchange(&g_ddraw->render.palette_updated, TRUE);
InterlockedExchange(&g_ddraw->render.surface_updated, TRUE);
ReleaseSemaphore(g_ddraw->render.sem, 1, NULL);
g_ddraw->render.thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)g_ddraw->renderer, NULL, 0, NULL);
}
if (g_ddraw->sierrahack)
{
PostMessageA(g_ddraw->hwnd, WM_MOVE, 0, MAKELPARAM(-32000, -32000));
PostMessageA(g_ddraw->hwnd, WM_DISPLAYCHANGE, g_ddraw->bpp, MAKELPARAM(g_ddraw->width, g_ddraw->height));
}
return DD_OK;
}
HRESULT dd_SetCooperativeLevel(HWND hwnd, DWORD dwFlags)
{
PIXELFORMATDESCRIPTOR pfd;
/* Red Alert for some weird reason does this on Windows XP */
if(hwnd == NULL)
{
return DD_OK;
}
if (g_ddraw->hwnd == NULL)
{
g_ddraw->hwnd = hwnd;
}
if (!g_ddraw->wndproc)
{
hook_init();
g_ddraw->wndproc = (LRESULT(CALLBACK *)(HWND, UINT, WPARAM, LPARAM))GetWindowLong(hwnd, GWL_WNDPROC);
real_SetWindowLongA(g_ddraw->hwnd, GWL_WNDPROC, (LONG)fake_WndProc);
if (!g_ddraw->render.hdc)
{
g_ddraw->render.hdc = GetDC(g_ddraw->hwnd);
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER | (g_ddraw->renderer == ogl_render_main ? PFD_SUPPORT_OPENGL : 0);
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = g_ddraw->render.bpp ? g_ddraw->render.bpp : g_ddraw->mode.dmBitsPerPel;
pfd.iLayerType = PFD_MAIN_PLANE;
SetPixelFormat(g_ddraw->render.hdc, ChoosePixelFormat(g_ddraw->render.hdc, &pfd), &pfd);
}
if (g_ddraw->handlemouse && g_ddraw->windowed)
{
while (real_ShowCursor(FALSE) > 0); //workaround for direct input games
while (real_ShowCursor(TRUE) < 0);
}
real_SetCursor(LoadCursor(NULL, IDC_ARROW));
GetWindowText(g_ddraw->hwnd, (LPTSTR)&g_ddraw->title, sizeof(g_ddraw->title));
g_ddraw->isredalert = strcmp(g_ddraw->title, "Red Alert") == 0;
g_ddraw->iscnc1 = strcmp(g_ddraw->title, "Command & Conquer") == 0;
if (g_ddraw->vhack && !g_ddraw->isredalert && !g_ddraw->iscnc1)
g_ddraw->vhack = 0;
}
return DD_OK;
}
HRESULT dd_WaitForVerticalBlank(DWORD dwFlags, HANDLE h)
{
if (!g_ddraw->flip_limiter.tick_length)
return DD_OK;
if (g_ddraw->flip_limiter.htimer)
{
FILETIME last_flip_ft = { 0 };
GetSystemTimeAsFileTime(&last_flip_ft);
if (!g_ddraw->flip_limiter.due_time.QuadPart)
{
memcpy(&g_ddraw->flip_limiter.due_time, &last_flip_ft, sizeof(LARGE_INTEGER));
}
else
{
while (CompareFileTime((FILETIME*)&g_ddraw->flip_limiter.due_time, &last_flip_ft) == -1)
g_ddraw->flip_limiter.due_time.QuadPart += g_ddraw->flip_limiter.tick_length_ns;
SetWaitableTimer(g_ddraw->flip_limiter.htimer, &g_ddraw->flip_limiter.due_time, 0, NULL, NULL, FALSE);
WaitForSingleObject(g_ddraw->flip_limiter.htimer, g_ddraw->flip_limiter.tick_length * 2);
}
}
else
{
static DWORD next_game_tick;
if (!next_game_tick)
{
next_game_tick = timeGetTime();
return DD_OK;
}
next_game_tick += g_ddraw->flip_limiter.tick_length;
DWORD tick_count = timeGetTime();
int sleep_time = next_game_tick - tick_count;
if (sleep_time <= 0 || sleep_time > g_ddraw->flip_limiter.tick_length)
next_game_tick = tick_count;
else
Sleep(sleep_time);
}
return DD_OK;
}
ULONG dd_AddRef()
{
return ++g_ddraw->ref;
}
ULONG dd_Release()
{
g_ddraw->ref--;
if (g_ddraw->ref == 0)
{
if (g_ddraw->bpp)
cfg_save();
if(g_ddraw->render.run)
{
EnterCriticalSection(&g_ddraw->cs);
g_ddraw->render.run = FALSE;
ReleaseSemaphore(g_ddraw->render.sem, 1, NULL);
LeaveCriticalSection(&g_ddraw->cs);
if (g_ddraw->render.thread)
{
WaitForSingleObject(g_ddraw->render.thread, INFINITE);
g_ddraw->render.thread = NULL;
}
if (g_ddraw->renderer == d3d9_render_main)
{
d3d9_release();
}
else if (!g_ddraw->windowed)
{
ChangeDisplaySettings(NULL, 0);
}
}
if(g_ddraw->render.hdc)
{
ReleaseDC(g_ddraw->hwnd, g_ddraw->render.hdc);
g_ddraw->render.hdc = NULL;
}
if (g_ddraw->ticks_limiter.htimer)
{
CancelWaitableTimer(g_ddraw->ticks_limiter.htimer);
CloseHandle(g_ddraw->ticks_limiter.htimer);
g_ddraw->ticks_limiter.htimer = NULL;
}
if (g_ddraw->flip_limiter.htimer)
{
CancelWaitableTimer(g_ddraw->flip_limiter.htimer);
CloseHandle(g_ddraw->flip_limiter.htimer);
g_ddraw->flip_limiter.htimer = NULL;
}
if (g_ddraw->fps_limiter.htimer)
{
CancelWaitableTimer(g_ddraw->fps_limiter.htimer);
CloseHandle(g_ddraw->fps_limiter.htimer);
g_ddraw->fps_limiter.htimer = NULL;
}
DeleteCriticalSection(&g_ddraw->cs);
/* restore old wndproc, subsequent ddraw creation will otherwise fail */
real_SetWindowLongA(g_ddraw->hwnd, GWL_WNDPROC, (LONG)g_ddraw->wndproc);
HeapFree(GetProcessHeap(), 0, g_ddraw);
g_ddraw = NULL;
return 0;
}
return g_ddraw->ref;
}
HRESULT dd_GetAvailableVidMem(void* lpDDCaps, LPDWORD lpdwTotal, LPDWORD lpdwFree)
{
*lpdwTotal = 16777216;
*lpdwFree = 16777216;
return DD_OK;
}
HRESULT dd_GetVerticalBlankStatus(LPBOOL lpbIsInVB)
{
*lpbIsInVB = TRUE;
return DD_OK;
}

21
src/ddclipper.c Normal file
View file

@ -0,0 +1,21 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "IDirectDrawClipper.h"
#include "ddclipper.h"
#include "debug.h"
HRESULT dd_CreateClipper(DWORD dwFlags, LPDIRECTDRAWCLIPPER FAR *lplpDDClipper, IUnknown FAR *pUnkOuter )
{
if (!lplpDDClipper)
return DDERR_INVALIDPARAMS;
IDirectDrawClipperImpl *c = (IDirectDrawClipperImpl *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawClipperImpl));
c->lpVtbl = &g_ddc_vtbl;
dprintf(" Clipper = %p\n", c);
*lplpDDClipper = (LPDIRECTDRAWCLIPPER)c;
IDirectDrawClipper_AddRef(c);
return DD_OK;
}

65
src/ddpalette.c Normal file
View file

@ -0,0 +1,65 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "dd.h"
#include "ddpalette.h"
#include "ddsurface.h"
#include "IDirectDrawPalette.h"
#include "debug.h"
HRESULT ddp_GetEntries(IDirectDrawPaletteImpl *This, DWORD dwFlags, DWORD dwBase, DWORD dwNumEntries, LPPALETTEENTRY lpEntries)
{
int i, x;
for (i = dwBase, x = 0; i < dwBase + dwNumEntries; i++, x++)
{
if (This->data_rgb)
{
lpEntries[x].peRed = This->data_rgb[i].rgbRed;
lpEntries[x].peGreen = This->data_rgb[i].rgbGreen;
lpEntries[x].peBlue = This->data_rgb[i].rgbBlue;
}
}
return DD_OK;
}
HRESULT ddp_SetEntries(IDirectDrawPaletteImpl *This, DWORD dwFlags, DWORD dwStartingEntry, DWORD dwCount, LPPALETTEENTRY lpEntries)
{
int i, x;
for (i = dwStartingEntry, x = 0; i < dwStartingEntry + dwCount; i++, x++)
{
This->data_bgr[i] = (lpEntries[x].peBlue << 16) | (lpEntries[x].peGreen << 8) | lpEntries[x].peRed;
if (This->data_rgb)
{
This->data_rgb[i].rgbRed = lpEntries[x].peRed;
This->data_rgb[i].rgbGreen = lpEntries[x].peGreen;
This->data_rgb[i].rgbBlue = lpEntries[x].peBlue;
This->data_rgb[i].rgbReserved = 0;
}
}
if (g_ddraw->primary && g_ddraw->primary->palette == This && g_ddraw->render.run)
{
InterlockedExchange(&g_ddraw->render.palette_updated, TRUE);
ReleaseSemaphore(g_ddraw->render.sem, 1, NULL);
}
return DD_OK;
}
HRESULT dd_CreatePalette(DWORD dwFlags, LPPALETTEENTRY lpDDColorArray, LPDIRECTDRAWPALETTE FAR * lpDDPalette, IUnknown FAR * unkOuter)
{
IDirectDrawPaletteImpl *p = (IDirectDrawPaletteImpl *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawPaletteImpl));
p->lpVtbl = &g_ddp_vtbl;
dprintf(" Palette = %p\n", p);
*lpDDPalette = (LPDIRECTDRAWPALETTE)p;
ddp_SetEntries(p, dwFlags, 0, 256, lpDDColorArray);
IDirectDrawPalette_AddRef(p);
return DD_OK;
}

887
src/ddsurface.c Normal file
View file

@ -0,0 +1,887 @@
#include <windows.h>
#include <stdio.h>
#include "dd.h"
#include "hook.h"
#include "ddsurface.h"
#include "mouse.h"
#include "scale_pattern.h"
#include "IDirectDrawSurface.h"
#include "winapi_hooks.h"
#include "debug.h"
#include "utils.h"
void *g_fake_primary_surface_export; // hack for some warcraft II tools
HRESULT dds_AddAttachedSurface(IDirectDrawSurfaceImpl *This, LPDIRECTDRAWSURFACE lpDDSurface)
{
IDirectDrawSurface_AddRef(lpDDSurface);
return DD_OK;
}
HRESULT dds_Blt(IDirectDrawSurfaceImpl *This, LPRECT lpDestRect, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx)
{
IDirectDrawSurfaceImpl *src_surface = (IDirectDrawSurfaceImpl *)lpDDSrcSurface;
dbg_dump_dds_blt_flags(dwFlags);
RECT src_rect = { 0, 0, src_surface ? src_surface->width : 0, src_surface ? src_surface->height : 0 };
RECT dst_rect = { 0, 0, This->width, This->height };
if (lpSrcRect && src_surface)
memcpy(&src_rect, lpSrcRect, sizeof(src_rect));
if (lpDestRect)
memcpy(&dst_rect, lpDestRect, sizeof(dst_rect));
// stretch or clip?
BOOL is_stretch_blt =
((src_rect.right - src_rect.left) != (dst_rect.right - dst_rect.left)) ||
((src_rect.bottom - src_rect.top) != (dst_rect.bottom - dst_rect.top));
if (src_surface)
{
if (src_rect.right > src_surface->width)
src_rect.right = src_surface->width;
if (src_rect.bottom > src_surface->height)
src_rect.bottom = src_surface->height;
}
if (dst_rect.right > This->width)
dst_rect.right = This->width;
if (dst_rect.bottom > This->height)
dst_rect.bottom = This->height;
int src_w = src_rect.right - src_rect.left;
int src_h = src_rect.bottom - src_rect.top;
int src_x = src_rect.left;
int src_y = src_rect.top;
int dst_w = dst_rect.right - dst_rect.left;
int dst_h = dst_rect.bottom - dst_rect.top;
int dst_x = dst_rect.left;
int dst_y = dst_rect.top;
if (This->surface && (dwFlags & DDBLT_COLORFILL))
{
unsigned char *dst = (unsigned char *)This->surface + (dst_x * This->lx_pitch) + (This->l_pitch * dst_y);
unsigned char *first_row = dst;
unsigned int dst_pitch = dst_w * This->lx_pitch;
int x, i;
if (This->bpp == 8)
{
unsigned char color = (unsigned char)lpDDBltFx->dwFillColor;
for (i = 0; i < dst_h; i++)
{
memset(dst, color, dst_pitch);
dst += This->l_pitch;
}
}
else if (This->bpp == 16)
{
unsigned short *row1 = (unsigned short *)dst;
unsigned short color = (unsigned short)lpDDBltFx->dwFillColor;
if ((color & 0xFF) == (color >> 8))
{
unsigned char c8 = (unsigned char)(color & 0xFF);
for (i = 0; i < dst_h; i++)
{
memset(dst, c8, dst_pitch);
dst += This->l_pitch;
}
}
else
{
for (x = 0; x < dst_w; x++)
row1[x] = color;
for (i = 1; i < dst_h; i++)
{
dst += This->l_pitch;
memcpy(dst, first_row, dst_pitch);
}
}
}
}
if (src_surface)
{
if ((dwFlags & DDBLT_KEYSRC) || (dwFlags & DDBLT_KEYSRCOVERRIDE))
{
DDCOLORKEY color_key;
color_key.dwColorSpaceLowValue =
(dwFlags & DDBLT_KEYSRCOVERRIDE) ?
lpDDBltFx->ddckSrcColorkey.dwColorSpaceLowValue : src_surface->color_key.dwColorSpaceLowValue;
color_key.dwColorSpaceHighValue =
(dwFlags & DDBLT_KEYSRCOVERRIDE) ?
lpDDBltFx->ddckSrcColorkey.dwColorSpaceHighValue : src_surface->color_key.dwColorSpaceHighValue;
if (!is_stretch_blt)
{
int width = dst_w > src_w ? src_w : dst_w;
int height = dst_h > src_h ? src_h : dst_h;
if (This->bpp == 8)
{
int y1, x1;
for (y1 = 0; y1 < height; y1++)
{
int ydst = This->width * (y1 + dst_y);
int ysrc = src_surface->width * (y1 + src_y);
for (x1 = 0; x1 < width; x1++)
{
unsigned char c = ((unsigned char *)src_surface->surface)[x1 + src_x + ysrc];
if (c < color_key.dwColorSpaceLowValue || c > color_key.dwColorSpaceHighValue)
{
((unsigned char *)This->surface)[x1 + dst_x + ydst] = c;
}
}
}
}
else if (This->bpp == 16)
{
int y1, x1;
for (y1 = 0; y1 < height; y1++)
{
int ydst = This->width * (y1 + dst_y);
int ysrc = src_surface->width * (y1 + src_y);
for (x1 = 0; x1 < width; x1++)
{
unsigned short c = ((unsigned short *)src_surface->surface)[x1 + src_x + ysrc];
if (c < color_key.dwColorSpaceLowValue || c > color_key.dwColorSpaceHighValue)
{
((unsigned short *)This->surface)[x1 + dst_x + ydst] = c;
}
}
}
}
}
else
{
dprintf(" DDBLT_KEYSRC / DDBLT_KEYSRCOVERRIDE does not support stretching\n");
}
}
else
{
if (!is_stretch_blt)
{
int width = dst_w > src_w ? src_w : dst_w;
int height = dst_h > src_h ? src_h : dst_h;
unsigned char *src =
(unsigned char *)src_surface->surface + (src_x * src_surface->lx_pitch) + (src_surface->l_pitch * src_y);
unsigned char *dst =
(unsigned char *)This->surface + (dst_x * This->lx_pitch) + (This->l_pitch * dst_y);
unsigned int dst_pitch = width * This->lx_pitch;
int i;
for (i = 0; i < height; i++)
{
memcpy(dst, src, dst_pitch);
src += src_surface->l_pitch;
dst += This->l_pitch;
}
}
else
{
/* Linear scaling using integer math
* Since the scaling pattern for x will aways be the same, the pattern itself gets pre-calculated
* and stored in an array.
* Y scaling pattern gets calculated during the blit loop
*/
unsigned int x_ratio = (unsigned int)((src_w << 16) / dst_w) + 1;
unsigned int y_ratio = (unsigned int)((src_h << 16) / dst_h) + 1;
unsigned int s_src_x, s_src_y;
unsigned int dest_base, source_base;
scale_pattern *pattern = malloc((dst_w + 1) * (sizeof(scale_pattern)));
int pattern_idx = 0;
unsigned int last_src_x = 0;
if (pattern != NULL)
{
pattern[pattern_idx] = (scale_pattern) { ONCE, 0, 0, 1 };
/* Build the pattern! */
int x;
for (x = 1; x < dst_w; x++) {
s_src_x = (x * x_ratio) >> 16;
if (s_src_x == last_src_x)
{
if (pattern[pattern_idx].type == REPEAT || pattern[pattern_idx].type == ONCE)
{
pattern[pattern_idx].type = REPEAT;
pattern[pattern_idx].count++;
}
else if (pattern[pattern_idx].type == SEQUENCE)
{
pattern_idx++;
pattern[pattern_idx] = (scale_pattern) { REPEAT, x, s_src_x, 1 };
}
}
else if (s_src_x == last_src_x + 1)
{
if (pattern[pattern_idx].type == SEQUENCE || pattern[pattern_idx].type == ONCE)
{
pattern[pattern_idx].type = SEQUENCE;
pattern[pattern_idx].count++;
}
else if (pattern[pattern_idx].type == REPEAT)
{
pattern_idx++;
pattern[pattern_idx] = (scale_pattern) { ONCE, x, s_src_x, 1 };
}
}
else
{
pattern_idx++;
pattern[pattern_idx] = (scale_pattern) { ONCE, x, s_src_x, 1 };
}
last_src_x = s_src_x;
}
pattern[pattern_idx + 1] = (scale_pattern) { END, 0, 0, 0 };
/* Do the actual blitting */
int count = 0;
int y;
for (y = 0; y < dst_h; y++) {
dest_base = dst_x + This->width * (y + dst_y);
s_src_y = (y * y_ratio) >> 16;
source_base = src_x + src_surface->width * (s_src_y + src_y);
pattern_idx = 0;
scale_pattern *current = &pattern[pattern_idx];
if (This->bpp == 8)
{
unsigned char *d, *s, v;
unsigned char *src = (unsigned char *)src_surface->surface;
unsigned char *dst = (unsigned char *)This->surface;
do {
switch (current->type)
{
case ONCE:
dst[dest_base + current->dst_index] =
src[source_base + current->src_index];
break;
case REPEAT:
d = (dst + dest_base + current->dst_index);
v = src[source_base + current->src_index];
count = current->count;
while (count-- > 0)
*d++ = v;
break;
case SEQUENCE:
d = dst + dest_base + current->dst_index;
s = src + source_base + current->src_index;
memcpy((void *)d, (void *)s, current->count * This->lx_pitch);
break;
case END:
default:
break;
}
current = &pattern[++pattern_idx];
} while (current->type != END);
}
else if (This->bpp == 16)
{
unsigned short *d, *s, v;
unsigned short *src = (unsigned short *)src_surface->surface;
unsigned short *dst = (unsigned short *)This->surface;
do {
switch (current->type)
{
case ONCE:
dst[dest_base + current->dst_index] =
src[source_base + current->src_index];
break;
case REPEAT:
d = (dst + dest_base + current->dst_index);
v = src[source_base + current->src_index];
count = current->count;
while (count-- > 0)
*d++ = v;
break;
case SEQUENCE:
d = dst + dest_base + current->dst_index;
s = src + source_base + current->src_index;
memcpy((void *)d, (void *)s, current->count * This->lx_pitch);
break;
case END:
default:
break;
}
current = &pattern[++pattern_idx];
} while (current->type != END);
}
}
free(pattern);
}
}
}
}
if((This->caps & DDSCAPS_PRIMARYSURFACE) && g_ddraw->render.run)
{
InterlockedExchange(&g_ddraw->render.surface_updated, TRUE);
if (!(This->flags & DDSD_BACKBUFFERCOUNT) || This->last_flip_tick + FLIP_REDRAW_TIMEOUT < timeGetTime())
{
This->last_blt_tick = timeGetTime();
ReleaseSemaphore(g_ddraw->render.sem, 1, NULL);
SwitchToThread();
if (g_ddraw->ticks_limiter.tick_length > 0)
{
g_ddraw->ticks_limiter.use_blt_or_flip = TRUE;
util_limit_game_ticks();
}
}
}
return DD_OK;
}
HRESULT dds_BltFast(IDirectDrawSurfaceImpl *This, DWORD dst_x, DWORD dst_y, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DWORD flags)
{
IDirectDrawSurfaceImpl *src_surface = (IDirectDrawSurfaceImpl *)lpDDSrcSurface;
dbg_dump_dds_blt_fast_flags(flags);
RECT src_rect = { 0, 0, src_surface ? src_surface->width : 0, src_surface ? src_surface->height : 0 };
if (lpSrcRect && src_surface)
{
memcpy(&src_rect, lpSrcRect, sizeof(src_rect));
if (src_rect.right > src_surface->width)
src_rect.right = src_surface->width;
if (src_rect.bottom > src_surface->height)
src_rect.bottom = src_surface->height;
}
int src_x = src_rect.left;
int src_y = src_rect.top;
RECT dst_rect = { dst_x, dst_y, (src_rect.right - src_rect.left) + dst_x, (src_rect.bottom - src_rect.top) + dst_y };
if (dst_rect.right > This->width)
dst_rect.right = This->width;
if (dst_rect.bottom > This->height)
dst_rect.bottom = This->height;
int dst_w = dst_rect.right - dst_rect.left;
int dst_h = dst_rect.bottom - dst_rect.top;
if (src_surface)
{
if (flags & DDBLTFAST_SRCCOLORKEY)
{
if (This->bpp == 8)
{
int y1, x1;
for (y1 = 0; y1 < dst_h; y1++)
{
int ydst = This->width * (y1 + dst_y);
int ysrc = src_surface->width * (y1 + src_y);
for (x1 = 0; x1 < dst_w; x1++)
{
unsigned char c = ((unsigned char *)src_surface->surface)[x1 + src_x + ysrc];
if (c < src_surface->color_key.dwColorSpaceLowValue || c > src_surface->color_key.dwColorSpaceHighValue)
{
((unsigned char *)This->surface)[x1 + dst_x + ydst] = c;
}
}
}
}
else if (This->bpp == 16)
{
int y1, x1;
for (y1 = 0; y1 < dst_h; y1++)
{
int ydst = This->width * (y1 + dst_y);
int ysrc = src_surface->width * (y1 + src_y);
for (x1 = 0; x1 < dst_w; x1++)
{
unsigned short c = ((unsigned short *)src_surface->surface)[x1 + src_x + ysrc];
if (c < src_surface->color_key.dwColorSpaceLowValue || c > src_surface->color_key.dwColorSpaceHighValue)
{
((unsigned short *)This->surface)[x1 + dst_x + ydst] = c;
}
}
}
}
}
else
{
unsigned char *src =
(unsigned char *)src_surface->surface + (src_x * src_surface->lx_pitch) + (src_surface->l_pitch * src_y);
unsigned char *dst =
(unsigned char *)This->surface + (dst_x * This->lx_pitch) + (This->l_pitch * dst_y);
unsigned int dst_pitch = dst_w * This->lx_pitch;
int i;
for (i = 0; i < dst_h; i++)
{
memcpy(dst, src, dst_pitch);
src += src_surface->l_pitch;
dst += This->l_pitch;
}
}
}
if ((This->caps & DDSCAPS_PRIMARYSURFACE) && g_ddraw->render.run)
{
InterlockedExchange(&g_ddraw->render.surface_updated, TRUE);
DWORD time = timeGetTime();
if (!(This->flags & DDSD_BACKBUFFERCOUNT) ||
(This->last_flip_tick + FLIP_REDRAW_TIMEOUT < time && This->last_blt_tick + FLIP_REDRAW_TIMEOUT < time))
{
ReleaseSemaphore(g_ddraw->render.sem, 1, NULL);
}
}
return DD_OK;
}
HRESULT dds_DeleteAttachedSurface(IDirectDrawSurfaceImpl *This, DWORD dwFlags, LPDIRECTDRAWSURFACE lpDDSurface)
{
IDirectDrawSurface_Release(lpDDSurface);
return DD_OK;
}
HRESULT dds_GetSurfaceDesc(IDirectDrawSurfaceImpl *This, LPDDSURFACEDESC lpDDSurfaceDesc)
{
lpDDSurfaceDesc->dwSize = sizeof(DDSURFACEDESC);
lpDDSurfaceDesc->dwFlags = DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_PIXELFORMAT|DDSD_LPSURFACE;
lpDDSurfaceDesc->dwWidth = This->width;
lpDDSurfaceDesc->dwHeight = This->height;
lpDDSurfaceDesc->lPitch = This->l_pitch;
lpDDSurfaceDesc->lpSurface = This->surface;
lpDDSurfaceDesc->ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = This->bpp;
lpDDSurfaceDesc->ddsCaps.dwCaps = This->caps | DDSCAPS_VIDEOMEMORY;
if (This->bpp == 8)
{
lpDDSurfaceDesc->ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED8;
}
else if (This->bpp == 16)
{
lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0xF800;
lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0x07E0;
lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = 0x001F;
}
return DD_OK;
}
HRESULT dds_EnumAttachedSurfaces(IDirectDrawSurfaceImpl *This, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback)
{
/* this is not actually complete, but Carmageddon seems to call EnumAttachedSurfaces instead of GetSurfaceDesc to get the main surface description */
static DDSURFACEDESC dd_surface_desc;
memset(&dd_surface_desc, 0, sizeof(DDSURFACEDESC));
dds_GetSurfaceDesc(This, &dd_surface_desc);
This->caps |= DDSCAPS_BACKBUFFER; // Nox hack
lpEnumSurfacesCallback((LPDIRECTDRAWSURFACE)This, &dd_surface_desc, lpContext);
if ((This->caps & DDSCAPS_PRIMARYSURFACE) && (This->caps & DDSCAPS_FLIP) && !(This->caps & DDSCAPS_BACKBUFFER))
IDirectDrawSurface_AddRef(This);
This->caps &= ~DDSCAPS_BACKBUFFER;
return DD_OK;
}
HRESULT dds_Flip(IDirectDrawSurfaceImpl *This, LPDIRECTDRAWSURFACE surface, DWORD flags)
{
if(This->caps & DDSCAPS_PRIMARYSURFACE && g_ddraw->render.run)
{
This->last_flip_tick = timeGetTime();
InterlockedExchange(&g_ddraw->render.surface_updated, TRUE);
ReleaseSemaphore(g_ddraw->render.sem, 1, NULL);
SwitchToThread();
if (flags & DDFLIP_WAIT)
{
dd_WaitForVerticalBlank(DDWAITVB_BLOCKEND, NULL);
}
if (g_ddraw->ticks_limiter.tick_length > 0)
{
g_ddraw->ticks_limiter.use_blt_or_flip = TRUE;
util_limit_game_ticks();
}
}
return DD_OK;
}
HRESULT dds_GetAttachedSurface(IDirectDrawSurfaceImpl *This, LPDDSCAPS lpDdsCaps, LPDIRECTDRAWSURFACE FAR *surface)
{
if ((This->caps & DDSCAPS_PRIMARYSURFACE) && (This->caps & DDSCAPS_FLIP) && (lpDdsCaps->dwCaps & DDSCAPS_BACKBUFFER))
{
IDirectDrawSurface_AddRef(This);
*surface = (LPDIRECTDRAWSURFACE)This;
}
return DD_OK;
}
HRESULT dds_GetCaps(IDirectDrawSurfaceImpl *This, LPDDSCAPS lpDDSCaps)
{
lpDDSCaps->dwCaps = This->caps;
return DD_OK;
}
HRESULT dds_GetColorKey(IDirectDrawSurfaceImpl *This, DWORD flags, LPDDCOLORKEY colorKey)
{
if (colorKey)
{
colorKey->dwColorSpaceHighValue = This->color_key.dwColorSpaceHighValue;
colorKey->dwColorSpaceLowValue = This->color_key.dwColorSpaceLowValue;
}
return DD_OK;
}
HRESULT dds_GetDC(IDirectDrawSurfaceImpl *This, HDC FAR *a)
{
if ((This->width % 4))
{
dprintf(" GetDC: width=%d height=%d\n", This->width, This->height);
}
RGBQUAD *data =
This->palette && This->palette->data_rgb ? This->palette->data_rgb :
g_ddraw->primary && g_ddraw->primary->palette ? g_ddraw->primary->palette->data_rgb :
NULL;
if (data)
SetDIBColorTable(This->hdc, 0, 256, data);
*a = This->hdc;
return DD_OK;
}
HRESULT dds_GetPalette(IDirectDrawSurfaceImpl *This, LPDIRECTDRAWPALETTE FAR *lplpDDPalette)
{
*lplpDDPalette = (LPDIRECTDRAWPALETTE)This->palette;
if (This->palette)
{
return DD_OK;
}
else
{
return DDERR_NOPALETTEATTACHED;
}
}
HRESULT dds_GetPixelFormat(IDirectDrawSurfaceImpl *This, LPDDPIXELFORMAT ddpfPixelFormat)
{
DWORD size = ddpfPixelFormat->dwSize;
if (size == sizeof(DDPIXELFORMAT))
{
memset(ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT));
ddpfPixelFormat->dwSize = size;
ddpfPixelFormat->dwFlags = DDPF_RGB;
ddpfPixelFormat->dwRGBBitCount = This->bpp;
if (This->bpp == 8)
{
ddpfPixelFormat->dwFlags |= DDPF_PALETTEINDEXED8;
}
else if (This->bpp == 16)
{
ddpfPixelFormat->dwRBitMask = 0xF800;
ddpfPixelFormat->dwGBitMask = 0x07E0;
ddpfPixelFormat->dwBBitMask = 0x001F;
}
return DD_OK;
}
return DDERR_INVALIDPARAMS;
}
HRESULT dds_Lock(IDirectDrawSurfaceImpl *This, LPRECT lpDestRect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD dwFlags, HANDLE hEvent)
{
dbg_dump_dds_lock_flags(dwFlags);
return dds_GetSurfaceDesc(This, lpDDSurfaceDesc);
}
HRESULT dds_SetColorKey(IDirectDrawSurfaceImpl *This, DWORD flags, LPDDCOLORKEY colorKey)
{
if (colorKey)
{
dprintfex(" dwColorSpaceHighValue=%d\n", colorKey->dwColorSpaceHighValue);
dprintfex(" dwColorSpaceLowValue=%d\n", colorKey->dwColorSpaceLowValue);
This->color_key.dwColorSpaceHighValue = colorKey->dwColorSpaceHighValue;
This->color_key.dwColorSpaceLowValue = colorKey->dwColorSpaceLowValue;
}
return DD_OK;
}
HRESULT dds_SetPalette(IDirectDrawSurfaceImpl *This, LPDIRECTDRAWPALETTE lpDDPalette)
{
IDirectDrawPalette_AddRef(lpDDPalette);
if (This->palette)
{
IDirectDrawPalette_Release(This->palette);
}
EnterCriticalSection(&g_ddraw->cs);
This->palette = (IDirectDrawPaletteImpl *)lpDDPalette;
This->palette->data_rgb = &This->bmi->bmiColors[0];
int i;
for (i = 0; i < 256; i++)
{
This->palette->data_rgb[i].rgbRed = This->palette->data_bgr[i] & 0xFF;
This->palette->data_rgb[i].rgbGreen = (This->palette->data_bgr[i] >> 8) & 0xFF;
This->palette->data_rgb[i].rgbBlue = (This->palette->data_bgr[i] >> 16) & 0xFF;
This->palette->data_rgb[i].rgbReserved = 0;
}
LeaveCriticalSection(&g_ddraw->cs);
return DD_OK;
}
HRESULT dds_Unlock(IDirectDrawSurfaceImpl *This, LPVOID lpRect)
{
HWND hwnd = g_ddraw->bnet_active ? FindWindowEx(HWND_DESKTOP, NULL, "SDlgDialog", NULL) : NULL;
if (hwnd && (This->caps & DDSCAPS_PRIMARYSURFACE))
{
if (g_ddraw->primary->palette && g_ddraw->primary->palette->data_rgb)
SetDIBColorTable(g_ddraw->primary->hdc, 0, 256, g_ddraw->primary->palette->data_rgb);
//GdiTransparentBlt idea taken from Aqrit's war2 ddraw
RGBQUAD quad;
GetDIBColorTable(g_ddraw->primary->hdc, 0xFE, 1, &quad);
COLORREF color = RGB(quad.rgbRed, quad.rgbGreen, quad.rgbBlue);
BOOL erase = FALSE;
do
{
RECT rc;
if (fake_GetWindowRect(hwnd, &rc))
{
if (rc.bottom - rc.top == 479)
erase = TRUE;
HDC hdc = GetDCEx(hwnd, NULL, DCX_PARENTCLIP | DCX_CACHE);
GdiTransparentBlt(
hdc,
0,
0,
rc.right - rc.left,
rc.bottom - rc.top,
g_ddraw->primary->hdc,
rc.left,
rc.top,
rc.right - rc.left,
rc.bottom - rc.top,
color
);
ReleaseDC(hwnd, hdc);
}
} while ((hwnd = FindWindowEx(HWND_DESKTOP, hwnd, "SDlgDialog", NULL)));
if (erase)
{
BOOL x = g_ddraw->ticks_limiter.use_blt_or_flip;
DDBLTFX fx = { .dwFillColor = 0xFE };
IDirectDrawSurface_Blt(This, NULL, NULL, NULL, DDBLT_COLORFILL, &fx);
g_ddraw->ticks_limiter.use_blt_or_flip = x;
}
}
if ((This->caps & DDSCAPS_PRIMARYSURFACE) && g_ddraw->render.run)
{
InterlockedExchange(&g_ddraw->render.surface_updated, TRUE);
DWORD time = timeGetTime();
if (!(This->flags & DDSD_BACKBUFFERCOUNT) ||
(This->last_flip_tick + FLIP_REDRAW_TIMEOUT < time && This->last_blt_tick + FLIP_REDRAW_TIMEOUT < time))
{
ReleaseSemaphore(g_ddraw->render.sem, 1, NULL);
if (g_ddraw->ticks_limiter.tick_length > 0 && !g_ddraw->ticks_limiter.use_blt_or_flip)
util_limit_game_ticks();
}
}
return DD_OK;
}
HRESULT dd_CreateSurface(LPDDSURFACEDESC lpDDSurfaceDesc, LPDIRECTDRAWSURFACE FAR *lpDDSurface, IUnknown FAR * unkOuter)
{
dbg_dump_dds_flags(lpDDSurfaceDesc->dwFlags);
IDirectDrawSurfaceImpl *dst_surface = (IDirectDrawSurfaceImpl *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawSurfaceImpl));
dst_surface->lpVtbl = &g_dds_vtbl;
lpDDSurfaceDesc->dwFlags |= DDSD_CAPS;
/* private stuff */
dst_surface->bpp = g_ddraw->bpp;
dst_surface->flags = lpDDSurfaceDesc->dwFlags;
if(lpDDSurfaceDesc->dwFlags & DDSD_CAPS)
{
if(lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
{
g_ddraw->primary = dst_surface;
dst_surface->width = g_ddraw->width;
dst_surface->height = g_ddraw->height;
}
dbg_dump_dds_caps(lpDDSurfaceDesc->ddsCaps.dwCaps);
dst_surface->caps = lpDDSurfaceDesc->ddsCaps.dwCaps;
}
if( !(lpDDSurfaceDesc->dwFlags & DDSD_CAPS) || !(lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) )
{
dst_surface->width = lpDDSurfaceDesc->dwWidth;
dst_surface->height = lpDDSurfaceDesc->dwHeight;
}
if(dst_surface->width && dst_surface->height)
{
if (dst_surface->width == 622 && dst_surface->height == 51) dst_surface->width = 624; //AoE2
if (dst_surface->width == 71 && dst_surface->height == 24) dst_surface->width = 72; //Commandos
dst_surface->bmi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
dst_surface->bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
dst_surface->bmi->bmiHeader.biWidth = dst_surface->width;
dst_surface->bmi->bmiHeader.biHeight = -(dst_surface->height + 200);
dst_surface->bmi->bmiHeader.biPlanes = 1;
dst_surface->bmi->bmiHeader.biBitCount = dst_surface->bpp;
dst_surface->bmi->bmiHeader.biCompression = dst_surface->bpp == 16 ? BI_BITFIELDS : BI_RGB;
WORD c_clr_bits = (WORD)(dst_surface->bmi->bmiHeader.biPlanes * dst_surface->bmi->bmiHeader.biBitCount);
if (c_clr_bits < 24)
dst_surface->bmi->bmiHeader.biClrUsed = (1 << c_clr_bits);
dst_surface->bmi->bmiHeader.biSizeImage = ((dst_surface->width * c_clr_bits + 31) & ~31) / 8 * dst_surface->height;
if (dst_surface->bpp == 8)
{
int i;
for (i = 0; i < 256; i++)
{
dst_surface->bmi->bmiColors[i].rgbRed = i;
dst_surface->bmi->bmiColors[i].rgbGreen = i;
dst_surface->bmi->bmiColors[i].rgbBlue = i;
dst_surface->bmi->bmiColors[i].rgbReserved = 0;
}
}
else if (dst_surface->bpp == 16)
{
((DWORD *)dst_surface->bmi->bmiColors)[0] = 0xF800;
((DWORD *)dst_surface->bmi->bmiColors)[1] = 0x07E0;
((DWORD *)dst_surface->bmi->bmiColors)[2] = 0x001F;
}
dst_surface->lx_pitch = dst_surface->bpp / 8;
dst_surface->l_pitch = dst_surface->width * dst_surface->lx_pitch;
dst_surface->hdc = CreateCompatibleDC(g_ddraw->render.hdc);
dst_surface->bitmap = CreateDIBSection(dst_surface->hdc, dst_surface->bmi, DIB_RGB_COLORS, (void **)&dst_surface->surface, NULL, 0);
dst_surface->bmi->bmiHeader.biHeight = -dst_surface->height;
if (!dst_surface->bitmap)
dst_surface->surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dst_surface->l_pitch * (dst_surface->height + 200) * dst_surface->lx_pitch);
if (lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
g_fake_primary_surface_export = dst_surface->surface;
SelectObject(dst_surface->hdc, dst_surface->bitmap);
}
if (lpDDSurfaceDesc->dwFlags & DDSD_BACKBUFFERCOUNT)
{
dprintf(" dwBackBufferCount=%d\n", lpDDSurfaceDesc->dwBackBufferCount);
}
dprintf(" dst_surface = %p (%dx%d@%d)\n", dst_surface, (int)dst_surface->width, (int)dst_surface->height, (int)dst_surface->bpp);
*lpDDSurface = (LPDIRECTDRAWSURFACE)dst_surface;
dst_surface->ref = 0;
IDirectDrawSurface_AddRef(dst_surface);
return DD_OK;
}

View file

@ -1,41 +1,72 @@
#include <windows.h>
#include <stdio.h>
#include "main.h"
#include "surface.h"
#include "dd.h"
#include "ddraw.h"
#include "ddsurface.h"
#include "debug.h"
double DebugFrameTime = 0;
DWORD DebugFrameCount = 0;
static LONGLONG CounterStartTime = 0;
static double CounterFreq = 0.0;
double g_dbg_frame_time = 0;
DWORD g_dbg_frame_count = 0;
void CounterStart()
static LONGLONG g_dbg_counter_start_time = 0;
static double g_dbg_counter_freq = 0.0;
void dbg_init()
{
static int stdout_open = 0;
if (!stdout_open)
{
freopen("cnc-ddraw.log", "w", stdout);
setvbuf(stdout, NULL, _IOLBF, 1024);
stdout_open = 1;
HKEY hkey;
LONG status =
RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0L, KEY_READ, &hkey);
if (status == ERROR_SUCCESS)
{
char name[256] = { 0 };
DWORD name_size = sizeof(name);
RegQueryValueExA(hkey, "ProductName", NULL, NULL, (PVOID)&name, &name_size);
char build[256] = { 0 };
DWORD build_size = sizeof(build);
RegQueryValueExA(hkey, "BuildLab", NULL, NULL, (PVOID)&build, &build_size);
dbg_printf("%s (%s)\n", name, build);
}
}
}
void dbg_counter_start()
{
LARGE_INTEGER li;
QueryPerformanceFrequency(&li);
CounterFreq = (double)(li.QuadPart) / 1000.0;
g_dbg_counter_freq = (double)(li.QuadPart) / 1000.0;
QueryPerformanceCounter(&li);
CounterStartTime = li.QuadPart;
g_dbg_counter_start_time = li.QuadPart;
}
double CounterStop()
double dbg_counter_stop()
{
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
return (double)(li.QuadPart - CounterStartTime) / CounterFreq;
return (double)(li.QuadPart - g_dbg_counter_start_time) / g_dbg_counter_freq;
}
void DebugPrint(const char *format, ...)
void dbg_debug_string(const char *format, ...)
{
va_list args;
va_start(args, format);
char buffer[512];
char buffer[512] = { 0 };
_vsnprintf(buffer, sizeof(buffer), format, args);
OutputDebugStringA(buffer);
}
int dprintf(const char *fmt, ...)
int dbg_printf(const char *fmt, ...)
{
static CRITICAL_SECTION cs;
static BOOL initialized;
@ -65,42 +96,292 @@ int dprintf(const char *fmt, ...)
return ret;
}
void DrawFrameInfoStart()
void dbg_draw_frame_info_start()
{
static DWORD tick_fps = 0;
static char debugText[512] = { 0 };
static char debug_text[512] = { 0 };
RECT debugrc = { 0, 0, ddraw->width, ddraw->height };
RECT debugrc = { 0, 0, g_ddraw->width, g_ddraw->height };
if (ddraw->primary)
if (g_ddraw->primary)
{
if (ddraw->primary->palette && ddraw->primary->palette->data_rgb)
SetDIBColorTable(ddraw->primary->hDC, 0, 256, ddraw->primary->palette->data_rgb);
if (g_ddraw->primary->palette && g_ddraw->primary->palette->data_rgb)
SetDIBColorTable(g_ddraw->primary->hdc, 0, 256, g_ddraw->primary->palette->data_rgb);
DrawText(ddraw->primary->hDC, debugText, -1, &debugrc, DT_NOCLIP);
DrawText(g_ddraw->primary->hdc, debug_text, -1, &debugrc, DT_NOCLIP);
}
DWORD tick_start = timeGetTime();
if (tick_start >= tick_fps)
{
_snprintf(
debugText,
sizeof(debugText),
debug_text,
sizeof(debug_text)-1,
"FPS: %lu | Time: %2.2f ms ",
DebugFrameCount,
DebugFrameTime);
g_dbg_frame_count,
g_dbg_frame_time);
DebugFrameCount = 0;
g_dbg_frame_count = 0;
tick_fps = tick_start + 1000;
CounterStart();
dbg_counter_start();
}
DebugFrameCount++;
g_dbg_frame_count++;
}
void DrawFrameInfoEnd()
void dbg_draw_frame_info_end()
{
if (DebugFrameCount == 1)
DebugFrameTime = CounterStop();
if (g_dbg_frame_count == 1)
g_dbg_frame_time = dbg_counter_stop();
}
void dbg_dump_dds_blt_flags(DWORD flags)
{
#ifdef _DEBUG_X
if (flags & DDBLT_ALPHADEST) {
dprintf(" DDBLT_ALPHADEST\n");
}
if (flags & DDBLT_ALPHADESTCONSTOVERRIDE) {
dprintf(" DDBLT_ALPHADESTCONSTOVERRIDE\n");
}
if (flags & DDBLT_ALPHADESTNEG) {
dprintf(" DDBLT_ALPHADESTNEG\n");
}
if (flags & DDBLT_ALPHADESTSURFACEOVERRIDE) {
dprintf(" DDBLT_ALPHADESTSURFACEOVERRIDE\n");
}
if (flags & DDBLT_ALPHAEDGEBLEND) {
dprintf(" DDBLT_ALPHAEDGEBLEND\n");
}
if (flags & DDBLT_ALPHASRC) {
dprintf(" DDBLT_ALPHASRC\n");
}
if (flags & DDBLT_ALPHASRCCONSTOVERRIDE) {
dprintf(" DDBLT_ALPHASRCCONSTOVERRIDE\n");
}
if (flags & DDBLT_ALPHASRCNEG) {
dprintf(" DDBLT_ALPHASRCNEG\n");
}
if (flags & DDBLT_ALPHASRCSURFACEOVERRIDE) {
dprintf(" DDBLT_ALPHASRCSURFACEOVERRIDE\n");
}
if (flags & DDBLT_ASYNC) {
dprintf(" DDBLT_ASYNC\n");
}
if (flags & DDBLT_COLORFILL) {
dprintf(" DDBLT_COLORFILL\n");
}
if (flags & DDBLT_DDFX) {
dprintf(" DDBLT_DDFX\n");
}
if (flags & DDBLT_DDROPS) {
dprintf(" DDBLT_DDROPS\n");
}
if (flags & DDBLT_KEYDEST) {
dprintf(" DDBLT_KEYDEST\n");
}
if (flags & DDBLT_KEYDESTOVERRIDE) {
dprintf(" DDBLT_KEYDESTOVERRIDE\n");
}
if (flags & DDBLT_KEYSRC) {
dprintf(" DDBLT_KEYSRC\n");
}
if (flags & DDBLT_KEYSRCOVERRIDE) {
dprintf(" DDBLT_KEYSRCOVERRIDE\n");
}
if (flags & DDBLT_ROP) {
dprintf(" DDBLT_ROP\n");
}
if (flags & DDBLT_ROTATIONANGLE) {
dprintf(" DDBLT_ROTATIONANGLE\n");
}
if (flags & DDBLT_ZBUFFER) {
dprintf(" DDBLT_ZBUFFER\n");
}
if (flags & DDBLT_ZBUFFERDESTCONSTOVERRIDE) {
dprintf(" DDBLT_ZBUFFERDESTCONSTOVERRIDE\n");
}
if (flags & DDBLT_ZBUFFERDESTOVERRIDE) {
dprintf(" DDBLT_ZBUFFERDESTOVERRIDE\n");
}
if (flags & DDBLT_ZBUFFERSRCCONSTOVERRIDE) {
dprintf(" DDBLT_ZBUFFERSRCCONSTOVERRIDE\n");
}
if (flags & DDBLT_ZBUFFERSRCOVERRIDE) {
dprintf(" DDBLT_ZBUFFERSRCOVERRIDE\n");
}
if (flags & DDBLT_WAIT) {
dprintf(" DDBLT_WAIT\n");
}
if (flags & DDBLT_DEPTHFILL) {
dprintf(" DDBLT_DEPTHFILL\n");
}
#endif
}
void dbg_dump_dds_caps(DWORD caps)
{
#ifdef _DEBUG_X
if (caps & DDSCAPS_ALPHA)
{
dprintf(" DDSCAPS_ALPHA\n");
}
if (caps & DDSCAPS_BACKBUFFER)
{
dprintf(" DDSCAPS_BACKBUFFER\n");
}
if (caps & DDSCAPS_FLIP)
{
dprintf(" DDSCAPS_FLIP\n");
}
if (caps & DDSCAPS_FRONTBUFFER)
{
dprintf(" DDSCAPS_FRONTBUFFER\n");
}
if (caps & DDSCAPS_PALETTE)
{
dprintf(" DDSCAPS_PALETTE\n");
}
if (caps & DDSCAPS_TEXTURE)
{
dprintf(" DDSCAPS_TEXTURE\n");
}
if (caps & DDSCAPS_PRIMARYSURFACE)
{
dprintf(" DDSCAPS_PRIMARYSURFACE\n");
}
if (caps & DDSCAPS_OFFSCREENPLAIN)
{
dprintf(" DDSCAPS_OFFSCREENPLAIN\n");
}
if (caps & DDSCAPS_VIDEOMEMORY)
{
dprintf(" DDSCAPS_VIDEOMEMORY\n");
}
if (caps & DDSCAPS_LOCALVIDMEM)
{
dprintf(" DDSCAPS_LOCALVIDMEM\n");
}
#endif
}
void dbg_dump_dds_flags(DWORD flags)
{
#ifdef _DEBUG_X
if (flags & DDSD_CAPS)
{
dprintf(" DDSD_CAPS\n");
}
if (flags & DDSD_HEIGHT)
{
dprintf(" DDSD_HEIGHT\n");
}
if (flags & DDSD_WIDTH)
{
dprintf(" DDSD_WIDTH\n");
}
if (flags & DDSD_PITCH)
{
dprintf(" DDSD_PITCH\n");
}
if (flags & DDSD_BACKBUFFERCOUNT)
{
dprintf(" DDSD_BACKBUFFERCOUNT\n");
}
if (flags & DDSD_ZBUFFERBITDEPTH)
{
dprintf(" DDSD_ZBUFFERBITDEPTH\n");
}
if (flags & DDSD_ALPHABITDEPTH)
{
dprintf(" DDSD_ALPHABITDEPTH\n");
}
if (flags & DDSD_LPSURFACE)
{
dprintf(" DDSD_LPSURFACE\n");
}
if (flags & DDSD_PIXELFORMAT)
{
dprintf(" DDSD_PIXELFORMAT\n");
}
if (flags & DDSD_CKDESTOVERLAY)
{
dprintf(" DDSD_CKDESTOVERLAY\n");
}
if (flags & DDSD_CKDESTBLT)
{
dprintf(" DDSD_CKDESTBLT\n");
}
if (flags & DDSD_CKSRCOVERLAY)
{
dprintf(" DDSD_CKSRCOVERLAY\n");
}
if (flags & DDSD_CKSRCBLT)
{
dprintf(" DDSD_CKSRCBLT\n");
}
if (flags & DDSD_MIPMAPCOUNT)
{
dprintf(" DDSD_MIPMAPCOUNT\n");
}
if (flags & DDSD_REFRESHRATE)
{
dprintf(" DDSD_REFRESHRATE\n");
}
if (flags & DDSD_LINEARSIZE)
{
dprintf(" DDSD_LINEARSIZE\n");
}
if (flags & DDSD_ALL)
{
dprintf(" DDSD_ALL\n");
}
#endif
}
void dbg_dump_dds_blt_fast_flags(DWORD flags)
{
#ifdef _DEBUG_X
if (flags & DDBLTFAST_NOCOLORKEY)
{
dprintf(" DDBLTFAST_NOCOLORKEY\n");
}
if (flags & DDBLTFAST_SRCCOLORKEY)
{
dprintf(" DDBLTFAST_SRCCOLORKEY\n");
}
if (flags & DDBLTFAST_DESTCOLORKEY)
{
dprintf(" DDBLTFAST_DESTCOLORKEY\n");
}
#endif
}
void dbg_dump_dds_lock_flags(DWORD flags)
{
#ifdef _DEBUG_X
if (flags & DDLOCK_SURFACEMEMORYPTR)
{
dprintf(" dwFlags: DDLOCK_SURFACEMEMORYPTR\n");
}
if (flags & DDLOCK_WAIT)
{
dprintf(" dwFlags: DDLOCK_WAIT\n");
}
if (flags & DDLOCK_EVENT)
{
dprintf(" dwFlags: DDLOCK_EVENT\n");
}
if (flags & DDLOCK_READONLY)
{
dprintf(" dwFlags: DDLOCK_READONLY\n");
}
if (flags & DDLOCK_WRITEONLY)
{
dprintf(" dwFlags: DDLOCK_WRITEONLY\n");
}
#endif
}

View file

@ -1,99 +0,0 @@
#include <windows.h>
#include <dinput.h>
#include "hook.h"
#include "main.h"
typedef HRESULT (WINAPI *DIRECTINPUTCREATEAPROC)(HINSTANCE, DWORD, LPDIRECTINPUTA*, LPUNKNOWN);
typedef HRESULT (WINAPI *DICREATEDEVICEPROC)(IDirectInputA*, REFGUID, LPDIRECTINPUTDEVICEA *, LPUNKNOWN);
typedef HRESULT (WINAPI *DIDSETCOOPERATIVELEVELPROC)(IDirectInputDeviceA *, HWND, DWORD);
typedef HRESULT (WINAPI *DIDGETDEVICEDATAPROC)(IDirectInputDeviceA*, DWORD, LPDIDEVICEOBJECTDATA, LPDWORD, DWORD);
static DIRECTINPUTCREATEAPROC DInputCreateA;
static DICREATEDEVICEPROC DICreateDevice;
static DIDSETCOOPERATIVELEVELPROC DIDSetCooperativeLevel;
static DIDGETDEVICEDATAPROC DIDGetDeviceData;
static PROC HookFunc(PROC *orgFunc, PROC newFunc)
{
PROC org = *orgFunc;
DWORD oldProtect;
if (VirtualProtect(orgFunc, sizeof(PROC), PAGE_EXECUTE_READWRITE, &oldProtect))
{
*orgFunc = newFunc;
VirtualProtect(orgFunc, sizeof(PROC), oldProtect, &oldProtect);
return org;
}
return 0;
}
static HRESULT WINAPI fake_DIDSetCooperativeLevel(IDirectInputDeviceA *This, HWND hwnd, DWORD dwFlags)
{
return DIDSetCooperativeLevel(This, hwnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE);
}
static HRESULT WINAPI fake_DIDGetDeviceData(IDirectInputDeviceA *This, DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags)
{
HRESULT result = DIDGetDeviceData(This, cbObjectData, rgdod, pdwInOut, dwFlags);
if (SUCCEEDED(result) && ddraw && !ddraw->locked)
{
*pdwInOut = 0;
}
return result;
}
static HRESULT WINAPI fake_DICreateDevice(IDirectInputA *This, REFGUID rguid, LPDIRECTINPUTDEVICEA * lplpDIDevice, LPUNKNOWN pUnkOuter)
{
HRESULT result = DICreateDevice(This, rguid, lplpDIDevice, pUnkOuter);
if (SUCCEEDED(result) && !DIDSetCooperativeLevel)
{
DIDSetCooperativeLevel =
(DIDSETCOOPERATIVELEVELPROC)HookFunc(
(PROC *)&(*lplpDIDevice)->lpVtbl->SetCooperativeLevel, (PROC)fake_DIDSetCooperativeLevel);
DIDGetDeviceData =
(DIDGETDEVICEDATAPROC)HookFunc(
(PROC*)&(*lplpDIDevice)->lpVtbl->GetDeviceData, (PROC)fake_DIDGetDeviceData);
}
return result;
}
static HRESULT WINAPI fake_DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA* lplpDirectInput, LPUNKNOWN punkOuter)
{
printf("??? DirectInputCreateA\n");
DInputCreateA =
(DIRECTINPUTCREATEAPROC)GetProcAddress(GetModuleHandle("dinput.dll"), "DirectInputCreateA");
if (!DInputCreateA)
return DIERR_GENERIC;
HRESULT result = DInputCreateA(hinst, dwVersion, lplpDirectInput, punkOuter);
if (SUCCEEDED(result) && !DICreateDevice)
{
DICreateDevice =
(DICREATEDEVICEPROC)HookFunc((PROC *)&(*lplpDirectInput)->lpVtbl->CreateDevice, (PROC)fake_DICreateDevice);
}
return result;
}
void DInput_Hook()
{
Hook_PatchIAT(GetModuleHandle(NULL), "dinput.dll", "DirectInputCreateA", (PROC)fake_DirectInputCreateA);
}
void DInput_UnHook()
{
Hook_PatchIAT(
GetModuleHandle(NULL),
"dinput.dll",
"DirectInputCreateA",
(PROC)GetProcAddress(GetModuleHandle("dinput.dll"), "DirectInputCreateA"));
}

101
src/directinput.c Normal file
View file

@ -0,0 +1,101 @@
#include <windows.h>
#include <dinput.h>
#include "debug.h"
#include "hook.h"
#include "dd.h"
typedef HRESULT (WINAPI *DIRECTINPUTCREATEAPROC)(HINSTANCE, DWORD, LPDIRECTINPUTA*, LPUNKNOWN);
typedef HRESULT (WINAPI *DICREATEDEVICEPROC)(IDirectInputA*, REFGUID, LPDIRECTINPUTDEVICEA *, LPUNKNOWN);
typedef HRESULT (WINAPI *DIDSETCOOPERATIVELEVELPROC)(IDirectInputDeviceA *, HWND, DWORD);
typedef HRESULT (WINAPI *DIDGETDEVICEDATAPROC)(IDirectInputDeviceA*, DWORD, LPDIDEVICEOBJECTDATA, LPDWORD, DWORD);
static DIRECTINPUTCREATEAPROC real_DirectInputCreateA;
static DICREATEDEVICEPROC real_di_CreateDevice;
static DIDSETCOOPERATIVELEVELPROC real_did_SetCooperativeLevel;
static DIDGETDEVICEDATAPROC real_did_GetDeviceData;
static PROC hook_func(PROC *org_func, PROC new_func)
{
PROC org = *org_func;
DWORD old_protect;
if (VirtualProtect(org_func, sizeof(PROC), PAGE_EXECUTE_READWRITE, &old_protect))
{
*org_func = new_func;
VirtualProtect(org_func, sizeof(PROC), old_protect, &old_protect);
return org;
}
return 0;
}
static HRESULT WINAPI fake_did_SetCooperativeLevel(IDirectInputDeviceA *This, HWND hwnd, DWORD dwFlags)
{
return real_did_SetCooperativeLevel(This, hwnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE);
}
static HRESULT WINAPI fake_did_GetDeviceData(IDirectInputDeviceA *This, DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags)
{
HRESULT result = real_did_GetDeviceData(This, cbObjectData, rgdod, pdwInOut, dwFlags);
if (SUCCEEDED(result) && g_ddraw && !g_ddraw->locked)
{
*pdwInOut = 0;
}
return result;
}
static HRESULT WINAPI fake_di_CreateDevice(IDirectInputA *This, REFGUID rguid, LPDIRECTINPUTDEVICEA * lplpDIDevice, LPUNKNOWN pUnkOuter)
{
HRESULT result = real_di_CreateDevice(This, rguid, lplpDIDevice, pUnkOuter);
if (SUCCEEDED(result) && !real_did_SetCooperativeLevel)
{
real_did_SetCooperativeLevel =
(DIDSETCOOPERATIVELEVELPROC)hook_func(
(PROC *)&(*lplpDIDevice)->lpVtbl->SetCooperativeLevel, (PROC)fake_did_SetCooperativeLevel);
real_did_GetDeviceData =
(DIDGETDEVICEDATAPROC)hook_func(
(PROC*)&(*lplpDIDevice)->lpVtbl->GetDeviceData, (PROC)fake_did_GetDeviceData);
}
return result;
}
static HRESULT WINAPI fake_DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA* lplpDirectInput, LPUNKNOWN punkOuter)
{
dprintf("DirectInputCreateA\n");
real_DirectInputCreateA =
(DIRECTINPUTCREATEAPROC)GetProcAddress(GetModuleHandle("dinput.dll"), "DirectInputCreateA");
if (!real_DirectInputCreateA)
return DIERR_GENERIC;
HRESULT result = real_DirectInputCreateA(hinst, dwVersion, lplpDirectInput, punkOuter);
if (SUCCEEDED(result) && !real_di_CreateDevice)
{
real_di_CreateDevice =
(DICREATEDEVICEPROC)hook_func((PROC *)&(*lplpDirectInput)->lpVtbl->CreateDevice, (PROC)fake_di_CreateDevice);
}
return result;
}
void dinput_hook()
{
hook_patch_iat(GetModuleHandle(NULL), "dinput.dll", "DirectInputCreateA", (PROC)fake_DirectInputCreateA);
}
void dinput_unhook()
{
hook_patch_iat(
GetModuleHandle(NULL),
"dinput.dll",
"DirectInputCreateA",
(PROC)GetProcAddress(GetModuleHandle("dinput.dll"), "DirectInputCreateA"));
}

181
src/dllmain.c Normal file
View file

@ -0,0 +1,181 @@
#include <windows.h>
#include <ddraw.h>
#include <stdio.h>
#include "dllmain.h"
#include "dd.h"
#include "ddclipper.h"
#include "debug.h"
#include "config.h"
#include "directinput.h"
#include "IDirectDraw.h"
#include "hook.h"
// exports to force usage of discrete high performance graphics device
DWORD NvOptimusEnablement = 1;
DWORD AmdPowerXpressRequestHighPerformance = 1;
// export for cncnet cnc games
BOOL GameHandlesClose;
HMODULE g_ddraw_module;
BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
{
#if _DEBUG
dbg_init();
#endif
g_ddraw_module = hDll;
char buf[1024];
if (GetEnvironmentVariable("__COMPAT_LAYER", buf, sizeof(buf)))
{
char* s = strtok(buf, " ");
while (s)
{
if (_strcmpi(s, "WIN95") == 0 || strcmpi(s, "WIN98") == 0 || strcmpi(s, "NT4SP5") == 0)
{
char mes[128] = { 0 };
_snprintf(
mes,
sizeof(mes),
"Please disable the '%s' compatibility mode for all game executables and "
"then try to start the game again.",
s);
MessageBoxA(NULL, mes, "Compatibility modes detected - cnc-ddraw", MB_OK);
break;
}
s = strtok(NULL, " ");
}
}
BOOL set_dpi_aware = FALSE;
HMODULE hshcore = GetModuleHandle("shcore.dll");
if (hshcore)
{
typedef HRESULT(__stdcall* SETPROCESSDPIAWERENESSPROC)(PROCESS_DPI_AWARENESS value);
SETPROCESSDPIAWERENESSPROC set_awareness =
(SETPROCESSDPIAWERENESSPROC)GetProcAddress(hshcore, "SetProcessDpiAwareness");
if (set_awareness)
{
HRESULT result = set_awareness(PROCESS_PER_MONITOR_DPI_AWARE);
set_dpi_aware = result == S_OK || result == E_ACCESSDENIED;
}
}
if (!set_dpi_aware)
{
HMODULE hUser32 = GetModuleHandle("user32.dll");
if (hUser32)
{
typedef BOOL(__stdcall* SETPROCESSDPIAWAREPROC)();
SETPROCESSDPIAWAREPROC set_aware =
(SETPROCESSDPIAWAREPROC)GetProcAddress(hUser32, "SetProcessDPIAware");
if (set_aware)
set_aware();
}
}
timeBeginPeriod(1);
dinput_hook();
break;
}
case DLL_PROCESS_DETACH:
{
dprintf("cnc-ddraw DLL_PROCESS_DETACH\n");
cfg_save();
timeEndPeriod(1);
hook_exit();
dinput_unhook();
break;
}
}
return TRUE;
}
HRESULT WINAPI DirectDrawEnumerateA(LPDDENUMCALLBACK lpCallback, LPVOID lpContext)
{
dprintf("-> %s(lpCallback=%p, lpContext=%p)\n", __FUNCTION__, lpCallback, lpContext);
if (lpCallback)
lpCallback(NULL, "display", "(null)", lpContext);
dprintf("<- %s\n", __FUNCTION__);
return DD_OK;
}
HRESULT WINAPI DirectDrawCreateClipper(DWORD dwFlags, LPDIRECTDRAWCLIPPER FAR* lplpDDClipper, IUnknown FAR* pUnkOuter)
{
dprintf("-> %s(dwFlags=%08X, DDClipper=%p, unkOuter=%p)\n", __FUNCTION__, (int)dwFlags, lplpDDClipper, pUnkOuter);
HRESULT ret = dd_CreateClipper(dwFlags, lplpDDClipper, pUnkOuter);
dprintf("<- %s\n", __FUNCTION__);
return ret;
}
HRESULT WINAPI DirectDrawCreate(GUID FAR* lpGUID, LPDIRECTDRAW FAR* lplpDD, IUnknown FAR* pUnkOuter)
{
dprintf("-> %s(lpGUID=%p, lplpDD=%p, pUnkOuter=%p)\n", __FUNCTION__, lpGUID, lplpDD, pUnkOuter);
if (g_ddraw)
{
/* FIXME: check the calling module before passing the call! */
if (g_ddraw->DirectDrawCreate)
{
dprintf("<- %s\n", __FUNCTION__);
return g_ddraw->DirectDrawCreate(lpGUID, lplpDD, pUnkOuter);
}
dprintf("<- %s\n", __FUNCTION__);
return DDERR_DIRECTDRAWALREADYCREATED;
}
g_ddraw = (cnc_ddraw*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(cnc_ddraw));
IDirectDrawImpl* dst_ddraw = (IDirectDrawImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawImpl));
dst_ddraw->lpVtbl = &g_dd_vtbl1;
*lplpDD = (LPDIRECTDRAW)dst_ddraw;
IDirectDraw_AddRef(dst_ddraw);
if (!g_ddraw->real_dll)
g_ddraw->real_dll = LoadLibrary("system32\\ddraw.dll");
if (g_ddraw->real_dll && !g_ddraw->DirectDrawCreate)
{
g_ddraw->DirectDrawCreate =
(HRESULT(WINAPI*)(GUID FAR*, LPDIRECTDRAW FAR*, IUnknown FAR*))GetProcAddress(g_ddraw->real_dll, "DirectDrawCreate");
if (g_ddraw->DirectDrawCreate == DirectDrawCreate)
g_ddraw->DirectDrawCreate = NULL;
}
InitializeCriticalSection(&g_ddraw->cs);
g_ddraw->render.sem = CreateSemaphore(NULL, 0, 1, NULL);
g_ddraw->wine = GetProcAddress(GetModuleHandleA("ntdll.dll"), "wine_get_version") != 0;
cfg_load();
dprintf("<- %s\n", __FUNCTION__);
return DD_OK;
}

View file

@ -1,15 +1,18 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include "main.h"
#include "mouse.h"
#include "dd.h"
#include "winapi_hooks.h"
#include "hook.h"
#include "dllmain.h"
#ifdef _MSC_VER
#include "detours.h"
#endif
BOOL Hook_Active;
int HookingMethod = 1;
BOOL g_hook_active;
int g_hook_method = 1;
GETCURSORPOSPROC real_GetCursorPos = GetCursorPos;
CLIPCURSORPROC real_ClipCursor = ClipCursor;
SHOWCURSORPROC real_ShowCursor = ShowCursor;
@ -37,66 +40,66 @@ LOADLIBRARYEXAPROC real_LoadLibraryExA = LoadLibraryExA;
LOADLIBRARYEXWPROC real_LoadLibraryExW = LoadLibraryExW;
void Hook_PatchIAT(HMODULE hMod, char *moduleName, char *functionName, PROC newFunction)
void hook_patch_iat(HMODULE hmod, char *module_name, char *function_name, PROC new_function)
{
if (!hMod || hMod == INVALID_HANDLE_VALUE || !newFunction)
if (!hmod || hmod == INVALID_HANDLE_VALUE || !new_function)
return;
#ifdef _MSC_VER
__try
{
#endif
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hMod;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)hmod;
if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
return;
PIMAGE_NT_HEADERS pNTHeaders = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + (DWORD)pDosHeader->e_lfanew);
if (pNTHeaders->Signature != IMAGE_NT_SIGNATURE)
PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)((DWORD)dos_header + (DWORD)dos_header->e_lfanew);
if (nt_headers->Signature != IMAGE_NT_SIGNATURE)
return;
PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pDosHeader +
(DWORD)(pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));
PIMAGE_IMPORT_DESCRIPTOR import_desc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)dos_header +
(DWORD)(nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));
if (pImportDescriptor == (PIMAGE_IMPORT_DESCRIPTOR)pNTHeaders)
if (import_desc == (PIMAGE_IMPORT_DESCRIPTOR)nt_headers)
return;
while (pImportDescriptor->FirstThunk)
while (import_desc->FirstThunk)
{
char* impModuleName = (char*)((DWORD)pDosHeader + (DWORD)(pImportDescriptor->Name));
char* imp_module_name = (char*)((DWORD)dos_header + (DWORD)(import_desc->Name));
if (_stricmp(impModuleName, moduleName) == 0)
if (_stricmp(imp_module_name, module_name) == 0)
{
PIMAGE_THUNK_DATA pFirstThunk =
(PIMAGE_THUNK_DATA)((DWORD)pDosHeader + (DWORD)pImportDescriptor->FirstThunk);
PIMAGE_THUNK_DATA first_thunk =
(PIMAGE_THUNK_DATA)((DWORD)dos_header + (DWORD)import_desc->FirstThunk);
PIMAGE_THUNK_DATA pOrigFirstThunk =
(PIMAGE_THUNK_DATA)((DWORD)pDosHeader + (DWORD)pImportDescriptor->OriginalFirstThunk);
PIMAGE_THUNK_DATA original_first_thunk =
(PIMAGE_THUNK_DATA)((DWORD)dos_header + (DWORD)import_desc->OriginalFirstThunk);
while (pFirstThunk->u1.Function && pOrigFirstThunk->u1.AddressOfData)
while (first_thunk->u1.Function && original_first_thunk->u1.AddressOfData)
{
PIMAGE_IMPORT_BY_NAME pImport =
(PIMAGE_IMPORT_BY_NAME)((DWORD)pDosHeader + pOrigFirstThunk->u1.AddressOfData);
PIMAGE_IMPORT_BY_NAME import =
(PIMAGE_IMPORT_BY_NAME)((DWORD)dos_header + original_first_thunk->u1.AddressOfData);
if ((pOrigFirstThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) == 0 &&
_stricmp((const char*)pImport->Name, functionName) == 0)
if ((original_first_thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) == 0 &&
_stricmp((const char*)import->Name, function_name) == 0)
{
DWORD oldProtect;
DWORD old_protect;
if (VirtualProtect(&pFirstThunk->u1.Function, sizeof(DWORD), PAGE_READWRITE, &oldProtect))
if (VirtualProtect(&first_thunk->u1.Function, sizeof(DWORD), PAGE_READWRITE, &old_protect))
{
pFirstThunk->u1.Function = (DWORD)newFunction;
VirtualProtect(&pFirstThunk->u1.Function, sizeof(DWORD), oldProtect, &oldProtect);
first_thunk->u1.Function = (DWORD)new_function;
VirtualProtect(&first_thunk->u1.Function, sizeof(DWORD), old_protect, &old_protect);
}
break;
}
pFirstThunk++;
pOrigFirstThunk++;
first_thunk++;
original_first_thunk++;
}
}
pImportDescriptor++;
import_desc++;
}
#ifdef _MSC_VER
}
@ -106,42 +109,42 @@ void Hook_PatchIAT(HMODULE hMod, char *moduleName, char *functionName, PROC newF
#endif
}
void Hook_Create(char *moduleName, char *functionName, PROC newFunction, PROC *function)
void hook_create(char *module_name, char *function_name, PROC new_function, PROC *function)
{
#ifdef _MSC_VER
if (HookingMethod == 2)
if (g_hook_method == 2)
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach((PVOID *)function, (PVOID)newFunction);
DetourAttach((PVOID *)function, (PVOID)new_function);
DetourTransactionCommit();
}
if (HookingMethod == 3 || HookingMethod == 4)
if (g_hook_method == 3 || g_hook_method == 4)
{
WCHAR gameExePath[MAX_PATH] = { 0 };
WCHAR gameDir[MAX_PATH] = { 0 };
WCHAR game_exe_path[MAX_PATH] = { 0 };
WCHAR game_dir[MAX_PATH] = { 0 };
if (GetModuleFileNameW(NULL, gameExePath, MAX_PATH))
if (GetModuleFileNameW(NULL, game_exe_path, MAX_PATH))
{
_wsplitpath(gameExePath, NULL, gameDir, NULL, NULL);
_wsplitpath(game_exe_path, NULL, game_dir, NULL, NULL);
WCHAR modPath[MAX_PATH] = { 0 };
WCHAR modDir[MAX_PATH] = { 0 };
HMODULE hMod = NULL;
WCHAR mod_path[MAX_PATH] = { 0 };
WCHAR mod_dir[MAX_PATH] = { 0 };
HMODULE hmod = NULL;
while (hMod = DetourEnumerateModules(hMod))
while (hmod = DetourEnumerateModules(hmod))
{
if (hMod == DDrawModule)
if (hmod == g_ddraw_module)
continue;
if (GetModuleFileNameW(hMod, modPath, MAX_PATH))
if (GetModuleFileNameW(hmod, mod_path, MAX_PATH))
{
_wsplitpath(modPath, NULL, modDir, NULL, NULL);
_wsplitpath(mod_path, NULL, mod_dir, NULL, NULL);
if (_wcsnicmp(gameDir, modDir, wcslen(gameDir)) == 0)
if (_wcsnicmp(game_dir, mod_dir, wcslen(game_dir)) == 0)
{
Hook_PatchIAT(hMod, moduleName, functionName, newFunction);
hook_patch_iat(hmod, module_name, function_name, new_function);
}
}
}
@ -149,53 +152,53 @@ void Hook_Create(char *moduleName, char *functionName, PROC newFunction, PROC *f
}
#endif
if (HookingMethod == 1)
if (g_hook_method == 1)
{
Hook_PatchIAT(GetModuleHandle(NULL), moduleName, functionName, newFunction);
Hook_PatchIAT(GetModuleHandle("storm.dll"), moduleName, functionName, newFunction);
hook_patch_iat(GetModuleHandle(NULL), module_name, function_name, new_function);
hook_patch_iat(GetModuleHandle("storm.dll"), module_name, function_name, new_function);
}
}
void Hook_Revert(char *moduleName, char *functionName, PROC newFunction, PROC *function)
void hook_revert(char *module_name, char *function_name, PROC new_function, PROC *function)
{
#ifdef _MSC_VER
if (HookingMethod == 2)
if (g_hook_method == 2)
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach((PVOID *)function, (PVOID)newFunction);
DetourDetach((PVOID *)function, (PVOID)new_function);
DetourTransactionCommit();
}
if (HookingMethod == 3 || HookingMethod == 4)
if (g_hook_method == 3 || g_hook_method == 4)
{
WCHAR gameExePath[MAX_PATH] = { 0 };
WCHAR gameDir[MAX_PATH] = { 0 };
WCHAR game_exe_path[MAX_PATH] = { 0 };
WCHAR game_dir[MAX_PATH] = { 0 };
if (GetModuleFileNameW(NULL, gameExePath, MAX_PATH))
if (GetModuleFileNameW(NULL, game_exe_path, MAX_PATH))
{
_wsplitpath(gameExePath, NULL, gameDir, NULL, NULL);
_wsplitpath(game_exe_path, NULL, game_dir, NULL, NULL);
WCHAR modPath[MAX_PATH] = { 0 };
WCHAR modDir[MAX_PATH] = { 0 };
HMODULE hMod = NULL;
WCHAR mod_path[MAX_PATH] = { 0 };
WCHAR mod_dir[MAX_PATH] = { 0 };
HMODULE hmod = NULL;
while (hMod = DetourEnumerateModules(hMod))
while (hmod = DetourEnumerateModules(hmod))
{
if (hMod == DDrawModule)
if (hmod == g_ddraw_module)
continue;
if (GetModuleFileNameW(hMod, modPath, MAX_PATH))
if (GetModuleFileNameW(hmod, mod_path, MAX_PATH))
{
_wsplitpath(modPath, NULL, modDir, NULL, NULL);
_wsplitpath(mod_path, NULL, mod_dir, NULL, NULL);
if (_wcsnicmp(gameDir, modDir, wcslen(gameDir)) == 0)
if (_wcsnicmp(game_dir, mod_dir, wcslen(game_dir)) == 0)
{
Hook_PatchIAT(
hMod,
moduleName,
functionName,
GetProcAddress(GetModuleHandle(moduleName), functionName));
hook_patch_iat(
hmod,
module_name,
function_name,
GetProcAddress(GetModuleHandle(module_name), function_name));
}
}
}
@ -203,28 +206,28 @@ void Hook_Revert(char *moduleName, char *functionName, PROC newFunction, PROC *f
}
#endif
if (HookingMethod == 1)
if (g_hook_method == 1)
{
Hook_PatchIAT(
hook_patch_iat(
GetModuleHandle(NULL),
moduleName,
functionName,
GetProcAddress(GetModuleHandle(moduleName), functionName));
module_name,
function_name,
GetProcAddress(GetModuleHandle(module_name), function_name));
Hook_PatchIAT(
hook_patch_iat(
GetModuleHandle("storm.dll"),
moduleName,
functionName,
GetProcAddress(GetModuleHandle(moduleName), functionName));
module_name,
function_name,
GetProcAddress(GetModuleHandle(module_name), function_name));
}
}
void Hook_Init()
void hook_init()
{
if (!Hook_Active || HookingMethod == 3 || HookingMethod == 4)
if (!g_hook_active || g_hook_method == 3 || g_hook_method == 4)
{
#ifdef _MSC_VER
if (!Hook_Active && HookingMethod == 3)
if (!g_hook_active && g_hook_method == 3)
{
FARPROC proc = GetProcAddress(GetModuleHandle("kernelbase.dll"), "LoadLibraryExW");
@ -238,48 +241,48 @@ void Hook_Init()
}
#endif
Hook_Active = TRUE;
g_hook_active = TRUE;
Hook_Create("user32.dll", "GetCursorPos", (PROC)fake_GetCursorPos, (PROC *)&real_GetCursorPos);
Hook_Create("user32.dll", "ClipCursor", (PROC)fake_ClipCursor, (PROC *)&real_ClipCursor);
Hook_Create("user32.dll", "ShowCursor", (PROC)fake_ShowCursor, (PROC *)&real_ShowCursor);
Hook_Create("user32.dll", "SetCursor", (PROC)fake_SetCursor, (PROC *)&real_SetCursor);
Hook_Create("user32.dll", "GetWindowRect", (PROC)fake_GetWindowRect, (PROC *)&real_GetWindowRect);
Hook_Create("user32.dll", "GetClientRect", (PROC)fake_GetClientRect, (PROC *)&real_GetClientRect);
Hook_Create("user32.dll", "ClientToScreen", (PROC)fake_ClientToScreen, (PROC *)&real_ClientToScreen);
Hook_Create("user32.dll", "ScreenToClient", (PROC)fake_ScreenToClient, (PROC *)&real_ScreenToClient);
Hook_Create("user32.dll", "SetCursorPos", (PROC)fake_SetCursorPos, (PROC *)&real_SetCursorPos);
Hook_Create("user32.dll", "GetClipCursor", (PROC)fake_GetClipCursor, (PROC *)&real_GetClipCursor);
Hook_Create("user32.dll", "WindowFromPoint", (PROC)fake_WindowFromPoint, (PROC *)&real_WindowFromPoint);
Hook_Create("user32.dll", "GetCursorInfo", (PROC)fake_GetCursorInfo, (PROC *)&real_GetCursorInfo);
Hook_Create("user32.dll", "GetSystemMetrics", (PROC)fake_GetSystemMetrics, (PROC *)&real_GetSystemMetrics);
Hook_Create("user32.dll", "SetWindowPos", (PROC)fake_SetWindowPos, (PROC *)&real_SetWindowPos);
Hook_Create("user32.dll", "MoveWindow", (PROC)fake_MoveWindow, (PROC *)&real_MoveWindow);
Hook_Create("user32.dll", "SendMessageA", (PROC)fake_SendMessageA, (PROC *)&real_SendMessageA);
Hook_Create("user32.dll", "SetWindowLongA", (PROC)fake_SetWindowLongA, (PROC *)&real_SetWindowLongA);
Hook_Create("user32.dll", "EnableWindow", (PROC)fake_EnableWindow, (PROC *)&real_EnableWindow);
Hook_Create("user32.dll", "CreateWindowExA", (PROC)fake_CreateWindowExA, (PROC *)&real_CreateWindowExA);
Hook_Create("user32.dll", "DestroyWindow", (PROC)fake_DestroyWindow, (PROC *)&real_DestroyWindow);
Hook_Create("gdi32.dll", "GetDeviceCaps", (PROC)fake_GetDeviceCaps, (PROC*)&real_GetDeviceCaps);
hook_create("user32.dll", "GetCursorPos", (PROC)fake_GetCursorPos, (PROC *)&real_GetCursorPos);
hook_create("user32.dll", "ClipCursor", (PROC)fake_ClipCursor, (PROC *)&real_ClipCursor);
hook_create("user32.dll", "ShowCursor", (PROC)fake_ShowCursor, (PROC *)&real_ShowCursor);
hook_create("user32.dll", "SetCursor", (PROC)fake_SetCursor, (PROC *)&real_SetCursor);
hook_create("user32.dll", "GetWindowRect", (PROC)fake_GetWindowRect, (PROC *)&real_GetWindowRect);
hook_create("user32.dll", "GetClientRect", (PROC)fake_GetClientRect, (PROC *)&real_GetClientRect);
hook_create("user32.dll", "ClientToScreen", (PROC)fake_ClientToScreen, (PROC *)&real_ClientToScreen);
hook_create("user32.dll", "ScreenToClient", (PROC)fake_ScreenToClient, (PROC *)&real_ScreenToClient);
hook_create("user32.dll", "SetCursorPos", (PROC)fake_SetCursorPos, (PROC *)&real_SetCursorPos);
hook_create("user32.dll", "GetClipCursor", (PROC)fake_GetClipCursor, (PROC *)&real_GetClipCursor);
hook_create("user32.dll", "WindowFromPoint", (PROC)fake_WindowFromPoint, (PROC *)&real_WindowFromPoint);
hook_create("user32.dll", "GetCursorInfo", (PROC)fake_GetCursorInfo, (PROC *)&real_GetCursorInfo);
hook_create("user32.dll", "GetSystemMetrics", (PROC)fake_GetSystemMetrics, (PROC *)&real_GetSystemMetrics);
hook_create("user32.dll", "SetWindowPos", (PROC)fake_SetWindowPos, (PROC *)&real_SetWindowPos);
hook_create("user32.dll", "MoveWindow", (PROC)fake_MoveWindow, (PROC *)&real_MoveWindow);
hook_create("user32.dll", "SendMessageA", (PROC)fake_SendMessageA, (PROC *)&real_SendMessageA);
hook_create("user32.dll", "SetWindowLongA", (PROC)fake_SetWindowLongA, (PROC *)&real_SetWindowLongA);
hook_create("user32.dll", "EnableWindow", (PROC)fake_EnableWindow, (PROC *)&real_EnableWindow);
hook_create("user32.dll", "CreateWindowExA", (PROC)fake_CreateWindowExA, (PROC *)&real_CreateWindowExA);
hook_create("user32.dll", "DestroyWindow", (PROC)fake_DestroyWindow, (PROC *)&real_DestroyWindow);
hook_create("gdi32.dll", "GetDeviceCaps", (PROC)fake_GetDeviceCaps, (PROC*)&real_GetDeviceCaps);
if (HookingMethod == 4)
if (g_hook_method == 4)
{
Hook_Create("kernel32.dll", "LoadLibraryA", (PROC)fake_LoadLibraryA, (PROC*)&real_LoadLibraryA);
Hook_Create("kernel32.dll", "LoadLibraryW", (PROC)fake_LoadLibraryW, (PROC*)&real_LoadLibraryW);
Hook_Create("kernel32.dll", "LoadLibraryExA", (PROC)fake_LoadLibraryExA, (PROC*)&real_LoadLibraryExA);
Hook_Create("kernel32.dll", "LoadLibraryExW", (PROC)fake_LoadLibraryExW, (PROC*)&real_LoadLibraryExW);
hook_create("kernel32.dll", "LoadLibraryA", (PROC)fake_LoadLibraryA, (PROC*)&real_LoadLibraryA);
hook_create("kernel32.dll", "LoadLibraryW", (PROC)fake_LoadLibraryW, (PROC*)&real_LoadLibraryW);
hook_create("kernel32.dll", "LoadLibraryExA", (PROC)fake_LoadLibraryExA, (PROC*)&real_LoadLibraryExA);
hook_create("kernel32.dll", "LoadLibraryExW", (PROC)fake_LoadLibraryExW, (PROC*)&real_LoadLibraryExW);
}
}
}
void Hook_Exit()
void hook_exit()
{
if (Hook_Active)
if (g_hook_active)
{
Hook_Active = FALSE;
g_hook_active = FALSE;
#ifdef _MSC_VER
if (HookingMethod == 3)
if (g_hook_method == 3)
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
@ -288,34 +291,34 @@ void Hook_Exit()
}
#endif
Hook_Revert("user32.dll", "GetCursorPos", (PROC)fake_GetCursorPos, (PROC *)&real_GetCursorPos);
Hook_Revert("user32.dll", "ClipCursor", (PROC)fake_ClipCursor, (PROC *)&real_ClipCursor);
Hook_Revert("user32.dll", "ShowCursor", (PROC)fake_ShowCursor, (PROC *)&real_ShowCursor);
Hook_Revert("user32.dll", "SetCursor", (PROC)fake_SetCursor, (PROC *)&real_SetCursor);
Hook_Revert("user32.dll", "GetWindowRect", (PROC)fake_GetWindowRect, (PROC *)&real_GetWindowRect);
Hook_Revert("user32.dll", "GetClientRect", (PROC)fake_GetClientRect, (PROC *)&real_GetClientRect);
Hook_Revert("user32.dll", "ClientToScreen", (PROC)fake_ClientToScreen, (PROC *)&real_ClientToScreen);
Hook_Revert("user32.dll", "ScreenToClient", (PROC)fake_ScreenToClient, (PROC *)&real_ScreenToClient);
Hook_Revert("user32.dll", "SetCursorPos", (PROC)fake_SetCursorPos, (PROC *)&real_SetCursorPos);
Hook_Revert("user32.dll", "GetClipCursor", (PROC)fake_GetClipCursor, (PROC *)&real_GetClipCursor);
Hook_Revert("user32.dll", "WindowFromPoint", (PROC)fake_WindowFromPoint, (PROC *)&real_WindowFromPoint);
Hook_Revert("user32.dll", "GetCursorInfo", (PROC)fake_GetCursorInfo, (PROC *)&real_GetCursorInfo);
Hook_Revert("user32.dll", "GetSystemMetrics", (PROC)fake_GetSystemMetrics, (PROC *)&real_GetSystemMetrics);
Hook_Revert("user32.dll", "SetWindowPos", (PROC)fake_SetWindowPos, (PROC *)&real_SetWindowPos);
Hook_Revert("user32.dll", "MoveWindow", (PROC)fake_MoveWindow, (PROC *)&real_MoveWindow);
Hook_Revert("user32.dll", "SendMessageA", (PROC)fake_SendMessageA, (PROC *)&real_SendMessageA);
Hook_Revert("user32.dll", "SetWindowLongA", (PROC)fake_SetWindowLongA, (PROC *)&real_SetWindowLongA);
Hook_Revert("user32.dll", "EnableWindow", (PROC)fake_EnableWindow, (PROC *)&real_EnableWindow);
Hook_Revert("user32.dll", "CreateWindowExA", (PROC)fake_CreateWindowExA, (PROC *)&real_CreateWindowExA);
Hook_Revert("user32.dll", "DestroyWindow", (PROC)fake_DestroyWindow, (PROC *)&real_DestroyWindow);
Hook_Revert("gdi32.dll", "GetDeviceCaps", (PROC)fake_GetDeviceCaps, (PROC*)&real_GetDeviceCaps);
hook_revert("user32.dll", "GetCursorPos", (PROC)fake_GetCursorPos, (PROC *)&real_GetCursorPos);
hook_revert("user32.dll", "ClipCursor", (PROC)fake_ClipCursor, (PROC *)&real_ClipCursor);
hook_revert("user32.dll", "ShowCursor", (PROC)fake_ShowCursor, (PROC *)&real_ShowCursor);
hook_revert("user32.dll", "SetCursor", (PROC)fake_SetCursor, (PROC *)&real_SetCursor);
hook_revert("user32.dll", "GetWindowRect", (PROC)fake_GetWindowRect, (PROC *)&real_GetWindowRect);
hook_revert("user32.dll", "GetClientRect", (PROC)fake_GetClientRect, (PROC *)&real_GetClientRect);
hook_revert("user32.dll", "ClientToScreen", (PROC)fake_ClientToScreen, (PROC *)&real_ClientToScreen);
hook_revert("user32.dll", "ScreenToClient", (PROC)fake_ScreenToClient, (PROC *)&real_ScreenToClient);
hook_revert("user32.dll", "SetCursorPos", (PROC)fake_SetCursorPos, (PROC *)&real_SetCursorPos);
hook_revert("user32.dll", "GetClipCursor", (PROC)fake_GetClipCursor, (PROC *)&real_GetClipCursor);
hook_revert("user32.dll", "WindowFromPoint", (PROC)fake_WindowFromPoint, (PROC *)&real_WindowFromPoint);
hook_revert("user32.dll", "GetCursorInfo", (PROC)fake_GetCursorInfo, (PROC *)&real_GetCursorInfo);
hook_revert("user32.dll", "GetSystemMetrics", (PROC)fake_GetSystemMetrics, (PROC *)&real_GetSystemMetrics);
hook_revert("user32.dll", "SetWindowPos", (PROC)fake_SetWindowPos, (PROC *)&real_SetWindowPos);
hook_revert("user32.dll", "MoveWindow", (PROC)fake_MoveWindow, (PROC *)&real_MoveWindow);
hook_revert("user32.dll", "SendMessageA", (PROC)fake_SendMessageA, (PROC *)&real_SendMessageA);
hook_revert("user32.dll", "SetWindowLongA", (PROC)fake_SetWindowLongA, (PROC *)&real_SetWindowLongA);
hook_revert("user32.dll", "EnableWindow", (PROC)fake_EnableWindow, (PROC *)&real_EnableWindow);
hook_revert("user32.dll", "CreateWindowExA", (PROC)fake_CreateWindowExA, (PROC *)&real_CreateWindowExA);
hook_revert("user32.dll", "DestroyWindow", (PROC)fake_DestroyWindow, (PROC *)&real_DestroyWindow);
hook_revert("gdi32.dll", "GetDeviceCaps", (PROC)fake_GetDeviceCaps, (PROC*)&real_GetDeviceCaps);
if (HookingMethod == 4)
if (g_hook_method == 4)
{
Hook_Revert("kernel32.dll", "LoadLibraryA", (PROC)fake_LoadLibraryA, (PROC*)&real_LoadLibraryA);
Hook_Revert("kernel32.dll", "LoadLibraryW", (PROC)fake_LoadLibraryW, (PROC*)&real_LoadLibraryW);
Hook_Revert("kernel32.dll", "LoadLibraryExA", (PROC)fake_LoadLibraryExA, (PROC*)&real_LoadLibraryExA);
Hook_Revert("kernel32.dll", "LoadLibraryExW", (PROC)fake_LoadLibraryExW, (PROC*)&real_LoadLibraryExW);
hook_revert("kernel32.dll", "LoadLibraryA", (PROC)fake_LoadLibraryA, (PROC*)&real_LoadLibraryA);
hook_revert("kernel32.dll", "LoadLibraryW", (PROC)fake_LoadLibraryW, (PROC*)&real_LoadLibraryW);
hook_revert("kernel32.dll", "LoadLibraryExA", (PROC)fake_LoadLibraryExA, (PROC*)&real_LoadLibraryExA);
hook_revert("kernel32.dll", "LoadLibraryExW", (PROC)fake_LoadLibraryExW, (PROC*)&real_LoadLibraryExW);
}
}
}

2035
src/main.c

File diff suppressed because it is too large Load diff

View file

@ -1,213 +1,78 @@
/*
* Copyright (c) 2010 Toni Spets <toni.spets@iki.fi>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include "main.h"
#include "surface.h"
#include "dd.h"
#include "hook.h"
#include "render_d3d9.h"
int yAdjust = 0;
BOOL WINAPI fake_GetCursorPos(LPPOINT lpPoint)
{
POINT pt, realpt;
if (!real_GetCursorPos(&pt) || !ddraw)
return FALSE;
realpt.x = pt.x;
realpt.y = pt.y;
if(ddraw->locked && (!ddraw->windowed || real_ScreenToClient(ddraw->hWnd, &pt)))
{
//fallback solution for possible ClipCursor failure
int diffx = 0, diffy = 0;
int maxWidth = ddraw->adjmouse ? ddraw->render.viewport.width : ddraw->width;
int maxHeight = ddraw->adjmouse ? ddraw->render.viewport.height : ddraw->height;
if (pt.x < 0)
{
diffx = pt.x;
pt.x = 0;
}
if (pt.y < 0)
{
diffy = pt.y;
pt.y = 0;
}
if (pt.x > maxWidth)
{
diffx = pt.x - maxWidth;
pt.x = maxWidth;
}
if (pt.y > maxHeight)
{
diffy = pt.y - maxHeight;
pt.y = maxHeight;
}
if (diffx || diffy)
real_SetCursorPos(realpt.x - diffx, realpt.y - diffy);
if(ddraw->adjmouse)
{
ddraw->cursor.x = pt.x * ddraw->render.unScaleW;
ddraw->cursor.y = pt.y * ddraw->render.unScaleH;
}
else
{
ddraw->cursor.x = pt.x;
ddraw->cursor.y = pt.y;
}
if (ddraw->vhack && InterlockedExchangeAdd(&ddraw->incutscene, 0))
{
diffx = 0;
diffy = 0;
if (ddraw->cursor.x > CUTSCENE_WIDTH)
{
diffx = ddraw->cursor.x - CUTSCENE_WIDTH;
ddraw->cursor.x = CUTSCENE_WIDTH;
}
if (ddraw->cursor.y > CUTSCENE_HEIGHT)
{
diffy = ddraw->cursor.y - CUTSCENE_HEIGHT;
ddraw->cursor.y = CUTSCENE_HEIGHT;
}
if (diffx || diffy)
real_SetCursorPos(realpt.x - diffx, realpt.y - diffy);
}
}
if (lpPoint)
{
lpPoint->x = (int)ddraw->cursor.x;
lpPoint->y = (int)ddraw->cursor.y;
}
return TRUE;
}
BOOL WINAPI fake_ClipCursor(const RECT *lpRect)
{
if(lpRect)
{
/* hack for 640x480 mode */
if (lpRect->bottom == 400 && ddraw->height == 480)
yAdjust = 40;
}
return TRUE;
}
int WINAPI fake_ShowCursor(BOOL bShow)
{
static int count;
if (ddraw && !ddraw->handlemouse)
return real_ShowCursor(bShow);
return bShow ? ++count : --count;
}
HCURSOR WINAPI fake_SetCursor(HCURSOR hCursor)
{
if (ddraw && !ddraw->handlemouse)
return real_SetCursor(hCursor);
return NULL;
}
void mouse_lock()
{
RECT rc;
if (ddraw->bnetActive)
if (g_ddraw->bnet_active)
return;
if (ddraw->devmode)
if (g_ddraw->devmode)
{
if (ddraw->handlemouse)
if (g_ddraw->handlemouse)
while(real_ShowCursor(FALSE) > 0);
return;
}
if (Hook_Active && !ddraw->locked)
if (g_hook_active && !g_ddraw->locked)
{
// Get the window client area.
real_GetClientRect(ddraw->hWnd, &rc);
real_GetClientRect(g_ddraw->hwnd, &rc);
if(ddraw->adjmouse)
if(g_ddraw->adjmouse)
{
rc.right = ddraw->render.viewport.width;
rc.bottom = ddraw->render.viewport.height;
rc.right = g_ddraw->render.viewport.width;
rc.bottom = g_ddraw->render.viewport.height;
}
else
{
rc.right = ddraw->width;
rc.bottom = ddraw->height;
rc.right = g_ddraw->width;
rc.bottom = g_ddraw->height;
}
// Convert the client area to screen coordinates.
POINT pt = { rc.left, rc.top };
POINT pt2 = { rc.right, rc.bottom };
real_ClientToScreen(ddraw->hWnd, &pt);
real_ClientToScreen(ddraw->hWnd, &pt2);
real_ClientToScreen(g_ddraw->hwnd, &pt);
real_ClientToScreen(g_ddraw->hwnd, &pt2);
SetRect(&rc, pt.x, pt.y, pt2.x, pt2.y);
rc.bottom -= (yAdjust * 2) * ddraw->render.scaleH;
rc.bottom -= (g_ddraw->mouse_y_adjust * 2) * g_ddraw->render.scale_h;
if(ddraw->adjmouse)
if(g_ddraw->adjmouse)
{
real_SetCursorPos(
rc.left + (ddraw->cursor.x * ddraw->render.scaleW),
rc.top + ((ddraw->cursor.y - yAdjust) * ddraw->render.scaleH));
rc.left + (g_ddraw->cursor.x * g_ddraw->render.scale_w),
rc.top + ((g_ddraw->cursor.y - g_ddraw->mouse_y_adjust) * g_ddraw->render.scale_h));
}
else
{
real_SetCursorPos(rc.left + ddraw->cursor.x, rc.top + ddraw->cursor.y - yAdjust);
real_SetCursorPos(rc.left + g_ddraw->cursor.x, rc.top + g_ddraw->cursor.y - g_ddraw->mouse_y_adjust);
}
if (ddraw->handlemouse)
if (g_ddraw->handlemouse)
{
SetCapture(ddraw->hWnd);
SetCapture(g_ddraw->hwnd);
real_ClipCursor(&rc);
while (real_ShowCursor(FALSE) > 0);
}
else
{
if (ddraw->hidecursor)
if (g_ddraw->hidecursor)
{
ddraw->hidecursor = FALSE;
g_ddraw->hidecursor = FALSE;
real_ShowCursor(FALSE);
}
real_ClipCursor(&rc);
}
ddraw->locked = TRUE;
g_ddraw->locked = TRUE;
}
}
@ -215,34 +80,34 @@ void mouse_unlock()
{
RECT rc;
if (ddraw->devmode)
if (g_ddraw->devmode)
{
if (ddraw->handlemouse)
if (g_ddraw->handlemouse)
while(real_ShowCursor(TRUE) < 0);
return;
}
if(!Hook_Active)
if(!g_hook_active)
{
return;
}
if(ddraw->locked)
if(g_ddraw->locked)
{
ddraw->locked = FALSE;
g_ddraw->locked = FALSE;
// Get the window client area.
real_GetClientRect(ddraw->hWnd, &rc);
real_GetClientRect(g_ddraw->hwnd, &rc);
// Convert the client area to screen coordinates.
POINT pt = { rc.left, rc.top };
POINT pt2 = { rc.right, rc.bottom };
real_ClientToScreen(ddraw->hWnd, &pt);
real_ClientToScreen(ddraw->hWnd, &pt2);
real_ClientToScreen(g_ddraw->hwnd, &pt);
real_ClientToScreen(g_ddraw->hwnd, &pt2);
SetRect(&rc, pt.x, pt.y, pt2.x, pt2.y);
if (ddraw->handlemouse)
if (g_ddraw->handlemouse)
{
while (real_ShowCursor(TRUE) < 0);
real_SetCursor(LoadCursor(NULL, IDC_ARROW));
@ -252,7 +117,7 @@ void mouse_unlock()
CURSORINFO ci = { .cbSize = sizeof(CURSORINFO) };
if (real_GetCursorInfo(&ci) && ci.flags == 0)
{
ddraw->hidecursor = TRUE;
g_ddraw->hidecursor = TRUE;
while (real_ShowCursor(TRUE) < 0);
}
}
@ -261,308 +126,7 @@ void mouse_unlock()
ReleaseCapture();
real_SetCursorPos(
rc.left + ddraw->render.viewport.x + (ddraw->cursor.x * ddraw->render.scaleW),
rc.top + ddraw->render.viewport.y + ((ddraw->cursor.y + yAdjust) * ddraw->render.scaleH));
rc.left + g_ddraw->render.viewport.x + (g_ddraw->cursor.x * g_ddraw->render.scale_w),
rc.top + g_ddraw->render.viewport.y + ((g_ddraw->cursor.y + g_ddraw->mouse_y_adjust) * g_ddraw->render.scale_h));
}
}
BOOL WINAPI fake_GetWindowRect(HWND hWnd, LPRECT lpRect)
{
if (lpRect && ddraw)
{
if (ddraw->hWnd == hWnd)
{
lpRect->bottom = ddraw->height;
lpRect->left = 0;
lpRect->right = ddraw->width;
lpRect->top = 0;
return TRUE;
}
else
{
if (real_GetWindowRect(hWnd, lpRect))
{
MapWindowPoints(HWND_DESKTOP, ddraw->hWnd, (LPPOINT)lpRect, 2);
return TRUE;
}
return FALSE;
}
}
return real_GetWindowRect(hWnd, lpRect);
}
BOOL WINAPI fake_GetClientRect(HWND hWnd, LPRECT lpRect)
{
if (lpRect && ddraw && ddraw->hWnd == hWnd)
{
lpRect->bottom = ddraw->height;
lpRect->left = 0;
lpRect->right = ddraw->width;
lpRect->top = 0;
return TRUE;
}
return real_GetClientRect(hWnd, lpRect);
}
BOOL WINAPI fake_ClientToScreen(HWND hWnd, LPPOINT lpPoint)
{
if (ddraw && ddraw->hWnd != hWnd)
return real_ClientToScreen(hWnd, lpPoint) && real_ScreenToClient(ddraw->hWnd, lpPoint);
return TRUE;
}
BOOL WINAPI fake_ScreenToClient(HWND hWnd, LPPOINT lpPoint)
{
if (ddraw && ddraw->hWnd != hWnd)
return real_ClientToScreen(ddraw->hWnd, lpPoint) && real_ScreenToClient(hWnd, lpPoint);
return TRUE;
}
BOOL WINAPI fake_SetCursorPos(int X, int Y)
{
POINT pt = { X, Y };
return ddraw && real_ClientToScreen(ddraw->hWnd, &pt) && real_SetCursorPos(pt.x, pt.y);
}
HWND WINAPI fake_WindowFromPoint(POINT Point)
{
POINT pt = { Point.x, Point.y };
return ddraw && real_ClientToScreen(ddraw->hWnd, &pt) ? real_WindowFromPoint(pt) : NULL;
}
BOOL WINAPI fake_GetClipCursor(LPRECT lpRect)
{
if (lpRect && ddraw)
{
lpRect->bottom = ddraw->height;
lpRect->left = 0;
lpRect->right = ddraw->width;
lpRect->top = 0;
return TRUE;
}
return FALSE;
}
BOOL WINAPI fake_GetCursorInfo(PCURSORINFO pci)
{
return pci && ddraw && real_GetCursorInfo(pci) && real_ScreenToClient(ddraw->hWnd, &pci->ptScreenPos);
}
int WINAPI fake_GetSystemMetrics(int nIndex)
{
if (ddraw)
{
if (nIndex == SM_CXSCREEN)
return ddraw->width;
if (nIndex == SM_CYSCREEN)
return ddraw->height;
}
return real_GetSystemMetrics(nIndex);
}
BOOL WINAPI fake_SetWindowPos(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags)
{
UINT reqFlags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER;
if (ddraw && ddraw->hWnd == hWnd && (uFlags & reqFlags) != reqFlags)
return TRUE;
return real_SetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
}
BOOL WINAPI fake_MoveWindow(HWND hWnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint)
{
if (ddraw && ddraw->hWnd == hWnd)
return TRUE;
return real_MoveWindow(hWnd, X, Y, nWidth, nHeight, bRepaint);
}
LRESULT WINAPI fake_SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
LRESULT result = real_SendMessageA(hWnd, Msg, wParam, lParam);
if (result && ddraw && Msg == CB_GETDROPPEDCONTROLRECT)
{
RECT *rc = (RECT *)lParam;
if (rc)
MapWindowPoints(HWND_DESKTOP, ddraw->hWnd, (LPPOINT)rc, 2);
}
return result;
}
LONG WINAPI fake_SetWindowLongA(HWND hWnd, int nIndex, LONG dwNewLong)
{
if (ddraw && ddraw->hWnd == hWnd && nIndex == GWL_STYLE)
return 0;
return real_SetWindowLongA(hWnd, nIndex, dwNewLong);
}
BOOL WINAPI fake_EnableWindow(HWND hWnd, BOOL bEnable)
{
if (ddraw && ddraw->hWnd == hWnd)
{
return FALSE;
}
return real_EnableWindow(hWnd, bEnable);
}
int WINAPI fake_GetDeviceCaps(HDC hdc, int index)
{
if (ddraw && ddraw->bpp && index == BITSPIXEL)
{
return ddraw->bpp;
}
return real_GetDeviceCaps(hdc, index);
}
HMODULE WINAPI fake_LoadLibraryA(LPCSTR lpLibFileName)
{
HMODULE hMod = real_LoadLibraryA(lpLibFileName);
Hook_Init();
return hMod;
}
HMODULE WINAPI fake_LoadLibraryW(LPCWSTR lpLibFileName)
{
HMODULE hMod = real_LoadLibraryW(lpLibFileName);
Hook_Init();
return hMod;
}
HMODULE WINAPI fake_LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
{
HMODULE hMod = real_LoadLibraryExA(lpLibFileName, hFile, dwFlags);
Hook_Init();
return hMod;
}
HMODULE WINAPI fake_LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
{
HMODULE hMod = real_LoadLibraryExW(lpLibFileName, hFile, dwFlags);
Hook_Init();
return hMod;
}
BOOL WINAPI fake_DestroyWindow(HWND hWnd)
{
BOOL result = real_DestroyWindow(hWnd);
if (ddraw && ddraw->hWnd != hWnd && ddraw->bnetActive)
{
RedrawWindow(NULL, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN);
if (!FindWindowEx(HWND_DESKTOP, NULL, "SDlgDialog", NULL))
{
ddraw->bnetActive = FALSE;
SetFocus(ddraw->hWnd);
mouse_lock();
if (ddraw->windowed)
{
ddraw->bnetPos.x = ddraw->bnetPos.y = 0;
real_ClientToScreen(ddraw->hWnd, &ddraw->bnetPos);
if (!ddraw->bnetWasUpscaled)
{
int width = ddraw->bnetWinRect.right - ddraw->bnetWinRect.left;
int height = ddraw->bnetWinRect.bottom - ddraw->bnetWinRect.top;
UINT flags = width != ddraw->width || height != ddraw->height ? 0 : SWP_NOMOVE;
SetWindowRect(ddraw->bnetWinRect.left, ddraw->bnetWinRect.top, width, height, flags);
}
ddraw->fullscreen = ddraw->bnetWasUpscaled;
SetTimer(ddraw->hWnd, IDT_TIMER_LEAVE_BNET, 1000, (TIMERPROC)NULL);
ddraw->resizable = TRUE;
}
}
}
return result;
}
HWND WINAPI fake_CreateWindowExA(
DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y,
int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
{
if (lpClassName && _strcmpi(lpClassName, "SDlgDialog") == 0 && ddraw)
{
if (!ddraw->bnetActive)
{
ddraw->bnetWasUpscaled = ddraw->fullscreen;
ddraw->fullscreen = FALSE;
if (!ddraw->windowed && !ddraw->bnetWasFullscreen)
{
int ws = WindowState;
ToggleFullscreen();
WindowState = ws;
ddraw->bnetWasFullscreen = TRUE;
}
real_GetClientRect(ddraw->hWnd, &ddraw->bnetWinRect);
MapWindowPoints(ddraw->hWnd, HWND_DESKTOP, (LPPOINT)&ddraw->bnetWinRect, 2);
int width = ddraw->bnetWinRect.right - ddraw->bnetWinRect.left;
int height = ddraw->bnetWinRect.bottom - ddraw->bnetWinRect.top;
int x = ddraw->bnetPos.x || ddraw->bnetPos.y ? ddraw->bnetPos.x : -32000;
int y = ddraw->bnetPos.x || ddraw->bnetPos.y ? ddraw->bnetPos.y : -32000;
UINT flags = width != ddraw->width || height != ddraw->height ? 0 : SWP_NOMOVE;
SetWindowRect(x, y, ddraw->width, ddraw->height, flags);
ddraw->resizable = FALSE;
ddraw->bnetActive = TRUE;
mouse_unlock();
}
POINT pt = { 0, 0 };
real_ClientToScreen(ddraw->hWnd, &pt);
X += pt.x;
Y += pt.y;
dwStyle |= WS_CLIPCHILDREN;
}
return real_CreateWindowExA(
dwExStyle,
lpClassName,
lpWindowName,
dwStyle,
X,
Y,
nWidth,
nHeight,
hWndParent,
hMenu,
hInstance,
lpParam);
}

View file

@ -1,6 +1,6 @@
#include <windows.h>
#include <stdio.h>
#include "opengl.h"
#include "opengl_utils.h"
PFNWGLCREATECONTEXTPROC xwglCreateContext;
PFNWGLDELETECONTEXTPROC xwglDeleteContext;
@ -21,13 +21,10 @@ PFNGLGETTEXIMAGEPROC glGetTexImage;
PFNGLPIXELSTOREIPROC glPixelStorei;
PFNGLENABLEPROC glEnable;
PFNGLCLEARPROC glClear;
PFNGLBEGINPROC glBegin;
PFNGLENDPROC glEnd;
PFNGLTEXCOORD2FPROC glTexCoord2f;
PFNGLVERTEX2FPROC glVertex2f;
// Program
PFNGLCREATEPROGRAMPROC glCreateProgram;
PFNGLDELETEPROGRAMPROC glDeleteProgram;
PFNGLUSEPROGRAMPROC glUseProgram;
@ -59,13 +56,11 @@ PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
PFNGLGETACTIVEUNIFORMPROC glGetActiveUniform;
PFNGLCREATESHADERPROC glCreateShader;
PFNGLDELETESHADERPROC glDeleteShader;
PFNGLSHADERSOURCEPROC glShaderSource;
PFNGLCOMPILESHADERPROC glCompileShader;
PFNGLGETSHADERIVPROC glGetShaderiv;
PFNGLGENBUFFERSPROC glGenBuffers;
PFNGLBINDBUFFERPROC glBindBuffer;
PFNGLBUFFERDATAPROC glBufferData;
@ -77,59 +72,53 @@ PFNGLDELETEBUFFERSPROC glDeleteBuffers;
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
PFNGLACTIVETEXTUREPROC glActiveTexture;
PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
PFNGLDRAWBUFFERSPROC glDrawBuffers;
PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;
PFNGLTEXBUFFERPROC glTexBuffer;
HMODULE OpenGL_hModule;
HMODULE g_oglu_hmodule;
BOOL g_oglu_got_version2;
BOOL g_oglu_got_version3;
char g_oglu_version[128];
BOOL OpenGL_GotVersion2;
BOOL OpenGL_GotVersion3;
char OpenGL_Version[128];
BOOL OpenGL_LoadDll()
BOOL oglu_load_dll()
{
if (!OpenGL_hModule)
OpenGL_hModule = LoadLibrary("opengl32.dll");
if (!g_oglu_hmodule)
g_oglu_hmodule = LoadLibrary("opengl32.dll");
if (OpenGL_hModule)
if (g_oglu_hmodule)
{
xwglCreateContext = (PFNWGLCREATECONTEXTPROC)GetProcAddress(OpenGL_hModule, "wglCreateContext");
xwglDeleteContext = (PFNWGLDELETECONTEXTPROC)GetProcAddress(OpenGL_hModule, "wglDeleteContext");
xwglGetProcAddress = (PFNWGLGETPROCADDRESSPROC)GetProcAddress(OpenGL_hModule, "wglGetProcAddress");
xwglMakeCurrent = (PFNWGLMAKECURRENTPROC)GetProcAddress(OpenGL_hModule, "wglMakeCurrent");
xwglCreateContext = (PFNWGLCREATECONTEXTPROC)GetProcAddress(g_oglu_hmodule, "wglCreateContext");
xwglDeleteContext = (PFNWGLDELETECONTEXTPROC)GetProcAddress(g_oglu_hmodule, "wglDeleteContext");
xwglGetProcAddress = (PFNWGLGETPROCADDRESSPROC)GetProcAddress(g_oglu_hmodule, "wglGetProcAddress");
xwglMakeCurrent = (PFNWGLMAKECURRENTPROC)GetProcAddress(g_oglu_hmodule, "wglMakeCurrent");
glViewport = (PFNGLVIEWPORTPROC)GetProcAddress(OpenGL_hModule, "glViewport");
glBindTexture = (PFNGLBINDTEXTUREPROC)GetProcAddress(OpenGL_hModule, "glBindTexture");
glGenTextures = (PFNGLGENTEXTURESPROC)GetProcAddress(OpenGL_hModule, "glGenTextures");
glTexParameteri = (PFNGLTEXPARAMETERIPROC)GetProcAddress(OpenGL_hModule, "glTexParameteri");
glDeleteTextures = (PFNGLDELETETEXTURESPROC)GetProcAddress(OpenGL_hModule, "glDeleteTextures");
glTexImage2D = (PFNGLTEXIMAGE2DPROC)GetProcAddress(OpenGL_hModule, "glTexImage2D");
glDrawElements = (PFNGLDRAWELEMENTSPROC)GetProcAddress(OpenGL_hModule, "glDrawElements");
glTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC)GetProcAddress(OpenGL_hModule, "glTexSubImage2D");
glGetError = (PFNGLGETERRORPROC)GetProcAddress(OpenGL_hModule, "glGetError");
glGetString = (PFNGLGETSTRINGPROC)GetProcAddress(OpenGL_hModule, "glGetString");
glGetTexImage = (PFNGLGETTEXIMAGEPROC)GetProcAddress(OpenGL_hModule, "glGetTexImage");
glPixelStorei = (PFNGLPIXELSTOREIPROC)GetProcAddress(OpenGL_hModule, "glPixelStorei");
glEnable = (PFNGLENABLEPROC)GetProcAddress(OpenGL_hModule, "glEnable");
glClear = (PFNGLCLEARPROC)GetProcAddress(OpenGL_hModule, "glClear");
glViewport = (PFNGLVIEWPORTPROC)GetProcAddress(g_oglu_hmodule, "glViewport");
glBindTexture = (PFNGLBINDTEXTUREPROC)GetProcAddress(g_oglu_hmodule, "glBindTexture");
glGenTextures = (PFNGLGENTEXTURESPROC)GetProcAddress(g_oglu_hmodule, "glGenTextures");
glTexParameteri = (PFNGLTEXPARAMETERIPROC)GetProcAddress(g_oglu_hmodule, "glTexParameteri");
glDeleteTextures = (PFNGLDELETETEXTURESPROC)GetProcAddress(g_oglu_hmodule, "glDeleteTextures");
glTexImage2D = (PFNGLTEXIMAGE2DPROC)GetProcAddress(g_oglu_hmodule, "glTexImage2D");
glDrawElements = (PFNGLDRAWELEMENTSPROC)GetProcAddress(g_oglu_hmodule, "glDrawElements");
glTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC)GetProcAddress(g_oglu_hmodule, "glTexSubImage2D");
glGetError = (PFNGLGETERRORPROC)GetProcAddress(g_oglu_hmodule, "glGetError");
glGetString = (PFNGLGETSTRINGPROC)GetProcAddress(g_oglu_hmodule, "glGetString");
glGetTexImage = (PFNGLGETTEXIMAGEPROC)GetProcAddress(g_oglu_hmodule, "glGetTexImage");
glPixelStorei = (PFNGLPIXELSTOREIPROC)GetProcAddress(g_oglu_hmodule, "glPixelStorei");
glEnable = (PFNGLENABLEPROC)GetProcAddress(g_oglu_hmodule, "glEnable");
glClear = (PFNGLCLEARPROC)GetProcAddress(g_oglu_hmodule, "glClear");
glBegin = (PFNGLBEGINPROC)GetProcAddress(OpenGL_hModule, "glBegin");
glEnd = (PFNGLENDPROC)GetProcAddress(OpenGL_hModule, "glEnd");
glTexCoord2f = (PFNGLTEXCOORD2FPROC)GetProcAddress(OpenGL_hModule, "glTexCoord2f");
glVertex2f = (PFNGLVERTEX2FPROC)GetProcAddress(OpenGL_hModule, "glVertex2f");
glBegin = (PFNGLBEGINPROC)GetProcAddress(g_oglu_hmodule, "glBegin");
glEnd = (PFNGLENDPROC)GetProcAddress(g_oglu_hmodule, "glEnd");
glTexCoord2f = (PFNGLTEXCOORD2FPROC)GetProcAddress(g_oglu_hmodule, "glTexCoord2f");
glVertex2f = (PFNGLVERTEX2FPROC)GetProcAddress(g_oglu_hmodule, "glVertex2f");
}
return xwglCreateContext && xwglDeleteContext && xwglGetProcAddress && xwglMakeCurrent && glViewport &&
@ -138,7 +127,7 @@ BOOL OpenGL_LoadDll()
glEnable && glClear && glBegin && glEnd && glTexCoord2f && glVertex2f;
}
void OpenGL_Init()
void oglu_init()
{
// Program
glCreateProgram = (PFNGLCREATEPROGRAMPROC)xwglGetProcAddress("glCreateProgram");
@ -170,13 +159,11 @@ void OpenGL_Init()
glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC)xwglGetProcAddress("glVertexAttrib4fv");
glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)xwglGetProcAddress("glEnableVertexAttribArray");
glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)xwglGetProcAddress("glBindAttribLocation");
glCreateShader = (PFNGLCREATESHADERPROC)xwglGetProcAddress("glCreateShader");
glDeleteShader = (PFNGLDELETESHADERPROC)xwglGetProcAddress("glDeleteShader");
glShaderSource = (PFNGLSHADERSOURCEPROC)xwglGetProcAddress("glShaderSource");
glCompileShader = (PFNGLCOMPILESHADERPROC)xwglGetProcAddress("glCompileShader");
glGetShaderiv = (PFNGLGETSHADERIVPROC)xwglGetProcAddress("glGetShaderiv");
glGenBuffers = (PFNGLGENBUFFERSPROC)xwglGetProcAddress("glGenBuffers");
glBindBuffer = (PFNGLBINDBUFFERPROC)xwglGetProcAddress("glBindBuffer");
glBufferData = (PFNGLBUFFERDATAPROC)xwglGetProcAddress("glBufferData");
@ -188,9 +175,7 @@ void OpenGL_Init()
glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)xwglGetProcAddress("glGenVertexArrays");
glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)xwglGetProcAddress("glBindVertexArray");
glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)xwglGetProcAddress("glDeleteVertexArrays");
glActiveTexture = (PFNGLACTIVETEXTUREPROC)xwglGetProcAddress("glActiveTexture");
glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)xwglGetProcAddress("glGenFramebuffers");
glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)xwglGetProcAddress("glBindFramebuffer");
glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)xwglGetProcAddress("glFramebufferTexture2D");
@ -206,23 +191,23 @@ void OpenGL_Init()
char *glversion = (char *)glGetString(GL_VERSION);
if (glversion)
{
strncpy(OpenGL_Version, glversion, sizeof(OpenGL_Version));
strncpy(g_oglu_version, glversion, sizeof(g_oglu_version)-1);
const char deli[2] = " ";
strtok(OpenGL_Version, deli);
strtok(g_oglu_version, deli);
}
else
OpenGL_Version[0] = '0';
g_oglu_version[0] = '0';
OpenGL_GotVersion2 = glGetUniformLocation && glActiveTexture && glUniform1i;
g_oglu_got_version2 = glGetUniformLocation && glActiveTexture && glUniform1i;
OpenGL_GotVersion3 = glGenFramebuffers && glBindFramebuffer && glFramebufferTexture2D && glDrawBuffers &&
g_oglu_got_version3 = glGenFramebuffers && glBindFramebuffer && glFramebufferTexture2D && glDrawBuffers &&
glCheckFramebufferStatus && glUniform4f && glActiveTexture && glUniform1i &&
glGetAttribLocation && glGenBuffers && glBindBuffer && glBufferData && glVertexAttribPointer &&
glEnableVertexAttribArray && glUniform2fv && glUniformMatrix4fv && glGenVertexArrays && glBindVertexArray &&
glGetUniformLocation && glversion && glversion[0] != '2';
}
BOOL OpenGL_ExtExists(char *ext, HDC hdc)
BOOL oglu_ext_exists(char *ext, HDC hdc)
{
char *glext = (char *)glGetString(GL_EXTENSIONS);
if (glext)
@ -244,46 +229,46 @@ BOOL OpenGL_ExtExists(char *ext, HDC hdc)
return FALSE;
}
GLuint OpenGL_BuildProgram(const GLchar *vertSource, const GLchar *fragSource)
GLuint oglu_build_program(const GLchar *vertSource, const GLchar *fragSource)
{
if (!glCreateShader || !glShaderSource || !glCompileShader || !glCreateProgram ||
!glAttachShader || !glLinkProgram || !glUseProgram || !glDetachShader)
return 0;
GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
GLuint vert_shader = glCreateShader(GL_VERTEX_SHADER);
GLuint frag_shader = glCreateShader(GL_FRAGMENT_SHADER);
if (!vertShader || !fragShader)
if (!vert_shader || !frag_shader)
return 0;
glShaderSource(vertShader, 1, &vertSource, NULL);
glShaderSource(fragShader, 1, &fragSource, NULL);
glShaderSource(vert_shader, 1, &vertSource, NULL);
glShaderSource(frag_shader, 1, &fragSource, NULL);
GLint isCompiled = 0;
GLint is_compiled = 0;
glCompileShader(vertShader);
glCompileShader(vert_shader);
if (glGetShaderiv)
{
glGetShaderiv(vertShader, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
glGetShaderiv(vert_shader, GL_COMPILE_STATUS, &is_compiled);
if (is_compiled == GL_FALSE)
{
if (glDeleteShader)
glDeleteShader(vertShader);
glDeleteShader(vert_shader);
return 0;
}
}
glCompileShader(fragShader);
glCompileShader(frag_shader);
if (glGetShaderiv)
{
glGetShaderiv(fragShader, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
glGetShaderiv(frag_shader, GL_COMPILE_STATUS, &is_compiled);
if (is_compiled == GL_FALSE)
{
if (glDeleteShader)
{
glDeleteShader(fragShader);
glDeleteShader(vertShader);
glDeleteShader(frag_shader);
glDeleteShader(vert_shader);
}
return 0;
@ -293,21 +278,21 @@ GLuint OpenGL_BuildProgram(const GLchar *vertSource, const GLchar *fragSource)
GLuint program = glCreateProgram();
if (program)
{
glAttachShader(program, vertShader);
glAttachShader(program, fragShader);
glAttachShader(program, vert_shader);
glAttachShader(program, frag_shader);
glLinkProgram(program);
glDetachShader(program, vertShader);
glDetachShader(program, fragShader);
glDeleteShader(vertShader);
glDeleteShader(fragShader);
glDetachShader(program, vert_shader);
glDetachShader(program, frag_shader);
glDeleteShader(vert_shader);
glDeleteShader(frag_shader);
if (glGetProgramiv)
{
GLint isLinked = 0;
glGetProgramiv(program, GL_LINK_STATUS, &isLinked);
if (isLinked == GL_FALSE)
GLint is_linked = 0;
glGetProgramiv(program, GL_LINK_STATUS, &is_linked);
if (is_linked == GL_FALSE)
{
if (glDeleteProgram)
glDeleteProgram(program);
@ -320,7 +305,7 @@ GLuint OpenGL_BuildProgram(const GLchar *vertSource, const GLchar *fragSource)
return program;
}
GLuint OpenGL_BuildProgramFromFile(const char *filePath)
GLuint oglu_build_program_from_file(const char *filePath)
{
GLuint program = 0;
@ -328,47 +313,47 @@ GLuint OpenGL_BuildProgramFromFile(const char *filePath)
if (file)
{
fseek(file, 0, SEEK_END);
long fileSize = ftell(file);
long file_size = ftell(file);
fseek(file, 0, SEEK_SET);
char *source = fileSize > 0 ? calloc(fileSize + 1, 1) : NULL;
char *source = file_size > 0 ? calloc(file_size + 1, 1) : NULL;
if (source)
{
fread(source, fileSize, 1, file);
fread(source, file_size, 1, file);
fclose(file);
char *vertSource = calloc(fileSize + 50, 1);
char *fragSource = calloc(fileSize + 50, 1);
char *vert_source = calloc(file_size + 50, 1);
char *frag_source = calloc(file_size + 50, 1);
if (fragSource && vertSource)
if (frag_source && vert_source)
{
char *versionStart = strstr(source, "#version");
if (versionStart)
char *version_start = strstr(source, "#version");
if (version_start)
{
const char deli[2] = "\n";
char *version = strtok(versionStart, deli);
char *version = strtok(version_start, deli);
strcpy(vertSource, source);
strcpy(fragSource, source);
strcat(vertSource, "\n#define VERTEX\n");
strcat(fragSource, "\n#define FRAGMENT\n");
strcat(vertSource, version + strlen(version) + 1);
strcat(fragSource, version + strlen(version) + 1);
strcpy(vert_source, source);
strcpy(frag_source, source);
strcat(vert_source, "\n#define VERTEX\n");
strcat(frag_source, "\n#define FRAGMENT\n");
strcat(vert_source, version + strlen(version) + 1);
strcat(frag_source, version + strlen(version) + 1);
program = OpenGL_BuildProgram(vertSource, fragSource);
program = oglu_build_program(vert_source, frag_source);
}
else
{
strcpy(vertSource, "#define VERTEX\n");
strcpy(fragSource, "#define FRAGMENT\n");
strcat(vertSource, source);
strcat(fragSource, source);
strcpy(vert_source, "#define VERTEX\n");
strcpy(frag_source, "#define FRAGMENT\n");
strcat(vert_source, source);
strcat(frag_source, source);
program = OpenGL_BuildProgram(vertSource, fragSource);
program = oglu_build_program(vert_source, frag_source);
}
free(vertSource);
free(fragSource);
free(vert_source);
free(frag_source);
}
free(source);

View file

@ -1,146 +0,0 @@
/*
* Copyright (c) 2010 Toni Spets <toni.spets@iki.fi>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <windows.h>
#include <stdio.h>
#include "palette.h"
#include "surface.h"
IDirectDrawPaletteImpl *LastFreedPalette; // Dungeon Keeper hack
HRESULT __stdcall ddraw_palette_GetEntries(IDirectDrawPaletteImpl *This, DWORD dwFlags, DWORD dwBase, DWORD dwNumEntries, LPPALETTEENTRY lpEntries)
{
int i, x;
printf("DirectDrawPalette::GetEntries(This=%p, dwFlags=%08X, dwBase=%d, dwNumEntries=%d, lpEntries=%p)\n", This, (int)dwFlags, (int)dwBase, (int)dwNumEntries, lpEntries);
for (i = dwBase, x = 0; i < dwBase + dwNumEntries; i++, x++)
{
if (This->data_rgb)
{
lpEntries[x].peRed = This->data_rgb[i].rgbRed;
lpEntries[x].peGreen = This->data_rgb[i].rgbGreen;
lpEntries[x].peBlue = This->data_rgb[i].rgbBlue;
}
}
return DD_OK;
}
HRESULT __stdcall ddraw_palette_SetEntries(IDirectDrawPaletteImpl *This, DWORD dwFlags, DWORD dwStartingEntry, DWORD dwCount, LPPALETTEENTRY lpEntries)
{
int i, x;
#if _DEBUG_X
printf("DirectDrawPalette::SetEntries(This=%p, dwFlags=%08X, dwStartingEntry=%d, dwCount=%d, lpEntries=%p)\n", This, (int)dwFlags, (int)dwStartingEntry, (int)dwCount, lpEntries);
#endif
for (i = dwStartingEntry, x = 0; i < dwStartingEntry + dwCount; i++, x++)
{
This->data_bgr[i] = (lpEntries[x].peBlue << 16) | (lpEntries[x].peGreen << 8) | lpEntries[x].peRed;
if (This->data_rgb)
{
This->data_rgb[i].rgbRed = lpEntries[x].peRed;
This->data_rgb[i].rgbGreen = lpEntries[x].peGreen;
This->data_rgb[i].rgbBlue = lpEntries[x].peBlue;
This->data_rgb[i].rgbReserved = 0;
}
}
if (ddraw->primary && ddraw->primary->palette == This && ddraw->render.run)
{
InterlockedExchange(&ddraw->render.paletteUpdated, TRUE);
ReleaseSemaphore(ddraw->render.sem, 1, NULL);
}
return DD_OK;
}
HRESULT __stdcall ddraw_palette_QueryInterface(IDirectDrawPaletteImpl *This, REFIID riid, void **obj)
{
printf("??? DirectDrawPalette::QueryInterface(This=%p, riid=%08X, obj=%p)\n", This, (unsigned int)riid, obj);
return S_OK;
}
ULONG __stdcall ddraw_palette_AddRef(IDirectDrawPaletteImpl *This)
{
printf("DirectDrawPalette::AddRef(This=%p)\n", This);
This->Ref++;
return This->Ref;
}
ULONG __stdcall ddraw_palette_Release(IDirectDrawPaletteImpl *This)
{
printf("DirectDrawPalette::Release(This=%p)\n", This);
This->Ref--;
if(This->Ref == 0)
{
printf(" Released (%p)\n", This);
LastFreedPalette = This;
HeapFree(GetProcessHeap(), 0, This);
return 0;
}
return This->Ref;
}
HRESULT __stdcall ddraw_palette_GetCaps(IDirectDrawPaletteImpl *This, LPDWORD caps)
{
printf("??? DirectDrawPalette::GetCaps(This=%p, caps=%p)\n", This, caps);
return DD_OK;
}
HRESULT __stdcall ddraw_palette_Initialize(IDirectDrawPaletteImpl *This, LPDIRECTDRAW lpDD, DWORD dw, LPPALETTEENTRY paent)
{
printf("??? DirectDrawPalette::Initialize(This=%p, ...)\n", This);
return DD_OK;
}
struct IDirectDrawPaletteImplVtbl piface =
{
/* IUnknown */
ddraw_palette_QueryInterface,
ddraw_palette_AddRef,
ddraw_palette_Release,
/* IDirectDrawPalette */
ddraw_palette_GetCaps,
ddraw_palette_GetEntries,
ddraw_palette_Initialize,
ddraw_palette_SetEntries
};
HRESULT __stdcall ddraw_CreatePalette(IDirectDrawImpl *This, DWORD dwFlags, LPPALETTEENTRY lpDDColorArray, LPDIRECTDRAWPALETTE FAR * lpDDPalette, IUnknown FAR * unkOuter)
{
printf("DirectDraw::CreatePalette(This=%p, dwFlags=%08X, DDColorArray=%p, DDPalette=%p, unkOuter=%p)\n", This, (int)dwFlags, lpDDColorArray, lpDDPalette, unkOuter);
IDirectDrawPaletteImpl *Palette = (IDirectDrawPaletteImpl *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawPaletteImpl));
Palette->lpVtbl = &piface;
printf(" Palette = %p\n", Palette);
*lpDDPalette = (LPDIRECTDRAWPALETTE)Palette;
ddraw_palette_SetEntries(Palette, dwFlags, 0, 256, lpDDColorArray);
ddraw_palette_AddRef(Palette);
return DD_OK;
}

File diff suppressed because it is too large Load diff

View file

@ -1,58 +1,64 @@
#include <windows.h>
#include <stdio.h>
#include <d3d9.h>
#include "main.h"
#include "surface.h"
#include "dd.h"
#include "ddsurface.h"
#include "d3d9shader.h"
#include "render_d3d9.h"
#include "utils.h"
#include "wndproc.h"
#define TEXTURE_COUNT 2
HMODULE Direct3D9_hModule;
static BOOL d3d9_create_resouces();
static BOOL d3d9_set_states();
static BOOL d3d9_update_vertices(BOOL in_cutscene, BOOL stretch);
static void d3d9_set_max_fps();
static D3DPRESENT_PARAMETERS D3dpp;
static LPDIRECT3D9 D3d;
static LPDIRECT3DDEVICE9 D3dDev;
static LPDIRECT3DVERTEXBUFFER9 VertexBuf;
static IDirect3DTexture9 *SurfaceTex[TEXTURE_COUNT];
static IDirect3DTexture9 *PaletteTex[TEXTURE_COUNT];
static IDirect3DPixelShader9 *PixelShader;
static float ScaleW;
static float ScaleH;
static int BitsPerPixel;
static d3d9_renderer g_d3d9;
static BOOL CreateResources();
static BOOL SetStates();
static BOOL UpdateVertices(BOOL inCutscene, BOOL stretch);
static void SetMaxFPS();
BOOL Direct3D9_Create()
BOOL d3d9_is_available()
{
if (!Direct3D9_Release())
LPDIRECT3D9 d3d9 = NULL;
if ((g_d3d9.hmodule = LoadLibrary("d3d9.dll")))
{
IDirect3D9* (WINAPI * d3d_create9)(UINT) =
(IDirect3D9 * (WINAPI*)(UINT))GetProcAddress(g_d3d9.hmodule, "Direct3DCreate9");
if (d3d_create9 && (d3d9 = d3d_create9(D3D_SDK_VERSION)))
IDirect3D9_Release(d3d9);
}
return d3d9 != NULL;
}
BOOL d3d9_create()
{
if (!d3d9_release())
return FALSE;
if (!Direct3D9_hModule)
Direct3D9_hModule = LoadLibrary("d3d9.dll");
if (!g_d3d9.hmodule)
g_d3d9.hmodule = LoadLibrary("d3d9.dll");
if (Direct3D9_hModule)
if (g_d3d9.hmodule)
{
IDirect3D9 *(WINAPI *D3DCreate9)(UINT) =
(IDirect3D9 *(WINAPI *)(UINT))GetProcAddress(Direct3D9_hModule, "Direct3DCreate9");
IDirect3D9 *(WINAPI *d3d_create9)(UINT) =
(IDirect3D9 *(WINAPI *)(UINT))GetProcAddress(g_d3d9.hmodule, "Direct3DCreate9");
if (D3DCreate9 && (D3d = D3DCreate9(D3D_SDK_VERSION)))
if (d3d_create9 && (g_d3d9.instance = d3d_create9(D3D_SDK_VERSION)))
{
BitsPerPixel = ddraw->render.bpp ? ddraw->render.bpp : ddraw->mode.dmBitsPerPel;
g_d3d9.bits_per_pixel = g_ddraw->render.bpp ? g_ddraw->render.bpp : g_ddraw->mode.dmBitsPerPel;
D3dpp.Windowed = ddraw->windowed;
D3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
D3dpp.hDeviceWindow = ddraw->hWnd;
D3dpp.PresentationInterval = ddraw->vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
D3dpp.BackBufferWidth = D3dpp.Windowed ? 0 : ddraw->render.width;
D3dpp.BackBufferHeight = D3dpp.Windowed ? 0 : ddraw->render.height;
D3dpp.BackBufferFormat = BitsPerPixel == 16 ? D3DFMT_R5G6B5 : D3DFMT_X8R8G8B8;
D3dpp.BackBufferCount = 1;
g_d3d9.params.Windowed = g_ddraw->windowed;
g_d3d9.params.SwapEffect = D3DSWAPEFFECT_DISCARD;
g_d3d9.params.hDeviceWindow = g_ddraw->hwnd;
g_d3d9.params.PresentationInterval = g_ddraw->vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
g_d3d9.params.BackBufferWidth = g_d3d9.params.Windowed ? 0 : g_ddraw->render.width;
g_d3d9.params.BackBufferHeight = g_d3d9.params.Windowed ? 0 : g_ddraw->render.height;
g_d3d9.params.BackBufferFormat = g_d3d9.bits_per_pixel == 16 ? D3DFMT_R5G6B5 : D3DFMT_X8R8G8B8;
g_d3d9.params.BackBufferCount = 1;
DWORD behaviorFlags[] = {
DWORD behavior_flags[] = {
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE,
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE,
D3DCREATE_HARDWARE_VERTEXPROCESSING,
@ -61,18 +67,18 @@ BOOL Direct3D9_Create()
};
int i;
for (i = 0; i < sizeof(behaviorFlags) / sizeof(behaviorFlags[0]); i++)
for (i = 0; i < sizeof(behavior_flags) / sizeof(behavior_flags[0]); i++)
{
if (SUCCEEDED(
IDirect3D9_CreateDevice(
D3d,
g_d3d9.instance,
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
ddraw->hWnd,
D3DCREATE_MULTITHREADED | behaviorFlags[i],
&D3dpp,
&D3dDev)))
return D3dDev && CreateResources() && SetStates();
g_ddraw->hwnd,
D3DCREATE_MULTITHREADED | behavior_flags[i],
&g_d3d9.params,
&g_d3d9.device)))
return g_d3d9.device && d3d9_create_resouces() && d3d9_set_states();
}
}
}
@ -80,177 +86,177 @@ BOOL Direct3D9_Create()
return FALSE;
}
BOOL Direct3D9_OnDeviceLost()
BOOL d3d9_on_device_lost()
{
if (D3dDev && IDirect3DDevice9_TestCooperativeLevel(D3dDev) == D3DERR_DEVICENOTRESET)
return Direct3D9_Reset();
if (g_d3d9.device && IDirect3DDevice9_TestCooperativeLevel(g_d3d9.device) == D3DERR_DEVICENOTRESET)
return d3d9_reset();
return FALSE;
}
BOOL Direct3D9_Reset()
BOOL d3d9_reset()
{
D3dpp.Windowed = ddraw->windowed;
D3dpp.BackBufferWidth = D3dpp.Windowed ? 0 : ddraw->render.width;
D3dpp.BackBufferHeight = D3dpp.Windowed ? 0 : ddraw->render.height;
D3dpp.BackBufferFormat = BitsPerPixel == 16 ? D3DFMT_R5G6B5 : D3DFMT_X8R8G8B8;
g_d3d9.params.Windowed = g_ddraw->windowed;
g_d3d9.params.BackBufferWidth = g_d3d9.params.Windowed ? 0 : g_ddraw->render.width;
g_d3d9.params.BackBufferHeight = g_d3d9.params.Windowed ? 0 : g_ddraw->render.height;
g_d3d9.params.BackBufferFormat = g_d3d9.bits_per_pixel == 16 ? D3DFMT_R5G6B5 : D3DFMT_X8R8G8B8;
if (D3dDev && SUCCEEDED(IDirect3DDevice9_Reset(D3dDev, &D3dpp)))
return SetStates();
if (g_d3d9.device && SUCCEEDED(IDirect3DDevice9_Reset(g_d3d9.device, &g_d3d9.params)))
return d3d9_set_states();
return FALSE;
}
BOOL Direct3D9_Release()
BOOL d3d9_release()
{
if (VertexBuf)
if (g_d3d9.vertex_buf)
{
IDirect3DVertexBuffer9_Release(VertexBuf);
VertexBuf = NULL;
IDirect3DVertexBuffer9_Release(g_d3d9.vertex_buf);
g_d3d9.vertex_buf = NULL;
}
int i;
for (i = 0; i < TEXTURE_COUNT; i++)
for (i = 0; i < D3D9_TEXTURE_COUNT; i++)
{
if (SurfaceTex[i])
if (g_d3d9.surface_tex[i])
{
IDirect3DTexture9_Release(SurfaceTex[i]);
SurfaceTex[i] = NULL;
IDirect3DTexture9_Release(g_d3d9.surface_tex[i]);
g_d3d9.surface_tex[i] = NULL;
}
if (PaletteTex[i])
if (g_d3d9.palette_tex[i])
{
IDirect3DTexture9_Release(PaletteTex[i]);
PaletteTex[i] = NULL;
IDirect3DTexture9_Release(g_d3d9.palette_tex[i]);
g_d3d9.palette_tex[i] = NULL;
}
}
if (PixelShader)
if (g_d3d9.pixel_shader)
{
IDirect3DPixelShader9_Release(PixelShader);
PixelShader = NULL;
IDirect3DPixelShader9_Release(g_d3d9.pixel_shader);
g_d3d9.pixel_shader = NULL;
}
if (D3dDev)
if (g_d3d9.device)
{
IDirect3DDevice9_Release(D3dDev);
D3dDev = NULL;
IDirect3DDevice9_Release(g_d3d9.device);
g_d3d9.device = NULL;
}
if (D3d)
if (g_d3d9.instance)
{
IDirect3D9_Release(D3d);
D3d = NULL;
IDirect3D9_Release(g_d3d9.instance);
g_d3d9.instance = NULL;
}
return TRUE;
}
static BOOL CreateResources()
static BOOL d3d9_create_resouces()
{
BOOL err = FALSE;
int width = ddraw->width;
int height = ddraw->height;
int width = g_ddraw->width;
int height = g_ddraw->height;
int texWidth =
int tex_width =
width <= 1024 ? 1024 : width <= 2048 ? 2048 : width <= 4096 ? 4096 : width;
int texHeight =
height <= texWidth ? texWidth : height <= 2048 ? 2048 : height <= 4096 ? 4096 : height;
int tex_height =
height <= tex_width ? tex_width : height <= 2048 ? 2048 : height <= 4096 ? 4096 : height;
texWidth = texWidth > texHeight ? texWidth : texHeight;
tex_width = tex_width > tex_height ? tex_width : tex_height;
ScaleW = (float)width / texWidth;;
ScaleH = (float)height / texHeight;
g_d3d9.scale_w = (float)width / tex_width;;
g_d3d9.scale_h = (float)height / tex_height;
err = err || FAILED(
IDirect3DDevice9_CreateVertexBuffer(
D3dDev, sizeof(CUSTOMVERTEX) * 4, 0, D3DFVF_XYZRHW | D3DFVF_TEX1, D3DPOOL_MANAGED, &VertexBuf, NULL));
g_d3d9.device, sizeof(CUSTOMVERTEX) * 4, 0, D3DFVF_XYZRHW | D3DFVF_TEX1, D3DPOOL_MANAGED, &g_d3d9.vertex_buf, NULL));
err = err || !UpdateVertices(InterlockedExchangeAdd(&ddraw->incutscene, 0), TRUE);
err = err || !d3d9_update_vertices(InterlockedExchangeAdd(&g_ddraw->incutscene, 0), TRUE);
int i;
for (i = 0; i < TEXTURE_COUNT; i++)
for (i = 0; i < D3D9_TEXTURE_COUNT; i++)
{
err = err || FAILED(
IDirect3DDevice9_CreateTexture(
D3dDev,
texWidth,
texHeight,
g_d3d9.device,
tex_width,
tex_height,
1,
0,
ddraw->bpp == 16 ? D3DFMT_R5G6B5 : D3DFMT_L8,
g_ddraw->bpp == 16 ? D3DFMT_R5G6B5 : D3DFMT_L8,
D3DPOOL_MANAGED,
&SurfaceTex[i],
&g_d3d9.surface_tex[i],
0));
err = err || !SurfaceTex[i];
err = err || !g_d3d9.surface_tex[i];
if (ddraw->bpp == 8)
if (g_ddraw->bpp == 8)
{
err = err || FAILED(
IDirect3DDevice9_CreateTexture(
D3dDev,
g_d3d9.device,
256,
256,
1,
0,
D3DFMT_X8R8G8B8,
D3DPOOL_MANAGED,
&PaletteTex[i],
&g_d3d9.palette_tex[i],
0));
err = err || !PaletteTex[i];
err = err || !g_d3d9.palette_tex[i];
}
}
if (ddraw->bpp == 8)
if (g_ddraw->bpp == 8)
{
err = err || FAILED(
IDirect3DDevice9_CreatePixelShader(D3dDev, (DWORD *)PalettePixelShaderSrc, &PixelShader));
IDirect3DDevice9_CreatePixelShader(g_d3d9.device, (DWORD *)D3D9_PALETTE_SHADER, &g_d3d9.pixel_shader));
}
return VertexBuf && (PixelShader || ddraw->bpp == 16) && !err;
return g_d3d9.vertex_buf && (g_d3d9.pixel_shader || g_ddraw->bpp == 16) && !err;
}
static BOOL SetStates()
static BOOL d3d9_set_states()
{
BOOL err = FALSE;
err = err || FAILED(IDirect3DDevice9_SetFVF(D3dDev, D3DFVF_XYZRHW | D3DFVF_TEX1));
err = err || FAILED(IDirect3DDevice9_SetStreamSource(D3dDev, 0, VertexBuf, 0, sizeof(CUSTOMVERTEX)));
err = err || FAILED(IDirect3DDevice9_SetTexture(D3dDev, 0, (IDirect3DBaseTexture9 *)SurfaceTex[0]));
err = err || FAILED(IDirect3DDevice9_SetFVF(g_d3d9.device, D3DFVF_XYZRHW | D3DFVF_TEX1));
err = err || FAILED(IDirect3DDevice9_SetStreamSource(g_d3d9.device, 0, g_d3d9.vertex_buf, 0, sizeof(CUSTOMVERTEX)));
err = err || FAILED(IDirect3DDevice9_SetTexture(g_d3d9.device, 0, (IDirect3DBaseTexture9 *)g_d3d9.surface_tex[0]));
if (ddraw->bpp == 8)
if (g_ddraw->bpp == 8)
{
err = err || FAILED(IDirect3DDevice9_SetTexture(D3dDev, 1, (IDirect3DBaseTexture9 *)PaletteTex[0]));
err = err || FAILED(IDirect3DDevice9_SetPixelShader(D3dDev, PixelShader));
err = err || FAILED(IDirect3DDevice9_SetTexture(g_d3d9.device, 1, (IDirect3DBaseTexture9 *)g_d3d9.palette_tex[0]));
err = err || FAILED(IDirect3DDevice9_SetPixelShader(g_d3d9.device, g_d3d9.pixel_shader));
}
D3DVIEWPORT9 viewData = {
ddraw->render.viewport.x,
ddraw->render.viewport.y,
ddraw->render.viewport.width,
ddraw->render.viewport.height,
D3DVIEWPORT9 view_data = {
g_ddraw->render.viewport.x,
g_ddraw->render.viewport.y,
g_ddraw->render.viewport.width,
g_ddraw->render.viewport.height,
0.0f,
1.0f };
err = err || FAILED(IDirect3DDevice9_SetViewport(D3dDev, &viewData));
err = err || FAILED(IDirect3DDevice9_SetViewport(g_d3d9.device, &view_data));
return !err;
}
static BOOL UpdateVertices(BOOL inCutscene, BOOL stretch)
static BOOL d3d9_update_vertices(BOOL in_cutscene, BOOL stretch)
{
float vpX = stretch ? (float)ddraw->render.viewport.x : 0.0f;
float vpY = stretch ? (float)ddraw->render.viewport.y : 0.0f;
float vpX = stretch ? (float)g_ddraw->render.viewport.x : 0.0f;
float vpY = stretch ? (float)g_ddraw->render.viewport.y : 0.0f;
float vpW = stretch ? (float)(ddraw->render.viewport.width + ddraw->render.viewport.x) : (float)ddraw->width;
float vpH = stretch ? (float)(ddraw->render.viewport.height + ddraw->render.viewport.y) : (float)ddraw->height;
float vpW = stretch ? (float)(g_ddraw->render.viewport.width + g_ddraw->render.viewport.x) : (float)g_ddraw->width;
float vpH = stretch ? (float)(g_ddraw->render.viewport.height + g_ddraw->render.viewport.y) : (float)g_ddraw->height;
float sH = inCutscene ? ScaleH * ((float)CUTSCENE_HEIGHT / ddraw->height) : ScaleH;
float sW = inCutscene ? ScaleW * ((float)CUTSCENE_WIDTH / ddraw->width) : ScaleW;
float sH = in_cutscene ? g_d3d9.scale_h * ((float)CUTSCENE_HEIGHT / g_ddraw->height) : g_d3d9.scale_h;
float sW = in_cutscene ? g_d3d9.scale_w * ((float)CUTSCENE_WIDTH / g_ddraw->width) : g_d3d9.scale_w;
CUSTOMVERTEX vertices[] =
{
@ -261,197 +267,198 @@ static BOOL UpdateVertices(BOOL inCutscene, BOOL stretch)
};
void *data;
if (VertexBuf && SUCCEEDED(IDirect3DVertexBuffer9_Lock(VertexBuf, 0, 0, (void**)&data, 0)))
if (g_d3d9.vertex_buf && SUCCEEDED(IDirect3DVertexBuffer9_Lock(g_d3d9.vertex_buf, 0, 0, (void**)&data, 0)))
{
memcpy(data, vertices, sizeof(vertices));
IDirect3DVertexBuffer9_Unlock(VertexBuf);
IDirect3DVertexBuffer9_Unlock(g_d3d9.vertex_buf);
return TRUE;
}
return FALSE;
}
static void SetMaxFPS()
static void d3d9_set_max_fps()
{
int maxFPS = ddraw->render.maxfps;
ddraw->fpsLimiter.tickLengthNs = 0;
ddraw->fpsLimiter.ticklength = 0;
int max_fps = g_ddraw->render.maxfps;
if (maxFPS < 0 || ddraw->vsync)
maxFPS = ddraw->mode.dmDisplayFrequency;
g_ddraw->fps_limiter.tick_length_ns = 0;
g_ddraw->fps_limiter.tick_length = 0;
if (maxFPS > 1000)
maxFPS = 0;
if (max_fps < 0 || g_ddraw->vsync)
max_fps = g_ddraw->mode.dmDisplayFrequency;
if (maxFPS > 0)
if (max_fps > 1000)
max_fps = 0;
if (max_fps > 0)
{
float len = 1000.0f / maxFPS;
ddraw->fpsLimiter.tickLengthNs = len * 10000;
ddraw->fpsLimiter.ticklength = len;// + 0.5f;
float len = 1000.0f / max_fps;
g_ddraw->fps_limiter.tick_length_ns = len * 10000;
g_ddraw->fps_limiter.tick_length = len;// + 0.5f;
}
}
DWORD WINAPI render_d3d9_main(void)
DWORD WINAPI d3d9_render_main(void)
{
Sleep(500);
SetMaxFPS();
d3d9_set_max_fps();
DWORD tickStart = 0;
DWORD tickEnd = 0;
BOOL needsUpdate = FALSE;
DWORD tick_start = 0;
DWORD tick_end = 0;
BOOL needs_update = FALSE;
while (ddraw->render.run &&
(ddraw->render.forcefps || WaitForSingleObject(ddraw->render.sem, 200) != WAIT_FAILED))
while (g_ddraw->render.run &&
(g_ddraw->render.forcefps || WaitForSingleObject(g_ddraw->render.sem, 200) != WAIT_FAILED))
{
#if _DEBUG
DrawFrameInfoStart();
#endif
static int texIndex = 0, palIndex = 0;
static int tex_index = 0, palIndex = 0;
if (ddraw->fpsLimiter.ticklength > 0)
tickStart = timeGetTime();
if (g_ddraw->fps_limiter.tick_length > 0)
tick_start = timeGetTime();
EnterCriticalSection(&ddraw->cs);
EnterCriticalSection(&g_ddraw->cs);
if (ddraw->primary && (ddraw->bpp == 16 || (ddraw->primary->palette && ddraw->primary->palette->data_rgb)))
if (g_ddraw->primary && (g_ddraw->bpp == 16 || (g_ddraw->primary->palette && g_ddraw->primary->palette->data_rgb)))
{
if (ddraw->vhack)
if (g_ddraw->vhack)
{
if (detect_cutscene())
if (util_detect_cutscene())
{
if (!InterlockedExchange(&ddraw->incutscene, TRUE))
UpdateVertices(TRUE, TRUE);
if (!InterlockedExchange(&g_ddraw->incutscene, TRUE))
d3d9_update_vertices(TRUE, TRUE);
}
else
{
if (InterlockedExchange(&ddraw->incutscene, FALSE))
UpdateVertices(FALSE, TRUE);
if (InterlockedExchange(&g_ddraw->incutscene, FALSE))
d3d9_update_vertices(FALSE, TRUE);
}
}
D3DLOCKED_RECT lock_rc;
if (InterlockedExchange(&ddraw->render.surfaceUpdated, FALSE))
if (InterlockedExchange(&g_ddraw->render.surface_updated, FALSE))
{
if (++texIndex >= TEXTURE_COUNT)
texIndex = 0;
if (++tex_index >= D3D9_TEXTURE_COUNT)
tex_index = 0;
RECT rc = { 0,0,ddraw->width,ddraw->height };
RECT rc = { 0, 0, g_ddraw->width, g_ddraw->height };
if (SUCCEEDED(IDirect3DDevice9_SetTexture(D3dDev, 0, (IDirect3DBaseTexture9 *)SurfaceTex[texIndex])) &&
SUCCEEDED(IDirect3DTexture9_LockRect(SurfaceTex[texIndex], 0, &lock_rc, &rc, 0)))
if (SUCCEEDED(IDirect3DDevice9_SetTexture(g_d3d9.device, 0, (IDirect3DBaseTexture9 *)g_d3d9.surface_tex[tex_index])) &&
SUCCEEDED(IDirect3DTexture9_LockRect(g_d3d9.surface_tex[tex_index], 0, &lock_rc, &rc, 0)))
{
unsigned char *src = (unsigned char *)ddraw->primary->surface;
unsigned char *src = (unsigned char *)g_ddraw->primary->surface;
unsigned char *dst = (unsigned char *)lock_rc.pBits;
int i;
for (i = 0; i < ddraw->height; i++)
for (i = 0; i < g_ddraw->height; i++)
{
memcpy(dst, src, ddraw->primary->lPitch);
memcpy(dst, src, g_ddraw->primary->l_pitch);
src += ddraw->primary->lPitch;
src += g_ddraw->primary->l_pitch;
dst += lock_rc.Pitch;
}
IDirect3DTexture9_UnlockRect(SurfaceTex[texIndex], 0);
IDirect3DTexture9_UnlockRect(g_d3d9.surface_tex[tex_index], 0);
}
}
if (ddraw->bpp == 8 && InterlockedExchange(&ddraw->render.paletteUpdated, FALSE))
if (g_ddraw->bpp == 8 && InterlockedExchange(&g_ddraw->render.palette_updated, FALSE))
{
if (++palIndex >= TEXTURE_COUNT)
if (++palIndex >= D3D9_TEXTURE_COUNT)
palIndex = 0;
RECT rc = { 0,0,256,1 };
if (SUCCEEDED(IDirect3DDevice9_SetTexture(D3dDev, 1, (IDirect3DBaseTexture9 *)PaletteTex[palIndex])) &&
SUCCEEDED(IDirect3DTexture9_LockRect(PaletteTex[palIndex], 0, &lock_rc, &rc, 0)))
if (SUCCEEDED(IDirect3DDevice9_SetTexture(g_d3d9.device, 1, (IDirect3DBaseTexture9 *)g_d3d9.palette_tex[palIndex])) &&
SUCCEEDED(IDirect3DTexture9_LockRect(g_d3d9.palette_tex[palIndex], 0, &lock_rc, &rc, 0)))
{
memcpy(lock_rc.pBits, ddraw->primary->palette->data_rgb, 256 * sizeof(int));
memcpy(lock_rc.pBits, g_ddraw->primary->palette->data_rgb, 256 * sizeof(int));
IDirect3DTexture9_UnlockRect(PaletteTex[palIndex], 0);
IDirect3DTexture9_UnlockRect(g_d3d9.palette_tex[palIndex], 0);
}
}
if (!ddraw->handlemouse)
if (!g_ddraw->handlemouse)
{
ChildWindowExists = FALSE;
EnumChildWindows(ddraw->hWnd, EnumChildProc, (LPARAM)ddraw->primary);
g_ddraw->child_window_exists = FALSE;
EnumChildWindows(g_ddraw->hwnd, util_enum_child_proc, (LPARAM)g_ddraw->primary);
if (ddraw->render.width != ddraw->width || ddraw->render.height != ddraw->height)
if (g_ddraw->render.width != g_ddraw->width || g_ddraw->render.height != g_ddraw->height)
{
if (ChildWindowExists)
if (g_ddraw->child_window_exists)
{
IDirect3DDevice9_Clear(D3dDev, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
IDirect3DDevice9_Clear(g_d3d9.device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
if (!needsUpdate && UpdateVertices(FALSE, FALSE))
needsUpdate = TRUE;
if (!needs_update && d3d9_update_vertices(FALSE, FALSE))
needs_update = TRUE;
}
else if (needsUpdate)
else if (needs_update)
{
if (UpdateVertices(FALSE, TRUE))
needsUpdate = FALSE;
if (d3d9_update_vertices(FALSE, TRUE))
needs_update = FALSE;
}
}
}
}
LeaveCriticalSection(&ddraw->cs);
LeaveCriticalSection(&g_ddraw->cs);
IDirect3DDevice9_BeginScene(D3dDev);
IDirect3DDevice9_DrawPrimitive(D3dDev, D3DPT_TRIANGLESTRIP, 0, 2);
IDirect3DDevice9_EndScene(D3dDev);
IDirect3DDevice9_BeginScene(g_d3d9.device);
IDirect3DDevice9_DrawPrimitive(g_d3d9.device, D3DPT_TRIANGLESTRIP, 0, 2);
IDirect3DDevice9_EndScene(g_d3d9.device);
if (ddraw->bnetActive)
IDirect3DDevice9_Clear(D3dDev, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
if (g_ddraw->bnet_active)
IDirect3DDevice9_Clear(g_d3d9.device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
if (FAILED(IDirect3DDevice9_Present(D3dDev, NULL, NULL, NULL, NULL)))
if (FAILED(IDirect3DDevice9_Present(g_d3d9.device, NULL, NULL, NULL, NULL)))
{
DWORD_PTR dwResult;
SendMessageTimeout(ddraw->hWnd, WM_D3D9DEVICELOST, 0, 0, 0, 1000, &dwResult);
DWORD_PTR result;
SendMessageTimeout(g_ddraw->hwnd, WM_D3D9DEVICELOST, 0, 0, 0, 1000, &result);
}
#if _DEBUG
DrawFrameInfoEnd();
#endif
if (ddraw->fpsLimiter.ticklength > 0)
if (g_ddraw->fps_limiter.tick_length > 0)
{
if (ddraw->fpsLimiter.hTimer)
if (g_ddraw->fps_limiter.htimer)
{
if (ddraw->vsync)
if (g_ddraw->vsync)
{
WaitForSingleObject(ddraw->fpsLimiter.hTimer, ddraw->fpsLimiter.ticklength * 2);
LARGE_INTEGER liDueTime = { .QuadPart = -ddraw->fpsLimiter.tickLengthNs };
SetWaitableTimer(ddraw->fpsLimiter.hTimer, &liDueTime, 0, NULL, NULL, FALSE);
WaitForSingleObject(g_ddraw->fps_limiter.htimer, g_ddraw->fps_limiter.tick_length * 2);
LARGE_INTEGER due_time = { .QuadPart = -g_ddraw->fps_limiter.tick_length_ns };
SetWaitableTimer(g_ddraw->fps_limiter.htimer, &due_time, 0, NULL, NULL, FALSE);
}
else
{
FILETIME ft = { 0 };
GetSystemTimeAsFileTime(&ft);
if (CompareFileTime((FILETIME *)&ddraw->fpsLimiter.dueTime, &ft) == -1)
if (CompareFileTime((FILETIME *)&g_ddraw->fps_limiter.due_time, &ft) == -1)
{
memcpy(&ddraw->fpsLimiter.dueTime, &ft, sizeof(LARGE_INTEGER));
memcpy(&g_ddraw->fps_limiter.due_time, &ft, sizeof(LARGE_INTEGER));
}
else
{
WaitForSingleObject(ddraw->fpsLimiter.hTimer, ddraw->fpsLimiter.ticklength * 2);
WaitForSingleObject(g_ddraw->fps_limiter.htimer, g_ddraw->fps_limiter.tick_length * 2);
}
ddraw->fpsLimiter.dueTime.QuadPart += ddraw->fpsLimiter.tickLengthNs;
SetWaitableTimer(ddraw->fpsLimiter.hTimer, &ddraw->fpsLimiter.dueTime, 0, NULL, NULL, FALSE);
g_ddraw->fps_limiter.due_time.QuadPart += g_ddraw->fps_limiter.tick_length_ns;
SetWaitableTimer(g_ddraw->fps_limiter.htimer, &g_ddraw->fps_limiter.due_time, 0, NULL, NULL, FALSE);
}
}
else
{
tickEnd = timeGetTime();
tick_end = timeGetTime();
if (tickEnd - tickStart < ddraw->fpsLimiter.ticklength)
Sleep(ddraw->fpsLimiter.ticklength - (tickEnd - tickStart));
if (tick_end - tick_start < g_ddraw->fps_limiter.tick_length)
Sleep(g_ddraw->fps_limiter.tick_length - (tick_end - tick_start));
}
}
}

181
src/render_gdi.c Normal file
View file

@ -0,0 +1,181 @@
#include <windows.h>
#include <stdio.h>
#include "dd.h"
#include "ddsurface.h"
#include "opengl_utils.h"
#include "utils.h"
#include "wndproc.h"
DWORD WINAPI gdi_render_main(void)
{
DWORD warning_end_tick = timeGetTime() + (15 * 1000);
char warning_text[512] = { 0 };
if (g_ddraw->show_driver_warning)
{
g_ddraw->show_driver_warning = FALSE;
if (!g_ddraw->windowed)
PostMessage(g_ddraw->hwnd, WM_AUTORENDERER, 0, 0);
_snprintf(
warning_text, sizeof(warning_text),
"-WARNING- Using slow software rendering, please update your graphics card driver (%s)",
strlen(g_oglu_version) > 10 ? "" : g_oglu_version);
}
Sleep(500);
DWORD tick_start = 0;
DWORD tick_end = 0;
int max_fps = g_ddraw->render.maxfps;
g_ddraw->fps_limiter.tick_length_ns = 0;
g_ddraw->fps_limiter.tick_length = 0;
if (max_fps < 0)
max_fps = g_ddraw->mode.dmDisplayFrequency;
if (max_fps > 1000)
max_fps = 0;
if (max_fps > 0)
{
float len = 1000.0f / max_fps;
g_ddraw->fps_limiter.tick_length_ns = len * 10000;
g_ddraw->fps_limiter.tick_length = len + (g_ddraw->accurate_timers ? 0.5f : 0.0f);
}
while (g_ddraw->render.run &&
(g_ddraw->render.forcefps || WaitForSingleObject(g_ddraw->render.sem, 200) != WAIT_FAILED))
{
#if _DEBUG
DrawFrameInfoStart();
#endif
if (g_ddraw->fps_limiter.tick_length > 0)
tick_start = timeGetTime();
EnterCriticalSection(&g_ddraw->cs);
if (g_ddraw->primary && (g_ddraw->bpp == 16 || (g_ddraw->primary->palette && g_ddraw->primary->palette->data_rgb)))
{
if (warning_text[0])
{
if (timeGetTime() < warning_end_tick)
{
RECT rc = { 0, 0, g_ddraw->width, g_ddraw->height };
DrawText(g_ddraw->primary->hdc, warning_text, -1, &rc, DT_NOCLIP | DT_CENTER);
}
else
warning_text[0] = 0;
}
BOOL scale_cutscene = g_ddraw->vhack && util_detect_cutscene();
if (g_ddraw->vhack)
InterlockedExchange(&g_ddraw->incutscene, scale_cutscene);
if (!g_ddraw->handlemouse)
{
g_ddraw->child_window_exists = FALSE;
EnumChildWindows(g_ddraw->hwnd, util_enum_child_proc, (LPARAM)g_ddraw->primary);
}
if (g_ddraw->bnet_active)
{
RECT rc = { 0, 0, g_ddraw->render.width, g_ddraw->render.height };
FillRect(g_ddraw->render.hdc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));
}
else if (scale_cutscene)
{
StretchDIBits(
g_ddraw->render.hdc,
g_ddraw->render.viewport.x,
g_ddraw->render.viewport.y,
g_ddraw->render.viewport.width,
g_ddraw->render.viewport.height,
0,
g_ddraw->height - 400,
CUTSCENE_WIDTH,
CUTSCENE_HEIGHT,
g_ddraw->primary->surface,
g_ddraw->primary->bmi,
DIB_RGB_COLORS,
SRCCOPY);
}
else if (!g_ddraw->child_window_exists &&
(g_ddraw->render.width != g_ddraw->width || g_ddraw->render.height != g_ddraw->height))
{
StretchDIBits(
g_ddraw->render.hdc,
g_ddraw->render.viewport.x,
g_ddraw->render.viewport.y,
g_ddraw->render.viewport.width,
g_ddraw->render.viewport.height,
0,
0,
g_ddraw->width,
g_ddraw->height,
g_ddraw->primary->surface,
g_ddraw->primary->bmi,
DIB_RGB_COLORS,
SRCCOPY);
}
else
{
SetDIBitsToDevice(
g_ddraw->render.hdc,
0,
0,
g_ddraw->width,
g_ddraw->height,
0,
0,
0,
g_ddraw->height,
g_ddraw->primary->surface,
g_ddraw->primary->bmi,
DIB_RGB_COLORS);
}
}
LeaveCriticalSection(&g_ddraw->cs);
#if _DEBUG
DrawFrameInfoEnd();
#endif
if (g_ddraw->fps_limiter.tick_length > 0)
{
if (g_ddraw->fps_limiter.htimer)
{
FILETIME ft = { 0 };
GetSystemTimeAsFileTime(&ft);
if (CompareFileTime((FILETIME*)&g_ddraw->fps_limiter.due_time, &ft) == -1)
{
memcpy(&g_ddraw->fps_limiter.due_time, &ft, sizeof(LARGE_INTEGER));
}
else
{
WaitForSingleObject(g_ddraw->fps_limiter.htimer, g_ddraw->fps_limiter.tick_length * 2);
}
g_ddraw->fps_limiter.due_time.QuadPart += g_ddraw->fps_limiter.tick_length_ns;
SetWaitableTimer(g_ddraw->fps_limiter.htimer, &g_ddraw->fps_limiter.due_time, 0, NULL, NULL, FALSE);
}
else
{
tick_end = timeGetTime();
if (tick_end - tick_start < g_ddraw->fps_limiter.tick_length)
Sleep(g_ddraw->fps_limiter.tick_length - (tick_end - tick_start));
}
}
}
return TRUE;
}

1025
src/render_ogl.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,193 +0,0 @@
/*
* Copyright (c) 2011 Toni Spets <toni.spets@iki.fi>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <windows.h>
#include <stdio.h>
#include "main.h"
#include "surface.h"
#include "opengl.h"
BOOL ShowDriverWarning;
DWORD WINAPI render_soft_main(void)
{
DWORD warningEndTick = timeGetTime() + (15 * 1000);
char warningText[512] = { 0 };
if (ShowDriverWarning)
{
ShowDriverWarning = FALSE;
if (!ddraw->windowed)
PostMessage(ddraw->hWnd, WM_AUTORENDERER, 0, 0);
_snprintf(
warningText, sizeof(warningText),
"-WARNING- Using slow software rendering, please update your graphics card driver (%s)",
strlen(OpenGL_Version) > 10 ? "" : OpenGL_Version);
}
Sleep(500);
DWORD tickStart = 0;
DWORD tickEnd = 0;
int maxFPS = ddraw->render.maxfps;
ddraw->fpsLimiter.tickLengthNs = 0;
ddraw->fpsLimiter.ticklength = 0;
if (maxFPS < 0)
maxFPS = ddraw->mode.dmDisplayFrequency;
if (maxFPS > 1000)
maxFPS = 0;
if (maxFPS > 0)
{
float len = 1000.0f / maxFPS;
ddraw->fpsLimiter.tickLengthNs = len * 10000;
ddraw->fpsLimiter.ticklength = len + (ddraw->accurateTimers ? 0.5f : 0.0f);
}
while (ddraw->render.run &&
(ddraw->render.forcefps || WaitForSingleObject(ddraw->render.sem, 200) != WAIT_FAILED))
{
#if _DEBUG
DrawFrameInfoStart();
#endif
if (ddraw->fpsLimiter.ticklength > 0)
tickStart = timeGetTime();
EnterCriticalSection(&ddraw->cs);
if (ddraw->primary && (ddraw->bpp == 16 || (ddraw->primary->palette && ddraw->primary->palette->data_rgb)))
{
if (warningText[0])
{
if (timeGetTime() < warningEndTick)
{
RECT rc = { 0, 0, ddraw->width, ddraw->height };
DrawText(ddraw->primary->hDC, warningText, -1, &rc, DT_NOCLIP | DT_CENTER);
}
else
warningText[0] = 0;
}
BOOL scaleCutscene = ddraw->vhack && detect_cutscene();
if (ddraw->vhack)
InterlockedExchange(&ddraw->incutscene, scaleCutscene);
if (!ddraw->handlemouse)
{
ChildWindowExists = FALSE;
EnumChildWindows(ddraw->hWnd, EnumChildProc, (LPARAM)ddraw->primary);
}
if (ddraw->bnetActive)
{
RECT rc = { 0, 0, ddraw->render.width, ddraw->render.height };
FillRect(ddraw->render.hDC, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));
}
else if (scaleCutscene)
{
StretchDIBits(
ddraw->render.hDC,
ddraw->render.viewport.x,
ddraw->render.viewport.y,
ddraw->render.viewport.width,
ddraw->render.viewport.height,
0,
ddraw->height - 400,
CUTSCENE_WIDTH,
CUTSCENE_HEIGHT,
ddraw->primary->surface,
ddraw->primary->bmi,
DIB_RGB_COLORS,
SRCCOPY);
}
else if (!ChildWindowExists && (ddraw->render.width != ddraw->width || ddraw->render.height != ddraw->height))
{
StretchDIBits(
ddraw->render.hDC,
ddraw->render.viewport.x,
ddraw->render.viewport.y,
ddraw->render.viewport.width,
ddraw->render.viewport.height,
0,
0,
ddraw->width,
ddraw->height,
ddraw->primary->surface,
ddraw->primary->bmi,
DIB_RGB_COLORS,
SRCCOPY);
}
else
{
SetDIBitsToDevice(
ddraw->render.hDC,
0,
0,
ddraw->width,
ddraw->height,
0,
0,
0,
ddraw->height,
ddraw->primary->surface,
ddraw->primary->bmi,
DIB_RGB_COLORS);
}
}
LeaveCriticalSection(&ddraw->cs);
#if _DEBUG
DrawFrameInfoEnd();
#endif
if (ddraw->fpsLimiter.ticklength > 0)
{
if (ddraw->fpsLimiter.hTimer)
{
FILETIME ft = { 0 };
GetSystemTimeAsFileTime(&ft);
if (CompareFileTime((FILETIME*)&ddraw->fpsLimiter.dueTime, &ft) == -1)
{
memcpy(&ddraw->fpsLimiter.dueTime, &ft, sizeof(LARGE_INTEGER));
}
else
{
WaitForSingleObject(ddraw->fpsLimiter.hTimer, ddraw->fpsLimiter.ticklength * 2);
}
ddraw->fpsLimiter.dueTime.QuadPart += ddraw->fpsLimiter.tickLengthNs;
SetWaitableTimer(ddraw->fpsLimiter.hTimer, &ddraw->fpsLimiter.dueTime, 0, NULL, NULL, FALSE);
}
else
{
tickEnd = timeGetTime();
if (tickEnd - tickStart < ddraw->fpsLimiter.ticklength)
Sleep(ddraw->fpsLimiter.ticklength - (tickEnd - tickStart));
}
}
}
return TRUE;
}

View file

@ -1,28 +1,13 @@
/*
* Copyright (c) 2010 Toni Spets <toni.spets@iki.fi>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include "ddraw.h"
#include "palette.h"
#include "surface.h"
#include "dd.h"
#include "ddpalette.h"
#include "ddsurface.h"
#include "lodepng.h"
BOOL screenshot(struct IDirectDrawSurfaceImpl *src)
BOOL ss_take_screenshot(struct IDirectDrawSurfaceImpl *src)
{
if (!src || !src->palette || !src->surface)
return FALSE;
@ -33,7 +18,7 @@ BOOL screenshot(struct IDirectDrawSurfaceImpl *src)
char str_time[64];
time_t t = time(NULL);
strncpy(title, ddraw->title, sizeof(ddraw->title));
strncpy(title, g_ddraw->title, sizeof(g_ddraw->title));
for (i = 0; i<strlen(title); i++) {
if (title[i] == ' ')

File diff suppressed because it is too large Load diff

301
src/utils.c Normal file
View file

@ -0,0 +1,301 @@
#include <windows.h>
#include "ddraw.h"
#include "dd.h"
#include "ddsurface.h"
#include "hook.h"
#include "mouse.h"
#include "render_d3d9.h"
#include "utils.h"
#include "config.h"
void util_limit_game_ticks()
{
if (g_ddraw->ticks_limiter.htimer)
{
FILETIME ft = { 0 };
GetSystemTimeAsFileTime(&ft);
if (CompareFileTime((FILETIME *)&g_ddraw->ticks_limiter.due_time, &ft) == -1)
{
memcpy(&g_ddraw->ticks_limiter.due_time, &ft, sizeof(LARGE_INTEGER));
}
else
{
WaitForSingleObject(g_ddraw->ticks_limiter.htimer, g_ddraw->ticks_limiter.tick_length * 2);
}
g_ddraw->ticks_limiter.due_time.QuadPart += g_ddraw->ticks_limiter.tick_length_ns;
SetWaitableTimer(g_ddraw->ticks_limiter.htimer, &g_ddraw->ticks_limiter.due_time, 0, NULL, NULL, FALSE);
}
else
{
static DWORD next_game_tick;
if (!next_game_tick)
{
next_game_tick = timeGetTime();
return;
}
next_game_tick += g_ddraw->ticks_limiter.tick_length;
DWORD tick_count = timeGetTime();
int sleep_time = next_game_tick - tick_count;
if (sleep_time <= 0 || sleep_time > g_ddraw->ticks_limiter.tick_length)
next_game_tick = tick_count;
else
Sleep(sleep_time);
}
}
void util_update_bnet_pos(int new_x, int new_y)
{
static int old_x = -32000;
static int old_y = -32000;
if (old_x == -32000 || old_y == -32000 || !g_ddraw->bnet_active)
{
old_x = new_x;
old_y = new_y;
return;
}
POINT pt = { 0, 0 };
real_ClientToScreen(g_ddraw->hwnd, &pt);
RECT mainrc;
SetRect(&mainrc, pt.x, pt.y, pt.x + g_ddraw->width, pt.y + g_ddraw->height);
int adj_y = 0;
int adj_x = 0;
HWND hwnd = FindWindowEx(HWND_DESKTOP, NULL, "SDlgDialog", NULL);
while (hwnd != NULL)
{
RECT rc;
real_GetWindowRect(hwnd, &rc);
OffsetRect(&rc, new_x - old_x, new_y - old_y);
real_SetWindowPos(
hwnd,
0,
rc.left,
rc.top,
0,
0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
if (rc.bottom - rc.top <= g_ddraw->height)
{
if (rc.bottom > mainrc.bottom && abs(mainrc.bottom - rc.bottom) > abs(adj_y))
adj_y = mainrc.bottom - rc.bottom;
else if (rc.top < mainrc.top && abs(mainrc.top - rc.top) > abs(adj_y))
adj_y = mainrc.top - rc.top;
}
if (rc.right - rc.left <= g_ddraw->width)
{
if (rc.right > mainrc.right && abs(mainrc.right - rc.right) > abs(adj_x))
adj_x = mainrc.right - rc.right;
else if (rc.left < mainrc.left && abs(mainrc.left - rc.left) > abs(adj_x))
adj_x = mainrc.left - rc.left;
}
hwnd = FindWindowEx(HWND_DESKTOP, hwnd, "SDlgDialog", NULL);
}
if (adj_x || adj_y)
{
HWND hwnd = FindWindowEx(HWND_DESKTOP, NULL, "SDlgDialog", NULL);
while (hwnd != NULL)
{
RECT rc;
real_GetWindowRect(hwnd, &rc);
OffsetRect(&rc, adj_x, adj_y);
real_SetWindowPos(
hwnd,
0,
rc.left,
rc.top,
0,
0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
hwnd = FindWindowEx(HWND_DESKTOP, hwnd, "SDlgDialog", NULL);
}
}
old_x = new_x;
old_y = new_y;
}
BOOL util_get_lowest_resolution(float ratio, SIZE *out_res, DWORD min_width, DWORD min_height, DWORD max_width, DWORD max_height)
{
BOOL result = FALSE;
int org_ratio = (int)(ratio * 100);
SIZE lowest = { .cx = max_width + 1, .cy = max_height + 1 };
DWORD i = 0;
DEVMODE m;
memset(&m, 0, sizeof(DEVMODE));
m.dmSize = sizeof(DEVMODE);
while (EnumDisplaySettings(NULL, i, &m))
{
if (m.dmPelsWidth >= min_width &&
m.dmPelsHeight >= min_height &&
m.dmPelsWidth <= max_width &&
m.dmPelsHeight <= max_height &&
m.dmPelsWidth < lowest.cx &&
m.dmPelsHeight < lowest.cy)
{
int res_ratio = (int)(((float)m.dmPelsWidth / m.dmPelsHeight) * 100);
if (res_ratio == org_ratio)
{
result = TRUE;
out_res->cx = lowest.cx = m.dmPelsWidth;
out_res->cy = lowest.cy = m.dmPelsHeight;
}
}
memset(&m, 0, sizeof(DEVMODE));
m.dmSize = sizeof(DEVMODE);
i++;
}
return result;
}
void util_toggle_fullscreen()
{
if (g_ddraw->bnet_active)
return;
if (g_ddraw->windowed)
{
mouse_unlock();
g_config.window_state = g_ddraw->windowed = FALSE;
real_SetWindowLongA(g_ddraw->hwnd, GWL_STYLE, GetWindowLong(g_ddraw->hwnd, GWL_STYLE) & ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU));
g_ddraw->altenter = TRUE;
dd_SetDisplayMode(g_ddraw->width, g_ddraw->height, g_ddraw->bpp);
util_update_bnet_pos(0, 0);
mouse_lock();
}
else
{
mouse_unlock();
g_config.window_state = g_ddraw->windowed = TRUE;
if (g_ddraw->renderer == d3d9_render_main)
d3d9_reset();
else
ChangeDisplaySettings(NULL, g_ddraw->bnet_active ? CDS_FULLSCREEN : 0);
dd_SetDisplayMode(g_ddraw->width, g_ddraw->height, g_ddraw->bpp);
mouse_lock();
}
}
BOOL util_unadjust_window_rect(LPRECT prc, DWORD dwStyle, BOOL fMenu, DWORD dwExStyle)
{
RECT rc;
SetRectEmpty(&rc);
BOOL fRc = AdjustWindowRectEx(&rc, dwStyle, fMenu, dwExStyle);
if (fRc)
{
prc->left -= rc.left;
prc->top -= rc.top;
prc->right -= rc.right;
prc->bottom -= rc.bottom;
}
return fRc;
}
void util_set_window_rect(int x, int y, int width, int height, UINT flags)
{
if (g_ddraw->windowed)
{
if (g_ddraw->render.thread)
{
EnterCriticalSection(&g_ddraw->cs);
g_ddraw->render.run = FALSE;
ReleaseSemaphore(g_ddraw->render.sem, 1, NULL);
LeaveCriticalSection(&g_ddraw->cs);
WaitForSingleObject(g_ddraw->render.thread, INFINITE);
g_ddraw->render.thread = NULL;
}
if ((flags & SWP_NOMOVE) == 0)
{
g_config.window_rect.left = x;
g_config.window_rect.top = y;
}
if ((flags & SWP_NOSIZE) == 0)
{
g_config.window_rect.bottom = height;
g_config.window_rect.right = width;
}
dd_SetDisplayMode(g_ddraw->width, g_ddraw->height, g_ddraw->bpp);
}
}
BOOL CALLBACK util_enum_child_proc(HWND hwnd, LPARAM lparam)
{
IDirectDrawSurfaceImpl* this = (IDirectDrawSurfaceImpl*)lparam;
RECT size;
RECT pos;
if (real_GetClientRect(hwnd, &size) && real_GetWindowRect(hwnd, &pos) && size.right > 1 && size.bottom > 1)
{
g_ddraw->child_window_exists = TRUE;
HDC hdc = GetDC(hwnd);
MapWindowPoints(HWND_DESKTOP, g_ddraw->hwnd, (LPPOINT)&pos, 2);
BitBlt(hdc, 0, 0, size.right, size.bottom, this->hdc, pos.left, pos.top, SRCCOPY);
ReleaseDC(hwnd, hdc);
}
return FALSE;
}
static unsigned char util_get_pixel(int x, int y)
{
return ((unsigned char*)g_ddraw->primary->surface)[y * g_ddraw->primary->l_pitch + x * g_ddraw->primary->lx_pitch];
}
BOOL util_detect_cutscene()
{
static int* in_movie = (int*)0x00665F58;
static int* is_vqa_640 = (int*)0x0065D7BC;
static BYTE* should_stretch = (BYTE*)0x00607D78;
if (g_ddraw->width <= CUTSCENE_WIDTH || g_ddraw->height <= CUTSCENE_HEIGHT)
return FALSE;
if (g_ddraw->isredalert)
{
if ((*in_movie && !*is_vqa_640) || *should_stretch)
{
return TRUE;
}
return FALSE;
}
else if (g_ddraw->iscnc1)
{
return util_get_pixel(CUTSCENE_WIDTH + 1, 0) == 0 || util_get_pixel(CUTSCENE_WIDTH + 5, 1) == 0 ? TRUE : FALSE;
}
return FALSE;
}

425
src/winapi_hooks.c Normal file
View file

@ -0,0 +1,425 @@
#include <windows.h>
#include "dd.h"
#include "hook.h"
#include "config.h"
#include "utils.h"
#include "mouse.h"
#include "wndproc.h"
BOOL WINAPI fake_GetCursorPos(LPPOINT lpPoint)
{
POINT pt, realpt;
if (!real_GetCursorPos(&pt) || !g_ddraw)
return FALSE;
realpt.x = pt.x;
realpt.y = pt.y;
if(g_ddraw->locked && (!g_ddraw->windowed || real_ScreenToClient(g_ddraw->hwnd, &pt)))
{
//fallback solution for possible ClipCursor failure
int diffx = 0, diffy = 0;
int max_width = g_ddraw->adjmouse ? g_ddraw->render.viewport.width : g_ddraw->width;
int max_height = g_ddraw->adjmouse ? g_ddraw->render.viewport.height : g_ddraw->height;
if (pt.x < 0)
{
diffx = pt.x;
pt.x = 0;
}
if (pt.y < 0)
{
diffy = pt.y;
pt.y = 0;
}
if (pt.x > max_width)
{
diffx = pt.x - max_width;
pt.x = max_width;
}
if (pt.y > max_height)
{
diffy = pt.y - max_height;
pt.y = max_height;
}
if (diffx || diffy)
real_SetCursorPos(realpt.x - diffx, realpt.y - diffy);
if(g_ddraw->adjmouse)
{
g_ddraw->cursor.x = pt.x * g_ddraw->render.unscale_w;
g_ddraw->cursor.y = pt.y * g_ddraw->render.unscale_h;
}
else
{
g_ddraw->cursor.x = pt.x;
g_ddraw->cursor.y = pt.y;
}
if (g_ddraw->vhack && InterlockedExchangeAdd(&g_ddraw->incutscene, 0))
{
diffx = 0;
diffy = 0;
if (g_ddraw->cursor.x > CUTSCENE_WIDTH)
{
diffx = g_ddraw->cursor.x - CUTSCENE_WIDTH;
g_ddraw->cursor.x = CUTSCENE_WIDTH;
}
if (g_ddraw->cursor.y > CUTSCENE_HEIGHT)
{
diffy = g_ddraw->cursor.y - CUTSCENE_HEIGHT;
g_ddraw->cursor.y = CUTSCENE_HEIGHT;
}
if (diffx || diffy)
real_SetCursorPos(realpt.x - diffx, realpt.y - diffy);
}
}
if (lpPoint)
{
lpPoint->x = (int)g_ddraw->cursor.x;
lpPoint->y = (int)g_ddraw->cursor.y;
}
return TRUE;
}
BOOL WINAPI fake_ClipCursor(const RECT *lpRect)
{
if(lpRect)
{
/* hack for 640x480 mode */
if (lpRect->bottom == 400 && g_ddraw && g_ddraw->height == 480)
g_ddraw->mouse_y_adjust = 40;
}
return TRUE;
}
int WINAPI fake_ShowCursor(BOOL bShow)
{
static int count;
if (g_ddraw && !g_ddraw->handlemouse)
return real_ShowCursor(bShow);
return bShow ? ++count : --count;
}
HCURSOR WINAPI fake_SetCursor(HCURSOR hCursor)
{
if (g_ddraw && !g_ddraw->handlemouse)
return real_SetCursor(hCursor);
return NULL;
}
BOOL WINAPI fake_GetWindowRect(HWND hWnd, LPRECT lpRect)
{
if (lpRect && g_ddraw)
{
if (g_ddraw->hwnd == hWnd)
{
lpRect->bottom = g_ddraw->height;
lpRect->left = 0;
lpRect->right = g_ddraw->width;
lpRect->top = 0;
return TRUE;
}
else
{
if (real_GetWindowRect(hWnd, lpRect))
{
MapWindowPoints(HWND_DESKTOP, g_ddraw->hwnd, (LPPOINT)lpRect, 2);
return TRUE;
}
return FALSE;
}
}
return real_GetWindowRect(hWnd, lpRect);
}
BOOL WINAPI fake_GetClientRect(HWND hWnd, LPRECT lpRect)
{
if (lpRect && g_ddraw && g_ddraw->hwnd == hWnd)
{
lpRect->bottom = g_ddraw->height;
lpRect->left = 0;
lpRect->right = g_ddraw->width;
lpRect->top = 0;
return TRUE;
}
return real_GetClientRect(hWnd, lpRect);
}
BOOL WINAPI fake_ClientToScreen(HWND hWnd, LPPOINT lpPoint)
{
if (g_ddraw && g_ddraw->hwnd != hWnd)
return real_ClientToScreen(hWnd, lpPoint) && real_ScreenToClient(g_ddraw->hwnd, lpPoint);
return TRUE;
}
BOOL WINAPI fake_ScreenToClient(HWND hWnd, LPPOINT lpPoint)
{
if (g_ddraw && g_ddraw->hwnd != hWnd)
return real_ClientToScreen(g_ddraw->hwnd, lpPoint) && real_ScreenToClient(hWnd, lpPoint);
return TRUE;
}
BOOL WINAPI fake_SetCursorPos(int X, int Y)
{
POINT pt = { X, Y };
return g_ddraw && real_ClientToScreen(g_ddraw->hwnd, &pt) && real_SetCursorPos(pt.x, pt.y);
}
HWND WINAPI fake_WindowFromPoint(POINT Point)
{
POINT pt = { Point.x, Point.y };
return g_ddraw && real_ClientToScreen(g_ddraw->hwnd, &pt) ? real_WindowFromPoint(pt) : NULL;
}
BOOL WINAPI fake_GetClipCursor(LPRECT lpRect)
{
if (lpRect && g_ddraw)
{
lpRect->bottom = g_ddraw->height;
lpRect->left = 0;
lpRect->right = g_ddraw->width;
lpRect->top = 0;
return TRUE;
}
return FALSE;
}
BOOL WINAPI fake_GetCursorInfo(PCURSORINFO pci)
{
return pci && g_ddraw && real_GetCursorInfo(pci) && real_ScreenToClient(g_ddraw->hwnd, &pci->ptScreenPos);
}
int WINAPI fake_GetSystemMetrics(int nIndex)
{
if (g_ddraw)
{
if (nIndex == SM_CXSCREEN)
return g_ddraw->width;
if (nIndex == SM_CYSCREEN)
return g_ddraw->height;
}
return real_GetSystemMetrics(nIndex);
}
BOOL WINAPI fake_SetWindowPos(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags)
{
UINT reqFlags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER;
if (g_ddraw && g_ddraw->hwnd == hWnd && (uFlags & reqFlags) != reqFlags)
return TRUE;
return real_SetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
}
BOOL WINAPI fake_MoveWindow(HWND hWnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint)
{
if (g_ddraw && g_ddraw->hwnd == hWnd)
return TRUE;
return real_MoveWindow(hWnd, X, Y, nWidth, nHeight, bRepaint);
}
LRESULT WINAPI fake_SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
LRESULT result = real_SendMessageA(hWnd, Msg, wParam, lParam);
if (result && g_ddraw && Msg == CB_GETDROPPEDCONTROLRECT)
{
RECT *rc = (RECT *)lParam;
if (rc)
MapWindowPoints(HWND_DESKTOP, g_ddraw->hwnd, (LPPOINT)rc, 2);
}
return result;
}
LONG WINAPI fake_SetWindowLongA(HWND hWnd, int nIndex, LONG dwNewLong)
{
if (g_ddraw && g_ddraw->hwnd == hWnd && nIndex == GWL_STYLE)
return 0;
return real_SetWindowLongA(hWnd, nIndex, dwNewLong);
}
BOOL WINAPI fake_EnableWindow(HWND hWnd, BOOL bEnable)
{
if (g_ddraw && g_ddraw->hwnd == hWnd)
{
return FALSE;
}
return real_EnableWindow(hWnd, bEnable);
}
int WINAPI fake_GetDeviceCaps(HDC hdc, int index)
{
if (g_ddraw && g_ddraw->bpp && index == BITSPIXEL)
{
return g_ddraw->bpp;
}
return real_GetDeviceCaps(hdc, index);
}
HMODULE WINAPI fake_LoadLibraryA(LPCSTR lpLibFileName)
{
HMODULE hmod = real_LoadLibraryA(lpLibFileName);
hook_init();
return hmod;
}
HMODULE WINAPI fake_LoadLibraryW(LPCWSTR lpLibFileName)
{
HMODULE hmod = real_LoadLibraryW(lpLibFileName);
hook_init();
return hmod;
}
HMODULE WINAPI fake_LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
{
HMODULE hmod = real_LoadLibraryExA(lpLibFileName, hFile, dwFlags);
hook_init();
return hmod;
}
HMODULE WINAPI fake_LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
{
HMODULE hmod = real_LoadLibraryExW(lpLibFileName, hFile, dwFlags);
hook_init();
return hmod;
}
BOOL WINAPI fake_DestroyWindow(HWND hWnd)
{
BOOL result = real_DestroyWindow(hWnd);
if (g_ddraw && g_ddraw->hwnd != hWnd && g_ddraw->bnet_active)
{
RedrawWindow(NULL, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN);
if (!FindWindowEx(HWND_DESKTOP, NULL, "SDlgDialog", NULL))
{
g_ddraw->bnet_active = FALSE;
SetFocus(g_ddraw->hwnd);
mouse_lock();
if (g_ddraw->windowed)
{
g_ddraw->bnet_pos.x = g_ddraw->bnet_pos.y = 0;
real_ClientToScreen(g_ddraw->hwnd, &g_ddraw->bnet_pos);
if (!g_ddraw->bnet_was_upscaled)
{
int width = g_ddraw->bnet_win_rect.right - g_ddraw->bnet_win_rect.left;
int height = g_ddraw->bnet_win_rect.bottom - g_ddraw->bnet_win_rect.top;
UINT flags = width != g_ddraw->width || height != g_ddraw->height ? 0 : SWP_NOMOVE;
util_set_window_rect(g_ddraw->bnet_win_rect.left, g_ddraw->bnet_win_rect.top, width, height, flags);
}
g_ddraw->fullscreen = g_ddraw->bnet_was_upscaled;
SetTimer(g_ddraw->hwnd, IDT_TIMER_LEAVE_BNET, 1000, (TIMERPROC)NULL);
g_ddraw->resizable = TRUE;
}
}
}
return result;
}
HWND WINAPI fake_CreateWindowExA(
DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y,
int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
{
if (lpClassName && _strcmpi(lpClassName, "SDlgDialog") == 0 && g_ddraw)
{
if (!g_ddraw->bnet_active)
{
g_ddraw->bnet_was_upscaled = g_ddraw->fullscreen;
g_ddraw->fullscreen = FALSE;
if (!g_ddraw->windowed && !g_ddraw->bnet_was_fullscreen)
{
int ws = g_config.window_state;
util_toggle_fullscreen();
g_config.window_state = ws;
g_ddraw->bnet_was_fullscreen = TRUE;
}
real_GetClientRect(g_ddraw->hwnd, &g_ddraw->bnet_win_rect);
MapWindowPoints(g_ddraw->hwnd, HWND_DESKTOP, (LPPOINT)&g_ddraw->bnet_win_rect, 2);
int width = g_ddraw->bnet_win_rect.right - g_ddraw->bnet_win_rect.left;
int height = g_ddraw->bnet_win_rect.bottom - g_ddraw->bnet_win_rect.top;
int x = g_ddraw->bnet_pos.x || g_ddraw->bnet_pos.y ? g_ddraw->bnet_pos.x : -32000;
int y = g_ddraw->bnet_pos.x || g_ddraw->bnet_pos.y ? g_ddraw->bnet_pos.y : -32000;
UINT flags = width != g_ddraw->width || height != g_ddraw->height ? 0 : SWP_NOMOVE;
util_set_window_rect(x, y, g_ddraw->width, g_ddraw->height, flags);
g_ddraw->resizable = FALSE;
g_ddraw->bnet_active = TRUE;
mouse_unlock();
}
POINT pt = { 0, 0 };
real_ClientToScreen(g_ddraw->hwnd, &pt);
X += pt.x;
Y += pt.y;
dwStyle |= WS_CLIPCHILDREN;
}
return real_CreateWindowExA(
dwExStyle,
lpClassName,
lpWindowName,
dwStyle,
X,
Y,
nWidth,
nHeight,
hWndParent,
hMenu,
hInstance,
lpParam);
}

620
src/wndproc.c Normal file
View file

@ -0,0 +1,620 @@
#include <windows.h>
#include <windowsx.h>
#include "dllmain.h"
#include "dd.h"
#include "hook.h"
#include "mouse.h"
#include "render_d3d9.h"
#include "config.h"
#include "screenshot.h"
#include "winapi_hooks.h"
#include "wndproc.h"
#include "utils.h"
LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
RECT rc = { 0, 0, g_ddraw->render.width, g_ddraw->render.height };
static BOOL in_size_move = FALSE;
static int redraw_count = 0;
switch(uMsg)
{
//case WM_NCACTIVATE:
case WM_GETMINMAXINFO:
case WM_MOVING:
case WM_NCLBUTTONDOWN:
case WM_NCLBUTTONUP:
case WM_NCPAINT:
{
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
case WM_NCHITTEST:
{
LRESULT result = DefWindowProc(hWnd, uMsg, wParam, lParam);
if (!g_ddraw->resizable)
{
switch (result)
{
case HTBOTTOM:
case HTBOTTOMLEFT:
case HTBOTTOMRIGHT:
case HTLEFT:
case HTRIGHT:
case HTTOP:
case HTTOPLEFT:
case HTTOPRIGHT:
return HTBORDER;
}
}
return result;
}
case WM_SETCURSOR:
{
// show resize cursor on window borders
if ((HWND)wParam == g_ddraw->hwnd)
{
WORD message = HIWORD(lParam);
if (message == WM_MOUSEMOVE)
{
WORD htcode = LOWORD(lParam);
switch (htcode)
{
case HTCAPTION:
case HTMINBUTTON:
case HTMAXBUTTON:
case HTCLOSE:
case HTBOTTOM:
case HTBOTTOMLEFT:
case HTBOTTOMRIGHT:
case HTLEFT:
case HTRIGHT:
case HTTOP:
case HTTOPLEFT:
case HTTOPRIGHT:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
case HTCLIENT:
if (!g_ddraw->locked)
return DefWindowProc(hWnd, uMsg, wParam, lParam);
default:
break;
}
}
}
break;
}
case WM_D3D9DEVICELOST:
{
if (g_ddraw->renderer == d3d9_render_main && d3d9_on_device_lost())
{
if (!g_ddraw->windowed)
mouse_lock();
}
return 0;
}
case WM_TIMER:
{
switch (wParam)
{
case IDT_TIMER_LEAVE_BNET:
{
KillTimer(g_ddraw->hwnd, IDT_TIMER_LEAVE_BNET);
if (!g_ddraw->windowed)
g_ddraw->bnet_was_fullscreen = FALSE;
if (!g_ddraw->bnet_active)
{
if (g_ddraw->bnet_was_fullscreen)
{
int ws = g_config.window_state;
util_toggle_fullscreen();
g_config.window_state = ws;
g_ddraw->bnet_was_fullscreen = FALSE;
}
else if (g_ddraw->bnet_was_upscaled)
{
util_set_window_rect(0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
g_ddraw->bnet_was_upscaled = FALSE;
}
}
return 0;
}
}
break;
}
case WM_WINDOWPOSCHANGED:
{
WINDOWPOS *pos = (WINDOWPOS *)lParam;
if (g_ddraw->wine && !g_ddraw->windowed && (pos->x > 0 || pos->y > 0) && g_ddraw->last_set_window_pos_tick + 500 < timeGetTime())
PostMessage(g_ddraw->hwnd, WM_WINEFULLSCREEN, 0, 0);
break;
}
case WM_WINEFULLSCREEN:
{
if (!g_ddraw->windowed)
{
g_ddraw->last_set_window_pos_tick = timeGetTime();
real_SetWindowPos(g_ddraw->hwnd, HWND_TOPMOST, 1, 1, g_ddraw->render.width, g_ddraw->render.height, SWP_SHOWWINDOW);
real_SetWindowPos(g_ddraw->hwnd, HWND_TOPMOST, 0, 0, g_ddraw->render.width, g_ddraw->render.height, SWP_SHOWWINDOW);
}
return 0;
}
case WM_ENTERSIZEMOVE:
{
if (g_ddraw->windowed)
{
in_size_move = TRUE;
}
break;
}
case WM_EXITSIZEMOVE:
{
if (g_ddraw->windowed)
{
in_size_move = FALSE;
if (!g_ddraw->render.thread)
dd_SetDisplayMode(g_ddraw->width, g_ddraw->height, g_ddraw->bpp);
}
break;
}
case WM_SIZING:
{
RECT *windowrc = (RECT *)lParam;
if (g_ddraw->windowed)
{
if (in_size_move)
{
if (g_ddraw->render.thread)
{
EnterCriticalSection(&g_ddraw->cs);
g_ddraw->render.run = FALSE;
ReleaseSemaphore(g_ddraw->render.sem, 1, NULL);
LeaveCriticalSection(&g_ddraw->cs);
WaitForSingleObject(g_ddraw->render.thread, INFINITE);
g_ddraw->render.thread = NULL;
}
RECT clientrc = { 0 };
// maintain aspect ratio
if (g_ddraw->maintas &&
CopyRect(&clientrc, windowrc) &&
util_unadjust_window_rect(&clientrc, GetWindowLong(hWnd, GWL_STYLE), FALSE, GetWindowLong(hWnd, GWL_EXSTYLE)) &&
SetRect(&clientrc, 0, 0, clientrc.right - clientrc.left, clientrc.bottom - clientrc.top))
{
float scaleH = (float)g_ddraw->height / g_ddraw->width;
float scaleW = (float)g_ddraw->width / g_ddraw->height;
switch (wParam)
{
case WMSZ_BOTTOMLEFT:
case WMSZ_BOTTOMRIGHT:
case WMSZ_LEFT:
case WMSZ_RIGHT:
{
windowrc->bottom += scaleH * clientrc.right - clientrc.bottom;
break;
}
case WMSZ_TOP:
case WMSZ_BOTTOM:
{
windowrc->right += scaleW * clientrc.bottom - clientrc.right;
break;
}
case WMSZ_TOPRIGHT:
case WMSZ_TOPLEFT:
{
windowrc->top -= scaleH * clientrc.right - clientrc.bottom;
break;
}
}
}
//enforce minimum window size
if (CopyRect(&clientrc, windowrc) &&
util_unadjust_window_rect(&clientrc, GetWindowLong(hWnd, GWL_STYLE), FALSE, GetWindowLong(hWnd, GWL_EXSTYLE)) &&
SetRect(&clientrc, 0, 0, clientrc.right - clientrc.left, clientrc.bottom - clientrc.top))
{
if (clientrc.right < g_ddraw->width)
{
switch (wParam)
{
case WMSZ_TOPRIGHT:
case WMSZ_BOTTOMRIGHT:
case WMSZ_RIGHT:
case WMSZ_BOTTOM:
case WMSZ_TOP:
{
windowrc->right += g_ddraw->width - clientrc.right;
break;
}
case WMSZ_TOPLEFT:
case WMSZ_BOTTOMLEFT:
case WMSZ_LEFT:
{
windowrc->left -= g_ddraw->width - clientrc.right;
break;
}
}
}
if (clientrc.bottom < g_ddraw->height)
{
switch (wParam)
{
case WMSZ_BOTTOMLEFT:
case WMSZ_BOTTOMRIGHT:
case WMSZ_BOTTOM:
case WMSZ_RIGHT:
case WMSZ_LEFT:
{
windowrc->bottom += g_ddraw->height - clientrc.bottom;
break;
}
case WMSZ_TOPLEFT:
case WMSZ_TOPRIGHT:
case WMSZ_TOP:
{
windowrc->top -= g_ddraw->height - clientrc.bottom;
break;
}
}
}
}
//save new window position
if (CopyRect(&clientrc, windowrc) &&
util_unadjust_window_rect(&clientrc, GetWindowLong(hWnd, GWL_STYLE), FALSE, GetWindowLong(hWnd, GWL_EXSTYLE)))
{
g_config.window_rect.left = clientrc.left;
g_config.window_rect.top = clientrc.top;
g_config.window_rect.right = clientrc.right - clientrc.left;
g_config.window_rect.bottom = clientrc.bottom - clientrc.top;
}
return TRUE;
}
}
break;
}
case WM_SIZE:
{
if (g_ddraw->windowed)
{
if (wParam == SIZE_RESTORED)
{
if (in_size_move && !g_ddraw->render.thread)
{
g_config.window_rect.right = LOWORD(lParam);
g_config.window_rect.bottom = HIWORD(lParam);
}
/*
else if (g_ddraw->wine)
{
WindowRect.right = LOWORD(lParam);
WindowRect.bottom = HIWORD(lParam);
if (WindowRect.right != g_ddraw->render.width || WindowRect.bottom != g_ddraw->render.height)
dd_SetDisplayMode(g_ddraw->width, g_ddraw->height, g_ddraw->bpp);
}
*/
}
}
if (!g_ddraw->handlemouse)
{
redraw_count = 2;
RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
}
return DefWindowProc(hWnd, uMsg, wParam, lParam); /* Carmageddon fix */
}
case WM_MOVE:
{
if (g_ddraw->windowed)
{
int x = (int)(short)LOWORD(lParam);
int y = (int)(short)HIWORD(lParam);
if (x != -32000 && y != -32000)
util_update_bnet_pos(x, y);
if (in_size_move || g_ddraw->wine)
{
if (x != -32000)
g_config.window_rect.left = x; // -32000 = Exit/Minimize
if (y != -32000)
g_config.window_rect.top = y;
}
}
if (!g_ddraw->handlemouse)
RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
if (g_ddraw->sierrahack)
{
lParam = 0;
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam); /* Carmageddon fix */
}
/* C&C and RA really don't want to close down */
case WM_SYSCOMMAND:
if (wParam == SC_CLOSE && !GameHandlesClose)
{
exit(0);
}
if (wParam == SC_KEYMENU)
return 0;
if (!GameHandlesClose)
return DefWindowProc(hWnd, uMsg, wParam, lParam);
break;
//workaround for a bug where sometimes a background window steals the focus
case WM_WINDOWPOSCHANGING:
{
if (g_ddraw->locked)
{
WINDOWPOS *pos = (WINDOWPOS *)lParam;
if (pos->flags == SWP_NOMOVE + SWP_NOSIZE)
{
mouse_unlock();
if (GetForegroundWindow() == g_ddraw->hwnd)
mouse_lock();
}
}
break;
}
case WM_MOUSELEAVE:
mouse_unlock();
return 0;
case WM_ACTIVATE:
if (wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE)
{
if (!g_ddraw->windowed)
{
if (g_ddraw->renderer != d3d9_render_main)
{
ChangeDisplaySettings(&g_ddraw->render.mode, CDS_FULLSCREEN);
if (wParam == WA_ACTIVE)
{
mouse_lock();
}
}
}
if (!g_ddraw->handlemouse)
RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
}
else if (wParam == WA_INACTIVE)
{
if (!g_ddraw->windowed && !g_ddraw->locked && g_ddraw->noactivateapp && !g_ddraw->devmode)
return 0;
mouse_unlock();
if (g_ddraw->wine && g_ddraw->last_set_window_pos_tick + 500 > timeGetTime())
return 0;
/* minimize our window on defocus when in fullscreen */
if (!g_ddraw->windowed)
{
if (g_ddraw->renderer != d3d9_render_main)
{
ShowWindow(g_ddraw->hwnd, SW_MINIMIZE);
ChangeDisplaySettings(NULL, g_ddraw->bnet_active ? CDS_FULLSCREEN : 0);
}
}
}
return 0;
case WM_ACTIVATEAPP:
/* C&C and RA stop drawing when they receive this with FALSE wParam, disable in windowed mode */
if (g_ddraw->windowed || g_ddraw->noactivateapp)
{
// let it pass through once (tiberian sun)
static BOOL one_time;
if (wParam && !one_time && !g_ddraw->handlemouse && g_ddraw->noactivateapp)
{
one_time = TRUE;
break;
}
return 0;
}
break;
case WM_AUTORENDERER:
{
mouse_unlock();
real_SetWindowPos(g_ddraw->hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
real_SetWindowPos(g_ddraw->hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
mouse_lock();
return 0;
}
case WM_NCLBUTTONDBLCLK:
{
util_toggle_fullscreen();
return 0;
}
case WM_SYSKEYDOWN:
{
BOOL context_code = (lParam & (1 << 29)) != 0;
BOOL key_state = (lParam & (1 << 30)) != 0;
if (wParam == VK_RETURN && context_code && !key_state)
{
util_toggle_fullscreen();
return 0;
}
break;
}
case WM_KEYDOWN:
if(wParam == VK_CONTROL || wParam == VK_TAB)
{
if(GetAsyncKeyState(VK_CONTROL) & 0x8000 && GetAsyncKeyState(VK_TAB) & 0x8000)
{
mouse_unlock();
return 0;
}
}
if (wParam == VK_CONTROL || wParam == VK_MENU)
{
if ((GetAsyncKeyState(VK_RMENU) & 0x8000) && GetAsyncKeyState(VK_RCONTROL) & 0x8000)
{
mouse_unlock();
return 0;
}
}
break;
case WM_KEYUP:
if (wParam == VK_SNAPSHOT)
ss_take_screenshot(g_ddraw->primary);
break;
/* button up messages reactivate cursor lock */
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
if (!g_ddraw->devmode && !g_ddraw->locked)
{
int x = GET_X_LPARAM(lParam);
int y = GET_Y_LPARAM(lParam);
if (x > g_ddraw->render.viewport.x + g_ddraw->render.viewport.width ||
x < g_ddraw->render.viewport.x ||
y > g_ddraw->render.viewport.y + g_ddraw->render.viewport.height ||
y < g_ddraw->render.viewport.y)
{
g_ddraw->cursor.x = g_ddraw->width / 2;
g_ddraw->cursor.y = g_ddraw->height / 2;
}
else
{
g_ddraw->cursor.x = (x - g_ddraw->render.viewport.x) * g_ddraw->render.unscale_w;
g_ddraw->cursor.y = (y - g_ddraw->render.viewport.y) * g_ddraw->render.unscale_h;
}
mouse_lock();
return 0;
}
/* fall through for lParam */
/* down messages are ignored if we have no cursor lock */
case WM_XBUTTONDBLCLK:
case WM_XBUTTONDOWN:
case WM_XBUTTONUP:
case WM_MOUSEWHEEL:
case WM_MOUSEHOVER:
case WM_LBUTTONDBLCLK:
case WM_MBUTTONDBLCLK:
case WM_RBUTTONDBLCLK:
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_MOUSEMOVE:
if (!g_ddraw->devmode)
{
if (!g_ddraw->locked)
{
return 0;
}
if(g_ddraw->adjmouse)
{
fake_GetCursorPos(NULL); /* update our own cursor */
lParam = MAKELPARAM(g_ddraw->cursor.x, g_ddraw->cursor.y);
}
}
if (g_ddraw->devmode)
{
mouse_lock();
g_ddraw->cursor.x = GET_X_LPARAM(lParam);
g_ddraw->cursor.y = GET_Y_LPARAM(lParam);
}
break;
case WM_PARENTNOTIFY:
{
if (!g_ddraw->handlemouse)
{
switch (LOWORD(wParam))
{
case WM_DESTROY: //Workaround for invisible menu on Load/Save/Delete in Tiberian Sun
redraw_count = 2;
break;
case WM_LBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_XBUTTONDOWN:
{
if (!g_ddraw->devmode && !g_ddraw->locked)
{
int x = GET_X_LPARAM(lParam);
int y = GET_Y_LPARAM(lParam);
g_ddraw->cursor.x = (x - g_ddraw->render.viewport.x) * g_ddraw->render.unscale_w;
g_ddraw->cursor.y = (y - g_ddraw->render.viewport.y) * g_ddraw->render.unscale_h;
g_ddraw->hidecursor = FALSE;
mouse_lock();
}
break;
}
}
}
break;
}
case WM_PAINT:
{
if (!g_ddraw->handlemouse && redraw_count > 0)
{
redraw_count--;
RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
}
EnterCriticalSection(&g_ddraw->cs);
ReleaseSemaphore(g_ddraw->render.sem, 1, NULL);
LeaveCriticalSection(&g_ddraw->cs);
break;
}
case WM_ERASEBKGND:
{
EnterCriticalSection(&g_ddraw->cs);
FillRect(g_ddraw->render.hdc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));
ReleaseSemaphore(g_ddraw->render.sem, 1, NULL);
LeaveCriticalSection(&g_ddraw->cs);
break;
}
}
return g_ddraw->wndproc(hWnd, uMsg, wParam, lParam);
}