1
0
mirror of https://github.com/FunkyFr3sh/cnc-ddraw.git synced 2025-03-15 06:04:49 +01:00

experimental tweaks for diablo and warcraft 2

This commit is contained in:
FunkyFr3sh 2019-03-17 00:16:09 +01:00
parent ee14204ced
commit 0f58746515
10 changed files with 176 additions and 57 deletions

View File

@ -1,6 +1,6 @@
LIBRARY ddraw.dll
EXPORTS
DirectDrawCreate @1
DirectDrawEnumerateA @2
GameHandlesClose DATA
DirectDrawCreate @1
DirectDrawEnumerateA @2
GameHandlesClose DATA

View File

@ -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"

View File

@ -125,6 +125,8 @@ typedef struct IDirectDrawImpl
BOOL altenter;
BOOL hidecursor;
BOOL accurateTimers;
int bnetHack;
BOOL bnetActive;
SpeedLimiter ticksLimiter;
SpeedLimiter flipLimiter;
SpeedLimiter fpsLimiter;

View File

@ -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;
}

View File

@ -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),

View File

@ -787,6 +787,9 @@ static void Render()
glEnd();
}
if (ddraw->bnetActive)
glClear(GL_COLOR_BUFFER_BIT);
SwapBuffers(ddraw->render.hDC);
#if _DEBUG

View File

@ -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;

View File

@ -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,

View File

@ -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);

View File

@ -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()))