1
0
mirror of https://github.com/FunkyFr3sh/cnc-ddraw.git synced 2025-03-24 17:49:52 +01:00

add OBS game capture support for bnet lobby

This commit is contained in:
FunkyFr3sh 2021-11-07 22:42:55 +01:00
parent b4cb502f6a
commit 6a241ca0ae
10 changed files with 160 additions and 14 deletions

View File

@ -30,6 +30,10 @@ typedef struct IDirectDrawSurfaceImpl
DWORD l_pitch; DWORD l_pitch;
DWORD lx_pitch; DWORD lx_pitch;
void* bnet_surface;
HDC bnet_dc;
HBITMAP bnet_bitmap;
PBITMAPINFO bmi; PBITMAPINFO bmi;
HBITMAP bitmap; HBITMAP bitmap;
HDC hdc; HDC hdc;

View File

@ -33,6 +33,6 @@ HRESULT dds_Unlock(IDirectDrawSurfaceImpl* This, LPRECT lpRect);
HRESULT dds_GetDDInterface(IDirectDrawSurfaceImpl* This, LPVOID* lplpDD); HRESULT dds_GetDDInterface(IDirectDrawSurfaceImpl* This, LPVOID* lplpDD);
void* dds_GetBuffer(IDirectDrawSurfaceImpl* This); void* dds_GetBuffer(IDirectDrawSurfaceImpl* This);
HRESULT dd_CreateSurface(IDirectDrawImpl* This, LPDDSURFACEDESC lpDDSurfaceDesc, IDirectDrawSurfaceImpl** lpDDSurface, IUnknown FAR* unkOuter); HRESULT dd_CreateSurface(IDirectDrawImpl* This, LPDDSURFACEDESC lpDDSurfaceDesc, IDirectDrawSurfaceImpl** lpDDSurface, IUnknown FAR* unkOuter);
void dds_RedrawBnet(IDirectDrawSurfaceImpl* This);
#endif #endif

View File

@ -9,6 +9,7 @@
#define WM_DISPLAYCHANGE_DDRAW WM_APP+116 #define WM_DISPLAYCHANGE_DDRAW WM_APP+116
#define IDT_TIMER_LEAVE_BNET 541287654 #define IDT_TIMER_LEAVE_BNET 541287654
#define IDT_TIMER_REDRAW_BNET 541287655
LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

View File

@ -90,9 +90,21 @@ ULONG __stdcall IDirectDrawSurface__Release(IDirectDrawSurfaceImpl* This)
HeapFree(GetProcessHeap(), 0, This->surface); HeapFree(GetProcessHeap(), 0, This->surface);
} }
if (This->bnet_bitmap)
{
DeleteObject(This->bnet_bitmap);
}
else if (This->bnet_surface)
{
HeapFree(GetProcessHeap(), 0, This->bnet_surface);
}
if (This->hdc) if (This->hdc)
DeleteDC(This->hdc); DeleteDC(This->hdc);
if (This->bnet_dc)
DeleteDC(This->bnet_dc);
if (This->bmi) if (This->bmi)
HeapFree(GetProcessHeap(), 0, This->bmi); HeapFree(GetProcessHeap(), 0, This->bmi);

View File

@ -1190,28 +1190,39 @@ HRESULT dds_SetPalette(IDirectDrawSurfaceImpl* This, IDirectDrawPaletteImpl* lpD
return DD_OK; return DD_OK;
} }
HRESULT dds_Unlock(IDirectDrawSurfaceImpl* This, LPRECT lpRect) void dds_RedrawBnet(IDirectDrawSurfaceImpl* This)
{ {
/* Hack for Warcraft II BNE and Diablo */ /* Hack for Warcraft II BNE and Diablo */
HWND hwnd = g_ddraw->bnet_active ? FindWindowEx(HWND_DESKTOP, NULL, "SDlgDialog", NULL) : NULL; HWND hwnd = g_ddraw->bnet_active ? FindWindowEx(HWND_DESKTOP, NULL, "SDlgDialog", NULL) : NULL;
if (hwnd && (This->caps & DDSCAPS_PRIMARYSURFACE)) if (hwnd)
{ {
HDC primary_dc; HDC primary_dc;
dds_GetDC(This, &primary_dc); dds_GetDC(This, &primary_dc);
if (g_ddraw->primary->palette)
{
SetDIBColorTable(g_ddraw->primary->bnet_dc, 0, 256, g_ddraw->primary->palette->data_rgb);
}
/* GdiTransparentBlt idea taken from Aqrit's war2 ddraw */ /* GdiTransparentBlt idea taken from Aqrit's war2 ddraw */
RGBQUAD quad; RGBQUAD quad;
GetDIBColorTable(primary_dc, 0xFE, 1, &quad); GetDIBColorTable(primary_dc, 0xFE, 1, &quad);
COLORREF color = RGB(quad.rgbRed, quad.rgbGreen, quad.rgbBlue); COLORREF color = RGB(quad.rgbRed, quad.rgbGreen, quad.rgbBlue);
BOOL erase = FALSE; BOOL erase = FALSE;
HWND hwnd_bnet[20];
int i = 0;
memset(&hwnd_bnet[0], 0, sizeof(hwnd_bnet));
do do
{ {
RECT rc; RECT rc;
if (fake_GetWindowRect(hwnd, &rc)) if (fake_GetWindowRect(hwnd, &rc))
{ {
hwnd_bnet[i++] = hwnd;
if (rc.bottom - rc.top == 479) if (rc.bottom - rc.top == 479)
erase = TRUE; erase = TRUE;
@ -1236,6 +1247,36 @@ HRESULT dds_Unlock(IDirectDrawSurfaceImpl* This, LPRECT lpRect)
} while ((hwnd = FindWindowEx(HWND_DESKTOP, hwnd, "SDlgDialog", NULL))); } while ((hwnd = FindWindowEx(HWND_DESKTOP, hwnd, "SDlgDialog", NULL)));
/* hack for windows 8/10 fullscreen exclusive mode */
EnterCriticalSection(&g_ddraw->cs);
for (i = sizeof(hwnd_bnet) / sizeof(hwnd_bnet[0]); i--; )
{
if (hwnd_bnet[i])
{
RECT rc;
if (fake_GetWindowRect(hwnd_bnet[i], &rc))
{
HDC dc = GetDC(hwnd_bnet[i]);
BitBlt(
g_ddraw->primary->bnet_dc,
rc.left,
rc.top,
rc.right - rc.left,
rc.bottom - rc.top,
dc,
0,
0,
SRCCOPY);
ReleaseDC(hwnd_bnet[i], dc);
}
}
}
LeaveCriticalSection(&g_ddraw->cs);
if (erase) if (erase)
{ {
BOOL x = g_ddraw->ticks_limiter.use_blt_or_flip; BOOL x = g_ddraw->ticks_limiter.use_blt_or_flip;
@ -1245,10 +1286,21 @@ HRESULT dds_Unlock(IDirectDrawSurfaceImpl* This, LPRECT lpRect)
g_ddraw->ticks_limiter.use_blt_or_flip = x; g_ddraw->ticks_limiter.use_blt_or_flip = x;
} }
if (g_ddraw->render.run)
ReleaseSemaphore(g_ddraw->render.sem, 1, NULL);
}
}
HRESULT dds_Unlock(IDirectDrawSurfaceImpl* This, LPRECT lpRect)
{
if ((This->caps & DDSCAPS_PRIMARYSURFACE))
{
dds_RedrawBnet(This);
} }
/* Hack for Star Trek Armada */ /* Hack for Star Trek Armada */
hwnd = g_ddraw->armadahack ? FindWindowEx(HWND_DESKTOP, NULL, "#32770", NULL) : NULL; HWND hwnd = g_ddraw->armadahack ? FindWindowEx(HWND_DESKTOP, NULL, "#32770", NULL) : NULL;
if (hwnd && (This->caps & DDSCAPS_PRIMARYSURFACE)) if (hwnd && (This->caps & DDSCAPS_PRIMARYSURFACE))
{ {
@ -1471,6 +1523,26 @@ HRESULT dd_CreateSurface(
{ {
g_ddraw->primary = dst_surface; g_ddraw->primary = dst_surface;
FakePrimarySurface = dst_surface->surface; FakePrimarySurface = dst_surface->surface;
dst_surface->bnet_dc = CreateCompatibleDC(g_ddraw->render.hdc);
dst_surface->bnet_bitmap =
CreateDIBSection(
dst_surface->bnet_dc,
dst_surface->bmi,
DIB_RGB_COLORS,
(void**)&dst_surface->bnet_surface, NULL, 0);
if (!dst_surface->bnet_bitmap)
{
dst_surface->bnet_surface =
HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
dst_surface->l_pitch * (dst_surface->height + 200) * dst_surface->lx_pitch);
}
SelectObject(dst_surface->bnet_dc, dst_surface->bnet_bitmap);
} }
SelectObject(dst_surface->hdc, dst_surface->bitmap); SelectObject(dst_surface->hdc, dst_surface->bitmap);

View File

@ -442,6 +442,27 @@ DWORD WINAPI d3d9_render_main(void)
} }
} }
} }
if (g_ddraw->bnet_active)
{
RECT rc = { 0,0,g_ddraw->width,g_ddraw->height };
if (SUCCEEDED(IDirect3DTexture9_LockRect(g_d3d9.surface_tex[tex_index], 0, &lock_rc, &rc, 0)))
{
unsigned char* src = (unsigned char*)g_ddraw->primary->bnet_surface;
unsigned char* dst = (unsigned char*)lock_rc.pBits;
for (int i = 0; i < g_ddraw->height; i++)
{
memcpy(dst, src, g_ddraw->primary->l_pitch);
src += g_ddraw->primary->l_pitch;
dst += lock_rc.Pitch;
}
IDirect3DTexture9_UnlockRect(g_d3d9.surface_tex[tex_index], 0);
}
}
} }
LeaveCriticalSection(&g_ddraw->cs); LeaveCriticalSection(&g_ddraw->cs);
@ -456,11 +477,6 @@ DWORD WINAPI d3d9_render_main(void)
IDirect3DDevice9_DrawPrimitive(g_d3d9.device, D3DPT_TRIANGLESTRIP, 0, 2); IDirect3DDevice9_DrawPrimitive(g_d3d9.device, D3DPT_TRIANGLESTRIP, 0, 2);
IDirect3DDevice9_EndScene(g_d3d9.device); IDirect3DDevice9_EndScene(g_d3d9.device);
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(g_d3d9.device, NULL, NULL, NULL, NULL))) if (FAILED(IDirect3DDevice9_Present(g_d3d9.device, NULL, NULL, NULL, NULL)))
{ {
DWORD_PTR result; DWORD_PTR result;

View File

@ -97,8 +97,20 @@ DWORD WINAPI gdi_render_main(void)
if (g_ddraw->bnet_active) if (g_ddraw->bnet_active)
{ {
RECT rc = { 0, 0, g_ddraw->render.width, g_ddraw->render.height }; StretchDIBits(
FillRect(g_ddraw->render.hdc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH)); 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->bnet_surface,
g_ddraw->primary->bmi,
DIB_RGB_COLORS,
SRCCOPY);
} }
else if (upscale_hack) else if (upscale_hack)
{ {

View File

@ -701,6 +701,28 @@ static void ogl_render()
} }
} }
} }
if (g_ddraw->bnet_active)
{
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->bnet_surface);
if (g_ogl.adjust_alignment)
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
}
} }
LeaveCriticalSection(&g_ddraw->cs); LeaveCriticalSection(&g_ddraw->cs);
@ -823,9 +845,6 @@ static void ogl_render()
glEnd(); glEnd();
} }
if (g_ddraw->bnet_active)
glClear(GL_COLOR_BUFFER_BIT);
SwapBuffers(g_ddraw->render.hdc); SwapBuffers(g_ddraw->render.hdc);
#if _DEBUG #if _DEBUG

View File

@ -591,6 +591,7 @@ BOOL WINAPI fake_DestroyWindow(HWND hWnd)
if (!FindWindowEx(HWND_DESKTOP, NULL, "SDlgDialog", NULL)) if (!FindWindowEx(HWND_DESKTOP, NULL, "SDlgDialog", NULL))
{ {
KillTimer(g_ddraw->hwnd, IDT_TIMER_REDRAW_BNET);
g_ddraw->bnet_active = FALSE; g_ddraw->bnet_active = FALSE;
SetFocus(g_ddraw->hwnd); SetFocus(g_ddraw->hwnd);
mouse_lock(); mouse_lock();
@ -680,6 +681,7 @@ HWND WINAPI fake_CreateWindowExA(
g_ddraw->resizable = FALSE; g_ddraw->resizable = FALSE;
g_ddraw->bnet_active = TRUE; g_ddraw->bnet_active = TRUE;
SetTimer(g_ddraw->hwnd, IDT_TIMER_REDRAW_BNET, 200, (TIMERPROC)NULL);
mouse_unlock(); mouse_unlock();
} }

View File

@ -4,6 +4,7 @@
#include "dllmain.h" #include "dllmain.h"
#include "dd.h" #include "dd.h"
#include "hook.h" #include "hook.h"
#include "ddsurface.h"
#include "mouse.h" #include "mouse.h"
#include "render_d3d9.h" #include "render_d3d9.h"
#include "config.h" #include "config.h"
@ -162,6 +163,13 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
return 0; return 0;
} }
case IDT_TIMER_REDRAW_BNET:
{
if (g_ddraw->primary)
dds_RedrawBnet(g_ddraw->primary);
return 0;
}
} }
break; break;
} }