Compare commits

...

38 commits

Author SHA1 Message Date
FunkyFr3sh
3c3af81cd9 try fpsl_wait_for_vblank first 2024-12-16 02:34:10 +01:00
FunkyFr3sh
92c0b2a3ed don't use DwmFlush in wine 2024-12-16 02:33:25 +01:00
FunkyFr3sh
c77a6ce19e use HKLM for wine 2024-12-06 22:09:53 +01:00
FunkyFr3sh
4b9bd890a4 fix for last commit 2024-12-06 20:02:09 +01:00
FunkyFr3sh
721cf6616a make emoon's patch working on windows as well 2024-12-06 20:01:49 +01:00
FunkyFr3sh
896c2f5def keep old maintas setting working for cutscenes 2024-12-06 20:00:58 +01:00
FunkyFr3sh
a556262670
Merge pull request #362 from EmoonX/claw-movie-hq-widescreen-fix
Fix stretched HQ cutscene videos on widescreen Claw
2024-12-06 19:57:22 +01:00
EmoonX
1e61ebc099 Fix stretched HQ cutscene videos on Claw 2024-12-06 14:55:50 -03:00
FunkyFr3sh
ff9edf3e92 fix some warnings 2024-12-06 06:21:51 +01:00
FunkyFr3sh
3624008099 copy IAT hook changes from master branch 2024-12-06 06:19:03 +01:00
FunkyFr3sh
0a7f877c8f fix build on linux 2024-12-06 05:58:32 +01:00
FunkyFr3sh
411f043827 update makefile 2024-12-06 05:35:12 +01:00
FunkyFr3sh
0f575b40ea enable singlecpu by default 2024-10-01 21:02:02 +02:00
FunkyFr3sh
9f58e7925d fix for last commit 2024-10-01 20:59:42 +02:00
FunkyFr3sh
5ee245651e enable maintain aspect ratio by default 2024-10-01 20:58:00 +02:00
FunkyFr3sh
ef0fff19bd don't emulate 60hz vblank if we are running at 60hz already 2024-10-01 20:57:02 +02:00
FunkyFr3sh
f3e69355e5 fix cutscene playback in some games 2024-06-01 22:56:17 +02:00
FunkyFr3sh
0100459248 fix cutscene playbakc issues on windows 7 2024-06-01 22:30:38 +02:00
FunkyFr3sh
c8ef48c2c9 fix wayland bug (linux) 2024-02-17 07:59:57 +01:00
FunkyFr3sh
393627ee39 make sure we forward the right mouse coords to video window 2023-10-16 03:19:13 +02:00
FunkyFr3sh
ddfae6cd67 forward all input to video window 2023-10-16 03:08:29 +02:00
FunkyFr3sh
65969de0bd allow cursor unlock while video is playing 2023-10-16 02:18:22 +02:00
FunkyFr3sh
743907669e allow cursor lock while playing videos 2023-10-16 02:14:06 +02:00
FunkyFr3sh
e874a7e305 ignore mouse input while dvd video is playing 2023-10-16 02:12:29 +02:00
FunkyFr3sh
4d7fc88d37 block all keys except Esc while a dvd video is playing 2023-10-16 02:08:38 +02:00
FunkyFr3sh
b63410c444 add fix for custom levels 2023-10-08 11:59:09 +02:00
FunkyFr3sh
e3142956dc add support for xvid 2023-09-26 22:48:30 +02:00
FunkyFr3sh
7b7fefcad1 create registry key if it doesn't exist 2023-09-26 19:35:12 +02:00
FunkyFr3sh
3ad8a5bd0e add new hook flag for local hooks 2023-09-26 10:41:20 +02:00
FunkyFr3sh
68bd087cf0 re-enable hook 2023-09-26 10:02:01 +02:00
FunkyFr3sh
c8c7ead36e bump version 2023-09-26 07:18:41 +02:00
FunkyFr3sh
4d8181099c don't lock on WM_PAINT 2023-09-26 06:50:48 +02:00
FunkyFr3sh
2cf14bf2ef fix random freezing 2023-09-26 06:16:45 +02:00
FunkyFr3sh
e414568af4 fix color issues 2023-09-26 04:50:12 +02:00
FunkyFr3sh
e5fb4a061a fix upscaling on win10 2023-09-26 04:49:02 +02:00
FunkyFr3sh
a119eddd53 adjust default settings for claw 2023-09-26 02:27:00 +02:00
FunkyFr3sh
453d266d76 add temporary game patches for testing 2023-09-26 01:50:58 +02:00
FunkyFr3sh
b4b3e95832 dvd movie tests 2023-09-26 00:51:53 +02:00
20 changed files with 371 additions and 160 deletions

View file

@ -1,53 +1,25 @@
-include config.mk -include config.mk
WINDRES ?= windres TARGET ?= ddraw.dll
LDFLAGS = -Iinc -Wall -Wl,--enable-stdcall-fixup -s
CFLAGS = -std=c99 -O2 -march=i486
LIBS = -lgdi32 -lwinmm -lpsapi -ldbghelp -lole32
FILES = src/IDirect3D/IDirect3D.c \ LDFLAGS ?= -Wl,--enable-stdcall-fixup -s -static -shared
src/IDirect3D/IDirect3D2.c \ CFLAGS ?= -Iinc -O2 -Wall -std=c99 -Wno-incompatible-pointer-types
src/IDirect3D/IDirect3D3.c \ LIBS = -lgdi32 -lwinmm -lole32 -lmsimg32 -lpsapi
src/IDirect3D/IDirect3D7.c \
src/IDirectDraw/IDirectDraw.c \
src/IDirectDraw/IDirectDrawPalette.c \
src/IDirectDraw/IDirectDrawClipper.c \
src/IDirectDraw/IDirectDrawSurface.c \
src/IDirectDraw/IDirectDrawGammaControl.c \
src/IAMMediaStream/IAMMediaStream.c \
src/crc32.c \
src/blt.c \
src/dd.c \
src/ddpalette.c \
src/ddsurface.c \
src/ddclipper.c \
src/render_ogl.c \
src/render_gdi.c \
src/render_d3d9.c \
src/debug.c \
src/mouse.c \
src/winapi_hooks.c \
src/screenshot.c \
src/config.c \
src/lodepng.c \
src/directinput.c \
src/hook.c \
src/dllmain.c \
src/wndproc.c \
src/utils.c \
src/fps_limiter.c \
src/opengl_utils.c
all: CC = i686-w64-mingw32-gcc
$(info ) WINDRES ?= i686-w64-mingw32-windres
$(info **********************************************************************************************)
$(info WARNING: This build is outdated and does not support all cnc-ddraw features [Detours/SEH]) SRCS := $(wildcard src/*.c) $(wildcard src/*/*.c) ddraw.rc
$(info WARNING: Some games that require hooks may crash or glitch, please use the msvc build instead) OBJS := $(addsuffix .o, $(basename $(SRCS)))
$(info **********************************************************************************************)
$(info ) .PHONY: clean all
$(WINDRES) -J rc ddraw.rc ddraw.rc.o all: $(TARGET)
$(CC) $(CFLAGS) $(LDFLAGS) -shared -o ddraw.dll $(FILES) ddraw.def ddraw.rc.o $(LIBS)
# $(CC) $(CFLAGS) $(LDFLAGS) -nostdlib -shared -o ddraw.dll $(FILES) ddraw.def ddraw.rc.o $(LIBS) -lkernel32 -luser32 -lmsvcrt %.o: %.rc
$(WINDRES) -J rc $< $@ || windres -J rc $< $@
$(TARGET): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $^ ddraw.def $(LIBS)
clean: clean:
$(RM) ddraw.dll ddraw.rc.o $(RM) $(TARGET) $(OBJS) || del $(TARGET) $(subst /,\\,$(OBJS))

View file

@ -2,7 +2,7 @@
REM REM
REM cnc-patch environment config REM cnc-patch environment config
REM REM
set PATH=C:\win-builds-patch-32\bin set PATH=C:\w64devkit\bin
gmake clean make clean
gmake make
pause pause

View file

@ -136,6 +136,7 @@ typedef struct CNCDDRAW
void* last_freed_palette; /* Dungeon Keeper hack */ void* last_freed_palette; /* Dungeon Keeper hack */
void* last_freed_surface; /* Nox hack */ void* last_freed_surface; /* Nox hack */
BOOL child_window_exists; BOOL child_window_exists;
HWND video_window_hwnd;
BOOL got_child_windows; BOOL got_child_windows;
DWORD last_set_window_pos_tick; /* WINE hack */ DWORD last_set_window_pos_tick; /* WINE hack */
SPEEDLIMITER ticks_limiter; SPEEDLIMITER ticks_limiter;

View file

@ -48,6 +48,7 @@ typedef struct FPSLIMITER
D3DKMTCLOSEADAPTERPROC D3DKMTCloseAdapter; D3DKMTCLOSEADAPTERPROC D3DKMTCloseAdapter;
BOOL got_adapter; BOOL got_adapter;
BOOL initialized; BOOL initialized;
BOOL is_wine;
} FPSLIMITER; } FPSLIMITER;
extern FPSLIMITER g_fpsl; extern FPSLIMITER g_fpsl;

View file

@ -1,11 +1,10 @@
#ifndef HOOK_H #ifndef HOOK_H
#define HOOK_H #define HOOK_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
#define HOOK_SKIP_2 0x00000001l
#define SKIP_HOOK2 0x00000001l #define HOOK_LOCAL_ONLY 0x00000002l
typedef struct HOOKLISTDATA { char function_name[32]; PROC new_function; PROC* function; DWORD flags; } HOOKLISTDATA; typedef struct HOOKLISTDATA { char function_name[32]; PROC new_function; PROC* function; DWORD flags; } HOOKLISTDATA;
typedef struct HOOKLIST { char module_name[32]; HOOKLISTDATA data[30]; } HOOKLIST; typedef struct HOOKLIST { char module_name[32]; HOOKLISTDATA data[30]; } HOOKLIST;
@ -58,6 +57,8 @@ typedef HMODULE(WINAPI* LOADLIBRARYEXWPROC)(LPCWSTR, HANDLE, DWORD);
typedef FARPROC(WINAPI* GETPROCADDRESSPROC)(HMODULE, LPCSTR); typedef FARPROC(WINAPI* GETPROCADDRESSPROC)(HMODULE, LPCSTR);
typedef BOOL(WINAPI* GETDISKFREESPACEAPROC)(LPCSTR, LPDWORD, LPDWORD, LPDWORD, LPDWORD); typedef BOOL(WINAPI* GETDISKFREESPACEAPROC)(LPCSTR, LPDWORD, LPDWORD, LPDWORD, LPDWORD);
typedef HRESULT(WINAPI* COCREATEINSTANCEPROC)(REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID*); typedef HRESULT(WINAPI* COCREATEINSTANCEPROC)(REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID*);
typedef MCIERROR(WINAPI* MCISENDCOMMANDAPROC)(MCIDEVICEID, UINT, DWORD_PTR, DWORD_PTR);
typedef LPTOP_LEVEL_EXCEPTION_FILTER(WINAPI* SETUNHANDLEDEXCEPTIONFILTERPROC)(LPTOP_LEVEL_EXCEPTION_FILTER); typedef LPTOP_LEVEL_EXCEPTION_FILTER(WINAPI* SETUNHANDLEDEXCEPTIONFILTERPROC)(LPTOP_LEVEL_EXCEPTION_FILTER);
extern GETCURSORPOSPROC real_GetCursorPos; extern GETCURSORPOSPROC real_GetCursorPos;
@ -101,6 +102,7 @@ extern LOADLIBRARYEXWPROC real_LoadLibraryExW;
extern GETPROCADDRESSPROC real_GetProcAddress; extern GETPROCADDRESSPROC real_GetProcAddress;
extern GETDISKFREESPACEAPROC real_GetDiskFreeSpaceA; extern GETDISKFREESPACEAPROC real_GetDiskFreeSpaceA;
extern COCREATEINSTANCEPROC real_CoCreateInstance; extern COCREATEINSTANCEPROC real_CoCreateInstance;
extern MCISENDCOMMANDAPROC real_mciSendCommandA;
extern SETUNHANDLEDEXCEPTIONFILTERPROC real_SetUnhandledExceptionFilter; extern SETUNHANDLEDEXCEPTIONFILTERPROC real_SetUnhandledExceptionFilter;
extern BOOL g_hook_active; extern BOOL g_hook_active;
@ -109,7 +111,7 @@ extern HOOKLIST g_hook_hooklist[];
void hook_init(BOOL initial_hook); void hook_init(BOOL initial_hook);
void hook_exit(); void hook_exit();
void hook_patch_iat(HMODULE hmod, BOOL unhook, char* module_name, char* function_name, PROC new_function); void hook_patch_iat(HMODULE hmod, BOOL unhook, char* module_name, char* function_name, PROC new_function);
void hook_patch_iat_list(HMODULE hmod, BOOL unhook, HOOKLIST* hooks); void hook_patch_iat_list(HMODULE hmod, BOOL unhook, HOOKLIST* hooks, BOOL is_local);
void hook_create(HOOKLIST* hooks, BOOL initial_hook); void hook_create(HOOKLIST* hooks, BOOL initial_hook);
void hook_revert(HOOKLIST* hooks); void hook_revert(HOOKLIST* hooks);

View file

@ -7,7 +7,7 @@
#define VERSION_MAJOR 5 #define VERSION_MAJOR 5
#define VERSION_MINOR 7 #define VERSION_MINOR 7
#define VERSION_BUILD 0 #define VERSION_BUILD 0
#define VERSION_REVISION 6 #define VERSION_REVISION 7
#define VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION #define VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION
#define VERSION_STRING ver_str(VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION) #define VERSION_STRING ver_str(VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION)

View file

@ -1,7 +1,6 @@
#ifndef WINAPI_HOOKS_H #ifndef WINAPI_HOOKS_H
#define WINAPI_HOOKS_H #define WINAPI_HOOKS_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
@ -66,6 +65,8 @@ HWND WINAPI fake_CreateWindowExA(
HRESULT WINAPI fake_CoCreateInstance( HRESULT WINAPI fake_CoCreateInstance(
REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID* ppv); REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID* ppv);
MCIERROR WINAPI fake_mciSendCommandA(MCIDEVICEID IDDevice, UINT uMsg, DWORD_PTR fdwCommand, DWORD_PTR dwParam);
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI fake_SetUnhandledExceptionFilter( LPTOP_LEVEL_EXCEPTION_FILTER WINAPI fake_SetUnhandledExceptionFilter(
LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter); LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);

View file

@ -1,3 +1,4 @@
#include <windows.h>
#include <initguid.h> #include <initguid.h>
#include "IDirectDraw.h" #include "IDirectDraw.h"
#include "IDirect3D.h" #include "IDirect3D.h"

View file

@ -34,7 +34,7 @@ void cfg_load()
GET_INT(g_config.window_rect.bottom, "height", 0); GET_INT(g_config.window_rect.bottom, "height", 0);
GET_BOOL(g_config.fullscreen, "fullscreen", FALSE); GET_BOOL(g_config.fullscreen, "fullscreen", FALSE);
GET_BOOL(g_config.windowed, "windowed", FALSE); GET_BOOL(g_config.windowed, "windowed", FALSE);
GET_BOOL(g_config.maintas, "maintas", FALSE); GET_BOOL(g_config.maintas, "maintas", TRUE);
GET_BOOL(g_config.boxing, "boxing", FALSE); GET_BOOL(g_config.boxing, "boxing", FALSE);
GET_INT(g_config.maxfps, "maxfps", -1); GET_INT(g_config.maxfps, "maxfps", -1);
GET_BOOL(g_config.vsync, "vsync", FALSE); GET_BOOL(g_config.vsync, "vsync", FALSE);
@ -167,13 +167,13 @@ static void cfg_create_ini()
"\n" "\n"
"; Override the width/height settings shown above and always stretch to fullscreen\n" "; Override the width/height settings shown above and always stretch to fullscreen\n"
"; Note: Can be combined with 'windowed=true' to get windowed-fullscreen aka borderless mode\n" "; Note: Can be combined with 'windowed=true' to get windowed-fullscreen aka borderless mode\n"
"fullscreen=false\n" "fullscreen=true\n"
"\n" "\n"
"; Run in windowed mode rather than going fullscreen\n" "; Run in windowed mode rather than going fullscreen\n"
"windowed=false\n" "windowed=true\n"
"\n" "\n"
"; Maintain aspect ratio\n" "; Maintain aspect ratio\n"
"maintas=false\n" "maintas=true\n"
"\n" "\n"
"; Windowboxing / Integer Scaling\n" "; Windowboxing / Integer Scaling\n"
"boxing=false\n" "boxing=false\n"
@ -201,7 +201,7 @@ static void cfg_create_ini()
"posY=-32000\n" "posY=-32000\n"
"\n" "\n"
"; Renderer, possible values: auto, opengl, openglcore, gdi, direct3d9, direct3d9on12 (auto = try direct3d9/opengl, fallback = gdi)\n" "; Renderer, possible values: auto, opengl, openglcore, gdi, direct3d9, direct3d9on12 (auto = try direct3d9/opengl, fallback = gdi)\n"
"renderer=auto\n" "renderer=opengl\n"
"\n" "\n"
"; Developer mode (don't lock the cursor)\n" "; Developer mode (don't lock the cursor)\n"
"devmode=false\n" "devmode=false\n"
@ -227,7 +227,7 @@ static void cfg_create_ini()
"screenshotdir=.\\Screenshots\\\n" "screenshotdir=.\\Screenshots\\\n"
"\n" "\n"
"; Switch between windowed/borderless modes with alt+enter rather than windowed/fullscreen modes\n" "; Switch between windowed/borderless modes with alt+enter rather than windowed/fullscreen modes\n"
"toggle_borderless=false\n" "toggle_borderless=true\n"
"\n" "\n"
"\n" "\n"
"\n" "\n"
@ -236,7 +236,7 @@ static void cfg_create_ini()
"\n" "\n"
"\n" "\n"
"; Hide WM_ACTIVATEAPP and WM_NCACTIVATE messages to prevent problems on alt+tab\n" "; Hide WM_ACTIVATEAPP and WM_NCACTIVATE messages to prevent problems on alt+tab\n"
"noactivateapp=false\n" "noactivateapp=true\n"
"\n" "\n"
"; Max game ticks per second, possible values: -1 = disabled, -2 = refresh rate, 0 = emulate 60hz vblank, 1-1000 = custom game speed\n" "; Max game ticks per second, possible values: -1 = disabled, -2 = refresh rate, 0 = emulate 60hz vblank, 1-1000 = custom game speed\n"
"; Note: Can be used to slow down a too fast running game, fix flickering or too fast animations\n" "; Note: Can be used to slow down a too fast running game, fix flickering or too fast animations\n"
@ -249,7 +249,7 @@ static void cfg_create_ini()
"\n" "\n"
"; Disable fullscreen-exclusive mode for the direct3d9*/opengl* renderers\n" "; Disable fullscreen-exclusive mode for the direct3d9*/opengl* renderers\n"
"; Note: Can be used in case some GUI elements like buttons/textboxes/videos/etc.. are invisible\n" "; Note: Can be used in case some GUI elements like buttons/textboxes/videos/etc.. are invisible\n"
"nonexclusive=false\n" "nonexclusive=true\n"
"\n" "\n"
"; Force CPU0 affinity, avoids crashes/freezing, *might* have a performance impact\n" "; Force CPU0 affinity, avoids crashes/freezing, *might* have a performance impact\n"
"; Note: Disable this if the game is not running smooth or there are sound issues\n" "; Note: Disable this if the game is not running smooth or there are sound issues\n"

View file

@ -590,6 +590,11 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
g_config.fullscreen = FALSE; g_config.fullscreen = FALSE;
} }
} }
if (g_config.maxgameticks == 0 && g_ddraw->mode.dmDisplayFrequency == 60)
{
g_config.maxgameticks = -2;
}
} }
g_ddraw->render.width = g_config.window_rect.right; g_ddraw->render.width = g_config.window_rect.right;
@ -1006,13 +1011,31 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
} }
} }
if ((!d3d9_active || g_config.nonexclusive) && if (!d3d9_active || g_config.nonexclusive)
ChangeDisplaySettings(&g_ddraw->render.mode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{ {
g_ddraw->render.run = FALSE; if (ChangeDisplaySettings(&g_ddraw->render.mode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
g_config.windowed = TRUE; {
g_config.fullscreen = TRUE; g_ddraw->render.run = FALSE;
return dd_SetDisplayMode(dwWidth, dwHeight, dwBPP, dwFlags); g_config.windowed = TRUE;
g_config.fullscreen = TRUE;
return dd_SetDisplayMode(dwWidth, dwHeight, dwBPP, dwFlags);
}
/*
Fix wayland bug:
ChangeDisplaySettings fails silently - enable borderless mode in case display resolution was not changed
*/
if (g_ddraw->wine &&
(g_ddraw->render.mode.dmPelsWidth != real_GetSystemMetrics(SM_CXSCREEN) ||
g_ddraw->render.mode.dmPelsHeight != real_GetSystemMetrics(SM_CYSCREEN)))
{
ChangeDisplaySettings(NULL, 0);
g_ddraw->render.run = FALSE;
g_config.windowed = TRUE;
g_config.fullscreen = TRUE;
return dd_SetDisplayMode(dwWidth, dwHeight, dwBPP, dwFlags);
}
} }
if (g_ddraw->wine) if (g_ddraw->wine)
@ -1189,7 +1212,7 @@ HRESULT dd_WaitForVerticalBlank(DWORD dwFlags, HANDLE hEvent)
{ {
if (g_config.maxgameticks == -2) if (g_config.maxgameticks == -2)
{ {
if (fpsl_dwm_flush() || fpsl_wait_for_vblank(g_config.maxfps >= 0 && !g_config.vsync)) if (fpsl_wait_for_vblank(g_config.maxfps >= 0 && !g_config.vsync) || fpsl_dwm_flush())
return DD_OK; return DD_OK;
} }

View file

@ -1442,7 +1442,8 @@ HRESULT dd_CreateSurface(
if (InterlockedExchangeAdd(&g_dds_gdi_handles, 0) < 4000 || if (InterlockedExchangeAdd(&g_dds_gdi_handles, 0) < 4000 ||
(dst_surface->width == g_ddraw->width && dst_surface->height == g_ddraw->height)) (dst_surface->width == g_ddraw->width && dst_surface->height == g_ddraw->height) ||
(dst_surface->width == 128 && dst_surface->height == 128))
{ {
dst_surface->hdc = CreateCompatibleDC(g_ddraw->render.hdc); dst_surface->hdc = CreateCompatibleDC(g_ddraw->render.hdc);

View file

@ -9,6 +9,7 @@
#include "debug.h" #include "debug.h"
#include "config.h" #include "config.h"
#include "hook.h" #include "hook.h"
#include "patch.h"
/* export for cncnet cnc games */ /* export for cncnet cnc games */
@ -38,6 +39,70 @@ BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
#endif #endif
g_ddraw_module = hDll; g_ddraw_module = hDll;
/* Claw DVD Movie experiments */
/* change file extension .vob to .avi */
HMODULE game_exe = GetModuleHandleA(NULL);
PIMAGE_DOS_HEADER dos_hdr = (void*)game_exe;
PIMAGE_NT_HEADERS nt_hdr = (void*)((char*)game_exe + dos_hdr->e_lfanew);
for (int i = 0; i < nt_hdr->FileHeader.NumberOfSections; i++)
{
PIMAGE_SECTION_HEADER sct_hdr = IMAGE_FIRST_SECTION(nt_hdr) + i;
if (strcmp(".data", (char*)sct_hdr->Name) == 0)
{
char* s = (char*)((char*)game_exe + sct_hdr->VirtualAddress);
int s_len = sct_hdr->Misc.VirtualSize;
for (int i = 0; i < s_len; i++, s++)
{
if (*s == '.' && memcmp(s, "\x2E\x76\x6F\x62\x00", 5) == 0) /* .vob */
{
memcpy(s, "\x2E\x61\x76\x69", 4); /* .avi */
}
}
break;
}
sct_hdr++;
}
/* add registry key for x264vfw */
BOOL is_wine = real_GetProcAddress(GetModuleHandleA("ntdll.dll"), "wine_get_version") != 0;
HKEY hkey;
LONG status =
RegCreateKeyExA(
is_wine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32",
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE | KEY_QUERY_VALUE,
NULL,
&hkey,
NULL);
if (status == ERROR_SUCCESS)
{
LPCTSTR x264 = "x264vfw.dll";
RegSetValueExA(hkey,"vidc.x264", 0, REG_SZ, (const BYTE*)x264, strlen(x264) + 1);
LPCTSTR xvid = "xvidvfw.dll";
RegSetValueExA(hkey, "vidc.xvid", 0, REG_SZ, (const BYTE*)xvid, strlen(xvid) + 1);
RegCloseKey(hkey);
}
char buf[1024]; char buf[1024];
if (GetEnvironmentVariable("__COMPAT_LAYER", buf, sizeof(buf))) if (GetEnvironmentVariable("__COMPAT_LAYER", buf, sizeof(buf)))

View file

@ -75,6 +75,8 @@ void fpsl_init()
(D3DKMTCLOSEADAPTERPROC)real_GetProcAddress(g_fpsl.gdi32_dll, "D3DKMTCloseAdapter"); (D3DKMTCLOSEADAPTERPROC)real_GetProcAddress(g_fpsl.gdi32_dll, "D3DKMTCloseAdapter");
} }
g_fpsl.is_wine = real_GetProcAddress(GetModuleHandleA("ntdll.dll"), "wine_get_version") != 0;
g_fpsl.initialized = TRUE; g_fpsl.initialized = TRUE;
} }
@ -104,7 +106,12 @@ BOOL fpsl_wait_for_vblank(BOOL open_adapter)
BOOL fpsl_dwm_flush() BOOL fpsl_dwm_flush()
{ {
return g_fpsl.initialized && fpsl_dwm_is_enabled() && g_fpsl.DwmFlush && SUCCEEDED(g_fpsl.DwmFlush()); return
g_fpsl.initialized &&
fpsl_dwm_is_enabled() &&
g_fpsl.DwmFlush &&
!g_fpsl.is_wine &&
SUCCEEDED(g_fpsl.DwmFlush());
} }
BOOL fpsl_dwm_is_enabled() BOOL fpsl_dwm_is_enabled()

View file

@ -1,4 +1,3 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
#include <stdio.h> #include <stdio.h>
#include <psapi.h> #include <psapi.h>
@ -57,6 +56,7 @@ LOADLIBRARYEXWPROC real_LoadLibraryExW = LoadLibraryExW;
GETPROCADDRESSPROC real_GetProcAddress = GetProcAddress; GETPROCADDRESSPROC real_GetProcAddress = GetProcAddress;
GETDISKFREESPACEAPROC real_GetDiskFreeSpaceA = GetDiskFreeSpaceA; GETDISKFREESPACEAPROC real_GetDiskFreeSpaceA = GetDiskFreeSpaceA;
COCREATEINSTANCEPROC real_CoCreateInstance = CoCreateInstance; COCREATEINSTANCEPROC real_CoCreateInstance = CoCreateInstance;
MCISENDCOMMANDAPROC real_mciSendCommandA = mciSendCommandA;
SETUNHANDLEDEXCEPTIONFILTERPROC real_SetUnhandledExceptionFilter = SetUnhandledExceptionFilter; SETUNHANDLEDEXCEPTIONFILTERPROC real_SetUnhandledExceptionFilter = SetUnhandledExceptionFilter;
HOOKLIST g_hook_hooklist[] = HOOKLIST g_hook_hooklist[] =
@ -98,33 +98,40 @@ HOOKLIST g_hook_hooklist[] =
{ {
"ole32.dll", "ole32.dll",
{ {
{ "CoCreateInstance", (PROC)fake_CoCreateInstance, (PROC*)&real_CoCreateInstance, SKIP_HOOK2 }, { "CoCreateInstance", (PROC)fake_CoCreateInstance, (PROC*)&real_CoCreateInstance, HOOK_SKIP_2 },
{ "", NULL, NULL, 0 }
}
},
{
"winmm.dll",
{
{ "mciSendCommandA", (PROC)fake_mciSendCommandA, (PROC*)&real_mciSendCommandA, HOOK_SKIP_2 },
{ "", NULL, NULL, 0 } { "", NULL, NULL, 0 }
} }
}, },
{ {
"dinput.dll", "dinput.dll",
{ {
{ "DirectInputCreateA", (PROC)fake_DirectInputCreateA, (PROC*)&real_DirectInputCreateA, SKIP_HOOK2 }, { "DirectInputCreateA", (PROC)fake_DirectInputCreateA, (PROC*)&real_DirectInputCreateA, HOOK_SKIP_2 },
//{ "DirectInputCreateW", (PROC)fake_DirectInputCreateW, (PROC*)&real_DirectInputCreateW, SKIP_HOOK2 }, //{ "DirectInputCreateW", (PROC)fake_DirectInputCreateW, (PROC*)&real_DirectInputCreateW, HOOK_SKIP_2 },
{ "DirectInputCreateEx", (PROC)fake_DirectInputCreateEx, (PROC*)&real_DirectInputCreateEx, SKIP_HOOK2 }, { "DirectInputCreateEx", (PROC)fake_DirectInputCreateEx, (PROC*)&real_DirectInputCreateEx, HOOK_SKIP_2 },
{ "", NULL, NULL, 0 } { "", NULL, NULL, 0 }
} }
}, },
{ {
"dinput8.dll", "dinput8.dll",
{ {
{ "DirectInput8Create", (PROC)fake_DirectInput8Create, (PROC*)&real_DirectInput8Create, SKIP_HOOK2 }, { "DirectInput8Create", (PROC)fake_DirectInput8Create, (PROC*)&real_DirectInput8Create, HOOK_SKIP_2 },
{ "", NULL, NULL, 0 } { "", NULL, NULL, 0 }
} }
}, },
{ {
"gdi32.dll", "gdi32.dll",
{ {
{ "StretchBlt", (PROC)fake_StretchBlt, (PROC*)&real_StretchBlt, SKIP_HOOK2 }, { "StretchBlt", (PROC)fake_StretchBlt, (PROC*)&real_StretchBlt, HOOK_SKIP_2 },
{ "SetDIBitsToDevice", (PROC)fake_SetDIBitsToDevice, (PROC*)&real_SetDIBitsToDevice, SKIP_HOOK2 }, { "SetDIBitsToDevice", (PROC)fake_SetDIBitsToDevice, (PROC*)&real_SetDIBitsToDevice, HOOK_SKIP_2 },
{ "StretchDIBits", (PROC)fake_StretchDIBits, (PROC*)&real_StretchDIBits, SKIP_HOOK2 }, { "StretchDIBits", (PROC)fake_StretchDIBits, (PROC*)&real_StretchDIBits, HOOK_SKIP_2 },
{ "GetDeviceCaps", (PROC)fake_GetDeviceCaps, (PROC*)&real_GetDeviceCaps, 0 }, { "GetDeviceCaps", (PROC)fake_GetDeviceCaps, (PROC*)&real_GetDeviceCaps, HOOK_LOCAL_ONLY },
{ "CreateFontA", (PROC)fake_CreateFontA, (PROC*)&real_CreateFontA, 0 }, { "CreateFontA", (PROC)fake_CreateFontA, (PROC*)&real_CreateFontA, 0 },
{ "CreateFontIndirectA", (PROC)fake_CreateFontIndirectA, (PROC*)&real_CreateFontIndirectA, 0 }, { "CreateFontIndirectA", (PROC)fake_CreateFontIndirectA, (PROC*)&real_CreateFontIndirectA, 0 },
{ "", NULL, NULL, 0 } { "", NULL, NULL, 0 }
@ -133,12 +140,12 @@ HOOKLIST g_hook_hooklist[] =
{ {
"kernel32.dll", "kernel32.dll",
{ {
{ "LoadLibraryA", (PROC)fake_LoadLibraryA, (PROC*)&real_LoadLibraryA, SKIP_HOOK2 }, { "LoadLibraryA", (PROC)fake_LoadLibraryA, (PROC*)&real_LoadLibraryA, HOOK_SKIP_2 },
{ "LoadLibraryW", (PROC)fake_LoadLibraryW, (PROC*)&real_LoadLibraryW, SKIP_HOOK2 }, { "LoadLibraryW", (PROC)fake_LoadLibraryW, (PROC*)&real_LoadLibraryW, HOOK_SKIP_2 },
{ "LoadLibraryExA", (PROC)fake_LoadLibraryExA, (PROC*)&real_LoadLibraryExA, SKIP_HOOK2 }, { "LoadLibraryExA", (PROC)fake_LoadLibraryExA, (PROC*)&real_LoadLibraryExA, HOOK_SKIP_2 },
{ "LoadLibraryExW", (PROC)fake_LoadLibraryExW, (PROC*)&real_LoadLibraryExW, SKIP_HOOK2 }, { "LoadLibraryExW", (PROC)fake_LoadLibraryExW, (PROC*)&real_LoadLibraryExW, HOOK_SKIP_2 },
{ "GetProcAddress", (PROC)fake_GetProcAddress, (PROC*)&real_GetProcAddress, SKIP_HOOK2 }, { "GetProcAddress", (PROC)fake_GetProcAddress, (PROC*)&real_GetProcAddress, HOOK_SKIP_2 },
{ "GetDiskFreeSpaceA", (PROC)fake_GetDiskFreeSpaceA, (PROC*)&real_GetDiskFreeSpaceA, SKIP_HOOK2 }, { "GetDiskFreeSpaceA", (PROC)fake_GetDiskFreeSpaceA, (PROC*)&real_GetDiskFreeSpaceA, HOOK_SKIP_2 },
{ "", NULL, NULL, 0 } { "", NULL, NULL, 0 }
} }
}, },
@ -160,10 +167,10 @@ void hook_patch_iat(HMODULE hmod, BOOL unhook, char* module_name, char* function
strncpy(hooks[0].module_name, module_name, sizeof(hooks[0].module_name) - 1); strncpy(hooks[0].module_name, module_name, sizeof(hooks[0].module_name) - 1);
strncpy(hooks[0].data[0].function_name, function_name, sizeof(hooks[0].data[0].function_name) - 1); strncpy(hooks[0].data[0].function_name, function_name, sizeof(hooks[0].data[0].function_name) - 1);
hook_patch_iat_list(hmod, unhook, (HOOKLIST*)&hooks); hook_patch_iat_list(hmod, unhook, (HOOKLIST*)&hooks, FALSE);
} }
void hook_patch_obfuscated_iat_list(HMODULE hmod, BOOL unhook, HOOKLIST* hooks) void hook_patch_obfuscated_iat_list(HMODULE hmod, BOOL unhook, HOOKLIST* hooks, BOOL is_local)
{ {
if (!hmod || hmod == INVALID_HANDLE_VALUE || !hooks) if (!hmod || hmod == INVALID_HANDLE_VALUE || !hooks)
return; return;
@ -178,14 +185,22 @@ void hook_patch_obfuscated_iat_list(HMODULE hmod, BOOL unhook, HOOKLIST* hooks)
if (nt_headers->Signature != IMAGE_NT_SIGNATURE) if (nt_headers->Signature != IMAGE_NT_SIGNATURE)
return; return;
PIMAGE_IMPORT_DESCRIPTOR import_desc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)dos_header + DWORD import_desc_rva = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
(DWORD)(nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)); DWORD import_desc_size = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
if (import_desc == (PIMAGE_IMPORT_DESCRIPTOR)nt_headers) if (import_desc_rva == 0 || import_desc_size == 0)
return; return;
PIMAGE_IMPORT_DESCRIPTOR import_desc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)dos_header + import_desc_rva);
while (import_desc->FirstThunk) while (import_desc->FirstThunk)
{ {
if (!import_desc->Name)
{
import_desc++;
continue;
}
for (int i = 0; hooks[i].module_name[0]; i++) for (int i = 0; hooks[i].module_name[0]; i++)
{ {
char* imp_module_name = (char*)((DWORD)dos_header + (DWORD)(import_desc->Name)); char* imp_module_name = (char*)((DWORD)dos_header + (DWORD)(import_desc->Name));
@ -212,6 +227,9 @@ void hook_patch_obfuscated_iat_list(HMODULE hmod, BOOL unhook, HOOKLIST* hooks)
if (!hooks[i].data[x].new_function || !org_function) if (!hooks[i].data[x].new_function || !org_function)
continue; continue;
if (!is_local && (hooks[i].data[x].flags & HOOK_LOCAL_ONLY))
continue;
if (unhook) if (unhook)
{ {
if (first_thunk->u1.Function == (DWORD)hooks[i].data[x].new_function) if (first_thunk->u1.Function == (DWORD)hooks[i].data[x].new_function)
@ -268,9 +286,9 @@ void hook_patch_obfuscated_iat_list(HMODULE hmod, BOOL unhook, HOOKLIST* hooks)
} }
} }
void hook_patch_iat_list(HMODULE hmod, BOOL unhook, HOOKLIST* hooks) void hook_patch_iat_list(HMODULE hmod, BOOL unhook, HOOKLIST* hooks, BOOL is_local)
{ {
hook_patch_obfuscated_iat_list(hmod, unhook, hooks); hook_patch_obfuscated_iat_list(hmod, unhook, hooks, is_local);
if (!hmod || hmod == INVALID_HANDLE_VALUE || !hooks) if (!hmod || hmod == INVALID_HANDLE_VALUE || !hooks)
return; return;
@ -285,39 +303,53 @@ void hook_patch_iat_list(HMODULE hmod, BOOL unhook, HOOKLIST* hooks)
if (nt_headers->Signature != IMAGE_NT_SIGNATURE) if (nt_headers->Signature != IMAGE_NT_SIGNATURE)
return; return;
PIMAGE_IMPORT_DESCRIPTOR import_desc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)dos_header + DWORD import_desc_rva = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
(DWORD)(nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)); DWORD import_desc_size = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
if (import_desc == (PIMAGE_IMPORT_DESCRIPTOR)nt_headers) if (import_desc_rva == 0 || import_desc_size == 0)
return; return;
PIMAGE_IMPORT_DESCRIPTOR import_desc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)dos_header + import_desc_rva);
while (import_desc->FirstThunk) while (import_desc->FirstThunk)
{ {
if (!import_desc->OriginalFirstThunk || !import_desc->Name)
{
import_desc++;
continue;
}
for (int i = 0; hooks[i].module_name[0]; i++) for (int i = 0; hooks[i].module_name[0]; i++)
{ {
char* imp_module_name = (char*)((DWORD)dos_header + (DWORD)(import_desc->Name)); char* imp_module_name = (char*)((DWORD)dos_header + import_desc->Name);
if (_stricmp(imp_module_name, hooks[i].module_name) == 0) if (_stricmp(imp_module_name, hooks[i].module_name) == 0)
{ {
PIMAGE_THUNK_DATA first_thunk = PIMAGE_THUNK_DATA first_thunk = (void*)((DWORD)dos_header + import_desc->FirstThunk);
(PIMAGE_THUNK_DATA)((DWORD)dos_header + (DWORD)import_desc->FirstThunk); PIMAGE_THUNK_DATA o_first_thunk = (void*)((DWORD)dos_header + import_desc->OriginalFirstThunk);
PIMAGE_THUNK_DATA original_first_thunk = while (first_thunk->u1.Function)
(PIMAGE_THUNK_DATA)((DWORD)dos_header + (DWORD)import_desc->OriginalFirstThunk);
while (first_thunk->u1.Function && original_first_thunk->u1.AddressOfData)
{ {
PIMAGE_IMPORT_BY_NAME import = if (!o_first_thunk->u1.AddressOfData)
(PIMAGE_IMPORT_BY_NAME)((DWORD)dos_header + original_first_thunk->u1.AddressOfData); {
first_thunk++;
o_first_thunk++;
continue;
}
if ((original_first_thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) == 0) PIMAGE_IMPORT_BY_NAME import = (void*)((DWORD)dos_header + o_first_thunk->u1.AddressOfData);
if ((o_first_thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) == 0)
{ {
for (int x = 0; hooks[i].data[x].function_name[0]; x++) for (int x = 0; hooks[i].data[x].function_name[0]; x++)
{ {
if (!unhook && !hooks[i].data[x].new_function) if (!unhook && !hooks[i].data[x].new_function)
continue; continue;
if (_stricmp((const char*)import->Name, hooks[i].data[x].function_name) == 0) if (!is_local && (hooks[i].data[x].flags & HOOK_LOCAL_ONLY))
continue;
if (strcmp((const char*)import->Name, hooks[i].data[x].function_name) == 0)
{ {
DWORD op; DWORD op;
@ -354,7 +386,7 @@ void hook_patch_iat_list(HMODULE hmod, BOOL unhook, HOOKLIST* hooks)
} }
first_thunk++; first_thunk++;
original_first_thunk++; o_first_thunk++;
} }
} }
} }
@ -415,7 +447,7 @@ void hook_create(HOOKLIST* hooks, BOOL initial_hook)
{ {
for (int x = 0; hooks[i].data[x].function_name[0]; x++) for (int x = 0; hooks[i].data[x].function_name[0]; x++)
{ {
if ((hooks[i].data[x].flags & SKIP_HOOK2)) if ((hooks[i].data[x].flags & HOOK_SKIP_2))
continue; continue;
DetourTransactionBegin(); DetourTransactionBegin();
@ -470,12 +502,18 @@ void hook_create(HOOKLIST* hooks, BOOL initial_hook)
_strcmpi(mod_filename, "Shw32") == 0) _strcmpi(mod_filename, "Shw32") == 0)
continue; continue;
if (_strnicmp(game_dir, mod_dir, strlen(game_dir)) == 0 || BOOL is_local = _strnicmp(game_dir, mod_dir, strlen(game_dir)) == 0;
BOOL is_wine = real_GetProcAddress(GetModuleHandleA("ntdll.dll"), "wine_get_version") != 0;
BOOL wine_hook = is_wine && _strcmpi(mod_filename, "mciavi32") == 0;
if (is_local ||
wine_hook ||
_strcmpi(mod_filename, "MSVFW32") == 0 || _strcmpi(mod_filename, "MSVFW32") == 0 ||
_strcmpi(mod_filename, "quartz") == 0 || _strcmpi(mod_filename, "quartz") == 0 ||
_strcmpi(mod_filename, "winmm") == 0) _strcmpi(mod_filename, "winmm") == 0)
{ {
hook_patch_iat_list(hmod, FALSE, hooks); hook_patch_iat_list(hmod, FALSE, hooks, is_local);
} }
} }
} }
@ -487,7 +525,7 @@ void hook_create(HOOKLIST* hooks, BOOL initial_hook)
if (g_config.hook == 1) if (g_config.hook == 1)
{ {
hook_patch_iat_list(GetModuleHandle(NULL), FALSE, hooks); hook_patch_iat_list(GetModuleHandle(NULL), FALSE, hooks, TRUE);
} }
} }
@ -500,7 +538,7 @@ void hook_revert(HOOKLIST* hooks)
{ {
for (int x = 0; hooks[i].data[x].function_name[0]; x++) for (int x = 0; hooks[i].data[x].function_name[0]; x++)
{ {
if ((hooks[i].data[x].flags & SKIP_HOOK2)) if ((hooks[i].data[x].flags & HOOK_SKIP_2))
continue; continue;
DetourTransactionBegin(); DetourTransactionBegin();
@ -544,12 +582,18 @@ void hook_revert(HOOKLIST* hooks)
{ {
_splitpath(mod_path, NULL, mod_dir, mod_filename, NULL); _splitpath(mod_path, NULL, mod_dir, mod_filename, NULL);
if (_strnicmp(game_dir, mod_dir, strlen(game_dir)) == 0 || BOOL is_local = _strnicmp(game_dir, mod_dir, strlen(game_dir)) == 0;
BOOL is_wine = real_GetProcAddress(GetModuleHandleA("ntdll.dll"), "wine_get_version") != 0;
BOOL wine_hook = is_wine && _strcmpi(mod_filename, "mciavi32") == 0;
if (is_local ||
wine_hook ||
_strcmpi(mod_filename, "MSVFW32") == 0 || _strcmpi(mod_filename, "MSVFW32") == 0 ||
_strcmpi(mod_filename, "quartz") == 0 || _strcmpi(mod_filename, "quartz") == 0 ||
_strcmpi(mod_filename, "winmm") == 0) _strcmpi(mod_filename, "winmm") == 0)
{ {
hook_patch_iat_list(hmod, TRUE, hooks); hook_patch_iat_list(hmod, TRUE, hooks, is_local);
} }
} }
} }
@ -561,7 +605,7 @@ void hook_revert(HOOKLIST* hooks)
if (g_config.hook == 1) if (g_config.hook == 1)
{ {
hook_patch_iat_list(GetModuleHandle(NULL), TRUE, hooks); hook_patch_iat_list(GetModuleHandle(NULL), TRUE, hooks, TRUE);
} }
} }

View file

@ -10,7 +10,7 @@
#include "wndproc.h" #include "wndproc.h"
#include "blt.h" #include "blt.h"
#include "debug.h" #include "debug.h"
#include "D3d9types.h" #include "d3d9types.h"
#include "hook.h" #include "hook.h"
#include "config.h" #include "config.h"
@ -541,6 +541,7 @@ DWORD WINAPI d3d9_render_main(void)
if (g_config.fixchilds) if (g_config.fixchilds)
{ {
g_ddraw->child_window_exists = FALSE; g_ddraw->child_window_exists = FALSE;
InterlockedExchangePointer(&g_ddraw->video_window_hwnd, NULL);
EnumChildWindows(g_ddraw->hwnd, util_enum_child_proc, (LPARAM)g_ddraw->primary); 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->render.width != g_ddraw->width || g_ddraw->render.height != g_ddraw->height)

View file

@ -84,6 +84,7 @@ DWORD WINAPI gdi_render_main(void)
if (g_config.fixchilds) if (g_config.fixchilds)
{ {
g_ddraw->child_window_exists = FALSE; g_ddraw->child_window_exists = FALSE;
InterlockedExchangePointer(&g_ddraw->video_window_hwnd, NULL);
EnumChildWindows(g_ddraw->hwnd, util_enum_child_proc, (LPARAM)g_ddraw->primary); EnumChildWindows(g_ddraw->hwnd, util_enum_child_proc, (LPARAM)g_ddraw->primary);
} }

View file

@ -770,6 +770,7 @@ static void ogl_render()
if (g_config.fixchilds) if (g_config.fixchilds)
{ {
g_ddraw->child_window_exists = FALSE; g_ddraw->child_window_exists = FALSE;
InterlockedExchangePointer(&g_ddraw->video_window_hwnd, NULL);
EnumChildWindows(g_ddraw->hwnd, util_enum_child_proc, (LPARAM)g_ddraw->primary); 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->render.width != g_ddraw->width || g_ddraw->render.height != g_ddraw->height)

View file

@ -472,24 +472,18 @@ BOOL CALLBACK util_enum_child_proc(HWND hwnd, LPARAM lparam)
if (g_config.fixchilds == FIX_CHILDS_DETECT_HIDE || if (g_config.fixchilds == FIX_CHILDS_DETECT_HIDE ||
strcmp(class_name, "VideoRenderer") == 0 || strcmp(class_name, "VideoRenderer") == 0 ||
strcmp(class_name, "MCIAVI") == 0 ||
strcmp(class_name, "AVIWnd32") == 0 || strcmp(class_name, "AVIWnd32") == 0 ||
strcmp(class_name, "Afx:400000:3") == 0 ||
strcmp(class_name, "MCIWndClass") == 0) strcmp(class_name, "MCIWndClass") == 0)
{ {
InterlockedExchangePointer(&g_ddraw->video_window_hwnd, hwnd);
LONG style = real_GetWindowLongA(hwnd, GWL_EXSTYLE); LONG style = real_GetWindowLongA(hwnd, GWL_EXSTYLE);
if (!(style & WS_EX_TRANSPARENT)) if (!(style & WS_EX_TRANSPARENT))
{ {
real_SetWindowLongA(hwnd, GWL_EXSTYLE, style | WS_EX_TRANSPARENT); real_SetWindowLongA(hwnd, GWL_EXSTYLE, style | WS_EX_TRANSPARENT);
real_SetWindowPos(
hwnd,
0,
0,
0,
0,
0,
SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER
);
} }
} }
else else

View file

@ -738,9 +738,11 @@ BOOL WINAPI fake_StretchBlt(
(g_config.fixchilds && IsChild(g_ddraw->hwnd, hwnd) && (g_config.fixchilds && IsChild(g_ddraw->hwnd, hwnd) &&
(g_config.fixchilds == FIX_CHILDS_DETECT_HIDE || (g_config.fixchilds == FIX_CHILDS_DETECT_HIDE ||
strcmp(class_name, "AVIWnd32") == 0 || strcmp(class_name, "AVIWnd32") == 0 ||
strcmp(class_name, "Afx:400000:3") == 0 ||
strcmp(class_name, "VideoRenderer") == 0 ||
strcmp(class_name, "MCIWndClass") == 0)))) strcmp(class_name, "MCIWndClass") == 0))))
{ {
if (g_ddraw->primary && (g_ddraw->primary->bpp == 16 || g_ddraw->primary->bpp == 32 || g_ddraw->primary->palette)) if (0)//g_ddraw->primary && (g_ddraw->primary->bpp == 16 || g_ddraw->primary->bpp == 32 || g_ddraw->primary->palette))
{ {
HDC primary_dc; HDC primary_dc;
dds_GetDC(g_ddraw->primary, &primary_dc); dds_GetDC(g_ddraw->primary, &primary_dc);
@ -757,12 +759,30 @@ BOOL WINAPI fake_StretchBlt(
} }
else if (g_ddraw->width > 0 && g_ddraw->render.hdc) else if (g_ddraw->width > 0 && g_ddraw->render.hdc)
{ {
// new logic by emoon
// g_ddraw->width check detects new widescreen patch
if (g_ddraw->width > 640 && g_config.maintas)
{
int base_width = g_ddraw->height * 4.0 / 3.0;
double scaling_factor = (double)g_ddraw->render.height / g_ddraw->height;
wDest = base_width * scaling_factor;
hDest = g_ddraw->render.height;
xDest += (g_ddraw->render.width - wDest) / 2;
}
else // original 4:3 logic
{
xDest += g_ddraw->render.viewport.x;
yDest += g_ddraw->render.viewport.y;
wDest = (int)(wDest * g_ddraw->render.scale_w);
hDest = (int)(hDest * g_ddraw->render.scale_h);
}
return real_StretchBlt( return real_StretchBlt(
g_ddraw->render.hdc, g_ddraw->render.hdc,
xDest + g_ddraw->render.viewport.x, xDest,
yDest + g_ddraw->render.viewport.y, yDest,
(int)(wDest * g_ddraw->render.scale_w), wDest,
(int)(hDest * g_ddraw->render.scale_h), hDest,
hdcSrc, hdcSrc,
xSrc, xSrc,
ySrc, ySrc,
@ -838,9 +858,26 @@ int WINAPI fake_StretchDIBits(
UINT iUsage, UINT iUsage,
DWORD rop) DWORD rop)
{ {
if (g_ddraw && g_ddraw->hwnd && WindowFromDC(hdc) == g_ddraw->hwnd) HWND hwnd = WindowFromDC(hdc);
char class_name[MAX_PATH] = { 0 };
if (g_ddraw && g_ddraw->hwnd && hwnd && hwnd != g_ddraw->hwnd)
{ {
if (g_ddraw->primary && (g_ddraw->primary->bpp == 16 || g_ddraw->primary->bpp == 32 || g_ddraw->primary->palette)) GetClassNameA(hwnd, class_name, sizeof(class_name) - 1);
}
if (g_ddraw && g_ddraw->hwnd &&
(hwnd == g_ddraw->hwnd ||
(g_config.fixchilds && IsChild(g_ddraw->hwnd, hwnd) &&
(g_config.fixchilds == FIX_CHILDS_DETECT_HIDE ||
strcmp(class_name, "MCIAVI") == 0 ||
strcmp(class_name, "AVIWnd32") == 0 ||
strcmp(class_name, "Afx:400000:3") == 0 ||
strcmp(class_name, "VideoRenderer") == 0 ||
strcmp(class_name, "MCIWndClass") == 0))))
{
if (0) // g_ddraw->primary && (g_ddraw->primary->bpp == 16 || g_ddraw->primary->bpp == 32 || g_ddraw->primary->palette))
{ {
HDC primary_dc; HDC primary_dc;
dds_GetDC(g_ddraw->primary, &primary_dc); dds_GetDC(g_ddraw->primary, &primary_dc);
@ -868,15 +905,33 @@ int WINAPI fake_StretchDIBits(
return result; return result;
} }
} }
else if (g_ddraw->width > 0) else if (g_ddraw->width > 0 && g_ddraw->render.hdc)
{ {
// new logic by emoon
// g_ddraw->width check detects new widescreen patch
if (g_ddraw->width > 640 && g_config.maintas)
{
int base_width = g_ddraw->height * 4.0 / 3.0;
double scaling_factor = (double)g_ddraw->render.height / g_ddraw->height;
DestWidth = base_width * scaling_factor;
DestHeight = g_ddraw->render.height;
xDest += (g_ddraw->render.width - DestWidth) / 2;
}
else // original 4:3 logic
{
xDest += g_ddraw->render.viewport.x;
yDest += g_ddraw->render.viewport.y;
DestWidth = (int)(DestWidth * g_ddraw->render.scale_w);
DestHeight = (int)(DestHeight * g_ddraw->render.scale_h);
}
return return
real_StretchDIBits( real_StretchDIBits(
hdc, g_ddraw->render.hdc,
xDest + g_ddraw->render.viewport.x, xDest,
yDest + g_ddraw->render.viewport.y, yDest,
(int)(DestWidth * g_ddraw->render.scale_w), DestWidth,
(int)(DestHeight * g_ddraw->render.scale_h), DestHeight,
xSrc, xSrc,
ySrc, ySrc,
SrcWidth, SrcWidth,
@ -1190,22 +1245,15 @@ HWND WINAPI fake_CreateWindowExA(
DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y, DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y,
int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
{ {
/* Center Claw DVD movies */ /* Claw DVD movies */
if (HIWORD(lpClassName) && if (HIWORD(lpClassName) && _strcmpi(lpClassName, "Afx:400000:3") == 0 &&
_strcmpi(lpClassName, "Afx:400000:3") == 0 && g_ddraw && g_ddraw->hwnd &&
g_ddraw && g_ddraw->hwnd && g_ddraw->width &&
(dwStyle & (WS_POPUP | WS_CHILD)) == (WS_POPUP | WS_CHILD)) (dwStyle & (WS_POPUP | WS_CHILD)) == (WS_POPUP | WS_CHILD))
{ {
POINT pt = { 0, 0 }; dwStyle &= ~WS_POPUP;
real_ClientToScreen(g_ddraw->hwnd, &pt); LoadLibraryA("quartz.dll");
LoadLibraryA("MSVFW32.dll");
int added_height = g_ddraw->render.height - g_ddraw->height; hook_init(FALSE);
int added_width = g_ddraw->render.width - g_ddraw->width;
int align_y = added_height > 0 ? added_height / 2 : 0;
int align_x = added_width > 0 ? added_width / 2 : 0;
X = pt.x + align_x;
Y = pt.y + align_y;
} }
/* Fix for SMACKW32.DLL creating another window that steals the focus */ /* Fix for SMACKW32.DLL creating another window that steals the focus */
@ -1312,7 +1360,36 @@ HRESULT WINAPI fake_CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD
} }
} }
return real_CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv); /* These dlls must be hooked for cutscene uscaling and windowed mode */
HMODULE quartz_dll = GetModuleHandleA("quartz");
HMODULE msvfw32_dll = GetModuleHandleA("msvfw32");
HRESULT result = real_CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv);
if ((!quartz_dll && GetModuleHandleA("quartz")) ||
(!msvfw32_dll && GetModuleHandleA("msvfw32")))
{
hook_init(FALSE);
}
return result;
}
MCIERROR WINAPI fake_mciSendCommandA(MCIDEVICEID IDDevice, UINT uMsg, DWORD_PTR fdwCommand, DWORD_PTR dwParam)
{
/* These dlls must be hooked for cutscene uscaling and windowed mode */
HMODULE quartz_dll = GetModuleHandleA("quartz");
HMODULE msvfw32_dll = GetModuleHandleA("msvfw32");
MCIERROR result = real_mciSendCommandA(IDDevice, uMsg, fdwCommand, dwParam);
if ((!quartz_dll && GetModuleHandleA("quartz")) ||
(!msvfw32_dll && GetModuleHandleA("msvfw32")))
{
hook_init(FALSE);
}
return result;
} }
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI fake_SetUnhandledExceptionFilter( LPTOP_LEVEL_EXCEPTION_FILTER WINAPI fake_SetUnhandledExceptionFilter(

View file

@ -729,6 +729,13 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
} }
} }
HWND video_hwnd = (HWND)InterlockedExchangeAdd((LONG*)&g_ddraw->video_window_hwnd, 0);
if (video_hwnd)
{
PostMessageA(video_hwnd, uMsg, wParam, lParam);
return 0;
}
break; break;
} }
case WM_KEYUP: case WM_KEYUP:
@ -736,6 +743,13 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
if (g_config.hotkeys.screenshot && wParam == g_config.hotkeys.screenshot) if (g_config.hotkeys.screenshot && wParam == g_config.hotkeys.screenshot)
ss_take_screenshot(g_ddraw->primary); ss_take_screenshot(g_ddraw->primary);
HWND video_hwnd = (HWND)InterlockedExchangeAdd((LONG*)&g_ddraw->video_window_hwnd, 0);
if (video_hwnd)
{
PostMessageA(video_hwnd, uMsg, wParam, lParam);
return 0;
}
break; break;
} }
/* button up messages reactivate cursor lock */ /* button up messages reactivate cursor lock */
@ -817,6 +831,13 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
lParam = MAKELPARAM(x, y); lParam = MAKELPARAM(x, y);
HWND video_hwnd = (HWND)InterlockedExchangeAdd((LONG*)&g_ddraw->video_window_hwnd, 0);
if (video_hwnd)
{
PostMessageA(video_hwnd, uMsg, wParam, lParam);
return 0;
}
break; break;
} }
case WM_PARENTNOTIFY: case WM_PARENTNOTIFY:
@ -854,9 +875,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
} }
EnterCriticalSection(&g_ddraw->cs);
ReleaseSemaphore(g_ddraw->render.sem, 1, NULL); ReleaseSemaphore(g_ddraw->render.sem, 1, NULL);
LeaveCriticalSection(&g_ddraw->cs);
break; break;
} }
case WM_ERASEBKGND: case WM_ERASEBKGND: