From 0f5874651573f54dbaf160f526ff720bf952a708 Mon Sep 17 00:00:00 2001 From: FunkyFr3sh Date: Sun, 17 Mar 2019 00:16:09 +0100 Subject: [PATCH] experimental tweaks for diablo and warcraft 2 --- ddraw.def | 6 +- ddraw.rc | 2 +- inc/main.h | 2 + src/main.c | 136 +++++++++++++++++++++++++++++++--------------- src/mouse.c | 4 +- src/render.c | 3 + src/render_d3d9.c | 3 + src/render_soft.c | 7 ++- src/settings.c | 21 +++++-- src/surface.c | 49 +++++++++++++++++ 10 files changed, 176 insertions(+), 57 deletions(-) diff --git a/ddraw.def b/ddraw.def index 9e214cd..ff1a079 100644 --- a/ddraw.def +++ b/ddraw.def @@ -1,6 +1,6 @@ LIBRARY ddraw.dll EXPORTS - DirectDrawCreate @1 - DirectDrawEnumerateA @2 - GameHandlesClose DATA + DirectDrawCreate @1 + DirectDrawEnumerateA @2 + GameHandlesClose DATA diff --git a/ddraw.rc b/ddraw.rc index e9ed161..15528d4 100644 --- a/ddraw.rc +++ b/ddraw.rc @@ -21,7 +21,7 @@ PRODUCTVERSION VERSION VALUE "FileDescription", "DirectDraw replacement" VALUE "FileVersion", VERSION_STRING VALUE "InternalName", "ddraw" - VALUE "LegalCopyright", "Copyright (c) 2010-2018" + VALUE "LegalCopyright", "Copyright (c) 2010-2019" VALUE "LegalTrademarks", "" VALUE "OriginalFileName", "ddraw.dll" VALUE "ProductName", "cnc-ddraw" diff --git a/inc/main.h b/inc/main.h index 4599e17..c6248a9 100644 --- a/inc/main.h +++ b/inc/main.h @@ -125,6 +125,8 @@ typedef struct IDirectDrawImpl BOOL altenter; BOOL hidecursor; BOOL accurateTimers; + int bnetHack; + BOOL bnetActive; SpeedLimiter ticksLimiter; SpeedLimiter flipLimiter; SpeedLimiter fpsLimiter; diff --git a/src/main.c b/src/main.c index a46f6e2..a385297 100644 --- a/src/main.c +++ b/src/main.c @@ -1161,51 +1161,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) break; - 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(); - } - } - - InterlockedExchange(&ddraw->minimized, FALSE); - } - - if (!ddraw->handlemouse) - RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); - } - else if (wParam == WA_INACTIVE) - { - if (!ddraw->windowed && !ddraw->locked && ddraw->noactivateapp) - 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(&ddraw->mode, 0); - } - - InterlockedExchange(&ddraw->minimized, TRUE); - } - } - return 0; - //workaround for a bug where sometimes a background window steals the focus case WM_WINDOWPOSCHANGING: { @@ -1228,7 +1183,77 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) mouse_unlock(); return 0; + + case WM_ENABLE: + { + if (ddraw->bnetHack) + { + if (wParam) + mouse_lock(); + else + mouse_unlock(); + + HWND hWnd = FindWindowEx(HWND_DESKTOP, NULL, "SDlgDialog", NULL); + if (hWnd) + { + RECT rc; + if (GetWindowRect(hWnd, &rc) && (rc.bottom - rc.top != 479)) + while (ShowCursor(FALSE) > 0); + } + + ddraw->bnetActive = !wParam; + } + break; + } + + case WM_ACTIVATE: + { + return 0; + } + case WM_ACTIVATEAPP: + + if (wParam) + { + if (!ddraw->windowed) + { + if (!Direct3D9Active) + { + ChangeDisplaySettings(&ddraw->render.mode, CDS_FULLSCREEN); + + mouse_lock(); + } + + InterlockedExchange(&ddraw->minimized, FALSE); + } + + if (!ddraw->handlemouse) + RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); + } + else + { + if (!ddraw->windowed && !ddraw->locked && ddraw->noactivateapp) + goto aapp_end; + + mouse_unlock(); + + if (ddraw->wine && LastSetWindowPosTick + 500 > timeGetTime()) + goto aapp_end; + + /* minimize our window on defocus when in fullscreen */ + if (!ddraw->windowed) + { + if (!Direct3D9Active) + { + ShowWindow(ddraw->hWnd, SW_MINIMIZE); + ChangeDisplaySettings(&ddraw->mode, 0); + } + + InterlockedExchange(&ddraw->minimized, TRUE); + } + } + + aapp_end: /* C&C and RA stop drawing when they receive this with FALSE wParam, disable in windowed mode */ if (ddraw->windowed || ddraw->noactivateapp) { @@ -1619,6 +1644,16 @@ HRESULT WINAPI DirectDrawEnumerateA(LPDDENUMCALLBACK lpCallback, LPVOID lpContex return DD_OK; } +//Force redraw when the "Player Profile" screen exits - Idea taken from Aqrit's war2 ddraw +static WNDPROC ButtonWndProc_original; +LRESULT __stdcall ButtonWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (msg == WM_DESTROY) + RedrawWindow(NULL, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN); + + return ButtonWndProc_original(hwnd, msg, wParam, lParam); +} + int stdout_open = 0; HRESULT WINAPI DirectDrawCreate(GUID FAR* lpGUID, LPDIRECTDRAW FAR* lplpDD, IUnknown FAR* pUnkOuter) { @@ -1668,5 +1703,16 @@ HRESULT WINAPI DirectDrawCreate(GUID FAR* lpGUID, LPDIRECTDRAW FAR* lplpDD, IUnk Settings_Load(); + if (ddraw->bnetHack) + { + WNDCLASS wc; + HINSTANCE hInst = GetModuleHandle(NULL); + GetClassInfo(NULL, "Button", &wc); + wc.hInstance = hInst; + ButtonWndProc_original = wc.lpfnWndProc; + wc.lpfnWndProc = ButtonWndProc; + RegisterClass(&wc); + } + return DD_OK; } diff --git a/src/mouse.c b/src/mouse.c index 01be2b8..f4573fd 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -250,7 +250,7 @@ void mouse_lock() if (ddraw->handlemouse) { - SetCapture(ddraw->hWnd); + //SetCapture(ddraw->hWnd); ClipCursor(&rc); while (ShowCursor(FALSE) > 0); } @@ -315,7 +315,7 @@ void mouse_unlock() } ClipCursor(NULL); - ReleaseCapture(); + //ReleaseCapture(); SetCursorPos( rc.left + ddraw->render.viewport.x + (ddraw->cursor.x * ddraw->render.scaleW), diff --git a/src/render.c b/src/render.c index cfb40eb..805d7da 100644 --- a/src/render.c +++ b/src/render.c @@ -787,6 +787,9 @@ static void Render() glEnd(); } + if (ddraw->bnetActive) + glClear(GL_COLOR_BUFFER_BIT); + SwapBuffers(ddraw->render.hDC); #if _DEBUG diff --git a/src/render_d3d9.c b/src/render_d3d9.c index 10968f7..361241c 100644 --- a/src/render_d3d9.c +++ b/src/render_d3d9.c @@ -410,6 +410,9 @@ DWORD WINAPI render_d3d9_main(void) IDirect3DDevice9_DrawPrimitive(D3dDev, D3DPT_TRIANGLESTRIP, 0, 2); IDirect3DDevice9_EndScene(D3dDev); + if (ddraw->bnetActive) + IDirect3DDevice9_Clear(D3dDev, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); + if (FAILED(IDirect3DDevice9_Present(D3dDev, NULL, NULL, NULL, NULL))) { DWORD_PTR dwResult; diff --git a/src/render_soft.c b/src/render_soft.c index 4ab7203..cc08735 100644 --- a/src/render_soft.c +++ b/src/render_soft.c @@ -103,7 +103,12 @@ DWORD WINAPI render_soft_main(void) EnumChildWindows(ddraw->hWnd, EnumChildProc, (LPARAM)ddraw->primary); } - if (scaleCutscene) + 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, diff --git a/src/settings.c b/src/settings.c index f01b270..0aefa3f 100644 --- a/src/settings.c +++ b/src/settings.c @@ -49,6 +49,8 @@ void Settings_Load() ddraw->render.maxfps = GetInt("maxfps", 125); + ddraw->bnetHack = GetBool("bnetHack", TRUE); + 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 @@ -102,6 +104,9 @@ void Settings_Load() GetString("renderer", "auto", tmp, sizeof(tmp)); printf("Using %s renderer\n", tmp); + if (ddraw->bnetHack && tolower(tmp[0]) != 'g') + ddraw->windowed = TRUE; + if (tolower(tmp[0]) == 's' || tolower(tmp[0]) == 'g') //gdi { ddraw->renderer = render_soft_main; @@ -274,6 +279,10 @@ static void CreateSettingsIni() "; Force CPU0 affinity, avoids crashes/freezing, *might* have a performance impact\n" "singlecpu=true\n" "\n" + "; Workaround for battle.net on Diablo and Warcraft 2 BNE\n" + "; Note: This hack as a negative side-effect, you can only play fullscreen with 'renderer=gdi' or via 'fullscreen=true'\n" + "bnetHack=false\n" + "\n" "\n" "\n" "; ### Game specific settings ###\n" @@ -389,11 +398,13 @@ static void CreateSettingsIni() "handlemouse=false\n" "maxfps=60\n" "\n" - "; Command & Conquer: Red Alert 2: Yuri's Revenge - XWIS\n" - "[Yuri's Revenge]\n" - "noactivateapp=true\n" - "handlemouse=false\n" - "maxfps=60\n" + "; Diablo\n" + "[Diablo]\n" + "bnetHack=true\n" + "\n" + "; Warcraft 2 Battle.net Edition\n" + "[Warcraft II BNE]\n" + "bnetHack=true\n" "\n" , fh); diff --git a/src/surface.c b/src/surface.c index 27d8088..7e434ba 100644 --- a/src/surface.c +++ b/src/surface.c @@ -992,6 +992,55 @@ HRESULT __stdcall ddraw_surface_Unlock(IDirectDrawSurfaceImpl *This, LPVOID lpRe printf("DirectDrawSurface::Unlock(This=%p, lpRect=%p)\n", This, lpRect); #endif + HWND hWnd = ddraw->bnetHack ? 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 (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) + { + DDBLTFX fx = { .dwFillColor = 0xFE }; + IDirectDrawSurface_Blt(This, NULL, NULL, NULL, DDBLT_COLORFILL, &fx); + } + } + if (This->caps & DDSCAPS_PRIMARYSURFACE && ddraw->render.run && (!(This->flags & DDSD_BACKBUFFERCOUNT) || This->lastFlipTick + FLIP_REDRAW_TIMEOUT < timeGetTime()))