Compare commits

...

9 commits

Author SHA1 Message Date
FunkyFr3sh
798c281453 only create opengl core context once 2024-08-03 08:23:03 +02:00
FunkyFr3sh
bb08a08af0 adjust preset 2024-07-28 04:39:22 +02:00
FunkyFr3sh
5919c0e150 fix ValidateRect hook 2024-07-27 09:52:08 +02:00
FunkyFr3sh
889cfd92fa hook ValidateRect and InvalidateRect 2024-07-27 09:42:18 +02:00
FunkyFr3sh
ec0dbeca6b add workaround for flickering (black frames) during zoom 2024-07-26 08:29:43 +02:00
FunkyFr3sh
918037dd3e fix jumping cursor while zooming 2024-07-26 08:27:42 +02:00
FunkyFr3sh
fa14a8b60a fix downscaling with GDI renderer 2024-07-26 08:26:08 +02:00
FunkyFr3sh
72549b9610 disable some hooks to avoid conflicts with voobly patches 2024-07-26 08:25:36 +02:00
FunkyFr3sh
8b4f94dcd8 reduce delay for new zoom feature 2024-07-26 08:24:49 +02:00
13 changed files with 145 additions and 23 deletions

View file

@ -168,6 +168,7 @@ typedef struct CNCDDRAW
struct
{
LONG frame_skip;
BOOL enabled;
} zoom;
} CNCDDRAW;

View file

@ -58,6 +58,9 @@ typedef BOOL(WINAPI* PEEKMESSAGEAPROC)(LPMSG, HWND, UINT, UINT, UINT);
typedef BOOL(WINAPI* GETMESSAGEAPROC)(LPMSG, HWND, UINT, UINT);
typedef BOOL(WINAPI* GETWINDOWPLACEMENTPROC)(HWND, WINDOWPLACEMENT*);
typedef BOOL(WINAPI* ENUMDISPLAYSETTINGSAPROC)(LPCSTR, DWORD, DEVMODEA*);
typedef BOOL(WINAPI* VALIDATERECTPROC)(HWND, const RECT*);
typedef BOOL(WINAPI* INVALIDATERECTPROC)(HWND, const RECT*, BOOL);
typedef SHORT(WINAPI* GETKEYSTATEPROC)(int);
typedef SHORT(WINAPI* GETASYNCKEYSTATEPROC)(int);
@ -109,6 +112,8 @@ extern PEEKMESSAGEAPROC real_PeekMessageA;
extern GETMESSAGEAPROC real_GetMessageA;
extern GETWINDOWPLACEMENTPROC real_GetWindowPlacement;
extern ENUMDISPLAYSETTINGSAPROC real_EnumDisplaySettingsA;
extern VALIDATERECTPROC real_ValidateRect;
extern INVALIDATERECTPROC real_InvalidateRect;
extern GETKEYSTATEPROC real_GetKeyState;
extern GETASYNCKEYSTATEPROC real_GetAsyncKeyState;
extern GETDEVICECAPSPROC real_GetDeviceCaps;

View file

@ -34,6 +34,8 @@ BOOL WINAPI fake_PeekMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT w
BOOL WINAPI fake_GetMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax);
BOOL WINAPI fake_GetWindowPlacement(HWND hWnd, WINDOWPLACEMENT* lpwndpl);
BOOL WINAPI fake_EnumDisplaySettingsA(LPCSTR lpszDeviceName, DWORD iModeNum, DEVMODEA* lpDevMode);
BOOL WINAPI fake_ValidateRect(HWND hWnd, const RECT* lpRect);
BOOL WINAPI fake_InvalidateRect(HWND hWnd, const RECT* lpRect, BOOL bErase);
SHORT WINAPI fake_GetKeyState(int nVirtKey);
SHORT WINAPI fake_GetAsyncKeyState(int vKey);
int WINAPI fake_GetDeviceCaps(HDC hdc, int index);

View file

@ -795,6 +795,7 @@ static void cfg_create_ini()
"; Emperor: Rise of the Middle Kingdom\n"
"[Emperor]\n"
"nonexclusive=true\n"
"adjmouse=true\n"
"\n"
"; Enemy Infestation\n"
"[EI]\n"

View file

@ -642,8 +642,8 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl
g_ddraw.height = dwHeight;
g_ddraw.bpp = dwBPP;
InterlockedExchange((LONG*)&g_ddraw.cursor.x, dwWidth / 2);
InterlockedExchange((LONG*)&g_ddraw.cursor.y, dwHeight / 2);
//InterlockedExchange((LONG*)&g_ddraw.cursor.x, dwWidth / 2);
//InterlockedExchange((LONG*)&g_ddraw.cursor.y, dwHeight / 2);
BOOL border = g_config.border;
BOOL nonexclusive = FALSE;

View file

@ -418,6 +418,9 @@ HRESULT dds_Blt(
if ((This->caps & DDSCAPS_PRIMARYSURFACE) && g_ddraw.ref && g_ddraw.render.run)
{
if (!(dwFlags & DDBLT_COLORFILL))
InterlockedExchange(&g_ddraw.zoom.frame_skip, 0);
InterlockedExchange(&g_ddraw.render.surface_updated, TRUE);
if (!(This->flags & DDSD_BACKBUFFERCOUNT) || This->last_flip_tick + FLIP_REDRAW_TIMEOUT < timeGetTime())

View file

@ -152,6 +152,7 @@ void DDEnableZoom()
TRACE("%s [%p]\n", __FUNCTION__, _ReturnAddress());
g_ddraw.zoom.enabled = TRUE;
InterlockedExchange(&g_ddraw.zoom.frame_skip, 20);
}
BOOL DDIsWindowed()

View file

@ -51,6 +51,8 @@ PEEKMESSAGEAPROC real_PeekMessageA = PeekMessageA;
GETMESSAGEAPROC real_GetMessageA = GetMessageA;
GETWINDOWPLACEMENTPROC real_GetWindowPlacement = GetWindowPlacement;
ENUMDISPLAYSETTINGSAPROC real_EnumDisplaySettingsA = EnumDisplaySettingsA;
VALIDATERECTPROC real_ValidateRect = ValidateRect;
INVALIDATERECTPROC real_InvalidateRect = InvalidateRect;
GETKEYSTATEPROC real_GetKeyState = GetKeyState;
GETASYNCKEYSTATEPROC real_GetAsyncKeyState = GetAsyncKeyState;
GETDEVICECAPSPROC real_GetDeviceCaps = GetDeviceCaps;
@ -96,10 +98,12 @@ HOOKLIST g_hook_hooklist[] =
{ "ShowWindow", (PROC)fake_ShowWindow, (PROC*)&real_ShowWindow, 0 },
{ "GetTopWindow", (PROC)fake_GetTopWindow, (PROC*)&real_GetTopWindow, 0 },
{ "GetForegroundWindow", (PROC)fake_GetForegroundWindow, (PROC*)&real_GetForegroundWindow, 0 },
{ "PeekMessageA", (PROC)fake_PeekMessageA, (PROC*)&real_PeekMessageA, 0 },
{ "GetMessageA", (PROC)fake_GetMessageA, (PROC*)&real_GetMessageA, 0 },
//{ "PeekMessageA", (PROC)fake_PeekMessageA, (PROC*)&real_PeekMessageA, 0 },
//{ "GetMessageA", (PROC)fake_GetMessageA, (PROC*)&real_GetMessageA, 0 },
{ "GetWindowPlacement", (PROC)fake_GetWindowPlacement, (PROC*)&real_GetWindowPlacement, 0 },
{ "EnumDisplaySettingsA", (PROC)fake_EnumDisplaySettingsA, (PROC*)&real_EnumDisplaySettingsA, 0 },
{ "ValidateRect", (PROC)fake_ValidateRect, (PROC*)&real_ValidateRect, 0 },
{ "InvalidateRect", (PROC)fake_InvalidateRect, (PROC*)&real_InvalidateRect, 0 },
{ "GetKeyState", (PROC)fake_GetKeyState, (PROC*)&real_GetKeyState, 0 },
{ "GetAsyncKeyState", (PROC)fake_GetAsyncKeyState, (PROC*)&real_GetAsyncKeyState, 0 },
{ "SetForegroundWindow", (PROC)fake_SetForegroundWindow, (PROC*)&real_SetForegroundWindow, 0 },
@ -161,7 +165,7 @@ HOOKLIST g_hook_hooklist[] =
{
"kernel32.dll",
{
{ "LoadLibraryA", (PROC)fake_LoadLibraryA, (PROC*)&real_LoadLibraryA, HOOK_SKIP_2 },
//{ "LoadLibraryA", (PROC)fake_LoadLibraryA, (PROC*)&real_LoadLibraryA, HOOK_SKIP_2 },
{ "LoadLibraryW", (PROC)fake_LoadLibraryW, (PROC*)&real_LoadLibraryW, HOOK_SKIP_2 },
{ "LoadLibraryExA", (PROC)fake_LoadLibraryExA, (PROC*)&real_LoadLibraryExA, HOOK_SKIP_2 },
{ "LoadLibraryExW", (PROC)fake_LoadLibraryExW, (PROC*)&real_LoadLibraryExW, HOOK_SKIP_2 },

View file

@ -38,12 +38,35 @@ void mouse_lock()
real_MapWindowPoints(g_ddraw.hwnd, HWND_DESKTOP, (LPPOINT)&rc, 2);
OffsetRect(&rc, g_ddraw.render.viewport.x, g_ddraw.render.viewport.y);
int cur_x = InterlockedExchangeAdd((LONG*)&g_ddraw.cursor.x, 0);
int cur_y = InterlockedExchangeAdd((LONG*)&g_ddraw.cursor.y, 0);
POINT pt;
real_GetCursorPos(&pt);
if (!g_config.windowed || real_ScreenToClient(g_ddraw.hwnd, &pt))
{
if (pt.x > g_ddraw.render.viewport.x + g_ddraw.render.viewport.width ||
pt.x < g_ddraw.render.viewport.x ||
pt.y > g_ddraw.render.viewport.y + g_ddraw.render.viewport.height ||
pt.y < g_ddraw.render.viewport.y)
{
pt.x = g_ddraw.width / 2;
pt.y = g_ddraw.height / 2;
}
else
{
pt.x = (DWORD)((pt.x - g_ddraw.render.viewport.x) * g_ddraw.mouse.unscale_x);
pt.y = (DWORD)((pt.y - g_ddraw.render.viewport.y) * g_ddraw.mouse.unscale_y);
}
pt.x = min(pt.x, g_ddraw.width - 1);
pt.y = min(pt.y, g_ddraw.height - 1);
InterlockedExchange((LONG*)&g_ddraw.cursor.x, pt.x);
InterlockedExchange((LONG*)&g_ddraw.cursor.y, pt.y);
}
real_SetCursorPos(
g_config.adjmouse ? (int)(rc.left + (cur_x * g_ddraw.mouse.scale_x)) : rc.left + cur_x,
g_config.adjmouse ? (int)(rc.top + (cur_y * g_ddraw.mouse.scale_y)) : rc.top + cur_y);
g_config.adjmouse ? (int)(rc.left + (pt.x * g_ddraw.mouse.scale_x)) : rc.left + pt.x,
g_config.adjmouse ? (int)(rc.top + (pt.y * g_ddraw.mouse.scale_y)) : rc.top + pt.y);
CopyRect(&rc, &g_ddraw.mouse.rc);
real_MapWindowPoints(g_ddraw.hwnd, HWND_DESKTOP, (LPPOINT)&rc, 2);

View file

@ -540,7 +540,7 @@ static BOOL d3d9_update_vertices(BOOL upscale_hack, BOOL stretch)
DWORD WINAPI d3d9_render_main(void)
{
Sleep(250);
//Sleep(250);
fpsl_init();
@ -552,6 +552,9 @@ DWORD WINAPI d3d9_render_main(void)
(g_config.minfps < 0 || WaitForSingleObject(g_ddraw.render.sem, timeout) != WAIT_FAILED) &&
g_ddraw.render.run)
{
if (InterlockedDecrement(&g_ddraw.zoom.frame_skip) > 0)
continue;
#if _DEBUG
dbg_draw_frame_info_start();
#endif

View file

@ -37,6 +37,7 @@ DWORD WINAPI gdi_render_main(void)
Sleep(500);
fpsl_init();
SetStretchBltMode(g_ddraw.render.hdc, COLORONCOLOR);
DWORD timeout = g_config.minfps > 0 ? g_ddraw.minfps_tick_len : INFINITE;

View file

@ -41,6 +41,44 @@ BOOL ogl_create()
g_ogl.hwnd = g_ddraw.hwnd;
g_ogl.hdc = g_ddraw.render.hdc;
GLenum err = GL_NO_ERROR;
BOOL made_current = FALSE;
for (int i = 0; i < 5; i++)
{
if ((made_current = xwglMakeCurrent(g_ogl.hdc, g_ogl.context)))
break;
Sleep(50);
}
if (made_current && (err = glGetError()) == GL_NO_ERROR)
{
GL_CHECK(oglu_init());
TRACE("+--OpenGL-----------------------------------------\n");
TRACE("| GL_VERSION: %s\n", glGetString(GL_VERSION));
TRACE("| GL_VENDOR: %s\n", glGetString(GL_VENDOR));
TRACE("| GL_RENDERER: %s\n", glGetString(GL_RENDERER));
TRACE("| GL_SHADING_LANGUAGE_VERSION: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
TRACE("+------------------------------------------------\n");
GL_CHECK(g_ogl.context = ogl_create_core_context(g_ogl.hdc));
}
else
{
TRACE("OpenGL error %08x, GetLastError %lu (xwglMakeCurrent())\n", err, GetLastError());
ogl_check_error("xwglMakeCurrent()");
}
for (int i = 0; i < 5; i++)
{
if (xwglMakeCurrent(NULL, NULL))
break;
Sleep(50);
}
return TRUE;
}
@ -52,7 +90,7 @@ BOOL ogl_create()
DWORD WINAPI ogl_render_main(void)
{
Sleep(250);
//Sleep(250);
g_ogl.got_error = g_ogl.use_opengl = FALSE;
GLenum err = GL_NO_ERROR;
BOOL made_current = FALSE;
@ -69,15 +107,6 @@ DWORD WINAPI ogl_render_main(void)
{
GL_CHECK(oglu_init());
TRACE("+--OpenGL-----------------------------------------\n");
TRACE("| GL_VERSION: %s\n", glGetString(GL_VERSION));
TRACE("| GL_VENDOR: %s\n", glGetString(GL_VENDOR));
TRACE("| GL_RENDERER: %s\n", glGetString(GL_RENDERER));
TRACE("| GL_SHADING_LANGUAGE_VERSION: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
TRACE("+------------------------------------------------\n");
GL_CHECK(g_ogl.context = ogl_create_core_context(g_ogl.hdc));
BOOL got_swap_ctrl;
GL_CHECK(got_swap_ctrl = oglu_ext_exists("WGL_EXT_swap_control", g_ogl.hdc));
@ -91,8 +120,8 @@ DWORD WINAPI ogl_render_main(void)
GL_CHECK(ogl_init_shader1_program());
GL_CHECK(ogl_init_shader2_program());
GL_CHECK(g_ogl.got_error = g_ogl.got_error || !ogl_texture_upload_test());
GL_CHECK(g_ogl.got_error = g_ogl.got_error || !ogl_shader_test());
//GL_CHECK(g_ogl.got_error = g_ogl.got_error || !ogl_texture_upload_test());
//GL_CHECK(g_ogl.got_error = g_ogl.got_error || !ogl_shader_test());
g_ogl.got_error = g_ogl.got_error || (err = glGetError()) != GL_NO_ERROR;
g_ogl.use_opengl = (g_ogl.main_program || g_ddraw.bpp == 16 || g_ddraw.bpp == 32) && !g_ogl.got_error;
@ -108,7 +137,13 @@ DWORD WINAPI ogl_render_main(void)
ogl_check_error("xwglMakeCurrent()");
}
xwglMakeCurrent(NULL, NULL);
for (int i = 0; i < 5; i++)
{
if (xwglMakeCurrent(NULL, NULL))
break;
Sleep(50);
}
if (!g_ogl.use_opengl)
{
@ -887,6 +922,9 @@ static void ogl_render()
(g_config.minfps < 0 || WaitForSingleObject(g_ddraw.render.sem, timeout) != WAIT_FAILED) &&
g_ddraw.render.run)
{
if (InterlockedDecrement(&g_ddraw.zoom.frame_skip) > 0)
continue;
#if _DEBUG
dbg_draw_frame_info_start();
#endif

View file

@ -822,6 +822,46 @@ BOOL WINAPI fake_EnumDisplaySettingsA(LPCSTR lpszDeviceName, DWORD iModeNum, DEV
return result;
}
BOOL WINAPI fake_ValidateRect(HWND hWnd, const RECT* lpRect)
{
if (!g_ddraw.ref || !g_ddraw.width || !g_ddraw.hwnd || hWnd != g_ddraw.hwnd || !lpRect)
return real_ValidateRect(hWnd, lpRect);
RECT dst_rc;
dst_rc.left = (LONG)(roundf(lpRect->left * g_ddraw.render.scale_w));
dst_rc.top = (LONG)(roundf(lpRect->top * g_ddraw.render.scale_h));
dst_rc.bottom = (LONG)(roundf(lpRect->bottom * g_ddraw.render.scale_h));
dst_rc.right = (LONG)(roundf(lpRect->right * g_ddraw.render.scale_w));
OffsetRect(
&dst_rc,
g_ddraw.render.viewport.x,
g_ddraw.render.viewport.y);
return real_ValidateRect(hWnd, &dst_rc);
}
BOOL WINAPI fake_InvalidateRect(HWND hWnd, const RECT* lpRect, BOOL bErase)
{
if (!g_ddraw.ref || !g_ddraw.width || !g_ddraw.hwnd || hWnd != g_ddraw.hwnd || !lpRect)
return real_InvalidateRect(hWnd, lpRect, bErase);
RECT dst_rc;
dst_rc.left = (LONG)(roundf(lpRect->left * g_ddraw.render.scale_w));
dst_rc.top = (LONG)(roundf(lpRect->top * g_ddraw.render.scale_h));
dst_rc.bottom = (LONG)(roundf(lpRect->bottom * g_ddraw.render.scale_h));
dst_rc.right = (LONG)(roundf(lpRect->right * g_ddraw.render.scale_w));
OffsetRect(
&dst_rc,
g_ddraw.render.viewport.x,
g_ddraw.render.viewport.y);
return real_InvalidateRect(hWnd, &dst_rc, bErase);
}
SHORT WINAPI fake_GetKeyState(int nVirtKey)
{
if (g_config.windowed && g_ddraw.ref && g_ddraw.hwnd && !util_in_foreground())