1
0
mirror of https://github.com/FunkyFr3sh/cnc-ddraw.git synced 2025-03-15 06:04:49 +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 lx_pitch;
void* bnet_surface;
HDC bnet_dc;
HBITMAP bnet_bitmap;
PBITMAPINFO bmi;
HBITMAP bitmap;
HDC hdc;

View File

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

View File

@ -9,6 +9,7 @@
#define WM_DISPLAYCHANGE_DDRAW WM_APP+116
#define IDT_TIMER_LEAVE_BNET 541287654
#define IDT_TIMER_REDRAW_BNET 541287655
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);
}
if (This->bnet_bitmap)
{
DeleteObject(This->bnet_bitmap);
}
else if (This->bnet_surface)
{
HeapFree(GetProcessHeap(), 0, This->bnet_surface);
}
if (This->hdc)
DeleteDC(This->hdc);
if (This->bnet_dc)
DeleteDC(This->bnet_dc);
if (This->bmi)
HeapFree(GetProcessHeap(), 0, This->bmi);

View File

@ -1190,28 +1190,39 @@ HRESULT dds_SetPalette(IDirectDrawSurfaceImpl* This, IDirectDrawPaletteImpl* lpD
return DD_OK;
}
HRESULT dds_Unlock(IDirectDrawSurfaceImpl* This, LPRECT lpRect)
void dds_RedrawBnet(IDirectDrawSurfaceImpl* This)
{
/* Hack for Warcraft II BNE and Diablo */
HWND hwnd = g_ddraw->bnet_active ? FindWindowEx(HWND_DESKTOP, NULL, "SDlgDialog", NULL) : NULL;
if (hwnd && (This->caps & DDSCAPS_PRIMARYSURFACE))
if (hwnd)
{
HDC 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 */
RGBQUAD quad;
GetDIBColorTable(primary_dc, 0xFE, 1, &quad);
COLORREF color = RGB(quad.rgbRed, quad.rgbGreen, quad.rgbBlue);
BOOL erase = FALSE;
HWND hwnd_bnet[20];
int i = 0;
memset(&hwnd_bnet[0], 0, sizeof(hwnd_bnet));
do
{
RECT rc;
if (fake_GetWindowRect(hwnd, &rc))
{
hwnd_bnet[i++] = hwnd;
if (rc.bottom - rc.top == 479)
erase = TRUE;
@ -1236,6 +1247,36 @@ HRESULT dds_Unlock(IDirectDrawSurfaceImpl* This, LPRECT lpRect)
} 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)
{
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;
}
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 */
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))
{
@ -1471,6 +1523,26 @@ HRESULT dd_CreateSurface(
{
g_ddraw->primary = dst_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);

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);
@ -456,11 +477,6 @@ DWORD WINAPI d3d9_render_main(void)
IDirect3DDevice9_DrawPrimitive(g_d3d9.device, D3DPT_TRIANGLESTRIP, 0, 2);
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)))
{
DWORD_PTR result;

View File

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

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);
@ -823,9 +845,6 @@ static void ogl_render()
glEnd();
}
if (g_ddraw->bnet_active)
glClear(GL_COLOR_BUFFER_BIT);
SwapBuffers(g_ddraw->render.hdc);
#if _DEBUG

View File

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

View File

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