diff --git a/Makefile b/Makefile index 92071d1..5805122 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/cnc-ddraw.vcxproj b/cnc-ddraw.vcxproj index 3781845..ebdd647 100644 --- a/cnc-ddraw.vcxproj +++ b/cnc-ddraw.vcxproj @@ -11,7 +11,7 @@ - + @@ -26,37 +26,58 @@ true - + + + + + + + - + - - - + + + - + - - + + + + - + + + + + + + + + - - - + + + - + + - + + + + + diff --git a/cnc-ddraw.vcxproj.filters b/cnc-ddraw.vcxproj.filters index 24513d4..8f64818 100644 --- a/cnc-ddraw.vcxproj.filters +++ b/cnc-ddraw.vcxproj.filters @@ -16,53 +16,26 @@ {af194dd7-3316-4887-93d6-9f2af2135f94} + + {37ee5b88-e57f-4c55-a43e-e475cf4e8920} + - - Source Files - Source Files - - Source Files - Source Files - - Source Files - - - Source Files - - - Source Files - Source Files - - Source Files - - - Source Files - Source Files - - Source Files - Source Files - - Source Files - - - Source Files - Source Files\detours @@ -96,35 +69,71 @@ Source Files\detours + + Source Files + + + Source Files\IDirectDraw + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files\IDirectDraw + + + Source Files + + + Source Files\IDirectDraw + + + Source Files + + + Source Files\IDirectDraw + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + - - Header Files - Header Files Header Files - - Header Files - - - Header Files - - - Header Files - - - Header Files - Header Files - - Header Files - Header Files @@ -146,6 +155,63 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + diff --git a/ddraw.def b/ddraw.def index 855453b..c537348 100644 --- a/ddraw.def +++ b/ddraw.def @@ -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 diff --git a/ddraw.rc b/ddraw.rc index e2913cc..b34cb4a 100644 --- a/ddraw.rc +++ b/ddraw.rc @@ -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) diff --git a/inc/IDirectDraw.h b/inc/IDirectDraw.h new file mode 100644 index 0000000..b9d7550 --- /dev/null +++ b/inc/IDirectDraw.h @@ -0,0 +1,71 @@ +#ifndef IDIRECTDRAW_H +#define IDIRECTDRAW_H + +#define WIN32_LEAN_AND_MEAN +#include +#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 diff --git a/inc/IDirectDrawClipper.h b/inc/IDirectDrawClipper.h new file mode 100644 index 0000000..186695a --- /dev/null +++ b/inc/IDirectDrawClipper.h @@ -0,0 +1,40 @@ +#ifndef IDIRECTDRAWCLIPPER_H +#define IDIRECTDRAWCLIPPER_H + +#define WIN32_LEAN_AND_MEAN +#include +#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 diff --git a/inc/IDirectDrawPalette.h b/inc/IDirectDrawPalette.h new file mode 100644 index 0000000..3762897 --- /dev/null +++ b/inc/IDirectDrawPalette.h @@ -0,0 +1,42 @@ +#ifndef IDIRECTDRAWPALETTE_H +#define IDIRECTDRAWPALETTE_H + +#define WIN32_LEAN_AND_MEAN +#include +#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 diff --git a/inc/surface.h b/inc/IDirectDrawSurface.h similarity index 74% rename from inc/surface.h rename to inc/IDirectDrawSurface.h index 45631c1..b015fea 100644 --- a/inc/surface.h +++ b/inc/IDirectDrawSurface.h @@ -1,38 +1,20 @@ -/* - * Copyright (c) 2010 Toni Spets - * - * 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 +#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 diff --git a/inc/clipper.h b/inc/clipper.h deleted file mode 100644 index f716dcb..0000000 --- a/inc/clipper.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2010 Toni Spets - * - * 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 -#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 diff --git a/inc/config.h b/inc/config.h new file mode 100644 index 0000000..a63dc4f --- /dev/null +++ b/inc/config.h @@ -0,0 +1,23 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#define WIN32_LEAN_AND_MEAN +#include + + +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 diff --git a/inc/d3d9shader.h b/inc/d3d9shader.h index f2bad6b..6d32268 100644 --- a/inc/d3d9shader.h +++ b/inc/d3d9shader.h @@ -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 \ No newline at end of file diff --git a/inc/dd.h b/inc/dd.h new file mode 100644 index 0000000..f33a288 --- /dev/null +++ b/inc/dd.h @@ -0,0 +1,118 @@ +#ifndef DD_H +#define DD_H + +#define WIN32_LEAN_AND_MEAN +#include +#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 diff --git a/inc/ddclipper.h b/inc/ddclipper.h new file mode 100644 index 0000000..499b818 --- /dev/null +++ b/inc/ddclipper.h @@ -0,0 +1,11 @@ +#ifndef DDCLIPPER_H +#define DDCLIPPER_H + +#define WIN32_LEAN_AND_MEAN +#include +#include "ddraw.h" + + +HRESULT dd_CreateClipper(DWORD dwFlags, LPDIRECTDRAWCLIPPER FAR* lplpDDClipper, IUnknown FAR* pUnkOuter); + +#endif diff --git a/inc/ddpalette.h b/inc/ddpalette.h new file mode 100644 index 0000000..7bf3c92 --- /dev/null +++ b/inc/ddpalette.h @@ -0,0 +1,14 @@ +#ifndef DDPALETTE_H +#define DDPALETTE_H + +#define WIN32_LEAN_AND_MEAN +#include +#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 diff --git a/inc/ddraw.h b/inc/ddraw.h index 7923059..893a292 100644 --- a/inc/ddraw.h +++ b/inc/ddraw.h @@ -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 diff --git a/inc/ddsurface.h b/inc/ddsurface.h new file mode 100644 index 0000000..5f9f388 --- /dev/null +++ b/inc/ddsurface.h @@ -0,0 +1,32 @@ +#ifndef DDSURFACE_H +#define DDSURFACE_H + +#define WIN32_LEAN_AND_MEAN +#include +#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 diff --git a/inc/debug.h b/inc/debug.h index 19d9907..1e9165c 100644 --- a/inc/debug.h +++ b/inc/debug.h @@ -1,17 +1,25 @@ -#pragma once +#ifndef DEBUG_H +#define DEBUG_H + #define WIN32_LEAN_AND_MEAN #include -#include -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 diff --git a/inc/directinput.h b/inc/directinput.h new file mode 100644 index 0000000..50f251d --- /dev/null +++ b/inc/directinput.h @@ -0,0 +1,7 @@ +#ifndef DINPUTINPUT_H +#define DINPUTINPUT_H + +void dinput_hook(); +void dinput_unhook(); + +#endif diff --git a/inc/dllmain.h b/inc/dllmain.h new file mode 100644 index 0000000..78a2ff6 --- /dev/null +++ b/inc/dllmain.h @@ -0,0 +1,16 @@ +#ifndef DLLMAIN_H +#define DLLMAIN_H + +#define WIN32_LEAN_AND_MEAN +#include + +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 diff --git a/inc/hook.h b/inc/hook.h index 71c5714..8721f89 100644 --- a/inc/hook.h +++ b/inc/hook.h @@ -1,8 +1,10 @@ #ifndef HOOK_H #define HOOK_H +#define WIN32_LEAN_AND_MEAN #include + 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 diff --git a/inc/main.h b/inc/main.h deleted file mode 100644 index 9e12e5e..0000000 --- a/inc/main.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2010 Toni Spets - * - * 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 -#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 diff --git a/inc/mouse.h b/inc/mouse.h index 549bb39..b3c6460 100644 --- a/inc/mouse.h +++ b/inc/mouse.h @@ -1,37 +1,8 @@ #ifndef MOUSE_H #define MOUSE_H -#include - 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 diff --git a/inc/opengl.h b/inc/opengl_utils.h similarity index 91% rename from inc/opengl.h rename to inc/opengl_utils.h index ce46f55..a8046f4 100644 --- a/inc/opengl.h +++ b/inc/opengl_utils.h @@ -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 diff --git a/inc/openglshader.h b/inc/openglshader.h index 3edd3a6..5e08d6d 100644 --- a/inc/openglshader.h +++ b/inc/openglshader.h @@ -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 diff --git a/inc/palette.h b/inc/palette.h deleted file mode 100644 index 5132ee7..0000000 --- a/inc/palette.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2010 Toni Spets - * - * 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 -#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 diff --git a/inc/render_d3d9.h b/inc/render_d3d9.h index f2054bd..472a774 100644 --- a/inc/render_d3d9.h +++ b/inc/render_d3d9.h @@ -1,11 +1,35 @@ -#pragma once +#ifndef RENDER_D3D9_H +#define RENDER_D3D9_H + +#define WIN32_LEAN_AND_MEAN +#include +#include + +#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 diff --git a/inc/render_gdi.h b/inc/render_gdi.h new file mode 100644 index 0000000..caf9dab --- /dev/null +++ b/inc/render_gdi.h @@ -0,0 +1,10 @@ +#ifndef RENDER_GDI_H +#define RENDER_GDI_H + +#define WIN32_LEAN_AND_MEAN +#include + + +DWORD WINAPI gdi_render_main(void); + +#endif diff --git a/inc/render_ogl.h b/inc/render_ogl.h new file mode 100644 index 0000000..4fb46dc --- /dev/null +++ b/inc/render_ogl.h @@ -0,0 +1,40 @@ +#ifndef RENDER_OGL_H +#define RENDER_OGL_H + +#include +#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 diff --git a/inc/screenshot.h b/inc/screenshot.h new file mode 100644 index 0000000..f3289ea --- /dev/null +++ b/inc/screenshot.h @@ -0,0 +1,10 @@ +#ifndef SCREENSHOT_H +#define SCREENSHOT_H + +#define WIN32_LEAN_AND_MEAN +#include +#include "ddsurface.h" + +BOOL ss_take_screenshot(struct IDirectDrawSurfaceImpl* src); + +#endif diff --git a/inc/utils.h b/inc/utils.h new file mode 100644 index 0000000..293a565 --- /dev/null +++ b/inc/utils.h @@ -0,0 +1,20 @@ +#ifndef UTILS_H +#define UTILS_H + +#define WIN32_LEAN_AND_MEAN +#include + +#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 diff --git a/inc/winapi_hooks.h b/inc/winapi_hooks.h new file mode 100644 index 0000000..ecff33f --- /dev/null +++ b/inc/winapi_hooks.h @@ -0,0 +1,36 @@ +#ifndef WINAPI_HOOKS_H +#define WINAPI_HOOKS_H + +#define WIN32_LEAN_AND_MEAN +#include + + +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 diff --git a/inc/wndproc.h b/inc/wndproc.h new file mode 100644 index 0000000..14cce2a --- /dev/null +++ b/inc/wndproc.h @@ -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 diff --git a/src/IDirectDraw/IDirectDraw.c b/src/IDirectDraw/IDirectDraw.c new file mode 100644 index 0000000..bf3a4d4 --- /dev/null +++ b/src/IDirectDraw/IDirectDraw.c @@ -0,0 +1,369 @@ +#include +#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, +}; diff --git a/src/IDirectDraw/IDirectDrawClipper.c b/src/IDirectDraw/IDirectDrawClipper.c new file mode 100644 index 0000000..06c8c3c --- /dev/null +++ b/src/IDirectDraw/IDirectDrawClipper.c @@ -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 +}; diff --git a/src/IDirectDraw/IDirectDrawPalette.c b/src/IDirectDraw/IDirectDrawPalette.c new file mode 100644 index 0000000..74dcc19 --- /dev/null +++ b/src/IDirectDraw/IDirectDrawPalette.c @@ -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 +}; diff --git a/src/IDirectDraw/IDirectDrawSurface.c b/src/IDirectDraw/IDirectDrawSurface.c new file mode 100644 index 0000000..8b22601 --- /dev/null +++ b/src/IDirectDraw/IDirectDrawSurface.c @@ -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 +}; diff --git a/src/clipper.c b/src/clipper.c deleted file mode 100644 index fd70511..0000000 --- a/src/clipper.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2010 Toni Spets - * - * 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 -#include -#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; -} diff --git a/src/settings.c b/src/config.c similarity index 67% rename from src/settings.c rename to src/config.c index b923bda..b059801 100644 --- a/src/settings.c +++ b/src/config.c @@ -2,214 +2,205 @@ #include #include #include -#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); } diff --git a/src/dd.c b/src/dd.c new file mode 100644 index 0000000..ed67f60 --- /dev/null +++ b/src/dd.c @@ -0,0 +1,776 @@ +#include +#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; +} diff --git a/src/ddclipper.c b/src/ddclipper.c new file mode 100644 index 0000000..81847f6 --- /dev/null +++ b/src/ddclipper.c @@ -0,0 +1,21 @@ +#define WIN32_LEAN_AND_MEAN +#include +#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; +} diff --git a/src/ddpalette.c b/src/ddpalette.c new file mode 100644 index 0000000..892ad91 --- /dev/null +++ b/src/ddpalette.c @@ -0,0 +1,65 @@ +#define WIN32_LEAN_AND_MEAN +#include +#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; +} diff --git a/src/ddsurface.c b/src/ddsurface.c new file mode 100644 index 0000000..2e3311b --- /dev/null +++ b/src/ddsurface.c @@ -0,0 +1,887 @@ +#include +#include +#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; +} diff --git a/src/debug.c b/src/debug.c index b9e08f2..085f4d6 100644 --- a/src/debug.c +++ b/src/debug.c @@ -1,41 +1,72 @@ - #include #include -#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 } diff --git a/src/dinput.c b/src/dinput.c deleted file mode 100644 index 55f97ba..0000000 --- a/src/dinput.c +++ /dev/null @@ -1,99 +0,0 @@ -#include -#include -#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")); -} diff --git a/src/directinput.c b/src/directinput.c new file mode 100644 index 0000000..b6a5c51 --- /dev/null +++ b/src/directinput.c @@ -0,0 +1,101 @@ + +#include +#include +#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")); +} diff --git a/src/dllmain.c b/src/dllmain.c new file mode 100644 index 0000000..1fc519c --- /dev/null +++ b/src/dllmain.c @@ -0,0 +1,181 @@ +#include +#include +#include +#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; +} diff --git a/src/hook.c b/src/hook.c index 41f6420..fd8037a 100644 --- a/src/hook.c +++ b/src/hook.c @@ -1,15 +1,18 @@ +#define WIN32_LEAN_AND_MEAN #include #include -#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); } } } diff --git a/src/main.c b/src/main.c deleted file mode 100644 index 600eceb..0000000 --- a/src/main.c +++ /dev/null @@ -1,2035 +0,0 @@ -/* - * Copyright (c) 2010 Toni Spets - * - * 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 -#include -#include -#include -#include -#include -#include -#include "ddraw.h" -#include "main.h" -#include "opengl.h" -#include "palette.h" -#include "surface.h" -#include "clipper.h" -#include "hook.h" -#include "mouse.h" -#include "render_d3d9.h" - -#define IDR_MYMENU 93 - -BOOL screenshot(struct IDirectDrawSurfaceImpl *); -void Settings_Load(); -void Settings_Save(RECT *lpRect, int windowState); -void DInput_Hook(); -void DInput_UnHook(); - -IDirectDrawImpl *ddraw = NULL; - -RECT WindowRect = { .left = -32000, .top = -32000, .right = 0, .bottom = 0 }; -int WindowState = -1; -BOOL Direct3D9Active; -BOOL GameHandlesClose; -BOOL ChildWindowExists; -DWORD NvOptimusEnablement = 1; -DWORD AmdPowerXpressRequestHighPerformance = 1; -HMODULE DDrawModule; - -//BOOL WINAPI DllMainCRTStartup(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved) -BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved) -{ - switch (dwReason) - { - case DLL_PROCESS_ATTACH: - { - DDrawModule = 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); - - //return FALSE; - break; - } - - s = strtok(NULL, " "); - } - } - - printf("cnc-ddraw DLL_PROCESS_ATTACH\n"); - - //SetProcessPriorityBoost(GetCurrentProcess(), TRUE); - - BOOL setDpiAware = FALSE; - HMODULE hShcore = GetModuleHandle("shcore.dll"); - typedef HRESULT (__stdcall* SetProcessDpiAwareness_)(PROCESS_DPI_AWARENESS value); - if(hShcore) - { - SetProcessDpiAwareness_ setProcessDpiAwareness = - (SetProcessDpiAwareness_)GetProcAddress(hShcore, "SetProcessDpiAwareness"); - - if (setProcessDpiAwareness) - { - HRESULT result = setProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); - setDpiAware = result == S_OK || result == E_ACCESSDENIED; - } - } - if (!setDpiAware) - { - HMODULE hUser32 = GetModuleHandle("user32.dll"); - typedef BOOL (__stdcall* SetProcessDPIAware_)(); - if(hUser32) - { - SetProcessDPIAware_ setProcessDPIAware = - (SetProcessDPIAware_)GetProcAddress(hUser32, "SetProcessDPIAware"); - - if (setProcessDPIAware) - setProcessDPIAware(); - } - } - - timeBeginPeriod(1); - DInput_Hook(); - break; - } - case DLL_PROCESS_DETACH: - { - printf("cnc-ddraw DLL_PROCESS_DETACH\n"); - - Settings_Save(&WindowRect, WindowState); - - timeEndPeriod(1); - Hook_Exit(); - DInput_UnHook(); - break; - } - } - - return TRUE; -} - -BOOL CALLBACK EnumChildProc(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) - { - ChildWindowExists = TRUE; - - HDC hDC = GetDC(hWnd); - - MapWindowPoints(HWND_DESKTOP, 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 getPixel(int x, int y) -{ - return ((unsigned char *)ddraw->primary->surface)[y*ddraw->primary->lPitch + x*ddraw->primary->lXPitch]; -} - -int* InMovie = (int*)0x00665F58; -int* IsVQA640 = (int*)0x0065D7BC; -BYTE* ShouldStretch = (BYTE*)0x00607D78; - -BOOL detect_cutscene() -{ - if (ddraw->width <= CUTSCENE_WIDTH || ddraw->height <= CUTSCENE_HEIGHT) - return FALSE; - - if (ddraw->isredalert) - { - if ((*InMovie && !*IsVQA640) || *ShouldStretch) - { - return TRUE; - } - return FALSE; - } - else if (ddraw->iscnc1) - { - return getPixel(CUTSCENE_WIDTH + 1, 0) == 0 || getPixel(CUTSCENE_WIDTH + 5, 1) == 0 ? TRUE : FALSE; - } - - return FALSE; -} - -void LimitGameTicks() -{ - if (ddraw->ticksLimiter.hTimer) - { - FILETIME ft = { 0 }; - GetSystemTimeAsFileTime(&ft); - - if (CompareFileTime((FILETIME *)&ddraw->ticksLimiter.dueTime, &ft) == -1) - { - memcpy(&ddraw->ticksLimiter.dueTime, &ft, sizeof(LARGE_INTEGER)); - } - else - { - WaitForSingleObject(ddraw->ticksLimiter.hTimer, ddraw->ticksLimiter.ticklength * 2); - } - - ddraw->ticksLimiter.dueTime.QuadPart += ddraw->ticksLimiter.tickLengthNs; - SetWaitableTimer(ddraw->ticksLimiter.hTimer, &ddraw->ticksLimiter.dueTime, 0, NULL, NULL, FALSE); - } - else - { - static DWORD nextGameTick; - if (!nextGameTick) - { - nextGameTick = timeGetTime(); - return; - } - nextGameTick += ddraw->ticksLimiter.ticklength; - DWORD tickCount = timeGetTime(); - - int sleepTime = nextGameTick - tickCount; - if (sleepTime <= 0 || sleepTime > ddraw->ticksLimiter.ticklength) - nextGameTick = tickCount; - else - Sleep(sleepTime); - } -} - -void UpdateBnetPos(int newX, int newY) -{ - static int oldX = -32000; - static int oldY = -32000; - - if (oldX == -32000 || oldY == -32000 || !ddraw->bnetActive) - { - oldX = newX; - oldY = newY; - return; - } - - POINT pt = { 0, 0 }; - real_ClientToScreen(ddraw->hWnd, &pt); - - RECT mainrc; - SetRect(&mainrc, pt.x, pt.y, pt.x + ddraw->width, pt.y + ddraw->height); - - int adjY = 0; - int adjX = 0; - - HWND hWnd = FindWindowEx(HWND_DESKTOP, NULL, "SDlgDialog", NULL); - - while (hWnd != NULL) - { - RECT rc; - real_GetWindowRect(hWnd, &rc); - - OffsetRect(&rc, newX - oldX, newY - oldY); - - real_SetWindowPos( - hWnd, - 0, - rc.left, - rc.top, - 0, - 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); - - if (rc.bottom - rc.top <= ddraw->height) - { - if (rc.bottom > mainrc.bottom && abs(mainrc.bottom - rc.bottom) > abs(adjY)) - adjY = mainrc.bottom - rc.bottom; - else if (rc.top < mainrc.top && abs(mainrc.top - rc.top) > abs(adjY)) - adjY = mainrc.top - rc.top; - } - - if (rc.right - rc.left <= ddraw->width) - { - if (rc.right > mainrc.right && abs(mainrc.right - rc.right) > abs(adjX)) - adjX = mainrc.right - rc.right; - else if (rc.left < mainrc.left && abs(mainrc.left - rc.left) > abs(adjX)) - adjX = mainrc.left - rc.left; - } - - hWnd = FindWindowEx(HWND_DESKTOP, hWnd, "SDlgDialog", NULL); - } - - if (adjX || adjY) - { - HWND hWnd = FindWindowEx(HWND_DESKTOP, NULL, "SDlgDialog", NULL); - - while (hWnd != NULL) - { - RECT rc; - real_GetWindowRect(hWnd, &rc); - - OffsetRect(&rc, adjX, adjY); - - real_SetWindowPos( - hWnd, - 0, - rc.left, - rc.top, - 0, - 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); - - hWnd = FindWindowEx(HWND_DESKTOP, hWnd, "SDlgDialog", NULL); - } - } - - oldX = newX; - oldY = newY; -} - -HRESULT __stdcall ddraw_Compact(IDirectDrawImpl *This) -{ - printf("??? DirectDraw::Compact(This=%p)\n", This); - - return DD_OK; -} - -HRESULT __stdcall ddraw_DuplicateSurface(IDirectDrawImpl *This, LPDIRECTDRAWSURFACE src, LPDIRECTDRAWSURFACE *dest) -{ - printf("??? DirectDraw::DuplicateSurface(This=%p, ...)\n", This); - return DD_OK; -} - -HRESULT __stdcall ddraw_EnumDisplayModes(IDirectDrawImpl *This, DWORD dwFlags, LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext, LPDDENUMMODESCALLBACK lpEnumModesCallback) -{ - DWORD i = 0; - DDSURFACEDESC s; - - printf("DirectDraw::EnumDisplayModes(This=%p, dwFlags=%08X, lpDDSurfaceDesc=%p, lpContext=%p, lpEnumModesCallback=%p)\n", This, (unsigned int)dwFlags, lpDDSurfaceDesc, lpContext, lpEnumModesCallback); - - if (lpDDSurfaceDesc != NULL) - { - //return DDERR_UNSUPPORTED; - } - - // Some games crash when you feed them with too many resolutions... - - if (This->bpp) - { - printf(" This->bpp=%d\n", This->bpp); - - //set up some filters to keep the list short - DWORD refreshRate = 0; - DWORD bpp = 0; - DWORD flags = 99998; - DWORD fixedOutput = 99998; - DEVMODE m; - memset(&m, 0, sizeof(DEVMODE)); - m.dmSize = sizeof(DEVMODE); - - while (EnumDisplaySettings(NULL, i, &m)) - { - if (refreshRate != 60 && m.dmDisplayFrequency >= 50) - refreshRate = m.dmDisplayFrequency; - - if (bpp != 32 && m.dmBitsPerPel >= 16) - bpp = m.dmBitsPerPel; - - if (flags != 0) - flags = m.dmDisplayFlags; - - if (fixedOutput != DMDFO_DEFAULT) - fixedOutput = 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 (refreshRate == m.dmDisplayFrequency && - bpp == m.dmBitsPerPel && - flags == m.dmDisplayFlags && - fixedOutput == m.dmDisplayFixedOutput) - { -#if _DEBUG_X - printf(" %d: %dx%d@%d %d bpp\n", (int)i, (int)m.dmPelsWidth, (int)m.dmPelsHeight, (int)m.dmDisplayFrequency, (int)m.dmBitsPerPel); -#endif - 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 (This->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) - { - printf(" 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) - { - printf(" 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) - { - printf(" DDENUMRET_CANCEL returned, stopping\n"); - break; - } - } - } - - return DD_OK; -} - -HRESULT __stdcall ddraw_EnumSurfaces(IDirectDrawImpl *This, DWORD a, LPDDSURFACEDESC b, LPVOID c, LPDDENUMSURFACESCALLBACK d) -{ - printf("??? DirectDraw::EnumSurfaces(This=%p, ...)\n", This); - return DD_OK; -} - -HRESULT __stdcall ddraw_FlipToGDISurface(IDirectDrawImpl *This) -{ - printf("??? DirectDraw::FlipToGDISurface(This=%p)\n", This); - - return DD_OK; -} - -HRESULT __stdcall ddraw_GetCaps(IDirectDrawImpl *This, LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDEmulCaps) -{ - printf("DirectDraw::GetCaps(This=%p, lpDDDriverCaps=%p, lpDDEmulCaps=%p)\n", This, lpDDDriverCaps, 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 __stdcall ddraw_GetDisplayMode(IDirectDrawImpl *This, LPDDSURFACEDESC a) -{ - printf("??? DirectDraw::GetDisplayMode(This=%p, ...)\n", This); - return DDERR_UNSUPPORTEDMODE; -} - -HRESULT __stdcall ddraw_GetFourCCCodes(IDirectDrawImpl *This, LPDWORD a, LPDWORD b) -{ - printf("??? DirectDraw::GetFourCCCodes(This=%p, ...)\n", This); - return DD_OK; -} - -HRESULT __stdcall ddraw_GetGDISurface(IDirectDrawImpl *This, LPDIRECTDRAWSURFACE *a) -{ - printf("??? DirectDraw::GetGDISurface(This=%p, ...)\n", This); - return DD_OK; -} - -HRESULT __stdcall ddraw_GetMonitorFrequency(IDirectDrawImpl *This, LPDWORD a) -{ - printf("??? DirectDraw::GetMonitorFrequency(This=%p, ...)\n", This); - return DD_OK; -} - -HRESULT __stdcall ddraw_GetScanLine(IDirectDrawImpl *This, LPDWORD a) -{ - printf("??? DirectDraw::GetScanLine(This=%p, ...)\n", This); - return DD_OK; -} - -HRESULT __stdcall ddraw_GetVerticalBlankStatus(IDirectDrawImpl *This, LPBOOL lpbIsInVB) -{ - printf("??? DirectDraw::GetVerticalBlankStatus(This=%p, ...)\n", This); - *lpbIsInVB = TRUE; - return DD_OK; -} - -HRESULT __stdcall ddraw_Initialize(IDirectDrawImpl *This, GUID *a) -{ - printf("??? DirectDraw::Initialize(This=%p, ...)\n", This); - return DD_OK; -} - -HRESULT __stdcall ddraw_RestoreDisplayMode(IDirectDrawImpl *This) -{ - printf("DirectDraw::RestoreDisplayMode(This=%p)\n", This); - - if(!This->render.run) - { - return DD_OK; - } - - /* only stop drawing in GL mode when minimized */ - if (This->renderer != render_soft_main) - { - EnterCriticalSection(&This->cs); - This->render.run = FALSE; - ReleaseSemaphore(ddraw->render.sem, 1, NULL); - LeaveCriticalSection(&This->cs); - - if (This->render.thread) - { - WaitForSingleObject(This->render.thread, INFINITE); - This->render.thread = NULL; - } - - if (This->renderer == render_d3d9_main) - Direct3D9_Release(); - } - - if(!ddraw->windowed) - { - if (!Direct3D9Active) - ChangeDisplaySettings(NULL, 0); - } - - return DD_OK; -} - -BOOL GetLowestResolution(float ratio, SIZE *outRes, DWORD minWidth, DWORD minHeight, DWORD maxWidth, DWORD maxHeight) -{ - BOOL result = FALSE; - int orgRatio = (int)(ratio * 100); - SIZE lowest = { .cx = maxWidth + 1, .cy = maxHeight + 1 }; - DWORD i = 0; - DEVMODE m; - memset(&m, 0, sizeof(DEVMODE)); - m.dmSize = sizeof(DEVMODE); - - while (EnumDisplaySettings(NULL, i, &m)) - { - if (m.dmPelsWidth >= minWidth && - m.dmPelsHeight >= minHeight && - m.dmPelsWidth <= maxWidth && - m.dmPelsHeight <= maxHeight && - m.dmPelsWidth < lowest.cx && - m.dmPelsHeight < lowest.cy) - { - int resRatio = (int)(((float)m.dmPelsWidth / m.dmPelsHeight) * 100); - - if (resRatio == orgRatio) - { - result = TRUE; - outRes->cx = lowest.cx = m.dmPelsWidth; - outRes->cy = lowest.cy = m.dmPelsHeight; - } - } - memset(&m, 0, sizeof(DEVMODE)); - m.dmSize = sizeof(DEVMODE); - i++; - } - - return result; -} - -void InitDirect3D9() -{ - Direct3D9Active = Direct3D9_Create(); - if (!Direct3D9Active) - { - Direct3D9_Release(); - ShowDriverWarning = TRUE; - ddraw->renderer = render_soft_main; - } -} - -// LastSetWindowPosTick = Workaround for a wine+gnome bug where each SetWindowPos call triggers a WA_INACTIVE message -DWORD LastSetWindowPosTick; - -HRESULT __stdcall ddraw_SetDisplayMode(IDirectDrawImpl *This, DWORD width, DWORD height, DWORD bpp) -{ - printf("DirectDraw::SetDisplayMode(This=%p, width=%d, height=%d, bpp=%d)\n", This, (unsigned int)width, (unsigned int)height, (unsigned int)bpp); - - if (bpp != 8 && bpp != 16) - return DDERR_INVALIDMODE; - - if (This->render.thread) - { - EnterCriticalSection(&This->cs); - This->render.run = FALSE; - ReleaseSemaphore(ddraw->render.sem, 1, NULL); - LeaveCriticalSection(&This->cs); - - WaitForSingleObject(This->render.thread, INFINITE); - This->render.thread = NULL; - } - - if (!This->mode.dmPelsWidth) - { - This->mode.dmSize = sizeof(DEVMODE); - This->mode.dmDriverExtra = 0; - - if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &This->mode) == FALSE) - { - This->mode.dmSize = sizeof(DEVMODE); - This->mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY; - This->mode.dmPelsWidth = real_GetSystemMetrics(SM_CXSCREEN); - This->mode.dmPelsHeight = real_GetSystemMetrics(SM_CYSCREEN); - This->mode.dmDisplayFrequency = 60; - This->mode.dmBitsPerPel = 32; - - if (!This->mode.dmPelsWidth || !This->mode.dmPelsHeight) - { - This->fullscreen = FALSE; - } - } - - const HANDLE hbicon = LoadImage(GetModuleHandle(0), MAKEINTRESOURCE(IDR_MYMENU), IMAGE_ICON, real_GetSystemMetrics(SM_CXICON), real_GetSystemMetrics(SM_CYICON), 0); - if (hbicon) - real_SendMessageA(This->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(This->hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hsicon); - } - - if (ddraw->altenter) - { - ddraw->altenter = FALSE; - - memset(&This->render.mode, 0, sizeof(DEVMODE)); - This->render.mode.dmSize = sizeof(DEVMODE); - This->render.mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; - This->render.mode.dmPelsWidth = This->render.width; - This->render.mode.dmPelsHeight = This->render.height; - if (This->render.bpp) - { - This->render.mode.dmFields |= DM_BITSPERPEL; - This->render.mode.dmBitsPerPel = This->render.bpp; - } - - if (ChangeDisplaySettings(&This->render.mode, CDS_TEST) != DISP_CHANGE_SUCCESSFUL) - { - This->render.width = ddraw->width; - This->render.height = ddraw->height; - } - } - else - { - This->render.width = WindowRect.right; - This->render.height = WindowRect.bottom; - } - - //temporary fix: center window for games that keep changing their resolution - if (This->width && - (This->width != width || This->height != height) && - (width > WindowRect.right || height > WindowRect.bottom)) - { - WindowRect.left = -32000; - WindowRect.top = -32000; - } - - This->width = width; - This->height = height; - This->bpp = bpp; - - ddraw->cursor.x = width / 2; - ddraw->cursor.y = height / 2; - - BOOL border = This->border; - - if(This->fullscreen) - { - This->render.width = This->mode.dmPelsWidth; - This->render.height = This->mode.dmPelsHeight; - - if (This->windowed) //windowed-fullscreen aka borderless - { - border = FALSE; - WindowRect.left = -32000; - WindowRect.top = -32000; - - // prevent OpenGL from going automatically into fullscreen exclusive mode - if (This->renderer == render_main) - This->render.height++; - - } - } - - if(This->render.width < This->width) - { - This->render.width = This->width; - } - if(This->render.height < This->height) - { - This->render.height = This->height; - } - - This->render.run = TRUE; - - BOOL lockMouse = ddraw->locked || This->fullscreen; - mouse_unlock(); - - memset(&This->render.mode, 0, sizeof(DEVMODE)); - This->render.mode.dmSize = sizeof(DEVMODE); - This->render.mode.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT; - This->render.mode.dmPelsWidth = This->render.width; - This->render.mode.dmPelsHeight = This->render.height; - if(This->render.bpp) - { - This->render.mode.dmFields |= DM_BITSPERPEL; - This->render.mode.dmBitsPerPel = This->render.bpp; - } - - BOOL maintas = ddraw->maintas; - - if (!This->windowed) - { - // Making sure the chosen resolution is valid - int oldWidth = This->render.width; - int oldHeight = This->render.height; - - if (ChangeDisplaySettings(&This->render.mode, CDS_TEST) != DISP_CHANGE_SUCCESSFUL) - { - // fail... compare resolutions - if (This->render.width > This->mode.dmPelsWidth || This->render.height > This->mode.dmPelsHeight) - { - // chosen game resolution higher than current resolution, use windowed mode for this case - This->windowed = TRUE; - } - else - { - // Try 2x scaling - This->render.width *= 2; - This->render.height *= 2; - - This->render.mode.dmPelsWidth = This->render.width; - This->render.mode.dmPelsHeight = This->render.height; - - if ((This->render.width > This->mode.dmPelsWidth || This->render.height > This->mode.dmPelsHeight) || - ChangeDisplaySettings(&This->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 foundRes = GetLowestResolution( - (float)oldWidth / oldHeight, - &res, - oldWidth + 1, //don't return the original resolution since we tested that one already - oldHeight + 1, - This->mode.dmPelsWidth, - This->mode.dmPelsHeight); - - if (!foundRes) - { - //try to get a resolution with the same aspect ratio as the current display mode - foundRes = GetLowestResolution( - (float)This->mode.dmPelsWidth / This->mode.dmPelsHeight, - &res, - oldWidth, - oldHeight, - This->mode.dmPelsWidth, - This->mode.dmPelsHeight); - - if (foundRes) - maintas = TRUE; - } - - This->render.width = res.cx; - This->render.height = res.cy; - - This->render.mode.dmPelsWidth = This->render.width; - This->render.mode.dmPelsHeight = This->render.height; - - if (!foundRes || ChangeDisplaySettings(&This->render.mode, CDS_TEST) != DISP_CHANGE_SUCCESSFUL) - { - // try current display settings - This->render.width = This->mode.dmPelsWidth; - This->render.height = This->mode.dmPelsHeight; - - This->render.mode.dmPelsWidth = This->render.width; - This->render.mode.dmPelsHeight = This->render.height; - - if (ChangeDisplaySettings(&This->render.mode, CDS_TEST) != DISP_CHANGE_SUCCESSFUL) - { - // everything failed, use windowed mode instead - This->render.width = oldWidth; - This->render.height = oldHeight; - - This->render.mode.dmPelsWidth = This->render.width; - This->render.mode.dmPelsHeight = This->render.height; - - This->windowed = TRUE; - } - else - maintas = TRUE; - } - } - } - } - } - - if (ddraw->nonexclusive && !ddraw->windowed && ddraw->renderer == render_main) - This->render.height++; - - if (!ddraw->handlemouse) - This->boxing = maintas = FALSE; - - This->render.viewport.width = This->render.width; - This->render.viewport.height = This->render.height; - This->render.viewport.x = 0; - This->render.viewport.y = 0; - - if (This->boxing) - { - This->render.viewport.width = This->width; - This->render.viewport.height = This->height; - - int i; - for (i = 20; i-- > 1;) - { - if (This->width * i <= This->render.width && This->height * i <= This->render.height) - { - This->render.viewport.width *= i; - This->render.viewport.height *= i; - break; - } - } - - This->render.viewport.y = This->render.height / 2 - This->render.viewport.height / 2; - This->render.viewport.x = This->render.width / 2 - This->render.viewport.width / 2; - } - else if (maintas) - { - This->render.viewport.width = This->render.width; - This->render.viewport.height = ((float)This->height / This->width) * This->render.viewport.width; - - if (This->render.viewport.height > This->render.height) - { - This->render.viewport.width = - ((float)This->render.viewport.width / This->render.viewport.height) * This->render.height; - - This->render.viewport.height = This->render.height; - } - - This->render.viewport.y = This->render.height / 2 - This->render.viewport.height / 2; - This->render.viewport.x = This->render.width / 2 - This->render.viewport.width / 2; - } - - This->render.scaleW = ((float)This->render.viewport.width / This->width); - This->render.scaleH = ((float)This->render.viewport.height / This->height); - This->render.unScaleW = ((float)This->width / This->render.viewport.width); - This->render.unScaleH = ((float)This->height / This->render.viewport.height); - - if (This->windowed) - { - MSG msg; // workaround for "Not Responding" window problem in cnc games - PeekMessage(&msg, ddraw->hWnd, 0, 0, PM_NOREMOVE); - - if (!border) - { - real_SetWindowLongA(This->hWnd, GWL_STYLE, GetWindowLong(This->hWnd, GWL_STYLE) & ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU)); - } - else - { - real_SetWindowLongA(This->hWnd, GWL_STYLE, (GetWindowLong(This->hWnd, GWL_STYLE) | WS_OVERLAPPEDWINDOW) & ~WS_MAXIMIZEBOX); - } - - if (ddraw->wine) - real_SetWindowLongA(This->hWnd, GWL_STYLE, (GetWindowLong(This->hWnd, GWL_STYLE) | WS_MINIMIZEBOX) & ~(WS_MAXIMIZEBOX | WS_THICKFRAME)); - - /* center the window with correct dimensions */ - int cy = This->mode.dmPelsWidth ? This->mode.dmPelsWidth : This->render.width; - int cx = This->mode.dmPelsHeight ? This->mode.dmPelsHeight : This->render.height; - int x = (WindowRect.left != -32000) ? WindowRect.left : (cy / 2) - (This->render.width / 2); - int y = (WindowRect.top != -32000) ? WindowRect.top : (cx / 2) - (This->render.height / 2); - RECT dst = { x, y, This->render.width + x, This->render.height + y }; - AdjustWindowRect(&dst, GetWindowLong(This->hWnd, GWL_STYLE), FALSE); - real_SetWindowPos(ddraw->hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - real_MoveWindow(This->hWnd, dst.left, dst.top, (dst.right - dst.left), (dst.bottom - dst.top), TRUE); - - if (This->renderer == render_d3d9_main) - InitDirect3D9(); - - if (lockMouse) - mouse_lock(); - } - else - { - LONG style = GetWindowLong(This->hWnd, GWL_STYLE); - - if ((style & WS_CAPTION)) - { - real_SetWindowLongA(This->hWnd, GWL_STYLE, style & ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU)); - } - - if (This->renderer == render_d3d9_main) - InitDirect3D9(); - - if (!Direct3D9Active && ChangeDisplaySettings(&This->render.mode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) - { - This->render.run = FALSE; - This->windowed = TRUE; - return ddraw_SetDisplayMode(This, width, height, bpp); - } - - if (ddraw->wine) - real_SetWindowLongA(This->hWnd, GWL_STYLE, GetWindowLong(This->hWnd, GWL_STYLE) | WS_MINIMIZEBOX); - - real_SetWindowPos(This->hWnd, HWND_TOPMOST, 0, 0, This->render.width, This->render.height, SWP_SHOWWINDOW); - LastSetWindowPosTick = timeGetTime(); - - mouse_lock(); - } - - if(This->render.viewport.x != 0 || This->render.viewport.y != 0) - { - RedrawWindow(This->hWnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE); - } - - if(This->render.thread == NULL) - { - InterlockedExchange(&ddraw->render.paletteUpdated, TRUE); - InterlockedExchange(&ddraw->render.surfaceUpdated, TRUE); - ReleaseSemaphore(ddraw->render.sem, 1, NULL); - - This->render.thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)This->renderer, NULL, 0, NULL); - } - - if (ddraw->sierrahack) - { - PostMessageA(ddraw->hWnd, WM_MOVE, 0, MAKELPARAM(-32000, -32000)); - PostMessageA(ddraw->hWnd, WM_DISPLAYCHANGE, ddraw->bpp, MAKELPARAM(ddraw->width, ddraw->height)); - } - - return DD_OK; -} - -HRESULT __stdcall ddraw_SetDisplayMode2(IDirectDrawImpl *This, DWORD width, DWORD height, DWORD bpp, DWORD refreshRate, DWORD flags) -{ - printf("DirectDraw::SetDisplayMode2(refreshRate=%d, flags=%d)\n", (unsigned int)refreshRate, (unsigned int)flags); - - return ddraw_SetDisplayMode(This, width, height, bpp); -} - -void ToggleFullscreen() -{ - if (ddraw->bnetActive) - return; - - if (ddraw->windowed) - { - mouse_unlock(); - WindowState = ddraw->windowed = FALSE; - real_SetWindowLongA(ddraw->hWnd, GWL_STYLE, GetWindowLong(ddraw->hWnd, GWL_STYLE) & ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU)); - ddraw->altenter = TRUE; - ddraw_SetDisplayMode(ddraw, ddraw->width, ddraw->height, ddraw->bpp); - UpdateBnetPos(0, 0); - mouse_lock(); - } - else - { - mouse_unlock(); - WindowState = ddraw->windowed = TRUE; - - if (Direct3D9Active) - Direct3D9_Reset(); - else - ChangeDisplaySettings(NULL, ddraw->bnetActive ? CDS_FULLSCREEN : 0); - - ddraw_SetDisplayMode(ddraw, ddraw->width, ddraw->height, ddraw->bpp); - mouse_lock(); - } -} - -BOOL UnadjustWindowRectEx(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 SetWindowRect(int x, int y, int width, int height, UINT flags) -{ - if (ddraw->windowed) - { - if (ddraw->render.thread) - { - EnterCriticalSection(&ddraw->cs); - ddraw->render.run = FALSE; - ReleaseSemaphore(ddraw->render.sem, 1, NULL); - LeaveCriticalSection(&ddraw->cs); - - WaitForSingleObject(ddraw->render.thread, INFINITE); - ddraw->render.thread = NULL; - } - - if ((flags & SWP_NOMOVE) == 0) - { - WindowRect.left = x; - WindowRect.top = y; - } - - if ((flags & SWP_NOSIZE) == 0) - { - WindowRect.bottom = height; - WindowRect.right = width; - } - - ddraw_SetDisplayMode(ddraw, ddraw->width, ddraw->height, ddraw->bpp); - } -} - -LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - RECT rc = { 0, 0, ddraw->render.width, ddraw->render.height }; - static BOOL inSizeMove = FALSE; - static int redrawCount = 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 (!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 == 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 (!ddraw->locked) - return DefWindowProc(hWnd, uMsg, wParam, lParam); - default: - break; - } - } - } - - break; - } - case WM_D3D9DEVICELOST: - { - if (Direct3D9Active && Direct3D9_OnDeviceLost()) - { - if (!ddraw->windowed) - mouse_lock(); - } - return 0; - } - case WM_TIMER: - { - switch (wParam) - { - case IDT_TIMER_LEAVE_BNET: - { - KillTimer(ddraw->hWnd, IDT_TIMER_LEAVE_BNET); - - if (!ddraw->windowed) - ddraw->bnetWasFullscreen = FALSE; - - if (!ddraw->bnetActive) - { - if (ddraw->bnetWasFullscreen) - { - int ws = WindowState; - ToggleFullscreen(); - WindowState = ws; - ddraw->bnetWasFullscreen = FALSE; - } - else if (ddraw->bnetWasUpscaled) - { - SetWindowRect(0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - ddraw->bnetWasUpscaled = FALSE; - } - } - - return 0; - } - } - break; - } - case WM_WINDOWPOSCHANGED: - { - WINDOWPOS *pos = (WINDOWPOS *)lParam; - - if (ddraw->wine && !ddraw->windowed && (pos->x > 0 || pos->y > 0) && LastSetWindowPosTick + 500 < timeGetTime()) - PostMessage(ddraw->hWnd, WM_WINEFULLSCREEN, 0, 0); - - break; - } - case WM_WINEFULLSCREEN: - { - if (!ddraw->windowed) - { - LastSetWindowPosTick = timeGetTime(); - real_SetWindowPos(ddraw->hWnd, HWND_TOPMOST, 1, 1, ddraw->render.width, ddraw->render.height, SWP_SHOWWINDOW); - real_SetWindowPos(ddraw->hWnd, HWND_TOPMOST, 0, 0, ddraw->render.width, ddraw->render.height, SWP_SHOWWINDOW); - } - return 0; - } - case WM_ENTERSIZEMOVE: - { - if (ddraw->windowed) - { - inSizeMove = TRUE; - } - break; - } - case WM_EXITSIZEMOVE: - { - if (ddraw->windowed) - { - inSizeMove = FALSE; - - if (!ddraw->render.thread) - ddraw_SetDisplayMode(ddraw, ddraw->width, ddraw->height, ddraw->bpp); - } - break; - } - case WM_SIZING: - { - RECT *windowrc = (RECT *)lParam; - - if (ddraw->windowed) - { - if (inSizeMove) - { - if (ddraw->render.thread) - { - EnterCriticalSection(&ddraw->cs); - ddraw->render.run = FALSE; - ReleaseSemaphore(ddraw->render.sem, 1, NULL); - LeaveCriticalSection(&ddraw->cs); - - WaitForSingleObject(ddraw->render.thread, INFINITE); - ddraw->render.thread = NULL; - } - - RECT clientrc = { 0 }; - - // maintain aspect ratio - if (ddraw->maintas && - CopyRect(&clientrc, windowrc) && - UnadjustWindowRectEx(&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)ddraw->height / ddraw->width; - float scaleW = (float)ddraw->width / 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) && - UnadjustWindowRectEx(&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 < ddraw->width) - { - switch (wParam) - { - case WMSZ_TOPRIGHT: - case WMSZ_BOTTOMRIGHT: - case WMSZ_RIGHT: - case WMSZ_BOTTOM: - case WMSZ_TOP: - { - windowrc->right += ddraw->width - clientrc.right; - break; - } - case WMSZ_TOPLEFT: - case WMSZ_BOTTOMLEFT: - case WMSZ_LEFT: - { - windowrc->left -= ddraw->width - clientrc.right; - break; - } - } - } - - if (clientrc.bottom < ddraw->height) - { - switch (wParam) - { - case WMSZ_BOTTOMLEFT: - case WMSZ_BOTTOMRIGHT: - case WMSZ_BOTTOM: - case WMSZ_RIGHT: - case WMSZ_LEFT: - { - windowrc->bottom += ddraw->height - clientrc.bottom; - break; - } - case WMSZ_TOPLEFT: - case WMSZ_TOPRIGHT: - case WMSZ_TOP: - { - windowrc->top -= ddraw->height - clientrc.bottom; - break; - } - } - } - } - - //save new window position - if (CopyRect(&clientrc, windowrc) && - UnadjustWindowRectEx(&clientrc, GetWindowLong(hWnd, GWL_STYLE), FALSE, GetWindowLong(hWnd, GWL_EXSTYLE))) - { - WindowRect.left = clientrc.left; - WindowRect.top = clientrc.top; - WindowRect.right = clientrc.right - clientrc.left; - WindowRect.bottom = clientrc.bottom - clientrc.top; - } - - return TRUE; - } - } - break; - } - case WM_SIZE: - { - if (ddraw->windowed) - { - if (wParam == SIZE_RESTORED) - { - if (inSizeMove && !ddraw->render.thread) - { - WindowRect.right = LOWORD(lParam); - WindowRect.bottom = HIWORD(lParam); - } - /* - else if (ddraw->wine) - { - WindowRect.right = LOWORD(lParam); - WindowRect.bottom = HIWORD(lParam); - if (WindowRect.right != ddraw->render.width || WindowRect.bottom != ddraw->render.height) - ddraw_SetDisplayMode(ddraw, ddraw->width, ddraw->height, ddraw->bpp); - } - */ - } - } - - if (!ddraw->handlemouse) - { - redrawCount = 2; - RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); - } - - return DefWindowProc(hWnd, uMsg, wParam, lParam); /* Carmageddon fix */ - } - case WM_MOVE: - { - if (ddraw->windowed) - { - int x = (int)(short)LOWORD(lParam); - int y = (int)(short)HIWORD(lParam); - - if (x != -32000 && y != -32000) - UpdateBnetPos(x, y); - - if (inSizeMove || ddraw->wine) - { - if (x != -32000) - WindowRect.left = x; // -32000 = Exit/Minimize - - if (y != -32000) - WindowRect.top = y; - } - } - - if (!ddraw->handlemouse) - RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); - - if (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 (ddraw->locked) - { - WINDOWPOS *pos = (WINDOWPOS *)lParam; - - if (pos->flags == SWP_NOMOVE + SWP_NOSIZE) - { - mouse_unlock(); - - if (GetForegroundWindow() == ddraw->hWnd) - mouse_lock(); - } - } - break; - } - - case WM_MOUSELEAVE: - mouse_unlock(); - return 0; - - case WM_ACTIVATE: - if (wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE) - { - if (!ddraw->windowed) - { - if (!Direct3D9Active) - { - ChangeDisplaySettings(&ddraw->render.mode, CDS_FULLSCREEN); - - if (wParam == WA_ACTIVE) - { - mouse_lock(); - } - } - } - - if (!ddraw->handlemouse) - RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); - } - else if (wParam == WA_INACTIVE) - { - if (!ddraw->windowed && !ddraw->locked && ddraw->noactivateapp && !ddraw->devmode) - return 0; - - mouse_unlock(); - - if (ddraw->wine && LastSetWindowPosTick + 500 > timeGetTime()) - return 0; - - /* minimize our window on defocus when in fullscreen */ - if (!ddraw->windowed) - { - if (!Direct3D9Active) - { - ShowWindow(ddraw->hWnd, SW_MINIMIZE); - ChangeDisplaySettings(NULL, ddraw->bnetActive ? 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 (ddraw->windowed || ddraw->noactivateapp) - { - // let it pass through once (tiberian sun) - static BOOL oneTime; - if (wParam && !oneTime && !ddraw->handlemouse && ddraw->noactivateapp) - { - oneTime = TRUE; - break; - } - - return 0; - } - break; - case WM_AUTORENDERER: - { - mouse_unlock(); - real_SetWindowPos(ddraw->hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - real_SetWindowPos(ddraw->hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - mouse_lock(); - return 0; - } - case WM_NCLBUTTONDBLCLK: - { - ToggleFullscreen(); - return 0; - } - case WM_SYSKEYDOWN: - { - BOOL contextCode = (lParam & (1 << 29)) != 0; - BOOL keyState = (lParam & (1 << 30)) != 0; - - if (wParam == VK_RETURN && contextCode && !keyState) - { - ToggleFullscreen(); - 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) - screenshot(ddraw->primary); - - break; - - - /* button up messages reactivate cursor lock */ - case WM_LBUTTONUP: - case WM_RBUTTONUP: - case WM_MBUTTONUP: - if (!ddraw->devmode && !ddraw->locked) - { - int x = GET_X_LPARAM(lParam); - int y = GET_Y_LPARAM(lParam); - - if (x > ddraw->render.viewport.x + ddraw->render.viewport.width || - x < ddraw->render.viewport.x || - y > ddraw->render.viewport.y + ddraw->render.viewport.height || - y < ddraw->render.viewport.y) - { - ddraw->cursor.x = ddraw->width / 2; - ddraw->cursor.y = ddraw->height / 2; - } - else - { - ddraw->cursor.x = (x - ddraw->render.viewport.x) * ddraw->render.unScaleW; - ddraw->cursor.y = (y - ddraw->render.viewport.y) * ddraw->render.unScaleH; - } - - 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 (!ddraw->devmode) - { - if (!ddraw->locked) - { - return 0; - } - - if(ddraw->adjmouse) - { - fake_GetCursorPos(NULL); /* update our own cursor */ - lParam = MAKELPARAM(ddraw->cursor.x, ddraw->cursor.y); - } - } - - if (ddraw->devmode) - { - mouse_lock(); - ddraw->cursor.x = GET_X_LPARAM(lParam); - ddraw->cursor.y = GET_Y_LPARAM(lParam); - } - break; - - case WM_PARENTNOTIFY: - { - if (!ddraw->handlemouse) - { - switch (LOWORD(wParam)) - { - case WM_DESTROY: //Workaround for invisible menu on Load/Save/Delete in Tiberian Sun - redrawCount = 2; - break; - case WM_LBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_RBUTTONDOWN: - case WM_XBUTTONDOWN: - { - if (!ddraw->devmode && !ddraw->locked) - { - int x = GET_X_LPARAM(lParam); - int y = GET_Y_LPARAM(lParam); - - ddraw->cursor.x = (x - ddraw->render.viewport.x) * ddraw->render.unScaleW; - ddraw->cursor.y = (y - ddraw->render.viewport.y) * ddraw->render.unScaleH; - - ddraw->hidecursor = FALSE; - mouse_lock(); - } - break; - } - } - } - break; - } - case WM_PAINT: - { - if (!ddraw->handlemouse && redrawCount > 0) - { - redrawCount--; - RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); - } - - EnterCriticalSection(&ddraw->cs); - ReleaseSemaphore(ddraw->render.sem, 1, NULL); - LeaveCriticalSection(&ddraw->cs); - break; - } - case WM_ERASEBKGND: - { - EnterCriticalSection(&ddraw->cs); - FillRect(ddraw->render.hDC, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH)); - ReleaseSemaphore(ddraw->render.sem, 1, NULL); - LeaveCriticalSection(&ddraw->cs); - break; - } - } - - return ddraw->WndProc(hWnd, uMsg, wParam, lParam); -} - -HRESULT __stdcall ddraw_SetCooperativeLevel(IDirectDrawImpl *This, HWND hWnd, DWORD dwFlags) -{ - PIXELFORMATDESCRIPTOR pfd; - - printf("DirectDraw::SetCooperativeLevel(This=%p, hWnd=0x%08X, dwFlags=0x%08X)\n", This, (unsigned int)hWnd, (unsigned int)dwFlags); - - /* Red Alert for some weird reason does this on Windows XP */ - if(hWnd == NULL) - { - return DD_OK; - } - - if (This->hWnd == NULL) - { - This->hWnd = hWnd; - } - - if (!This->WndProc) - { - Hook_Init(); - - This->WndProc = (LRESULT(CALLBACK *)(HWND, UINT, WPARAM, LPARAM))GetWindowLong(hWnd, GWL_WNDPROC); - - real_SetWindowLongA(This->hWnd, GWL_WNDPROC, (LONG)WndProc); - - if (!This->render.hDC) - { - This->render.hDC = GetDC(This->hWnd); - - memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); - pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); - pfd.nVersion = 1; - pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER | (This->renderer == render_main ? PFD_SUPPORT_OPENGL : 0); - pfd.iPixelType = PFD_TYPE_RGBA; - pfd.cColorBits = ddraw->render.bpp ? ddraw->render.bpp : ddraw->mode.dmBitsPerPel; - pfd.iLayerType = PFD_MAIN_PLANE; - SetPixelFormat(This->render.hDC, ChoosePixelFormat(This->render.hDC, &pfd), &pfd); - } - - if (ddraw->handlemouse && ddraw->windowed) - { - while (real_ShowCursor(FALSE) > 0); //workaround for direct input games - while (real_ShowCursor(TRUE) < 0); - } - - real_SetCursor(LoadCursor(NULL, IDC_ARROW)); - - GetWindowText(This->hWnd, (LPTSTR)&This->title, sizeof(This->title)); - - ddraw->isredalert = strcmp(This->title, "Red Alert") == 0; - ddraw->iscnc1 = strcmp(This->title, "Command & Conquer") == 0; - - if (This->vhack && !ddraw->isredalert && !ddraw->iscnc1) - This->vhack = 0; - } - - return DD_OK; -} - -HRESULT __stdcall ddraw_WaitForVerticalBlank(IDirectDrawImpl *This, DWORD dwFlags, HANDLE h) -{ -#if _DEBUG_X - printf("DirectDraw::WaitForVerticalBlank(This=%p, flags=%08X, handle=%p)\n", This, dwFlags, h); -#endif - if (!ddraw->flipLimiter.ticklength) - return DD_OK; - - if (ddraw->flipLimiter.hTimer) - { - FILETIME lastFlipFT = { 0 }; - GetSystemTimeAsFileTime(&lastFlipFT); - - if (!ddraw->flipLimiter.dueTime.QuadPart) - { - memcpy(&ddraw->flipLimiter.dueTime, &lastFlipFT, sizeof(LARGE_INTEGER)); - } - else - { - while (CompareFileTime((FILETIME*)&ddraw->flipLimiter.dueTime, &lastFlipFT) == -1) - ddraw->flipLimiter.dueTime.QuadPart += ddraw->flipLimiter.tickLengthNs; - - SetWaitableTimer(ddraw->flipLimiter.hTimer, &ddraw->flipLimiter.dueTime, 0, NULL, NULL, FALSE); - WaitForSingleObject(ddraw->flipLimiter.hTimer, ddraw->flipLimiter.ticklength * 2); - } - } - else - { - static DWORD nextGameTick; - if (!nextGameTick) - { - nextGameTick = timeGetTime(); - return DD_OK; - } - nextGameTick += ddraw->flipLimiter.ticklength; - DWORD tickCount = timeGetTime(); - - int sleepTime = nextGameTick - tickCount; - if (sleepTime <= 0 || sleepTime > ddraw->flipLimiter.ticklength) - nextGameTick = tickCount; - else - Sleep(sleepTime); - } - - return DD_OK; -} - -HRESULT __stdcall ddraw_GetAvailableVidMem(IDirectDrawImpl *This, LPDDSCAPS lpDDCaps, LPDWORD lpdwTotal, LPDWORD lpdwFree) -{ - printf("??? DirectDraw::GetAvailableVidMem(This=%p)\n", This); - - *lpdwTotal = 16777216; - *lpdwFree = 16777216; - - return DD_OK; -} - -ULONG __stdcall ddraw_AddRef(IDirectDrawImpl *This) -{ - printf("DirectDraw::AddRef(This=%p)\n", This); - - This->Ref++; - - return This->Ref; -} - -HRESULT __stdcall ddraw_QueryInterface(IDirectDrawImpl *This, REFIID riid, void **obj) -{ - printf("DirectDraw::QueryInterface(This=%p, riid=%08X, obj=%p)\n", This, (unsigned int)riid, obj); - - if (riid && !IsEqualGUID(&IID_IDirectDraw, riid)) - { - printf(" GUID = %08X\n", ((GUID *)riid)->Data1); - - ddraw_AddRef(This); - *obj = This; - - if (!IsEqualGUID(&IID_IMediaStream, riid) && !IsEqualGUID(&IID_IAMMediaStream, riid)) - This->lpVtbl->SetDisplayMode2 = ddraw_SetDisplayMode2; - - return S_OK; - } - - *obj = This; - - return DDERR_UNSUPPORTED; -} - -ULONG __stdcall ddraw_Release(IDirectDrawImpl *This) -{ - printf("DirectDraw::Release(This=%p)\n", This); - - This->Ref--; - - if(This->Ref == 0) - { - printf(" Released (%p)\n", This); - - if (This->bpp) - Settings_Save(&WindowRect, WindowState); - - if(This->render.run) - { - EnterCriticalSection(&This->cs); - This->render.run = FALSE; - ReleaseSemaphore(ddraw->render.sem, 1, NULL); - LeaveCriticalSection(&This->cs); - - if (This->render.thread) - { - WaitForSingleObject(This->render.thread, INFINITE); - This->render.thread = NULL; - } - - if (This->renderer == render_d3d9_main) - { - Direct3D9_Release(); - } - else if (!ddraw->windowed) - { - ChangeDisplaySettings(NULL, 0); - } - } - - if(This->render.hDC) - { - ReleaseDC(This->hWnd, This->render.hDC); - This->render.hDC = NULL; - } - - if (This->ticksLimiter.hTimer) - { - CancelWaitableTimer(This->ticksLimiter.hTimer); - CloseHandle(This->ticksLimiter.hTimer); - This->ticksLimiter.hTimer = NULL; - } - - if (This->flipLimiter.hTimer) - { - CancelWaitableTimer(This->flipLimiter.hTimer); - CloseHandle(This->flipLimiter.hTimer); - This->flipLimiter.hTimer = NULL; - } - - if (This->fpsLimiter.hTimer) - { - CancelWaitableTimer(This->fpsLimiter.hTimer); - CloseHandle(This->fpsLimiter.hTimer); - This->fpsLimiter.hTimer = NULL; - } - - DeleteCriticalSection(&This->cs); - - /* restore old wndproc, subsequent ddraw creation will otherwise fail */ - real_SetWindowLongA(This->hWnd, GWL_WNDPROC, (LONG)This->WndProc); - HeapFree(GetProcessHeap(), 0, This); - ddraw = NULL; - return 0; - } - else - { - // This->lpVtbl->SetDisplayMode1 = ddraw_SetDisplayMode; - } - - if (This->tm2hack) - return 0; - - return This->Ref; -} - -struct IDirectDrawImplVtbl iface = -{ - /* IUnknown */ - ddraw_QueryInterface, - ddraw_AddRef, - ddraw_Release, - /* IDirectDrawImpl */ - ddraw_Compact, - ddraw_CreateClipper, - ddraw_CreatePalette, - ddraw_CreateSurface, - ddraw_DuplicateSurface, - ddraw_EnumDisplayModes, - ddraw_EnumSurfaces, - ddraw_FlipToGDISurface, - ddraw_GetCaps, - ddraw_GetDisplayMode, - ddraw_GetFourCCCodes, - ddraw_GetGDISurface, - ddraw_GetMonitorFrequency, - ddraw_GetScanLine, - ddraw_GetVerticalBlankStatus, - ddraw_Initialize, - ddraw_RestoreDisplayMode, - ddraw_SetCooperativeLevel, - ddraw_SetDisplayMode, - ddraw_WaitForVerticalBlank, - ddraw_GetAvailableVidMem -}; - -HRESULT WINAPI DirectDrawCreateClipper(DWORD dwFlags, LPDIRECTDRAWCLIPPER FAR *lplpDDClipper, IUnknown FAR *pUnkOuter) -{ - return ddraw_CreateClipper(NULL, dwFlags, lplpDDClipper, pUnkOuter); -} - -HRESULT WINAPI DirectDrawEnumerateA(LPDDENUMCALLBACK lpCallback, LPVOID lpContext) -{ - printf("??? DirectDrawEnumerateA(lpCallback=%p, lpContext=%p)\n", lpCallback, lpContext); - - if (lpCallback) - lpCallback(NULL, "display", "(null)", lpContext); - - return DD_OK; -} - -int stdout_open = 0; -HRESULT WINAPI DirectDrawCreate(GUID FAR* lpGUID, LPDIRECTDRAW FAR* lplpDD, IUnknown FAR* pUnkOuter) -{ -#if _DEBUG - 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 nameSize = sizeof(name); - RegQueryValueExA(hKey, "ProductName", NULL, NULL, (PVOID)&name, &nameSize); - - char build[256] = {0}; - DWORD buildSize = sizeof(build); - RegQueryValueExA(hKey, "BuildLab", NULL, NULL, (PVOID)&build, &buildSize); - - printf("%s (%s)\n", name, build); - } - } -#endif - - printf("DirectDrawCreate(lpGUID=%p, lplpDD=%p, pUnkOuter=%p)\n", lpGUID, lplpDD, pUnkOuter); - - if(ddraw) - { - /* FIXME: check the calling module before passing the call! */ - if (ddraw->DirectDrawCreate) - return ddraw->DirectDrawCreate(lpGUID, lplpDD, pUnkOuter); - - return DDERR_DIRECTDRAWALREADYCREATED; - } - - IDirectDrawImpl *This = (IDirectDrawImpl *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawImpl)); - This->lpVtbl = &iface; - printf(" This = %p\n", This); - *lplpDD = (LPDIRECTDRAW)This; - This->Ref = 0; - ddraw_AddRef(This); - - ddraw = This; - - if (!This->real_dll) - This->real_dll = LoadLibrary("system32\\ddraw.dll"); - - if(This->real_dll && !This->DirectDrawCreate) - { - This->DirectDrawCreate = - (HRESULT(WINAPI *)(GUID FAR*, LPDIRECTDRAW FAR*, IUnknown FAR*))GetProcAddress(This->real_dll, "DirectDrawCreate"); - - if (This->DirectDrawCreate == DirectDrawCreate) - This->DirectDrawCreate = NULL; - } - - InitializeCriticalSection(&This->cs); - This->render.sem = CreateSemaphore(NULL, 0, 1, NULL); - - This->wine = GetProcAddress(GetModuleHandleA("ntdll.dll"), "wine_get_version") != 0; - - Settings_Load(); - - return DD_OK; -} diff --git a/src/mouse.c b/src/mouse.c index 7755e12..5e45712 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -1,213 +1,78 @@ -/* - * Copyright (c) 2010 Toni Spets - * - * 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 -#include -#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); -} diff --git a/src/opengl.c b/src/opengl_utils.c similarity index 70% rename from src/opengl.c rename to src/opengl_utils.c index a13332a..f09788a 100644 --- a/src/opengl.c +++ b/src/opengl_utils.c @@ -1,6 +1,6 @@ #include #include -#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); diff --git a/src/palette.c b/src/palette.c deleted file mode 100644 index be87311..0000000 --- a/src/palette.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2010 Toni Spets - * - * 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 -#include -#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; -} - diff --git a/src/render.c b/src/render.c deleted file mode 100644 index f1e64ef..0000000 --- a/src/render.c +++ /dev/null @@ -1,1049 +0,0 @@ -/* -* Copyright (c) 2010 Toni Spets -* -* 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 -#include -#include "opengl.h" -#include "main.h" -#include "surface.h" -#include "openglshader.h" - -#define TEXTURE_COUNT 4 - -static HGLRC OpenGLContext; -static GLuint MainProgram; -static GLuint ScaleProgram; -static BOOL GotError; -static int SurfaceTexWidth; -static int SurfaceTexHeight; -static int *SurfaceTex; -static GLenum SurfaceFormat = GL_LUMINANCE; -static GLenum SurfaceType = GL_UNSIGNED_BYTE; -static GLuint SurfaceTexIds[TEXTURE_COUNT]; -static GLuint PaletteTexIds[TEXTURE_COUNT]; -static float ScaleW; -static float ScaleH; -static GLint MainTexCoordAttrLoc = -1; -static GLint MainVertexCoordAttrLoc = -1; -static GLuint MainVBOs[3], MainVAO; -static GLint FrameCountUniLoc = -1; -static GLuint FrameBufferId; -static GLuint FrameBufferTexId; -static GLuint ScaleVBOs[3], ScaleVAO; -static BOOL UseOpenGL; -static BOOL AdjustAlignment; -static BOOL FilterBilinear; - -static HGLRC CreateContext(HDC hdc); -static void SetMaxFPS(); -static void BuildPrograms(); -static void CreateTextures(int width, int height); -static void InitMainProgram(); -static void InitScaleProgram(); -static void Render(); -static void DeleteContext(HGLRC context); -static BOOL TextureUploadTest(); -static BOOL ShaderTest(); - -DWORD WINAPI render_main(void) -{ - Sleep(500); - GotError = UseOpenGL = FALSE; - - OpenGLContext = CreateContext(ddraw->render.hDC); - if (OpenGLContext) - { - OpenGL_Init(); - SetMaxFPS(); - BuildPrograms(); - CreateTextures(ddraw->width, ddraw->height); - InitMainProgram(); - InitScaleProgram(); - - GotError = GotError || !TextureUploadTest(); - GotError = GotError || !ShaderTest(); - GotError = GotError || glGetError() != GL_NO_ERROR; - UseOpenGL = (MainProgram || ddraw->bpp == 16) && !GotError; - - Render(); - - DeleteContext(OpenGLContext); - } - - if (!UseOpenGL) - { - ShowDriverWarning = TRUE; - ddraw->renderer = render_soft_main; - render_soft_main(); - } - - return 0; -} - -static HGLRC CreateContext(HDC hdc) -{ - HGLRC context = xwglCreateContext(hdc); - BOOL madeCurrent = context && xwglMakeCurrent(hdc, context); - - if (!madeCurrent || glGetError() != GL_NO_ERROR) - { - if (madeCurrent) - { - xwglMakeCurrent(NULL, NULL); - xwglDeleteContext(context); - } - - context = 0; - } - - return context; -} - -static void SetMaxFPS() -{ - int maxFPS = ddraw->render.maxfps; - ddraw->fpsLimiter.tickLengthNs = 0; - ddraw->fpsLimiter.ticklength = 0; - - /* - if (OpenGL_ExtExists("WGL_EXT_swap_control_tear", ddraw->render.hDC)) - { - if (wglSwapIntervalEXT) - { - if (ddraw->vsync) - { - wglSwapIntervalEXT(-1); - maxFPS = ddraw->mode.dmDisplayFrequency; - } - else - wglSwapIntervalEXT(0); - } - } - else */ - if (OpenGL_ExtExists("WGL_EXT_swap_control", ddraw->render.hDC)) - { - if (wglSwapIntervalEXT) - { - if (ddraw->vsync) - { - wglSwapIntervalEXT(1); - maxFPS = ddraw->mode.dmDisplayFrequency; - } - else - wglSwapIntervalEXT(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;// + 0.5f; - } -} - -static void BuildPrograms() -{ - MainProgram = ScaleProgram = 0; - - if (OpenGL_GotVersion3) - { - if (ddraw->bpp == 8) - MainProgram = OpenGL_BuildProgram(PassthroughVertShaderSrc, PaletteFragShaderSrc); - else if (ddraw->bpp == 16) - MainProgram = OpenGL_BuildProgram(PassthroughVertShaderSrc, PassthroughFragShaderSrc); - - if (MainProgram) - ScaleProgram = OpenGL_BuildProgramFromFile(ddraw->shader); - else - OpenGL_GotVersion3 = FALSE; - - FilterBilinear = strstr(ddraw->shader, "bilinear.glsl") != 0; - } - - if (OpenGL_GotVersion2 && !MainProgram) - { - if (ddraw->bpp == 8) - MainProgram = OpenGL_BuildProgram(PassthroughVertShader110Src, PaletteFragShader110Src); - else if (ddraw->bpp == 16) - MainProgram = OpenGL_BuildProgram(PassthroughVertShader110Src, PassthroughFragShader110Src); - } -} - -static void CreateTextures(int width, int height) -{ - SurfaceTexWidth = - width <= 1024 ? 1024 : width <= 2048 ? 2048 : width <= 4096 ? 4096 : width; - - SurfaceTexHeight = - height <= 512 ? 512 : height <= 1024 ? 1024 : height <= 2048 ? 2048 : height <= 4096 ? 4096 : height; - - SurfaceTex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SurfaceTexWidth * SurfaceTexHeight * sizeof(int)); - - AdjustAlignment = (width % 4) != 0; - - ScaleW = (float)width / SurfaceTexWidth; - ScaleH = (float)height / SurfaceTexHeight; - - glGenTextures(TEXTURE_COUNT, SurfaceTexIds); - - int i; - for (i = 0; i < TEXTURE_COUNT; i++) - { - glBindTexture(GL_TEXTURE_2D, SurfaceTexIds[i]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - GotError = GotError || glGetError() != GL_NO_ERROR; - - while (glGetError() != GL_NO_ERROR); - - if (ddraw->bpp == 16) - { - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_RGB565, - SurfaceTexWidth, - SurfaceTexHeight, - 0, - SurfaceFormat = GL_RGB, - SurfaceType = GL_UNSIGNED_SHORT_5_6_5, - 0); - - - if (glGetError() != GL_NO_ERROR) - { - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_RGB5, - SurfaceTexWidth, - SurfaceTexHeight, - 0, - SurfaceFormat = GL_RGB, - SurfaceType = GL_UNSIGNED_SHORT_5_6_5, - 0); - } - } - else if (ddraw->bpp == 8) - { - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_LUMINANCE8, - SurfaceTexWidth, - SurfaceTexHeight, - 0, - SurfaceFormat = GL_LUMINANCE, - SurfaceType = GL_UNSIGNED_BYTE, - 0); - - - if (glGetError() != GL_NO_ERROR) - { - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_R8, - SurfaceTexWidth, - SurfaceTexHeight, - 0, - SurfaceFormat = GL_RED, - SurfaceType = GL_UNSIGNED_BYTE, - 0); - } - - if (glGetError() != GL_NO_ERROR) - { - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_RED, - SurfaceTexWidth, - SurfaceTexHeight, - 0, - SurfaceFormat = GL_RED, - SurfaceType = GL_UNSIGNED_BYTE, - 0); - } - } - } - - if (ddraw->bpp == 8) - { - glGenTextures(TEXTURE_COUNT, PaletteTexIds); - - for (i = 0; i < TEXTURE_COUNT; i++) - { - glBindTexture(GL_TEXTURE_2D, PaletteTexIds[i]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - } - } -} - -static void InitMainProgram() -{ - if (!MainProgram) - return; - - glUseProgram(MainProgram); - - glUniform1i(glGetUniformLocation(MainProgram, "SurfaceTex"), 0); - - if (ddraw->bpp == 8) - glUniform1i(glGetUniformLocation(MainProgram, "PaletteTex"), 1); - - if (OpenGL_GotVersion3) - { - MainVertexCoordAttrLoc = glGetAttribLocation(MainProgram, "VertexCoord"); - MainTexCoordAttrLoc = glGetAttribLocation(MainProgram, "TexCoord"); - - glGenBuffers(3, MainVBOs); - - if (ScaleProgram) - { - glBindBuffer(GL_ARRAY_BUFFER, MainVBOs[0]); - static const GLfloat vertexCoord[] = { - -1.0f,-1.0f, - -1.0f, 1.0f, - 1.0f, 1.0f, - 1.0f,-1.0f, - }; - glBufferData(GL_ARRAY_BUFFER, sizeof(vertexCoord), vertexCoord, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glBindBuffer(GL_ARRAY_BUFFER, MainVBOs[1]); - GLfloat texCoord[] = { - 0.0f, 0.0f, - 0.0f, ScaleH, - ScaleW, ScaleH, - ScaleW, 0.0f, - }; - glBufferData(GL_ARRAY_BUFFER, sizeof(texCoord), texCoord, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } - else - { - glBindBuffer(GL_ARRAY_BUFFER, MainVBOs[0]); - static const GLfloat vertexCoord[] = { - -1.0f, 1.0f, - 1.0f, 1.0f, - 1.0f,-1.0f, - -1.0f,-1.0f, - }; - glBufferData(GL_ARRAY_BUFFER, sizeof(vertexCoord), vertexCoord, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glBindBuffer(GL_ARRAY_BUFFER, MainVBOs[1]); - GLfloat texCoord[] = { - 0.0f, 0.0f, - ScaleW, 0.0f, - ScaleW, ScaleH, - 0.0f, ScaleH, - }; - glBufferData(GL_ARRAY_BUFFER, sizeof(texCoord), texCoord, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } - - glGenVertexArrays(1, &MainVAO); - glBindVertexArray(MainVAO); - - glBindBuffer(GL_ARRAY_BUFFER, MainVBOs[0]); - glVertexAttribPointer(MainVertexCoordAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL); - glEnableVertexAttribArray(MainVertexCoordAttrLoc); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glBindBuffer(GL_ARRAY_BUFFER, MainVBOs[1]); - glVertexAttribPointer(MainTexCoordAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL); - glEnableVertexAttribArray(MainTexCoordAttrLoc); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, MainVBOs[2]); - static const GLushort indices[] = - { - 0, 1, 2, - 0, 2, 3, - }; - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); - - glBindVertexArray(0); - - const float mvpMatrix[16] = { - 1,0,0,0, - 0,1,0,0, - 0,0,1,0, - 0,0,0,1, - }; - glUniformMatrix4fv(glGetUniformLocation(MainProgram, "MVPMatrix"), 1, GL_FALSE, mvpMatrix); - - } -} - -static void InitScaleProgram() -{ - if (!ScaleProgram) - return; - - glUseProgram(ScaleProgram); - - GLint vertexCoordAttrLoc = glGetAttribLocation(ScaleProgram, "VertexCoord"); - GLint texCoordAttrLoc = glGetAttribLocation(ScaleProgram, "TexCoord"); - FrameCountUniLoc = glGetUniformLocation(ScaleProgram, "FrameCount"); - - glGenBuffers(3, ScaleVBOs); - - glBindBuffer(GL_ARRAY_BUFFER, ScaleVBOs[0]); - static const GLfloat vertexCoord[] = { - -1.0f, 1.0f, - 1.0f, 1.0f, - 1.0f,-1.0f, - -1.0f,-1.0f, - }; - glBufferData(GL_ARRAY_BUFFER, sizeof(vertexCoord), vertexCoord, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glBindBuffer(GL_ARRAY_BUFFER, ScaleVBOs[1]); - GLfloat texCoord[] = { - 0.0f, 0.0f, - ScaleW, 0.0f, - ScaleW, ScaleH, - 0.0f, ScaleH, - }; - glBufferData(GL_ARRAY_BUFFER, sizeof(texCoord), texCoord, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glGenVertexArrays(1, &ScaleVAO); - glBindVertexArray(ScaleVAO); - - glBindBuffer(GL_ARRAY_BUFFER, ScaleVBOs[0]); - glVertexAttribPointer(vertexCoordAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL); - glEnableVertexAttribArray(vertexCoordAttrLoc); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glBindBuffer(GL_ARRAY_BUFFER, ScaleVBOs[1]); - glVertexAttribPointer(texCoordAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL); - glEnableVertexAttribArray(texCoordAttrLoc); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ScaleVBOs[2]); - static const GLushort indices[] = - { - 0, 1, 2, - 0, 2, 3, - }; - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); - - glBindVertexArray(0); - - float inputSize[2], outputSize[2], textureSize[2]; - - inputSize[0] = ddraw->width; - inputSize[1] = ddraw->height; - textureSize[0] = SurfaceTexWidth; - textureSize[1] = SurfaceTexHeight; - outputSize[0] = ddraw->render.viewport.width; - outputSize[1] = ddraw->render.viewport.height; - - glUniform2fv(glGetUniformLocation(ScaleProgram, "OutputSize"), 1, outputSize); - glUniform2fv(glGetUniformLocation(ScaleProgram, "TextureSize"), 1, textureSize); - glUniform2fv(glGetUniformLocation(ScaleProgram, "InputSize"), 1, inputSize); - glUniform1i(glGetUniformLocation(ScaleProgram, "FrameDirection"), 1); - glUniform1i(glGetUniformLocation(ScaleProgram, "Texture"), 0); - - const float mvpMatrix[16] = { - 1,0,0,0, - 0,1,0,0, - 0,0,1,0, - 0,0,0,1, - }; - glUniformMatrix4fv(glGetUniformLocation(ScaleProgram, "MVPMatrix"), 1, GL_FALSE, mvpMatrix); - - glGenFramebuffers(1, &FrameBufferId); - glBindFramebuffer(GL_FRAMEBUFFER, FrameBufferId); - - glGenTextures(1, &FrameBufferTexId); - glBindTexture(GL_TEXTURE_2D, FrameBufferTexId); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, FilterBilinear ? GL_LINEAR : GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, FilterBilinear ? GL_LINEAR : GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, SurfaceTexWidth, SurfaceTexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, FrameBufferTexId, 0); - - GLenum drawBuffers[1] = { GL_COLOR_ATTACHMENT0 }; - glDrawBuffers(1, drawBuffers); - - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - { - glDeleteTextures(1, &FrameBufferTexId); - - if (glDeleteFramebuffers) - glDeleteFramebuffers(1, &FrameBufferId); - - if (glDeleteProgram) - glDeleteProgram(ScaleProgram); - - ScaleProgram = 0; - - if (glDeleteBuffers) - glDeleteBuffers(3, ScaleVBOs); - - if (glDeleteVertexArrays) - glDeleteVertexArrays(1, &ScaleVAO); - - if (MainProgram) - { - glBindVertexArray(MainVAO); - glBindBuffer(GL_ARRAY_BUFFER, MainVBOs[0]); - static const GLfloat vertexCoordPal[] = { - -1.0f, 1.0f, - 1.0f, 1.0f, - 1.0f,-1.0f, - -1.0f,-1.0f, - }; - glBufferData(GL_ARRAY_BUFFER, sizeof(vertexCoordPal), vertexCoordPal, GL_STATIC_DRAW); - glVertexAttribPointer(MainVertexCoordAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL); - glEnableVertexAttribArray(MainVertexCoordAttrLoc); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - - glBindVertexArray(MainVAO); - glBindBuffer(GL_ARRAY_BUFFER, MainVBOs[1]); - GLfloat texCoordPal[] = { - 0.0f, 0.0f, - ScaleW, 0.0f, - ScaleW, ScaleH, - 0.0f, ScaleH, - }; - glBufferData(GL_ARRAY_BUFFER, sizeof(texCoordPal), texCoordPal, GL_STATIC_DRAW); - glVertexAttribPointer(MainTexCoordAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL); - glEnableVertexAttribArray(MainTexCoordAttrLoc); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - } - } - - glBindFramebuffer(GL_FRAMEBUFFER, 0); -} - -static void Render() -{ - DWORD tickStart = 0; - DWORD tickEnd = 0; - BOOL needsUpdate = FALSE; - - glViewport( - ddraw->render.viewport.x, ddraw->render.viewport.y, - ddraw->render.viewport.width, ddraw->render.viewport.height); - - if (MainProgram) - glUseProgram(MainProgram); - else if (ddraw->bpp == 16) - glEnable(GL_TEXTURE_2D); - - while (UseOpenGL && ddraw->render.run && - (ddraw->render.forcefps || WaitForSingleObject(ddraw->render.sem, 200) != WAIT_FAILED)) - { -#if _DEBUG - DrawFrameInfoStart(); -#endif - - ScaleW = (float)ddraw->width / SurfaceTexWidth; - ScaleH = (float)ddraw->height / SurfaceTexHeight; - - static int texIndex = 0, palIndex = 0; - - BOOL scaleChanged = FALSE; - - if (ddraw->fpsLimiter.ticklength > 0) - tickStart = timeGetTime(); - - EnterCriticalSection(&ddraw->cs); - - if (ddraw->primary && (ddraw->bpp == 16 || ddraw->primary->palette)) - { - if (ddraw->vhack) - { - if (detect_cutscene()) - { - ScaleW *= (float)CUTSCENE_WIDTH / ddraw->width; - ScaleH *= (float)CUTSCENE_HEIGHT / ddraw->height; - - if (!InterlockedExchange(&ddraw->incutscene, TRUE)) - scaleChanged = TRUE; - } - else - { - if (InterlockedExchange(&ddraw->incutscene, FALSE)) - scaleChanged = TRUE; - } - } - - if (ddraw->bpp == 8 && InterlockedExchange(&ddraw->render.paletteUpdated, FALSE)) - { - if (++palIndex >= TEXTURE_COUNT) - palIndex = 0; - - glBindTexture(GL_TEXTURE_2D, PaletteTexIds[palIndex]); - - glTexSubImage2D( - GL_TEXTURE_2D, - 0, - 0, - 0, - 256, - 1, - GL_RGBA, - GL_UNSIGNED_BYTE, - ddraw->primary->palette->data_bgr); - } - - if (InterlockedExchange(&ddraw->render.surfaceUpdated, FALSE)) - { - if (++texIndex >= TEXTURE_COUNT) - texIndex = 0; - - glBindTexture(GL_TEXTURE_2D, SurfaceTexIds[texIndex]); - - if (AdjustAlignment) - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - glTexSubImage2D( - GL_TEXTURE_2D, - 0, - 0, - 0, - ddraw->width, - ddraw->height, - SurfaceFormat, - SurfaceType, - ddraw->primary->surface); - - if (AdjustAlignment) - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - } - - static int errorCheckCount = 0; - if (errorCheckCount < 20) - { - glClear(GL_COLOR_BUFFER_BIT); - - errorCheckCount++; - - if (glGetError() != GL_NO_ERROR) - UseOpenGL = FALSE; - } - - if (!ddraw->handlemouse) - { - ChildWindowExists = FALSE; - EnumChildWindows(ddraw->hWnd, EnumChildProc, (LPARAM)ddraw->primary); - - if (ddraw->render.width != ddraw->width || ddraw->render.height != ddraw->height) - { - if (ChildWindowExists) - { - glClear(GL_COLOR_BUFFER_BIT); - - if (!needsUpdate) - { - glViewport(0, ddraw->render.height - ddraw->height, ddraw->width, ddraw->height); - needsUpdate = TRUE; - } - } - else if (needsUpdate) - { - glViewport( - ddraw->render.viewport.x, ddraw->render.viewport.y, - ddraw->render.viewport.width, ddraw->render.viewport.height); - - needsUpdate = FALSE; - } - } - } - } - - LeaveCriticalSection(&ddraw->cs); - - if (scaleChanged) - { - if (ScaleProgram && MainProgram) - { - glBindVertexArray(MainVAO); - glBindBuffer(GL_ARRAY_BUFFER, MainVBOs[1]); - GLfloat texCoord[] = { - 0.0f, 0.0f, - 0.0f, ScaleH, - ScaleW, ScaleH, - ScaleW, 0.0f, - }; - glBufferData(GL_ARRAY_BUFFER, sizeof(texCoord), texCoord, GL_STATIC_DRAW); - glVertexAttribPointer(MainTexCoordAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL); - glEnableVertexAttribArray(MainTexCoordAttrLoc); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - } - else if (OpenGL_GotVersion3 && MainProgram) - { - glBindVertexArray(MainVAO); - glBindBuffer(GL_ARRAY_BUFFER, MainVBOs[1]); - GLfloat texCoord[] = { - 0.0f, 0.0f, - ScaleW, 0.0f, - ScaleW, ScaleH, - 0.0f, ScaleH, - }; - glBufferData(GL_ARRAY_BUFFER, sizeof(texCoord), texCoord, GL_STATIC_DRAW); - glVertexAttribPointer(MainTexCoordAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL); - glEnableVertexAttribArray(MainTexCoordAttrLoc); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - } - } - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, SurfaceTexIds[texIndex]); - - if (ddraw->bpp == 8) - { - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, PaletteTexIds[palIndex]); - - glActiveTexture(GL_TEXTURE0); - } - - if (ScaleProgram && MainProgram) - { - // draw surface into framebuffer - glUseProgram(MainProgram); - - glViewport(0, 0, ddraw->width, ddraw->height); - - glBindFramebuffer(GL_FRAMEBUFFER, FrameBufferId); - - glBindVertexArray(MainVAO); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); - glBindVertexArray(0); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, 0); - - if (ChildWindowExists) - glViewport(0, ddraw->render.height - ddraw->height, ddraw->width, ddraw->height); - else - glViewport( - ddraw->render.viewport.x, ddraw->render.viewport.y, - ddraw->render.viewport.width, ddraw->render.viewport.height); - - // apply filter - - glUseProgram(ScaleProgram); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, FrameBufferTexId); - - static int frames = 1; - if (FrameCountUniLoc != -1) - glUniform1i(FrameCountUniLoc, frames++); - - glBindVertexArray(ScaleVAO); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); - glBindVertexArray(0); - } - else if (OpenGL_GotVersion3 && MainProgram) - { - glBindVertexArray(MainVAO); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); - glBindVertexArray(0); - } - else - { - glBegin(GL_TRIANGLE_FAN); - glTexCoord2f(0, 0); glVertex2f(-1, 1); - glTexCoord2f(ScaleW, 0); glVertex2f(1, 1); - glTexCoord2f(ScaleW, ScaleH); glVertex2f(1, -1); - glTexCoord2f(0, ScaleH); glVertex2f(-1, -1); - glEnd(); - } - - if (ddraw->bnetActive) - glClear(GL_COLOR_BUFFER_BIT); - - SwapBuffers(ddraw->render.hDC); - -#if _DEBUG - DrawFrameInfoEnd(); -#endif - - if (ddraw->fpsLimiter.ticklength > 0) - { - if (ddraw->fpsLimiter.hTimer) - { - if (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); - } - else - { - 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)); - } - } - } -} - -static void DeleteContext(HGLRC context) -{ - HeapFree(GetProcessHeap(), 0, SurfaceTex); - glDeleteTextures(TEXTURE_COUNT, SurfaceTexIds); - - if (ddraw->bpp == 8) - glDeleteTextures(TEXTURE_COUNT, PaletteTexIds); - - if (glUseProgram) - glUseProgram(0); - - if (ScaleProgram) - { - glDeleteTextures(1, &FrameBufferTexId); - - if (glDeleteBuffers) - glDeleteBuffers(3, ScaleVBOs); - - if (glDeleteFramebuffers) - glDeleteFramebuffers(1, &FrameBufferId); - - if (glDeleteVertexArrays) - glDeleteVertexArrays(1, &ScaleVAO); - } - - if (glDeleteProgram) - { - if (MainProgram) - glDeleteProgram(MainProgram); - - if (ScaleProgram) - glDeleteProgram(ScaleProgram); - } - - if (OpenGL_GotVersion3) - { - if (MainProgram) - { - if (glDeleteBuffers) - glDeleteBuffers(3, MainVBOs); - - if (glDeleteVertexArrays) - glDeleteVertexArrays(1, &MainVAO); - } - } - - xwglMakeCurrent(NULL, NULL); - xwglDeleteContext(context); -} - -static BOOL TextureUploadTest() -{ - static char testData[] = { 0,1,2,0,0,2,3,0,0,4,5,0,0,6,7,0,0,8,9,0 }; - - int i; - for (i = 0; i < TEXTURE_COUNT; i++) - { - memcpy(SurfaceTex, testData, sizeof(testData)); - - glBindTexture(GL_TEXTURE_2D, SurfaceTexIds[i]); - - glTexSubImage2D( - GL_TEXTURE_2D, - 0, - 0, - 0, - ddraw->width, - ddraw->height, - SurfaceFormat, - SurfaceType, - SurfaceTex); - - memset(SurfaceTex, 0, sizeof(testData)); - - glGetTexImage(GL_TEXTURE_2D, 0, SurfaceFormat, SurfaceType, SurfaceTex); - - if (memcmp(SurfaceTex, testData, sizeof(testData)) != 0) - return FALSE; - } - - if (ddraw->bpp == 8) - { - for (i = 0; i < TEXTURE_COUNT; i++) - { - glBindTexture(GL_TEXTURE_2D, PaletteTexIds[i]); - - glTexSubImage2D( - GL_TEXTURE_2D, - 0, - 0, - 0, - 256, - 1, - GL_RGBA, - GL_UNSIGNED_BYTE, - SurfaceTex); - - memset(SurfaceTex, 0, sizeof(testData)); - - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, SurfaceTex); - - if (memcmp(SurfaceTex, testData, sizeof(testData)) != 0) - return FALSE; - } - } - return TRUE; -} - -static BOOL ShaderTest() -{ - BOOL result = TRUE; - - if (ddraw->bpp != 8) - return result; - - if (OpenGL_GotVersion3 && MainProgram) - { - memset(SurfaceTex, 0, SurfaceTexHeight * SurfaceTexWidth * sizeof(int)); - - GLuint fboId = 0; - glGenFramebuffers(1, &fboId); - - glBindFramebuffer(GL_FRAMEBUFFER, fboId); - - GLuint fboTexId = 0; - glGenTextures(1, &fboTexId); - glBindTexture(GL_TEXTURE_2D, fboTexId); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, SurfaceTexWidth, SurfaceTexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, SurfaceTex); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTexId, 0); - - GLenum drawBuffers[1] = { GL_COLOR_ATTACHMENT0 }; - glDrawBuffers(1, drawBuffers); - - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) - { - static char gray0pal[] = { 128,128,128,128 }; - - glBindTexture(GL_TEXTURE_2D, PaletteTexIds[0]); - - glTexSubImage2D( - GL_TEXTURE_2D, - 0, - 0, - 0, - 1, - 1, - GL_RGBA, - GL_UNSIGNED_BYTE, - gray0pal); - - glBindTexture(GL_TEXTURE_2D, SurfaceTexIds[0]); - - glTexSubImage2D( - GL_TEXTURE_2D, - 0, - 0, - 0, - SurfaceTexWidth, - SurfaceTexHeight, - SurfaceFormat, - GL_UNSIGNED_BYTE, - SurfaceTex); - - glViewport(0, 0, SurfaceTexWidth, SurfaceTexHeight); - - glUseProgram(MainProgram); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, PaletteTexIds[0]); - glActiveTexture(GL_TEXTURE0); - - glBindVertexArray(MainVAO); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); - glBindVertexArray(0); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE0); - - glBindTexture(GL_TEXTURE_2D, fboTexId); - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, SurfaceTex); - - int i; - for (i = 0; i < SurfaceTexHeight * SurfaceTexWidth; i++) - { - if (SurfaceTex[i] != 0x80808080) - { - result = FALSE; - break; - } - } - } - - glBindTexture(GL_TEXTURE_2D, 0); - - if (glDeleteFramebuffers) - glDeleteFramebuffers(1, &fboId); - - glDeleteTextures(1, &fboTexId); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - } - - return result; -} diff --git a/src/render_d3d9.c b/src/render_d3d9.c index afaf35d..d16c147 100644 --- a/src/render_d3d9.c +++ b/src/render_d3d9.c @@ -1,58 +1,64 @@ #include #include #include -#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)); } } } diff --git a/src/render_gdi.c b/src/render_gdi.c new file mode 100644 index 0000000..44d0850 --- /dev/null +++ b/src/render_gdi.c @@ -0,0 +1,181 @@ +#include +#include +#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; +} diff --git a/src/render_ogl.c b/src/render_ogl.c new file mode 100644 index 0000000..d09ebe7 --- /dev/null +++ b/src/render_ogl.c @@ -0,0 +1,1025 @@ +#include +#include +#include "opengl_utils.h" +#include "dd.h" +#include "ddsurface.h" +#include "openglshader.h" +#include "render_gdi.h" +#include "render_ogl.h" +#include "utils.h" + + +static HGLRC ogl_create_context(HDC hdc); +static void ogl_set_max_fps(); +static void ogl_build_programs(); +static void ogl_create_textures(int width, int height); +static void ogl_init_main_program(); +static void ogl_init_scale_program(); +static void ogl_render(); +static void ogl_delete_context(HGLRC context); +static BOOL ogl_texture_upload_test(); +static BOOL ogl_shader_test(); + +static ogl_renderer g_ogl; + +DWORD WINAPI ogl_render_main(void) +{ + Sleep(500); + g_ogl.got_error = g_ogl.use_opengl = FALSE; + + g_ogl.context = ogl_create_context(g_ddraw->render.hdc); + if (g_ogl.context) + { + oglu_init(); + ogl_set_max_fps(); + ogl_build_programs(); + ogl_create_textures(g_ddraw->width, g_ddraw->height); + ogl_init_main_program(); + ogl_init_scale_program(); + + g_ogl.got_error = g_ogl.got_error || !ogl_texture_upload_test(); + g_ogl.got_error = g_ogl.got_error || !ogl_shader_test(); + g_ogl.got_error = g_ogl.got_error || glGetError() != GL_NO_ERROR; + g_ogl.use_opengl = (g_ogl.main_program || g_ddraw->bpp == 16) && !g_ogl.got_error; + + ogl_render(); + + ogl_delete_context(g_ogl.context); + } + + if (!g_ogl.use_opengl) + { + g_ddraw->show_driver_warning = TRUE; + g_ddraw->renderer = gdi_render_main; + gdi_render_main(); + } + + return 0; +} + +static HGLRC ogl_create_context(HDC hdc) +{ + HGLRC context = xwglCreateContext(hdc); + BOOL made_current = context && xwglMakeCurrent(hdc, context); + + if (!made_current || glGetError() != GL_NO_ERROR) + { + if (made_current) + { + xwglMakeCurrent(NULL, NULL); + xwglDeleteContext(context); + } + + context = 0; + } + + return context; +} + +static void ogl_set_max_fps() +{ + int max_fps = g_ddraw->render.maxfps; + + g_ddraw->fps_limiter.tick_length_ns = 0; + g_ddraw->fps_limiter.tick_length = 0; + + /* + if (oglu_ext_exists("WGL_EXT_swap_control_tear", g_ddraw->render.hDC)) + { + if (wglSwapIntervalEXT) + { + if (g_ddraw->vsync) + { + wglSwapIntervalEXT(-1); + max_fps = g_ddraw->mode.dmDisplayFrequency; + } + else + wglSwapIntervalEXT(0); + } + } + else */ + if (oglu_ext_exists("WGL_EXT_swap_control", g_ddraw->render.hdc)) + { + if (wglSwapIntervalEXT) + { + if (g_ddraw->vsync) + { + wglSwapIntervalEXT(1); + max_fps = g_ddraw->mode.dmDisplayFrequency; + } + else + wglSwapIntervalEXT(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;// + 0.5f; + } +} + +static void ogl_build_programs() +{ + g_ogl.main_program = g_ogl.scale_program = 0; + + if (g_oglu_got_version3) + { + if (g_ddraw->bpp == 8) + { + g_ogl.main_program = oglu_build_program(PASSTHROUGH_VERT_SHADER, PALETTE_FRAG_SHADER); + } + else if (g_ddraw->bpp == 16) + { + g_ogl.main_program = oglu_build_program(PASSTHROUGH_VERT_SHADER, PASSTHROUGH_FRAG_SHADER); + } + + if (g_ogl.main_program) + { + g_ogl.scale_program = oglu_build_program_from_file(g_ddraw->shader); + } + else + { + g_oglu_got_version3 = FALSE; + } + + g_ogl.filter_bilinear = strstr(g_ddraw->shader, "bilinear.glsl") != 0; + } + + if (g_oglu_got_version2 && !g_ogl.main_program) + { + if (g_ddraw->bpp == 8) + { + g_ogl.main_program = oglu_build_program(PASSTHROUGH_VERT_SHADER_110, PALETTE_FRAG_SHADER_110); + } + else if (g_ddraw->bpp == 16) + { + g_ogl.main_program = oglu_build_program(PASSTHROUGH_VERT_SHADER_110, PASSTHROUGH_FRAG_SHADER_110); + } + } +} + +static void ogl_create_textures(int width, int height) +{ + g_ogl.surface_tex_width = + width <= 1024 ? 1024 : width <= 2048 ? 2048 : width <= 4096 ? 4096 : width; + + g_ogl.surface_tex_height = + height <= 512 ? 512 : height <= 1024 ? 1024 : height <= 2048 ? 2048 : height <= 4096 ? 4096 : height; + + g_ogl.surface_tex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, g_ogl.surface_tex_width * g_ogl.surface_tex_height * sizeof(int)); + + g_ogl.adjust_alignment = (width % 4) != 0; + + g_ogl.scale_w = (float)width / g_ogl.surface_tex_width; + g_ogl.scale_h = (float)height / g_ogl.surface_tex_height; + + glGenTextures(TEXTURE_COUNT, g_ogl.surface_tex_ids); + + int i; + for (i = 0; i < TEXTURE_COUNT; i++) + { + glBindTexture(GL_TEXTURE_2D, g_ogl.surface_tex_ids[i]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + g_ogl.got_error = g_ogl.got_error || glGetError() != GL_NO_ERROR; + + while (glGetError() != GL_NO_ERROR); + + if (g_ddraw->bpp == 16) + { + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGB565, + g_ogl.surface_tex_width, + g_ogl.surface_tex_height, + 0, + g_ogl.surface_format = GL_RGB, + g_ogl.surface_type = GL_UNSIGNED_SHORT_5_6_5, + 0); + + + if (glGetError() != GL_NO_ERROR) + { + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGB5, + g_ogl.surface_tex_width, + g_ogl.surface_tex_height, + 0, + g_ogl.surface_format = GL_RGB, + g_ogl.surface_type = GL_UNSIGNED_SHORT_5_6_5, + 0); + } + } + else if (g_ddraw->bpp == 8) + { + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_LUMINANCE8, + g_ogl.surface_tex_width, + g_ogl.surface_tex_height, + 0, + g_ogl.surface_format = GL_LUMINANCE, + g_ogl.surface_type = GL_UNSIGNED_BYTE, + 0); + + + if (glGetError() != GL_NO_ERROR) + { + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_R8, + g_ogl.surface_tex_width, + g_ogl.surface_tex_height, + 0, + g_ogl.surface_format = GL_RED, + g_ogl.surface_type = GL_UNSIGNED_BYTE, + 0); + } + + if (glGetError() != GL_NO_ERROR) + { + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RED, + g_ogl.surface_tex_width, + g_ogl.surface_tex_height, + 0, + g_ogl.surface_format = GL_RED, + g_ogl.surface_type = GL_UNSIGNED_BYTE, + 0); + } + } + } + + if (g_ddraw->bpp == 8) + { + glGenTextures(TEXTURE_COUNT, g_ogl.palette_tex_ids); + + for (i = 0; i < TEXTURE_COUNT; i++) + { + glBindTexture(GL_TEXTURE_2D, g_ogl.palette_tex_ids[i]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + } + } +} + +static void ogl_init_main_program() +{ + if (!g_ogl.main_program) + return; + + glUseProgram(g_ogl.main_program); + + glUniform1i(glGetUniformLocation(g_ogl.main_program, "SurfaceTex"), 0); + + if (g_ddraw->bpp == 8) + glUniform1i(glGetUniformLocation(g_ogl.main_program, "PaletteTex"), 1); + + if (g_oglu_got_version3) + { + g_ogl.main_vertex_coord_attr_loc = glGetAttribLocation(g_ogl.main_program, "VertexCoord"); + g_ogl.main_tex_coord_attr_loc = glGetAttribLocation(g_ogl.main_program, "TexCoord"); + + glGenBuffers(3, g_ogl.main_vbos); + + if (g_ogl.scale_program) + { + glBindBuffer(GL_ARRAY_BUFFER, g_ogl.main_vbos[0]); + static const GLfloat vertex_coord[] = { + -1.0f,-1.0f, + -1.0f, 1.0f, + 1.0f, 1.0f, + 1.0f,-1.0f, + }; + glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_coord), vertex_coord, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glBindBuffer(GL_ARRAY_BUFFER, g_ogl.main_vbos[1]); + GLfloat tex_coord[] = { + 0.0f, 0.0f, + 0.0f, g_ogl.scale_h, + g_ogl.scale_w, g_ogl.scale_h, + g_ogl.scale_w, 0.0f, + }; + glBufferData(GL_ARRAY_BUFFER, sizeof(tex_coord), tex_coord, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + glBindBuffer(GL_ARRAY_BUFFER, g_ogl.main_vbos[0]); + static const GLfloat vertex_coord[] = { + -1.0f, 1.0f, + 1.0f, 1.0f, + 1.0f,-1.0f, + -1.0f,-1.0f, + }; + glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_coord), vertex_coord, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glBindBuffer(GL_ARRAY_BUFFER, g_ogl.main_vbos[1]); + GLfloat tex_coord[] = { + 0.0f, 0.0f, + g_ogl.scale_w, 0.0f, + g_ogl.scale_w, g_ogl.scale_h, + 0.0f, g_ogl.scale_h, + }; + glBufferData(GL_ARRAY_BUFFER, sizeof(tex_coord), tex_coord, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + + glGenVertexArrays(1, &g_ogl.main_vao); + glBindVertexArray(g_ogl.main_vao); + + glBindBuffer(GL_ARRAY_BUFFER, g_ogl.main_vbos[0]); + glVertexAttribPointer(g_ogl.main_vertex_coord_attr_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glEnableVertexAttribArray(g_ogl.main_vertex_coord_attr_loc); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glBindBuffer(GL_ARRAY_BUFFER, g_ogl.main_vbos[1]); + glVertexAttribPointer(g_ogl.main_tex_coord_attr_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glEnableVertexAttribArray(g_ogl.main_tex_coord_attr_loc); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ogl.main_vbos[2]); + static const GLushort indices[] = + { + 0, 1, 2, + 0, 2, 3, + }; + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); + + glBindVertexArray(0); + + const float mvp_matrix[16] = { + 1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1, + }; + glUniformMatrix4fv(glGetUniformLocation(g_ogl.main_program, "MVPMatrix"), 1, GL_FALSE, mvp_matrix); + + } +} + +static void ogl_init_scale_program() +{ + if (!g_ogl.scale_program) + return; + + glUseProgram(g_ogl.scale_program); + + GLint vertex_coord_attr_loc = glGetAttribLocation(g_ogl.scale_program, "VertexCoord"); + GLint tex_coord_attr_loc = glGetAttribLocation(g_ogl.scale_program, "TexCoord"); + g_ogl.frame_count_uni_loc = glGetUniformLocation(g_ogl.scale_program, "FrameCount"); + + glGenBuffers(3, g_ogl.scale_vbos); + + glBindBuffer(GL_ARRAY_BUFFER, g_ogl.scale_vbos[0]); + static const GLfloat vertext_coord[] = { + -1.0f, 1.0f, + 1.0f, 1.0f, + 1.0f,-1.0f, + -1.0f,-1.0f, + }; + glBufferData(GL_ARRAY_BUFFER, sizeof(vertext_coord), vertext_coord, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glBindBuffer(GL_ARRAY_BUFFER, g_ogl.scale_vbos[1]); + GLfloat tex_coord[] = { + 0.0f, 0.0f, + g_ogl.scale_w, 0.0f, + g_ogl.scale_w, g_ogl.scale_h, + 0.0f, g_ogl.scale_h, + }; + glBufferData(GL_ARRAY_BUFFER, sizeof(tex_coord), tex_coord, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glGenVertexArrays(1, &g_ogl.scale_vao); + glBindVertexArray(g_ogl.scale_vao); + + glBindBuffer(GL_ARRAY_BUFFER, g_ogl.scale_vbos[0]); + glVertexAttribPointer(vertex_coord_attr_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glEnableVertexAttribArray(vertex_coord_attr_loc); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glBindBuffer(GL_ARRAY_BUFFER, g_ogl.scale_vbos[1]); + glVertexAttribPointer(tex_coord_attr_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glEnableVertexAttribArray(tex_coord_attr_loc); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ogl.scale_vbos[2]); + static const GLushort indices[] = + { + 0, 1, 2, + 0, 2, 3, + }; + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); + + glBindVertexArray(0); + + float input_size[2], output_size[2], texture_size[2]; + + input_size[0] = g_ddraw->width; + input_size[1] = g_ddraw->height; + texture_size[0] = g_ogl.surface_tex_width; + texture_size[1] = g_ogl.surface_tex_height; + output_size[0] = g_ddraw->render.viewport.width; + output_size[1] = g_ddraw->render.viewport.height; + + glUniform2fv(glGetUniformLocation(g_ogl.scale_program, "OutputSize"), 1, output_size); + glUniform2fv(glGetUniformLocation(g_ogl.scale_program, "TextureSize"), 1, texture_size); + glUniform2fv(glGetUniformLocation(g_ogl.scale_program, "InputSize"), 1, input_size); + glUniform1i(glGetUniformLocation(g_ogl.scale_program, "FrameDirection"), 1); + glUniform1i(glGetUniformLocation(g_ogl.scale_program, "Texture"), 0); + + const float mvp_matrix[16] = { + 1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1, + }; + glUniformMatrix4fv(glGetUniformLocation(g_ogl.scale_program, "MVPMatrix"), 1, GL_FALSE, mvp_matrix); + + glGenFramebuffers(1, &g_ogl.frame_buffer_id); + glBindFramebuffer(GL_FRAMEBUFFER, g_ogl.frame_buffer_id); + + glGenTextures(1, &g_ogl.frame_buffer_tex_id); + glBindTexture(GL_TEXTURE_2D, g_ogl.frame_buffer_tex_id); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, g_ogl.filter_bilinear ? GL_LINEAR : GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, g_ogl.filter_bilinear ? GL_LINEAR : GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, g_ogl.surface_tex_width, g_ogl.surface_tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, g_ogl.frame_buffer_tex_id, 0); + + GLenum draw_buffers[1] = { GL_COLOR_ATTACHMENT0 }; + glDrawBuffers(1, draw_buffers); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + { + glDeleteTextures(1, &g_ogl.frame_buffer_tex_id); + + if (glDeleteFramebuffers) + glDeleteFramebuffers(1, &g_ogl.frame_buffer_id); + + if (glDeleteProgram) + glDeleteProgram(g_ogl.scale_program); + + g_ogl.scale_program = 0; + + if (glDeleteBuffers) + glDeleteBuffers(3, g_ogl.scale_vbos); + + if (glDeleteVertexArrays) + glDeleteVertexArrays(1, &g_ogl.scale_vao); + + if (g_ogl.main_program) + { + glBindVertexArray(g_ogl.main_vao); + glBindBuffer(GL_ARRAY_BUFFER, g_ogl.main_vbos[0]); + static const GLfloat vertex_coord_pal[] = { + -1.0f, 1.0f, + 1.0f, 1.0f, + 1.0f,-1.0f, + -1.0f,-1.0f, + }; + glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_coord_pal), vertex_coord_pal, GL_STATIC_DRAW); + glVertexAttribPointer(g_ogl.main_vertex_coord_attr_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glEnableVertexAttribArray(g_ogl.main_vertex_coord_attr_loc); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + + glBindVertexArray(g_ogl.main_vao); + glBindBuffer(GL_ARRAY_BUFFER, g_ogl.main_vbos[1]); + GLfloat tex_coord_pal[] = { + 0.0f, 0.0f, + g_ogl.scale_w, 0.0f, + g_ogl.scale_w, g_ogl.scale_h, + 0.0f, g_ogl.scale_h, + }; + glBufferData(GL_ARRAY_BUFFER, sizeof(tex_coord_pal), tex_coord_pal, GL_STATIC_DRAW); + glVertexAttribPointer(g_ogl.main_tex_coord_attr_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glEnableVertexAttribArray(g_ogl.main_tex_coord_attr_loc); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + } + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +static void ogl_render() +{ + DWORD tick_start = 0; + DWORD tick_end = 0; + BOOL needs_update = FALSE; + + glViewport( + g_ddraw->render.viewport.x, g_ddraw->render.viewport.y, + g_ddraw->render.viewport.width, g_ddraw->render.viewport.height); + + if (g_ogl.main_program) + glUseProgram(g_ogl.main_program); + else if (g_ddraw->bpp == 16) + glEnable(GL_TEXTURE_2D); + + while (g_ogl.use_opengl && g_ddraw->render.run && + (g_ddraw->render.forcefps || WaitForSingleObject(g_ddraw->render.sem, 200) != WAIT_FAILED)) + { +#if _DEBUG + DrawFrameInfoStart(); +#endif + + g_ogl.scale_w = (float)g_ddraw->width / g_ogl.surface_tex_width; + g_ogl.scale_h = (float)g_ddraw->height / g_ogl.surface_tex_height; + + static int tex_index = 0, pal_index = 0; + + BOOL scale_changed = FALSE; + + 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)) + { + if (g_ddraw->vhack) + { + if (util_detect_cutscene()) + { + g_ogl.scale_w *= (float)CUTSCENE_WIDTH / g_ddraw->width; + g_ogl.scale_h *= (float)CUTSCENE_HEIGHT / g_ddraw->height; + + if (!InterlockedExchange(&g_ddraw->incutscene, TRUE)) + scale_changed = TRUE; + } + else + { + if (InterlockedExchange(&g_ddraw->incutscene, FALSE)) + scale_changed = TRUE; + } + } + + if (g_ddraw->bpp == 8 && InterlockedExchange(&g_ddraw->render.palette_updated, FALSE)) + { + if (++pal_index >= TEXTURE_COUNT) + pal_index = 0; + + glBindTexture(GL_TEXTURE_2D, g_ogl.palette_tex_ids[pal_index]); + + glTexSubImage2D( + GL_TEXTURE_2D, + 0, + 0, + 0, + 256, + 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + g_ddraw->primary->palette->data_bgr); + } + + if (InterlockedExchange(&g_ddraw->render.surface_updated, FALSE)) + { + if (++tex_index >= TEXTURE_COUNT) + tex_index = 0; + + glBindTexture(GL_TEXTURE_2D, g_ogl.surface_tex_ids[tex_index]); + + if (g_ogl.adjust_alignment) + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + glTexSubImage2D( + GL_TEXTURE_2D, + 0, + 0, + 0, + g_ddraw->width, + g_ddraw->height, + g_ogl.surface_format, + g_ogl.surface_type, + g_ddraw->primary->surface); + + if (g_ogl.adjust_alignment) + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + } + + static int error_check_count = 0; + if (error_check_count < 20) + { + glClear(GL_COLOR_BUFFER_BIT); + + error_check_count++; + + if (glGetError() != GL_NO_ERROR) + g_ogl.use_opengl = FALSE; + } + + 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->render.width != g_ddraw->width || g_ddraw->render.height != g_ddraw->height) + { + if (g_ddraw->child_window_exists) + { + glClear(GL_COLOR_BUFFER_BIT); + + if (!needs_update) + { + glViewport(0, g_ddraw->render.height - g_ddraw->height, g_ddraw->width, g_ddraw->height); + needs_update = TRUE; + } + } + else if (needs_update) + { + glViewport( + g_ddraw->render.viewport.x, g_ddraw->render.viewport.y, + g_ddraw->render.viewport.width, g_ddraw->render.viewport.height); + + needs_update = FALSE; + } + } + } + } + + LeaveCriticalSection(&g_ddraw->cs); + + if (scale_changed) + { + if (g_ogl.scale_program && g_ogl.main_program) + { + glBindVertexArray(g_ogl.main_vao); + glBindBuffer(GL_ARRAY_BUFFER, g_ogl.main_vbos[1]); + GLfloat texCoord[] = { + 0.0f, 0.0f, + 0.0f, g_ogl.scale_h, + g_ogl.scale_w, g_ogl.scale_h, + g_ogl.scale_w, 0.0f, + }; + glBufferData(GL_ARRAY_BUFFER, sizeof(texCoord), texCoord, GL_STATIC_DRAW); + glVertexAttribPointer(g_ogl.main_tex_coord_attr_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glEnableVertexAttribArray(g_ogl.main_tex_coord_attr_loc); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + } + else if (g_oglu_got_version3 && g_ogl.main_program) + { + glBindVertexArray(g_ogl.main_vao); + glBindBuffer(GL_ARRAY_BUFFER, g_ogl.main_vbos[1]); + GLfloat texCoord[] = { + 0.0f, 0.0f, + g_ogl.scale_w, 0.0f, + g_ogl.scale_w, g_ogl.scale_h, + 0.0f, g_ogl.scale_h, + }; + glBufferData(GL_ARRAY_BUFFER, sizeof(texCoord), texCoord, GL_STATIC_DRAW); + glVertexAttribPointer(g_ogl.main_tex_coord_attr_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glEnableVertexAttribArray(g_ogl.main_tex_coord_attr_loc); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + } + } + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, g_ogl.surface_tex_ids[tex_index]); + + if (g_ddraw->bpp == 8) + { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, g_ogl.palette_tex_ids[pal_index]); + + glActiveTexture(GL_TEXTURE0); + } + + if (g_ogl.scale_program && g_ogl.main_program) + { + // draw surface into framebuffer + glUseProgram(g_ogl.main_program); + + glViewport(0, 0, g_ddraw->width, g_ddraw->height); + + glBindFramebuffer(GL_FRAMEBUFFER, g_ogl.frame_buffer_id); + + glBindVertexArray(g_ogl.main_vao); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); + glBindVertexArray(0); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, 0); + + if (g_ddraw->child_window_exists) + glViewport(0, g_ddraw->render.height - g_ddraw->height, g_ddraw->width, g_ddraw->height); + else + glViewport( + g_ddraw->render.viewport.x, g_ddraw->render.viewport.y, + g_ddraw->render.viewport.width, g_ddraw->render.viewport.height); + + // apply filter + + glUseProgram(g_ogl.scale_program); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, g_ogl.frame_buffer_tex_id); + + static int frames = 1; + if (g_ogl.frame_count_uni_loc != -1) + glUniform1i(g_ogl.frame_count_uni_loc, frames++); + + glBindVertexArray(g_ogl.scale_vao); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); + glBindVertexArray(0); + } + else if (g_oglu_got_version3 && g_ogl.main_program) + { + glBindVertexArray(g_ogl.main_vao); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); + glBindVertexArray(0); + } + else + { + glBegin(GL_TRIANGLE_FAN); + glTexCoord2f(0, 0); glVertex2f(-1, 1); + glTexCoord2f(g_ogl.scale_w, 0); glVertex2f(1, 1); + glTexCoord2f(g_ogl.scale_w, g_ogl.scale_h); glVertex2f(1, -1); + glTexCoord2f(0, g_ogl.scale_h); glVertex2f(-1, -1); + glEnd(); + } + + if (g_ddraw->bnet_active) + glClear(GL_COLOR_BUFFER_BIT); + + SwapBuffers(g_ddraw->render.hdc); + +#if _DEBUG + DrawFrameInfoEnd(); +#endif + + if (g_ddraw->fps_limiter.tick_length > 0) + { + if (g_ddraw->fps_limiter.htimer) + { + if (g_ddraw->vsync) + { + 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 *)&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)); + } + } + } +} + +static void ogl_delete_context(HGLRC context) +{ + HeapFree(GetProcessHeap(), 0, g_ogl.surface_tex); + glDeleteTextures(TEXTURE_COUNT, g_ogl.surface_tex_ids); + + if (g_ddraw->bpp == 8) + glDeleteTextures(TEXTURE_COUNT, g_ogl.palette_tex_ids); + + if (glUseProgram) + glUseProgram(0); + + if (g_ogl.scale_program) + { + glDeleteTextures(1, &g_ogl.frame_buffer_tex_id); + + if (glDeleteBuffers) + glDeleteBuffers(3, g_ogl.scale_vbos); + + if (glDeleteFramebuffers) + glDeleteFramebuffers(1, &g_ogl.frame_buffer_id); + + if (glDeleteVertexArrays) + glDeleteVertexArrays(1, &g_ogl.scale_vao); + } + + if (glDeleteProgram) + { + if (g_ogl.main_program) + glDeleteProgram(g_ogl.main_program); + + if (g_ogl.scale_program) + glDeleteProgram(g_ogl.scale_program); + } + + if (g_oglu_got_version3) + { + if (g_ogl.main_program) + { + if (glDeleteBuffers) + glDeleteBuffers(3, g_ogl.main_vbos); + + if (glDeleteVertexArrays) + glDeleteVertexArrays(1, &g_ogl.main_vao); + } + } + + xwglMakeCurrent(NULL, NULL); + xwglDeleteContext(context); +} + +static BOOL ogl_texture_upload_test() +{ + static char test_data[] = { 0,1,2,0,0,2,3,0,0,4,5,0,0,6,7,0,0,8,9,0 }; + + int i; + for (i = 0; i < TEXTURE_COUNT; i++) + { + memcpy(g_ogl.surface_tex, test_data, sizeof(test_data)); + + glBindTexture(GL_TEXTURE_2D, g_ogl.surface_tex_ids[i]); + + glTexSubImage2D( + GL_TEXTURE_2D, + 0, + 0, + 0, + g_ddraw->width, + g_ddraw->height, + g_ogl.surface_format, + g_ogl.surface_type, + g_ogl.surface_tex); + + memset(g_ogl.surface_tex, 0, sizeof(test_data)); + + glGetTexImage(GL_TEXTURE_2D, 0, g_ogl.surface_format, g_ogl.surface_type, g_ogl.surface_tex); + + if (memcmp(g_ogl.surface_tex, test_data, sizeof(test_data)) != 0) + return FALSE; + } + + if (g_ddraw->bpp == 8) + { + for (i = 0; i < TEXTURE_COUNT; i++) + { + glBindTexture(GL_TEXTURE_2D, g_ogl.palette_tex_ids[i]); + + glTexSubImage2D( + GL_TEXTURE_2D, + 0, + 0, + 0, + 256, + 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + g_ogl.surface_tex); + + memset(g_ogl.surface_tex, 0, sizeof(test_data)); + + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, g_ogl.surface_tex); + + if (memcmp(g_ogl.surface_tex, test_data, sizeof(test_data)) != 0) + return FALSE; + } + } + return TRUE; +} + +static BOOL ogl_shader_test() +{ + BOOL result = TRUE; + + if (g_ddraw->bpp != 8) + return result; + + if (g_oglu_got_version3 && g_ogl.main_program) + { + memset(g_ogl.surface_tex, 0, g_ogl.surface_tex_height * g_ogl.surface_tex_width * sizeof(int)); + + GLuint fbo_id = 0; + glGenFramebuffers(1, &fbo_id); + + glBindFramebuffer(GL_FRAMEBUFFER, fbo_id); + + GLuint fbo_tex_id = 0; + glGenTextures(1, &fbo_tex_id); + glBindTexture(GL_TEXTURE_2D, fbo_tex_id); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, g_ogl.surface_tex_width, g_ogl.surface_tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, g_ogl.surface_tex); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo_tex_id, 0); + + GLenum draw_buffers[1] = { GL_COLOR_ATTACHMENT0 }; + glDrawBuffers(1, draw_buffers); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) + { + static char gray0pal[] = { 128,128,128,128 }; + + glBindTexture(GL_TEXTURE_2D, g_ogl.palette_tex_ids[0]); + + glTexSubImage2D( + GL_TEXTURE_2D, + 0, + 0, + 0, + 1, + 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + gray0pal); + + glBindTexture(GL_TEXTURE_2D, g_ogl.surface_tex_ids[0]); + + glTexSubImage2D( + GL_TEXTURE_2D, + 0, + 0, + 0, + g_ogl.surface_tex_width, + g_ogl.surface_tex_height, + g_ogl.surface_format, + GL_UNSIGNED_BYTE, + g_ogl.surface_tex); + + glViewport(0, 0, g_ogl.surface_tex_width, g_ogl.surface_tex_height); + + glUseProgram(g_ogl.main_program); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, g_ogl.palette_tex_ids[0]); + glActiveTexture(GL_TEXTURE0); + + glBindVertexArray(g_ogl.main_vao); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); + glBindVertexArray(0); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE0); + + glBindTexture(GL_TEXTURE_2D, fbo_tex_id); + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, g_ogl.surface_tex); + + int i; + for (i = 0; i < g_ogl.surface_tex_height * g_ogl.surface_tex_width; i++) + { + if (g_ogl.surface_tex[i] != 0x80808080) + { + result = FALSE; + break; + } + } + } + + glBindTexture(GL_TEXTURE_2D, 0); + + if (glDeleteFramebuffers) + glDeleteFramebuffers(1, &fbo_id); + + glDeleteTextures(1, &fbo_tex_id); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } + + return result; +} diff --git a/src/render_soft.c b/src/render_soft.c deleted file mode 100644 index 1dd6014..0000000 --- a/src/render_soft.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) 2011 Toni Spets - * - * 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 -#include - -#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; -} diff --git a/src/screenshot.c b/src/screenshot.c index afa77b9..ca9c4a3 100644 --- a/src/screenshot.c +++ b/src/screenshot.c @@ -1,28 +1,13 @@ -/* - * Copyright (c) 2010 Toni Spets - * - * 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 #include -#include #include -#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 - * - * 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 -#include - -#include "main.h" -#include "hook.h" -#include "surface.h" -#include "mouse.h" -#include "scale_pattern.h" - -// enables redraw via blt/unlock if there wasn't any flip for X ms -#define FLIP_REDRAW_TIMEOUT 1000 / 10 - -void dump_ddbltflags(DWORD dwFlags); -void dump_ddscaps(DWORD dwCaps); -void dump_ddsd(DWORD dwFlags); -DWORD WINAPI render_soft_main(void); -void *pvBmpBits; - -HRESULT __stdcall ddraw_surface_QueryInterface(IDirectDrawSurfaceImpl *This, REFIID riid, void **obj) -{ - printf("??? DirectDrawSurface::QueryInterface(This=%p, riid=%08X, obj=%p)\n", This, (unsigned int)riid, obj); - - if (riid && !IsEqualGUID(&IID_IDirectDrawSurface, riid)) - { - printf(" GUID = %08X\n", ((GUID *)riid)->Data1); - - IDirectDrawSurface_AddRef(This); - } - - *obj = This; - - return S_OK; -} - -ULONG __stdcall ddraw_surface_AddRef(IDirectDrawSurfaceImpl *This) -{ - printf("DirectDrawSurface::AddRef(This=%p)\n", This); - This->Ref++; - return This->Ref; -} - -ULONG __stdcall ddraw_surface_Release(IDirectDrawSurfaceImpl *This) -{ - printf("DirectDrawSurface::Release(This=%p)\n", This); - - This->Ref--; - - if(This->Ref == 0) - { - printf(" Released (%p)\n", This); - - if(This->caps & DDSCAPS_PRIMARYSURFACE) - { - EnterCriticalSection(&ddraw->cs); - ddraw->primary = NULL; - LeaveCriticalSection(&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 && This->palette != LastFreedPalette) - { - IDirectDrawPalette_Release(This->palette); - } - HeapFree(GetProcessHeap(), 0, This); - return 0; - } - return This->Ref; -} - -HRESULT __stdcall ddraw_surface_AddAttachedSurface(IDirectDrawSurfaceImpl *This, LPDIRECTDRAWSURFACE lpDDSurface) -{ - printf("??? DirectDrawSurface::AddAttachedSurface(This=%p, lpDDSurface=%p)\n", This, lpDDSurface); - IDirectDrawSurface_AddRef(lpDDSurface); - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_AddOverlayDirtyRect(IDirectDrawSurfaceImpl *This, LPRECT a) -{ - printf("??? DirectDrawSurface::AddOverlayDirtyRect(This=%p, ...)\n", This); - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_Blt(IDirectDrawSurfaceImpl *This, LPRECT lpDestRect, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx) -{ - IDirectDrawSurfaceImpl *Source = (IDirectDrawSurfaceImpl *)lpDDSrcSurface; - -#if _DEBUG_X - printf("DirectDrawSurface::Blt(This=%p, lpDestRect=%p, lpDDSrcSurface=%p, lpSrcRect=%p, dwFlags=%08X, lpDDBltFx=%p)\n", This, lpDestRect, lpDDSrcSurface, lpSrcRect, (int)dwFlags, lpDDBltFx); - - dump_ddbltflags(dwFlags); - - if(lpDestRect) - { - printf(" dest: l: %d t: %d r: %d b: %d\n", (int)lpDestRect->left, (int)lpDestRect->top, (int)lpDestRect->right, (int)lpDestRect->bottom); - } - if(lpSrcRect) - { - printf(" src: l: %d t: %d r: %d b: %d\n", (int)lpSrcRect->left, (int)lpSrcRect->top, (int)lpSrcRect->right, (int)lpSrcRect->bottom); - } -#endif - - RECT srcRect = { 0, 0, Source ? Source->width : 0, Source ? Source->height : 0 }; - RECT dstRect = { 0, 0, This->width, This->height }; - - if (lpSrcRect && Source) - memcpy(&srcRect, lpSrcRect, sizeof(srcRect)); - - if (lpDestRect) - memcpy(&dstRect, lpDestRect, sizeof(dstRect)); - - // stretch or clip? - BOOL isStretchBlt = - ((srcRect.right - srcRect.left) != (dstRect.right - dstRect.left)) || - ((srcRect.bottom - srcRect.top) != (dstRect.bottom - dstRect.top)); - - if (Source) - { - if (srcRect.right > Source->width) - srcRect.right = Source->width; - - if (srcRect.bottom > Source->height) - srcRect.bottom = Source->height; - } - - if (dstRect.right > This->width) - dstRect.right = This->width; - - if (dstRect.bottom > This->height) - dstRect.bottom = This->height; - - int src_w = srcRect.right - srcRect.left; - int src_h = srcRect.bottom - srcRect.top; - int src_x = srcRect.left; - int src_y = srcRect.top; - - int dst_w = dstRect.right - dstRect.left; - int dst_h = dstRect.bottom - dstRect.top; - int dst_x = dstRect.left; - int dst_y = dstRect.top; - - - if (This->surface && (dwFlags & DDBLT_COLORFILL)) - { - unsigned char *dst = (unsigned char *)This->surface + (dst_x * This->lXPitch) + (This->lPitch * dst_y); - unsigned char *firstRow = dst; - unsigned int dst_pitch = dst_w * This->lXPitch; - 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->lPitch; - } - } - 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->lPitch; - } - } - else - { - for (x = 0; x < dst_w; x++) - row1[x] = color; - - for (i = 1; i < dst_h; i++) - { - dst += This->lPitch; - memcpy(dst, firstRow, dst_pitch); - } - } - } - } - - if (Source) - { - if ((dwFlags & DDBLT_KEYSRC) || (dwFlags & DDBLT_KEYSRCOVERRIDE)) - { - DDCOLORKEY colorKey; - - colorKey.dwColorSpaceLowValue = - (dwFlags & DDBLT_KEYSRCOVERRIDE) ? - lpDDBltFx->ddckSrcColorkey.dwColorSpaceLowValue : Source->colorKey.dwColorSpaceLowValue; - - colorKey.dwColorSpaceHighValue = - (dwFlags & DDBLT_KEYSRCOVERRIDE) ? - lpDDBltFx->ddckSrcColorkey.dwColorSpaceHighValue : Source->colorKey.dwColorSpaceHighValue; - - if (!isStretchBlt) - { - 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 = Source->width * (y1 + src_y); - - for (x1 = 0; x1 < width; x1++) - { - unsigned char c = ((unsigned char *)Source->surface)[x1 + src_x + ysrc]; - - if (c < colorKey.dwColorSpaceLowValue || c > colorKey.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 = Source->width * (y1 + src_y); - - for (x1 = 0; x1 < width; x1++) - { - unsigned short c = ((unsigned short *)Source->surface)[x1 + src_x + ysrc]; - - if (c < colorKey.dwColorSpaceLowValue || c > colorKey.dwColorSpaceHighValue) - { - ((unsigned short *)This->surface)[x1 + dst_x + ydst] = c; - } - } - } - } - } - else - { - printf(" DDBLT_KEYSRC / DDBLT_KEYSRCOVERRIDE does not support stretching\n"); - } - } - else - { - if (!isStretchBlt) - { - 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 *)Source->surface + (src_x * Source->lXPitch) + (Source->lPitch * src_y); - - unsigned char *dst = - (unsigned char *)This->surface + (dst_x * This->lXPitch) + (This->lPitch * dst_y); - - unsigned int widthInBytes = width * This->lXPitch; - - int i; - for (i = 0; i < height; i++) - { - memcpy(dst, src, widthInBytes); - - src += Source->lPitch; - dst += This->lPitch; - } - } - 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 + Source->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 *)Source->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->lXPitch); - 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 *)Source->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->lXPitch); - break; - - case END: - default: - break; - } - - current = &pattern[++pattern_idx]; - } while (current->type != END); - } - } - free(pattern); - } - } - - } - } - - if((This->caps & DDSCAPS_PRIMARYSURFACE) && ddraw->render.run) - { - InterlockedExchange(&ddraw->render.surfaceUpdated, TRUE); - - if (!(This->flags & DDSD_BACKBUFFERCOUNT) || This->lastFlipTick + FLIP_REDRAW_TIMEOUT < timeGetTime()) - { - This->lastBltTick = timeGetTime(); - - ReleaseSemaphore(ddraw->render.sem, 1, NULL); - SwitchToThread(); - - if (ddraw->ticksLimiter.ticklength > 0) - { - ddraw->ticksLimiter.useBltOrFlip = TRUE; - LimitGameTicks(); - } - } - } - - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_BltBatch(IDirectDrawSurfaceImpl *This, LPDDBLTBATCH a, DWORD b, DWORD c) -{ - printf("??? IDirectDrawSurface::BltBatch(This=%p, ...)\n", This); - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_BltFast(IDirectDrawSurfaceImpl *This, DWORD dst_x, DWORD dst_y, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DWORD flags) -{ - IDirectDrawSurfaceImpl *Source = (IDirectDrawSurfaceImpl *)lpDDSrcSurface; - -#if _DEBUG_X - printf("IDirectDrawSurface::BltFast(This=%p, x=%d, y=%d, lpDDSrcSurface=%p, lpSrcRect=%p, flags=%08X)\n", This, dst_x, dst_y, lpDDSrcSurface, lpSrcRect, flags); - - if (flags & DDBLTFAST_NOCOLORKEY) - { - printf(" DDBLTFAST_NOCOLORKEY\n"); - } - - if (flags & DDBLTFAST_SRCCOLORKEY) - { - printf(" DDBLTFAST_SRCCOLORKEY\n"); - } - - if (flags & DDBLTFAST_DESTCOLORKEY) - { - printf(" DDBLTFAST_DESTCOLORKEY\n"); - } -#endif - - RECT srcRect = { 0, 0, Source ? Source->width : 0, Source ? Source->height : 0 }; - - if (lpSrcRect && Source) - { - memcpy(&srcRect, lpSrcRect, sizeof(srcRect)); - - if (srcRect.right > Source->width) - srcRect.right = Source->width; - - if (srcRect.bottom > Source->height) - srcRect.bottom = Source->height; - } - - int src_x = srcRect.left; - int src_y = srcRect.top; - - RECT dstRect = { dst_x, dst_y, (srcRect.right - srcRect.left) + dst_x, (srcRect.bottom - srcRect.top) + dst_y }; - - if (dstRect.right > This->width) - dstRect.right = This->width; - - if (dstRect.bottom > This->height) - dstRect.bottom = This->height; - - int dst_w = dstRect.right - dstRect.left; - int dst_h = dstRect.bottom - dstRect.top; - - if (Source) - { - 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 = Source->width * (y1 + src_y); - - for (x1 = 0; x1 < dst_w; x1++) - { - unsigned char c = ((unsigned char *)Source->surface)[x1 + src_x + ysrc]; - - if (c < Source->colorKey.dwColorSpaceLowValue || c > Source->colorKey.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 = Source->width * (y1 + src_y); - - for (x1 = 0; x1 < dst_w; x1++) - { - unsigned short c = ((unsigned short *)Source->surface)[x1 + src_x + ysrc]; - - if (c < Source->colorKey.dwColorSpaceLowValue || c > Source->colorKey.dwColorSpaceHighValue) - { - ((unsigned short *)This->surface)[x1 + dst_x + ydst] = c; - } - } - } - } - } - else - { - unsigned char *src = - (unsigned char *)Source->surface + (src_x * Source->lXPitch) + (Source->lPitch * src_y); - - unsigned char *dst = - (unsigned char *)This->surface + (dst_x * This->lXPitch) + (This->lPitch * dst_y); - - unsigned int widthInBytes = dst_w * This->lXPitch; - - int i; - for (i = 0; i < dst_h; i++) - { - memcpy(dst, src, widthInBytes); - - src += Source->lPitch; - dst += This->lPitch; - } - } - } - - if ((This->caps & DDSCAPS_PRIMARYSURFACE) && ddraw->render.run) - { - InterlockedExchange(&ddraw->render.surfaceUpdated, TRUE); - - DWORD time = timeGetTime(); - - if (!(This->flags & DDSD_BACKBUFFERCOUNT) || - (This->lastFlipTick + FLIP_REDRAW_TIMEOUT < time && This->lastBltTick + FLIP_REDRAW_TIMEOUT < time)) - { - ReleaseSemaphore(ddraw->render.sem, 1, NULL); - } - } - - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_DeleteAttachedSurface(IDirectDrawSurfaceImpl *This, DWORD dwFlags, LPDIRECTDRAWSURFACE lpDDSurface) -{ - printf("IDirectDrawSurface::DeleteAttachedSurface(This=%p, dwFlags=%08X, lpDDSurface=%p)\n", This, (int)dwFlags, lpDDSurface); - IDirectDrawSurface_Release(lpDDSurface); - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_GetSurfaceDesc(IDirectDrawSurfaceImpl *This, LPDDSURFACEDESC lpDDSurfaceDesc) -{ -#if _DEBUG_X - printf("IDirectDrawSurface::GetSurfaceDesc(This=%p, lpDDSurfaceDesc=%p)\n", This, lpDDSurfaceDesc); -#endif - - 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->lPitch; - 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 __stdcall ddraw_surface_EnumAttachedSurfaces(IDirectDrawSurfaceImpl *This, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback) -{ - printf("IDirectDrawSurface::EnumAttachedSurfaces(This=%p, lpContext=%p, lpEnumSurfacesCallback=%p)\n", This, lpContext, lpEnumSurfacesCallback); - - /* this is not actually complete, but Carmageddon seems to call EnumAttachedSurfaces instead of GetSurfaceDesc to get the main surface description */ - static DDSURFACEDESC ddSurfaceDesc; - memset(&ddSurfaceDesc, 0, sizeof(DDSURFACEDESC)); - - ddraw_surface_GetSurfaceDesc(This, &ddSurfaceDesc); - This->caps |= DDSCAPS_BACKBUFFER; // Nox hack - lpEnumSurfacesCallback((LPDIRECTDRAWSURFACE)This, &ddSurfaceDesc, lpContext); - - if ((This->caps & DDSCAPS_PRIMARYSURFACE) && (This->caps & DDSCAPS_FLIP) && !(This->caps & DDSCAPS_BACKBUFFER)) - ddraw_surface_AddRef(This); - - This->caps &= ~DDSCAPS_BACKBUFFER; - - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_EnumOverlayZOrders(IDirectDrawSurfaceImpl *This, DWORD a, LPVOID b, LPDDENUMSURFACESCALLBACK c) -{ - printf("??? IDirectDrawSurface::EnumOverlayZOrders(This=%p, ...)\n", This); - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_Flip(IDirectDrawSurfaceImpl *This, LPDIRECTDRAWSURFACE surface, DWORD flags) -{ -#if _DEBUG_X - printf("IDirectDrawSurface::Flip(This=%p, surface=%p, flags=%08X)\n", This, surface, flags); -#endif - - if(This->caps & DDSCAPS_PRIMARYSURFACE && ddraw->render.run) - { - This->lastFlipTick = timeGetTime(); - - InterlockedExchange(&ddraw->render.surfaceUpdated, TRUE); - ReleaseSemaphore(ddraw->render.sem, 1, NULL); - SwitchToThread(); - - if (flags & DDFLIP_WAIT) - { - IDirectDraw_WaitForVerticalBlank(ddraw, DDWAITVB_BLOCKEND, NULL); - } - - if (ddraw->ticksLimiter.ticklength > 0) - { - ddraw->ticksLimiter.useBltOrFlip = TRUE; - LimitGameTicks(); - } - } - - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_GetAttachedSurface(IDirectDrawSurfaceImpl *This, LPDDSCAPS lpDdsCaps, LPDIRECTDRAWSURFACE FAR *surface) -{ - printf("??? IDirectDrawSurface::GetAttachedSurface(This=%p, dwCaps=%08X, surface=%p)\n", This, lpDdsCaps->dwCaps, surface); - - if ((This->caps & DDSCAPS_PRIMARYSURFACE) && (This->caps & DDSCAPS_FLIP) && (lpDdsCaps->dwCaps & DDSCAPS_BACKBUFFER)) - { - ddraw_surface_AddRef(This); - *surface = (LPDIRECTDRAWSURFACE)This; - } - - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_GetBltStatus(IDirectDrawSurfaceImpl *This, DWORD a) -{ -#if _DEBUG_X - printf("??? IDirectDrawSurface::GetBltStatus(This=%p, ...)\n", This); -#endif - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_GetCaps(IDirectDrawSurfaceImpl *This, LPDDSCAPS lpDDSCaps) -{ - printf("DirectDrawSurface::GetCaps(This=%p, lpDDSCaps=%p)\n", This, lpDDSCaps); - lpDDSCaps->dwCaps = This->caps; - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_GetClipper(IDirectDrawSurfaceImpl *This, LPDIRECTDRAWCLIPPER FAR *a) -{ -#if _DEBUG_X - printf("??? IDirectDrawSurface::GetClipper(This=%p, ...)\n", This); -#endif - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_GetColorKey(IDirectDrawSurfaceImpl *This, DWORD flags, LPDDCOLORKEY colorKey) -{ -#if _DEBUG_X - printf("??? DirectDrawSurface::GetColorKey(This=%p, flags=0x%08X, colorKey=%p)\n", This, flags, colorKey); -#endif - - if (colorKey) - { - colorKey->dwColorSpaceHighValue = This->colorKey.dwColorSpaceHighValue; - colorKey->dwColorSpaceLowValue = This->colorKey.dwColorSpaceLowValue; - } - - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_GetDC(IDirectDrawSurfaceImpl *This, HDC FAR *a) -{ -#if _DEBUG_X - printf("IDirectDrawSurface::GetDC(This=%p, ...)\n", This); -#endif - if (This->width % 4) - { - printf(" GetDC: width=%d height=%d\n", This->width, This->height); - } - - RGBQUAD *data = - This->palette && This->palette->data_rgb ? This->palette->data_rgb : - ddraw->primary && ddraw->primary->palette ? ddraw->primary->palette->data_rgb : - NULL; - - if (data) - SetDIBColorTable(This->hDC, 0, 256, data); - - *a = This->hDC; - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_GetFlipStatus(IDirectDrawSurfaceImpl *This, DWORD a) -{ -#if _DEBUG_X - printf("??? IDirectDrawSurface::GetFlipStatus(This=%p, ...)\n", This); -#endif - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_GetOverlayPosition(IDirectDrawSurfaceImpl *This, LPLONG a, LPLONG b) -{ - printf("??? IDirectDrawSurface::GetOverlayPosition(This=%p, ...)\n", This); - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_GetPalette(IDirectDrawSurfaceImpl *This, LPDIRECTDRAWPALETTE FAR *lplpDDPalette) -{ - printf("DirectDrawSurface::GetPalette(This=%p, lplpDDPalette=%p)\n", This, lplpDDPalette); - *lplpDDPalette = (LPDIRECTDRAWPALETTE)This->palette; - - if (This->palette) - { - return DD_OK; - } - else - { - return DDERR_NOPALETTEATTACHED; - } -} - -HRESULT __stdcall ddraw_surface_GetPixelFormat(IDirectDrawSurfaceImpl *This, LPDDPIXELFORMAT ddpfPixelFormat) -{ - printf("IDirectDrawSurface::GetPixelFormat(This=%p, ...)\n", This); - - 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 __stdcall ddraw_surface_Initialize(IDirectDrawSurfaceImpl *This, LPDIRECTDRAW a, LPDDSURFACEDESC b) -{ - printf("??? IDirectDrawSurface::Initialize(This=%p, ...)\n", This); - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_IsLost(IDirectDrawSurfaceImpl *This) -{ -#if _DEBUG_X - printf("IDirectDrawSurface::IsLost(This=%p)\n", This); -#endif - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_Lock(IDirectDrawSurfaceImpl *This, LPRECT lpDestRect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD dwFlags, HANDLE hEvent) -{ -#if _DEBUG_X - printf("DirectDrawSurface::Lock(This=%p, lpDestRect=%p, lpDDSurfaceDesc=%p, dwFlags=%08X, hEvent=%p)\n", This, lpDestRect, lpDDSurfaceDesc, (int)dwFlags, hEvent); - - if(dwFlags & DDLOCK_SURFACEMEMORYPTR) - { - printf(" dwFlags: DDLOCK_SURFACEMEMORYPTR\n"); - } - if(dwFlags & DDLOCK_WAIT) - { - printf(" dwFlags: DDLOCK_WAIT\n"); - } - if(dwFlags & DDLOCK_EVENT) - { - printf(" dwFlags: DDLOCK_EVENT\n"); - } - if(dwFlags & DDLOCK_READONLY) - { - printf(" dwFlags: DDLOCK_READONLY\n"); - } - if(dwFlags & DDLOCK_WRITEONLY) - { - printf(" dwFlags: DDLOCK_WRITEONLY\n"); - } -#endif - - return ddraw_surface_GetSurfaceDesc(This, lpDDSurfaceDesc); -} - -HRESULT __stdcall ddraw_surface_ReleaseDC(IDirectDrawSurfaceImpl *This, HDC a) -{ -#if _DEBUG_X - printf("DirectDrawSurface::ReleaseDC(This=%p, ...)\n", This); -#endif - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_Restore(IDirectDrawSurfaceImpl *This) -{ -#if _DEBUG_X - printf("??? DirectDrawSurface::Restore(This=%p)\n", This); -#endif - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_SetClipper(IDirectDrawSurfaceImpl *This, LPDIRECTDRAWCLIPPER a) -{ - printf("??? DirectDrawSurface::SetClipper(This=%p, ...)\n", This); - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_SetColorKey(IDirectDrawSurfaceImpl *This, DWORD flags, LPDDCOLORKEY colorKey) -{ -#if _DEBUG_X - printf("??? DirectDrawSurface::SetColorKey(This=%p, flags=0x%08X, colorKey=%p)\n", This, flags, colorKey); - - if (colorKey) - { - printf(" dwColorSpaceHighValue=%d\n", colorKey->dwColorSpaceHighValue); - printf(" dwColorSpaceLowValue=%d\n", colorKey->dwColorSpaceLowValue); - } -#endif - - if (colorKey) - { - This->colorKey.dwColorSpaceHighValue = colorKey->dwColorSpaceHighValue; - This->colorKey.dwColorSpaceLowValue = colorKey->dwColorSpaceLowValue; - } - - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_SetOverlayPosition(IDirectDrawSurfaceImpl *This, LONG a, LONG b) -{ - printf("??? DirectDrawSurface::SetOverlayPosition(This=%p, ...)\n", This); - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_SetPalette(IDirectDrawSurfaceImpl *This, LPDIRECTDRAWPALETTE lpDDPalette) -{ - printf("DirectDrawSurface::SetPalette(This=%p, lpDDPalette=%p)\n", This, lpDDPalette); - - IDirectDrawPalette_AddRef(lpDDPalette); - - if(This->palette) - { - IDirectDrawPalette_Release(This->palette); - } - - EnterCriticalSection(&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(&ddraw->cs); - - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_Unlock(IDirectDrawSurfaceImpl *This, LPVOID lpRect) -{ -#if _DEBUG_X - printf("DirectDrawSurface::Unlock(This=%p, lpRect=%p)\n", This, lpRect); -#endif - - HWND hWnd = ddraw->bnetActive ? FindWindowEx(HWND_DESKTOP, NULL, "SDlgDialog", NULL) : NULL; - if (hWnd && (This->caps & DDSCAPS_PRIMARYSURFACE)) - { - if (ddraw->primary->palette && ddraw->primary->palette->data_rgb) - SetDIBColorTable(ddraw->primary->hDC, 0, 256, ddraw->primary->palette->data_rgb); - - //GdiTransparentBlt idea taken from Aqrit's war2 ddraw - - RGBQUAD quad; - GetDIBColorTable(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, - 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 = ddraw->ticksLimiter.useBltOrFlip; - - DDBLTFX fx = { .dwFillColor = 0xFE }; - IDirectDrawSurface_Blt(This, NULL, NULL, NULL, DDBLT_COLORFILL, &fx); - - ddraw->ticksLimiter.useBltOrFlip = x; - } - } - - if ((This->caps & DDSCAPS_PRIMARYSURFACE) && ddraw->render.run) - { - InterlockedExchange(&ddraw->render.surfaceUpdated, TRUE); - - DWORD time = timeGetTime(); - - if (!(This->flags & DDSD_BACKBUFFERCOUNT) || - (This->lastFlipTick + FLIP_REDRAW_TIMEOUT < time && This->lastBltTick + FLIP_REDRAW_TIMEOUT < time)) - { - ReleaseSemaphore(ddraw->render.sem, 1, NULL); - - if (ddraw->ticksLimiter.ticklength > 0 && !ddraw->ticksLimiter.useBltOrFlip) - LimitGameTicks(); - } - } - - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_UpdateOverlay(IDirectDrawSurfaceImpl *This, LPRECT a, LPDIRECTDRAWSURFACE b, LPRECT c, DWORD d, LPDDOVERLAYFX e) -{ - printf("??? DirectDrawSurface::UpdateOverlay(This=%p, ...)\n", This); - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_UpdateOverlayDisplay(IDirectDrawSurfaceImpl *This, DWORD a) -{ - printf("??? DirectDrawSurface::UpdateOverlayDisplay(This=%p, ...)\n", This); - return DD_OK; -} - -HRESULT __stdcall ddraw_surface_UpdateOverlayZOrder(IDirectDrawSurfaceImpl *This, DWORD a, LPDIRECTDRAWSURFACE b) -{ - printf("??? DirectDrawSurface::UpdateOverlayZOrder(This=%p, ...)\n", This); - return DD_OK; -} - -struct IDirectDrawSurfaceImplVtbl siface = -{ - /* IUnknown */ - ddraw_surface_QueryInterface, - ddraw_surface_AddRef, - ddraw_surface_Release, - /* IDirectDrawSurface */ - ddraw_surface_AddAttachedSurface, - ddraw_surface_AddOverlayDirtyRect, - ddraw_surface_Blt, - ddraw_surface_BltBatch, - ddraw_surface_BltFast, - ddraw_surface_DeleteAttachedSurface, - ddraw_surface_EnumAttachedSurfaces, - ddraw_surface_EnumOverlayZOrders, - ddraw_surface_Flip, - ddraw_surface_GetAttachedSurface, - ddraw_surface_GetBltStatus, - ddraw_surface_GetCaps, - ddraw_surface_GetClipper, - ddraw_surface_GetColorKey, - ddraw_surface_GetDC, - ddraw_surface_GetFlipStatus, - ddraw_surface_GetOverlayPosition, - ddraw_surface_GetPalette, - ddraw_surface_GetPixelFormat, - ddraw_surface_GetSurfaceDesc, - ddraw_surface_Initialize, - ddraw_surface_IsLost, - ddraw_surface_Lock, - ddraw_surface_ReleaseDC, - ddraw_surface_Restore, - ddraw_surface_SetClipper, - ddraw_surface_SetColorKey, - ddraw_surface_SetOverlayPosition, - ddraw_surface_SetPalette, - ddraw_surface_Unlock, - ddraw_surface_UpdateOverlay, - ddraw_surface_UpdateOverlayDisplay, - ddraw_surface_UpdateOverlayZOrder -}; - -HRESULT __stdcall ddraw_CreateSurface(IDirectDrawImpl *This, LPDDSURFACEDESC lpDDSurfaceDesc, LPDIRECTDRAWSURFACE FAR *lpDDSurface, IUnknown FAR * unkOuter) -{ - printf("DirectDraw::CreateSurface(This=%p, lpDDSurfaceDesc=%p, lpDDSurface=%p, unkOuter=%p)\n", This, lpDDSurfaceDesc, lpDDSurface, unkOuter); - - dump_ddsd(lpDDSurfaceDesc->dwFlags); - - IDirectDrawSurfaceImpl *Surface = (IDirectDrawSurfaceImpl *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawSurfaceImpl)); - - Surface->lpVtbl = &siface; - - lpDDSurfaceDesc->dwFlags |= DDSD_CAPS; - - /* private stuff */ - Surface->bpp = This->bpp; - Surface->flags = lpDDSurfaceDesc->dwFlags; - - if(lpDDSurfaceDesc->dwFlags & DDSD_CAPS) - { - if(lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) - { - ddraw->primary = Surface; - - Surface->width = This->width; - Surface->height = This->height; - } - - dump_ddscaps(lpDDSurfaceDesc->ddsCaps.dwCaps); - Surface->caps = lpDDSurfaceDesc->ddsCaps.dwCaps; - } - - if( !(lpDDSurfaceDesc->dwFlags & DDSD_CAPS) || !(lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) ) - { - Surface->width = lpDDSurfaceDesc->dwWidth; - Surface->height = lpDDSurfaceDesc->dwHeight; - } - - if(Surface->width && Surface->height) - { - if (Surface->width == 622 && Surface->height == 51) Surface->width = 624; //AoE2 - if (Surface->width == 71 && Surface->height == 24) Surface->width = 72; //Commandos - - Surface->bmi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256); - Surface->bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - Surface->bmi->bmiHeader.biWidth = Surface->width; - Surface->bmi->bmiHeader.biHeight = -(Surface->height + 200); - Surface->bmi->bmiHeader.biPlanes = 1; - Surface->bmi->bmiHeader.biBitCount = Surface->bpp; - Surface->bmi->bmiHeader.biCompression = Surface->bpp == 16 ? BI_BITFIELDS : BI_RGB; - - WORD cClrBits = (WORD)(Surface->bmi->bmiHeader.biPlanes * Surface->bmi->bmiHeader.biBitCount); - if (cClrBits < 24) - Surface->bmi->bmiHeader.biClrUsed = (1 << cClrBits); - - Surface->bmi->bmiHeader.biSizeImage = ((Surface->width * cClrBits + 31) & ~31) / 8 * Surface->height; - - if (Surface->bpp == 8) - { - int i; - for (i = 0; i < 256; i++) - { - Surface->bmi->bmiColors[i].rgbRed = i; - Surface->bmi->bmiColors[i].rgbGreen = i; - Surface->bmi->bmiColors[i].rgbBlue = i; - Surface->bmi->bmiColors[i].rgbReserved = 0; - } - } - else if (Surface->bpp == 16) - { - ((DWORD *)Surface->bmi->bmiColors)[0] = 0xF800; - ((DWORD *)Surface->bmi->bmiColors)[1] = 0x07E0; - ((DWORD *)Surface->bmi->bmiColors)[2] = 0x001F; - } - - Surface->lXPitch = Surface->bpp / 8; - Surface->lPitch = Surface->width * Surface->lXPitch; - - Surface->hDC = CreateCompatibleDC(ddraw->render.hDC); - Surface->bitmap = CreateDIBSection(Surface->hDC, Surface->bmi, DIB_RGB_COLORS, (void **)&Surface->surface, NULL, 0); - Surface->bmi->bmiHeader.biHeight = -Surface->height; - - if (!Surface->bitmap) - Surface->surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Surface->lPitch * (Surface->height + 200) * Surface->lXPitch); - - if (lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) - pvBmpBits = Surface->surface; - - SelectObject(Surface->hDC, Surface->bitmap); - } - - if (lpDDSurfaceDesc->dwFlags & DDSD_BACKBUFFERCOUNT) - { - printf(" dwBackBufferCount=%d\n", lpDDSurfaceDesc->dwBackBufferCount); - } - - printf(" Surface = %p (%dx%d@%d)\n", Surface, (int)Surface->width, (int)Surface->height, (int)Surface->bpp); - - *lpDDSurface = (LPDIRECTDRAWSURFACE)Surface; - - Surface->Ref = 0; - ddraw_surface_AddRef(Surface); - - return DD_OK; -} - -void dump_ddbltflags(DWORD dwFlags) -{ - if (dwFlags & DDBLT_ALPHADEST) { - printf(" DDBLT_ALPHADEST\n"); - } - if (dwFlags & DDBLT_ALPHADESTCONSTOVERRIDE) { - printf(" DDBLT_ALPHADESTCONSTOVERRIDE\n"); - } - if (dwFlags & DDBLT_ALPHADESTNEG) { - printf(" DDBLT_ALPHADESTNEG\n"); - } - if (dwFlags & DDBLT_ALPHADESTSURFACEOVERRIDE) { - printf(" DDBLT_ALPHADESTSURFACEOVERRIDE\n"); - } - if (dwFlags & DDBLT_ALPHAEDGEBLEND) { - printf(" DDBLT_ALPHAEDGEBLEND\n"); - } - if (dwFlags & DDBLT_ALPHASRC) { - printf(" DDBLT_ALPHASRC\n"); - } - if (dwFlags & DDBLT_ALPHASRCCONSTOVERRIDE) { - printf(" DDBLT_ALPHASRCCONSTOVERRIDE\n"); - } - if (dwFlags & DDBLT_ALPHASRCNEG) { - printf(" DDBLT_ALPHASRCNEG\n"); - } - if (dwFlags & DDBLT_ALPHASRCSURFACEOVERRIDE) { - printf(" DDBLT_ALPHASRCSURFACEOVERRIDE\n"); - } - if (dwFlags & DDBLT_ASYNC) { - printf(" DDBLT_ASYNC\n"); - } - if (dwFlags & DDBLT_COLORFILL) { - printf(" DDBLT_COLORFILL\n"); - } - if (dwFlags & DDBLT_DDFX) { - printf(" DDBLT_DDFX\n"); - } - if (dwFlags & DDBLT_DDROPS) { - printf(" DDBLT_DDROPS\n"); - } - if (dwFlags & DDBLT_KEYDEST) { - printf(" DDBLT_KEYDEST\n"); - } - if (dwFlags & DDBLT_KEYDESTOVERRIDE) { - printf(" DDBLT_KEYDESTOVERRIDE\n"); - } - if (dwFlags & DDBLT_KEYSRC) { - printf(" DDBLT_KEYSRC\n"); - } - if (dwFlags & DDBLT_KEYSRCOVERRIDE) { - printf(" DDBLT_KEYSRCOVERRIDE\n"); - } - if (dwFlags & DDBLT_ROP) { - printf(" DDBLT_ROP\n"); - } - if (dwFlags & DDBLT_ROTATIONANGLE) { - printf(" DDBLT_ROTATIONANGLE\n"); - } - if (dwFlags & DDBLT_ZBUFFER) { - printf(" DDBLT_ZBUFFER\n"); - } - if (dwFlags & DDBLT_ZBUFFERDESTCONSTOVERRIDE) { - printf(" DDBLT_ZBUFFERDESTCONSTOVERRIDE\n"); - } - if (dwFlags & DDBLT_ZBUFFERDESTOVERRIDE) { - printf(" DDBLT_ZBUFFERDESTOVERRIDE\n"); - } - if (dwFlags & DDBLT_ZBUFFERSRCCONSTOVERRIDE) { - printf(" DDBLT_ZBUFFERSRCCONSTOVERRIDE\n"); - } - if (dwFlags & DDBLT_ZBUFFERSRCOVERRIDE) { - printf(" DDBLT_ZBUFFERSRCOVERRIDE\n"); - } - if (dwFlags & DDBLT_WAIT) { - printf(" DDBLT_WAIT\n"); - } - if (dwFlags & DDBLT_DEPTHFILL) { - printf(" DDBLT_DEPTHFILL\n"); - } -} - -void dump_ddscaps(DWORD dwCaps) -{ - if (dwCaps & DDSCAPS_ALPHA) - { - printf(" DDSCAPS_ALPHA\n"); - } - if (dwCaps & DDSCAPS_BACKBUFFER) - { - printf(" DDSCAPS_BACKBUFFER\n"); - } - if (dwCaps & DDSCAPS_FLIP) - { - printf(" DDSCAPS_FLIP\n"); - } - if (dwCaps & DDSCAPS_FRONTBUFFER) - { - printf(" DDSCAPS_FRONTBUFFER\n"); - } - if (dwCaps & DDSCAPS_PALETTE) - { - printf(" DDSCAPS_PALETTE\n"); - } - if (dwCaps & DDSCAPS_TEXTURE) - { - printf(" DDSCAPS_TEXTURE\n"); - } - if(dwCaps & DDSCAPS_PRIMARYSURFACE) - { - printf(" DDSCAPS_PRIMARYSURFACE\n"); - } - if(dwCaps & DDSCAPS_OFFSCREENPLAIN) - { - printf(" DDSCAPS_OFFSCREENPLAIN\n"); - } - if(dwCaps & DDSCAPS_VIDEOMEMORY) - { - printf(" DDSCAPS_VIDEOMEMORY\n"); - } - if(dwCaps & DDSCAPS_LOCALVIDMEM) - { - printf(" DDSCAPS_LOCALVIDMEM\n"); - } -} - -void dump_ddsd(DWORD dwFlags) -{ - if(dwFlags & DDSD_CAPS) - { - printf(" DDSD_CAPS\n"); - } - if(dwFlags & DDSD_HEIGHT) - { - printf(" DDSD_HEIGHT\n"); - } - if(dwFlags & DDSD_WIDTH) - { - printf(" DDSD_WIDTH\n"); - } - if(dwFlags & DDSD_PITCH) - { - printf(" DDSD_PITCH\n"); - } - if(dwFlags & DDSD_BACKBUFFERCOUNT) - { - printf(" DDSD_BACKBUFFERCOUNT\n"); - } - if(dwFlags & DDSD_ZBUFFERBITDEPTH) - { - printf(" DDSD_ZBUFFERBITDEPTH\n"); - } - if(dwFlags & DDSD_ALPHABITDEPTH) - { - printf(" DDSD_ALPHABITDEPTH\n"); - } - if(dwFlags & DDSD_LPSURFACE) - { - printf(" DDSD_LPSURFACE\n"); - } - if(dwFlags & DDSD_PIXELFORMAT) - { - printf(" DDSD_PIXELFORMAT\n"); - } - if(dwFlags & DDSD_CKDESTOVERLAY) - { - printf(" DDSD_CKDESTOVERLAY\n"); - } - if(dwFlags & DDSD_CKDESTBLT) - { - printf(" DDSD_CKDESTBLT\n"); - } - if(dwFlags & DDSD_CKSRCOVERLAY) - { - printf(" DDSD_CKSRCOVERLAY\n"); - } - if(dwFlags & DDSD_CKSRCBLT) - { - printf(" DDSD_CKSRCBLT\n"); - } - if(dwFlags & DDSD_MIPMAPCOUNT) - { - printf(" DDSD_MIPMAPCOUNT\n"); - } - if(dwFlags & DDSD_REFRESHRATE) - { - printf(" DDSD_REFRESHRATE\n"); - } - if(dwFlags & DDSD_LINEARSIZE) - { - printf(" DDSD_LINEARSIZE\n"); - } - if(dwFlags & DDSD_ALL) - { - printf(" DDSD_ALL\n"); - } -} diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..8427d81 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,301 @@ +#include +#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; +} diff --git a/src/winapi_hooks.c b/src/winapi_hooks.c new file mode 100644 index 0000000..f33cd0c --- /dev/null +++ b/src/winapi_hooks.c @@ -0,0 +1,425 @@ +#include +#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); +} diff --git a/src/wndproc.c b/src/wndproc.c new file mode 100644 index 0000000..7cba714 --- /dev/null +++ b/src/wndproc.c @@ -0,0 +1,620 @@ +#include +#include +#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); +}