1
0
mirror of https://github.com/FunkyFr3sh/cnc-ddraw.git synced 2025-03-19 15:49:37 +01:00
cnc-ddraw/src/dd.c

1060 lines
34 KiB
C
Raw Normal View History

2020-10-13 09:20:52 +02:00
#include <windows.h>
#include "ddraw.h"
2020-10-15 05:13:37 +02:00
#include "IDirectDraw.h"
2020-10-13 09:20:52 +02:00
#include "dd.h"
#include "hook.h"
#include "config.h"
#include "mouse.h"
#include "wndproc.h"
#include "render_d3d9.h"
#include "render_gdi.h"
#include "render_ogl.h"
#include "fps_limiter.h"
2020-10-13 09:20:52 +02:00
#include "debug.h"
#include "utils.h"
2021-06-11 20:30:43 +02:00
CNCDDRAW* g_ddraw = NULL;
2020-10-13 09:20:52 +02:00
2021-06-11 20:30:43 +02:00
HRESULT dd_EnumDisplayModes(
DWORD dwFlags,
LPDDSURFACEDESC lpDDSurfaceDesc,
2021-06-11 20:30:43 +02:00
LPVOID lpContext,
LPDDENUMMODESCALLBACK lpEnumModesCallback)
2020-10-13 09:20:52 +02:00
{
DWORD i = 0;
2021-06-11 20:30:43 +02:00
DDSURFACEDESC2 s;
2020-10-13 09:20:52 +02:00
2021-06-11 20:30:43 +02:00
/* Some games crash when you feed them with too many resolutions so we have to keep the list short */
2020-10-13 09:20:52 +02:00
SIZE resolutions[] =
{
{ 320, 200 },
{ 320, 240 },
{ 512, 384 },
{ 640, 400 },
{ 640, 480 },
{ 800, 600 },
{ 1024, 768 },
{ 1280, 1024 },
{ 1600, 1200 },
{ 1280, 720 },
{ 1920, 1080 },
};
if (g_ddraw->bpp || g_ddraw->resolutions == RESLIST_FULL)
2020-10-13 09:20:52 +02:00
{
2021-06-11 20:30:43 +02:00
TRACE(" g_ddraw->bpp=%u\n", g_ddraw->bpp);
2020-10-13 09:20:52 +02:00
/* set up some filters to keep the list short */
2020-10-13 09:20:52 +02:00
DWORD refresh_rate = 0;
DWORD bpp = 0;
DWORD flags = 99998;
DWORD fixed_output = 99998;
DEVMODE m;
2020-10-13 21:58:04 +02:00
2020-10-13 09:20:52 +02:00
memset(&m, 0, sizeof(DEVMODE));
m.dmSize = sizeof(DEVMODE);
while (EnumDisplaySettings(NULL, i, &m))
{
if (refresh_rate != 60 && m.dmDisplayFrequency >= 50)
refresh_rate = m.dmDisplayFrequency;
if (bpp != 32 && m.dmBitsPerPel >= 16)
bpp = m.dmBitsPerPel;
if (flags != 0)
flags = m.dmDisplayFlags;
if (fixed_output != DMDFO_DEFAULT)
fixed_output = m.dmDisplayFixedOutput;
memset(&m, 0, sizeof(DEVMODE));
m.dmSize = sizeof(DEVMODE);
i++;
}
memset(&m, 0, sizeof(DEVMODE));
m.dmSize = sizeof(DEVMODE);
i = 0;
2020-10-13 11:29:52 +02:00
2020-10-13 09:20:52 +02:00
while (EnumDisplaySettings(NULL, i, &m))
{
if (refresh_rate == m.dmDisplayFrequency &&
bpp == m.dmBitsPerPel &&
flags == m.dmDisplayFlags &&
fixed_output == m.dmDisplayFixedOutput)
{
2021-06-11 20:30:43 +02:00
TRACE_EXT(
" %u: %ux%u@%u %u bpp\n",
i,
m.dmPelsWidth,
m.dmPelsHeight,
m.dmDisplayFrequency,
m.dmBitsPerPel);
2020-10-13 09:20:52 +02:00
2021-06-11 20:30:43 +02:00
memset(&s, 0, sizeof(s));
2020-10-15 01:17:40 +02:00
2020-10-13 09:20:52 +02:00
s.dwSize = sizeof(DDSURFACEDESC);
2021-05-23 08:09:15 +02:00
s.dwFlags = DDSD_HEIGHT | DDSD_REFRESHRATE | DDSD_WIDTH | DDSD_PITCH | DDSD_PIXELFORMAT;
2020-10-13 09:20:52 +02:00
s.dwHeight = m.dmPelsHeight;
s.dwWidth = m.dmPelsWidth;
2021-05-23 08:09:15 +02:00
s.lPitch = s.dwWidth;
2020-10-13 09:20:52 +02:00
s.dwRefreshRate = 60;
s.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
s.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
s.ddpfPixelFormat.dwRGBBitCount = 8;
if (g_ddraw->bpp == 8 || g_ddraw->resolutions == RESLIST_FULL)
{
if (lpEnumModesCallback((LPDDSURFACEDESC)&s, lpContext) == DDENUMRET_CANCEL)
{
2021-06-11 20:30:43 +02:00
TRACE(" DDENUMRET_CANCEL returned, stopping\n");
2021-06-10 03:53:48 +02:00
return DD_OK;
}
}
s.lPitch = s.dwWidth * 2;
s.ddpfPixelFormat.dwFlags = DDPF_RGB;
s.ddpfPixelFormat.dwRGBBitCount = 16;
s.ddpfPixelFormat.dwRBitMask = 0xF800;
s.ddpfPixelFormat.dwGBitMask = 0x07E0;
s.ddpfPixelFormat.dwBBitMask = 0x001F;
if (g_ddraw->bpp == 16 || g_ddraw->resolutions == RESLIST_FULL)
2020-10-13 09:20:52 +02:00
{
if (lpEnumModesCallback((LPDDSURFACEDESC)&s, lpContext) == DDENUMRET_CANCEL)
{
2021-06-11 20:30:43 +02:00
TRACE(" DDENUMRET_CANCEL returned, stopping\n");
2021-06-10 03:53:48 +02:00
return DD_OK;
}
2020-10-13 09:20:52 +02:00
}
s.lPitch = s.dwWidth * 4;
s.ddpfPixelFormat.dwFlags = DDPF_RGB;
s.ddpfPixelFormat.dwRGBBitCount = 32;
s.ddpfPixelFormat.dwRBitMask = 0xFF0000;
s.ddpfPixelFormat.dwGBitMask = 0x00FF00;
s.ddpfPixelFormat.dwBBitMask = 0x0000FF;
if (g_ddraw->bpp == 32 || g_ddraw->resolutions == RESLIST_FULL)
2021-06-02 01:52:45 +02:00
{
if (lpEnumModesCallback((LPDDSURFACEDESC)&s, lpContext) == DDENUMRET_CANCEL)
{
2021-06-11 20:30:43 +02:00
TRACE(" DDENUMRET_CANCEL returned, stopping\n");
2021-06-10 03:53:48 +02:00
return DD_OK;
}
2021-06-02 01:52:45 +02:00
}
for (int x = 0; x < sizeof(resolutions) / sizeof(resolutions[0]); x++)
2020-10-13 09:20:52 +02:00
{
if (resolutions[x].cx == m.dmPelsWidth && resolutions[x].cy == m.dmPelsHeight)
{
resolutions[x].cx = 0;
resolutions[x].cy = 0;
}
2020-10-13 09:20:52 +02:00
}
}
2020-10-13 11:29:52 +02:00
2020-10-13 09:20:52 +02:00
memset(&m, 0, sizeof(DEVMODE));
m.dmSize = sizeof(DEVMODE);
i++;
}
}
if (!g_ddraw->bpp || g_ddraw->resolutions == RESLIST_FULL)
{
2021-06-07 01:36:47 +02:00
DWORD max_w = 0;
DWORD max_h = 0;
DEVMODE m;
memset(&m, 0, sizeof(DEVMODE));
m.dmSize = sizeof(DEVMODE);
if (EnumDisplaySettings(NULL, ENUM_REGISTRY_SETTINGS, &m))
{
max_w = m.dmPelsWidth;
max_h = m.dmPelsHeight;
}
2020-10-13 09:20:52 +02:00
for (i = 0; i < sizeof(resolutions) / sizeof(resolutions[0]); i++)
{
if (!resolutions[i].cx || !resolutions[i].cy)
continue;
2021-06-07 01:36:47 +02:00
if ((max_w && resolutions[i].cx > max_w) || (max_h && resolutions[i].cy > max_h))
{
memset(&m, 0, sizeof(DEVMODE));
m.dmSize = sizeof(DEVMODE);
m.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
m.dmPelsWidth = resolutions[i].cx;
m.dmPelsHeight = resolutions[i].cy;
if (ChangeDisplaySettings(&m, CDS_TEST) != DISP_CHANGE_SUCCESSFUL)
continue;
}
2021-06-11 20:30:43 +02:00
memset(&s, 0, sizeof(s));
2020-10-15 01:17:40 +02:00
2020-10-13 09:20:52 +02:00
s.dwSize = sizeof(DDSURFACEDESC);
2021-05-23 08:09:15 +02:00
s.dwFlags = DDSD_HEIGHT | DDSD_REFRESHRATE | DDSD_WIDTH | DDSD_PITCH | DDSD_PIXELFORMAT;
2020-10-13 09:20:52 +02:00
s.dwHeight = resolutions[i].cy;
s.dwWidth = resolutions[i].cx;
2021-05-23 08:09:15 +02:00
s.lPitch = s.dwWidth;
2020-10-13 09:20:52 +02:00
s.dwRefreshRate = 60;
s.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
s.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
s.ddpfPixelFormat.dwRGBBitCount = 8;
if (lpEnumModesCallback((LPDDSURFACEDESC)&s, lpContext) == DDENUMRET_CANCEL)
2020-10-13 09:20:52 +02:00
{
2021-06-11 20:30:43 +02:00
TRACE(" DDENUMRET_CANCEL returned, stopping\n");
2021-06-10 03:53:48 +02:00
return DD_OK;
2020-10-13 09:20:52 +02:00
}
2021-05-23 08:09:15 +02:00
s.lPitch = s.dwWidth * 2;
2020-10-13 09:20:52 +02:00
s.ddpfPixelFormat.dwFlags = DDPF_RGB;
s.ddpfPixelFormat.dwRGBBitCount = 16;
s.ddpfPixelFormat.dwRBitMask = 0xF800;
s.ddpfPixelFormat.dwGBitMask = 0x07E0;
s.ddpfPixelFormat.dwBBitMask = 0x001F;
if (lpEnumModesCallback((LPDDSURFACEDESC)&s, lpContext) == DDENUMRET_CANCEL)
2020-10-13 09:20:52 +02:00
{
2021-06-11 20:30:43 +02:00
TRACE(" DDENUMRET_CANCEL returned, stopping\n");
2021-06-10 03:53:48 +02:00
return DD_OK;
2020-10-13 09:20:52 +02:00
}
2021-06-02 01:52:45 +02:00
if (g_ddraw->resolutions == RESLIST_MINI)
continue;
2021-06-02 01:52:45 +02:00
s.lPitch = s.dwWidth * 4;
s.ddpfPixelFormat.dwFlags = DDPF_RGB;
s.ddpfPixelFormat.dwRGBBitCount = 32;
s.ddpfPixelFormat.dwRBitMask = 0xFF0000;
s.ddpfPixelFormat.dwGBitMask = 0x00FF00;
s.ddpfPixelFormat.dwBBitMask = 0x0000FF;
if (lpEnumModesCallback((LPDDSURFACEDESC)&s, lpContext) == DDENUMRET_CANCEL)
2021-06-02 01:52:45 +02:00
{
2021-06-11 20:30:43 +02:00
TRACE(" DDENUMRET_CANCEL returned, stopping\n");
2021-06-10 03:53:48 +02:00
return DD_OK;
2021-06-02 01:52:45 +02:00
}
2020-10-13 09:20:52 +02:00
}
}
return DD_OK;
}
2021-06-14 09:18:14 +02:00
HRESULT dd_GetCaps(LPDDCAPS_DX1 lpDDDriverCaps, LPDDCAPS_DX1 lpDDEmulCaps)
2020-10-13 09:20:52 +02:00
{
2020-10-17 04:52:31 +02:00
if (lpDDDriverCaps)
2020-10-13 09:20:52 +02:00
{
2021-06-14 09:18:14 +02:00
int size =
lpDDDriverCaps->dwSize == sizeof(DDCAPS_DX3) ? sizeof(DDCAPS_DX3) :
lpDDDriverCaps->dwSize == sizeof(DDCAPS_DX5) ? sizeof(DDCAPS_DX5) :
lpDDDriverCaps->dwSize == sizeof(DDCAPS_DX6) ? sizeof(DDCAPS_DX6) :
lpDDDriverCaps->dwSize == sizeof(DDCAPS_DX7) ? sizeof(DDCAPS_DX7) :
sizeof(DDCAPS_DX1);
memset(lpDDDriverCaps, 0, size);
lpDDDriverCaps->dwSize = size;
2021-06-11 20:30:43 +02:00
lpDDDriverCaps->dwCaps =
DDCAPS_BLT |
DDCAPS_PALETTE |
DDCAPS_BLTCOLORFILL |
DDCAPS_BLTSTRETCH |
DDCAPS_CANCLIP |
DDCAPS_CANBLTSYSMEM;
2020-10-13 09:20:52 +02:00
lpDDDriverCaps->dwPalCaps = DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE;
lpDDDriverCaps->dwVidMemTotal = 16777216;
lpDDDriverCaps->dwVidMemFree = 16777216;
2021-06-14 09:18:14 +02:00
lpDDDriverCaps->ddsCaps.dwCaps = DDSCAPS_FLIP;
2020-10-13 09:20:52 +02:00
}
2020-10-17 04:52:31 +02:00
if (lpDDEmulCaps)
2020-10-13 09:20:52 +02:00
{
2021-06-14 09:18:14 +02:00
int size =
lpDDEmulCaps->dwSize == sizeof(DDCAPS_DX3) ? sizeof(DDCAPS_DX3) :
lpDDEmulCaps->dwSize == sizeof(DDCAPS_DX5) ? sizeof(DDCAPS_DX5) :
lpDDEmulCaps->dwSize == sizeof(DDCAPS_DX6) ? sizeof(DDCAPS_DX6) :
lpDDEmulCaps->dwSize == sizeof(DDCAPS_DX7) ? sizeof(DDCAPS_DX7) :
sizeof(DDCAPS_DX1);
memset(lpDDEmulCaps, 0, size);
lpDDEmulCaps->dwSize = size;
2020-10-13 09:20:52 +02:00
}
return DD_OK;
}
HRESULT dd_GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc)
2020-10-20 16:38:51 +02:00
{
if (lpDDSurfaceDesc)
{
2021-06-11 20:30:43 +02:00
int size = lpDDSurfaceDesc->dwSize == sizeof(DDSURFACEDESC2) ? sizeof(DDSURFACEDESC2) : sizeof(DDSURFACEDESC);
memset(lpDDSurfaceDesc, 0, size);
2020-10-20 16:38:51 +02:00
2021-06-11 20:30:43 +02:00
lpDDSurfaceDesc->dwSize = size;
2020-10-20 16:38:51 +02:00
lpDDSurfaceDesc->dwFlags = DDSD_HEIGHT | DDSD_REFRESHRATE | DDSD_WIDTH | DDSD_PITCH | DDSD_PIXELFORMAT;
lpDDSurfaceDesc->dwHeight = g_ddraw->height ? g_ddraw->height : 768;
lpDDSurfaceDesc->dwWidth = g_ddraw->width ? g_ddraw->width : 1024;
lpDDSurfaceDesc->lPitch = lpDDSurfaceDesc->dwWidth;
lpDDSurfaceDesc->dwRefreshRate = 60;
lpDDSurfaceDesc->ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = 8;
2021-06-02 01:52:45 +02:00
if (g_ddraw->bpp == 32)
{
lpDDSurfaceDesc->lPitch = lpDDSurfaceDesc->dwWidth * 4;
lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = 32;
lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0xFF0000;
lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0x00FF00;
lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = 0x0000FF;
}
else if (g_ddraw->bpp != 8)
2020-10-20 16:38:51 +02:00
{
lpDDSurfaceDesc->lPitch = lpDDSurfaceDesc->dwWidth * 2;
lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = 16;
lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0xF800;
lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0x07E0;
lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = 0x001F;
}
}
return DD_OK;
}
2020-10-13 22:55:49 +02:00
HRESULT dd_GetMonitorFrequency(LPDWORD lpdwFreq)
{
*lpdwFreq = 60;
return DD_OK;
}
2020-10-13 09:20:52 +02:00
HRESULT dd_RestoreDisplayMode()
{
2020-10-13 21:58:04 +02:00
if (!g_ddraw->render.run)
2020-10-13 09:20:52 +02:00
{
return DD_OK;
}
/* only stop drawing in GL mode when minimized */
if (g_ddraw->renderer != gdi_render_main)
{
EnterCriticalSection(&g_ddraw->cs);
g_ddraw->render.run = FALSE;
ReleaseSemaphore(g_ddraw->render.sem, 1, NULL);
LeaveCriticalSection(&g_ddraw->cs);
if (g_ddraw->render.thread)
{
WaitForSingleObject(g_ddraw->render.thread, INFINITE);
g_ddraw->render.thread = NULL;
}
if (g_ddraw->renderer == d3d9_render_main)
2020-10-13 21:58:04 +02:00
{
2020-10-13 09:20:52 +02:00
d3d9_release();
2020-10-13 21:58:04 +02:00
}
2020-10-13 09:20:52 +02:00
}
2021-06-11 20:30:43 +02:00
2020-10-13 21:58:04 +02:00
if (!g_ddraw->windowed)
2020-10-13 09:20:52 +02:00
{
if (g_ddraw->renderer != d3d9_render_main)
2020-10-13 21:58:04 +02:00
{
2020-10-13 09:20:52 +02:00
ChangeDisplaySettings(NULL, 0);
2020-10-13 21:58:04 +02:00
}
2020-10-13 09:20:52 +02:00
}
return DD_OK;
}
2021-07-03 18:07:38 +02:00
HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFlags)
2020-10-13 09:20:52 +02:00
{
2021-06-11 20:30:43 +02:00
if (dwBPP != 8 && dwBPP != 16 && dwBPP != 32)
2020-10-13 09:20:52 +02:00
return DDERR_INVALIDMODE;
if (g_ddraw->render.thread)
{
EnterCriticalSection(&g_ddraw->cs);
g_ddraw->render.run = FALSE;
ReleaseSemaphore(g_ddraw->render.sem, 1, NULL);
LeaveCriticalSection(&g_ddraw->cs);
WaitForSingleObject(g_ddraw->render.thread, INFINITE);
g_ddraw->render.thread = NULL;
}
if (!g_ddraw->mode.dmPelsWidth)
{
2021-05-24 10:20:00 +02:00
ChangeDisplaySettings(NULL, 0);
2020-10-13 09:20:52 +02:00
g_ddraw->mode.dmSize = sizeof(DEVMODE);
g_ddraw->mode.dmDriverExtra = 0;
if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &g_ddraw->mode) == FALSE)
{
g_ddraw->mode.dmSize = sizeof(DEVMODE);
g_ddraw->mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
g_ddraw->mode.dmPelsWidth = real_GetSystemMetrics(SM_CXSCREEN);
g_ddraw->mode.dmPelsHeight = real_GetSystemMetrics(SM_CYSCREEN);
g_ddraw->mode.dmDisplayFrequency = 60;
g_ddraw->mode.dmBitsPerPel = 32;
if (!g_ddraw->mode.dmPelsWidth || !g_ddraw->mode.dmPelsHeight)
{
g_ddraw->fullscreen = FALSE;
}
}
}
2021-07-03 18:07:38 +02:00
if (dwFlags & SDM_LEAVE_WINDOWED)
2020-10-13 09:20:52 +02:00
{
memset(&g_ddraw->render.mode, 0, sizeof(DEVMODE));
2020-10-15 01:17:40 +02:00
2020-10-13 09:20:52 +02:00
g_ddraw->render.mode.dmSize = sizeof(DEVMODE);
g_ddraw->render.mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
g_ddraw->render.mode.dmPelsWidth = g_ddraw->render.width;
g_ddraw->render.mode.dmPelsHeight = g_ddraw->render.height;
2020-10-13 11:29:52 +02:00
2020-10-13 09:20:52 +02:00
if (g_ddraw->render.bpp)
{
g_ddraw->render.mode.dmFields |= DM_BITSPERPEL;
g_ddraw->render.mode.dmBitsPerPel = g_ddraw->render.bpp;
}
if (ChangeDisplaySettings(&g_ddraw->render.mode, CDS_TEST) != DISP_CHANGE_SUCCESSFUL)
{
g_ddraw->render.width = g_ddraw->width;
g_ddraw->render.height = g_ddraw->height;
}
}
else
{
g_ddraw->render.width = g_config.window_rect.right;
g_ddraw->render.height = g_config.window_rect.bottom;
}
2021-06-11 20:30:43 +02:00
/* temporary fix: center window for games that keep changing their resolution */
if (g_ddraw->width &&
(g_ddraw->width != dwWidth || g_ddraw->height != dwHeight) &&
(dwWidth > g_config.window_rect.right || dwHeight > g_config.window_rect.bottom))
2020-10-13 09:20:52 +02:00
{
g_config.window_rect.left = -32000;
g_config.window_rect.top = -32000;
}
2021-06-11 20:30:43 +02:00
g_ddraw->width = dwWidth;
g_ddraw->height = dwHeight;
g_ddraw->bpp = dwBPP;
2020-10-13 09:20:52 +02:00
2021-06-17 06:13:16 +02:00
InterlockedExchange((LONG*)&g_ddraw->cursor.x, dwWidth / 2);
InterlockedExchange((LONG*)&g_ddraw->cursor.y, dwHeight / 2);
2020-10-13 09:20:52 +02:00
BOOL border = g_ddraw->border;
BOOL nonexclusive = FALSE;
2020-10-13 09:20:52 +02:00
2020-10-13 11:29:52 +02:00
if (g_ddraw->fullscreen)
2020-10-13 09:20:52 +02:00
{
g_ddraw->render.width = g_ddraw->mode.dmPelsWidth;
g_ddraw->render.height = g_ddraw->mode.dmPelsHeight;
2021-06-11 20:30:43 +02:00
if (g_ddraw->windowed) /* windowed-fullscreen aka borderless */
2020-10-13 09:20:52 +02:00
{
border = FALSE;
2020-10-15 01:17:40 +02:00
2020-10-13 09:20:52 +02:00
g_config.window_rect.left = -32000;
g_config.window_rect.top = -32000;
2021-06-11 20:30:43 +02:00
/* prevent OpenGL from going automatically into fullscreen exclusive mode */
2020-10-13 09:20:52 +02:00
if (g_ddraw->renderer == ogl_render_main)
nonexclusive = TRUE;
2020-10-13 09:20:52 +02:00
}
}
2020-10-13 11:29:52 +02:00
if (g_ddraw->render.width < g_ddraw->width)
2020-10-13 09:20:52 +02:00
{
g_ddraw->render.width = g_ddraw->width;
}
2020-10-13 21:58:04 +02:00
2020-10-13 11:29:52 +02:00
if (g_ddraw->render.height < g_ddraw->height)
2020-10-13 09:20:52 +02:00
{
g_ddraw->render.height = g_ddraw->height;
}
g_ddraw->render.run = TRUE;
2021-06-11 20:30:43 +02:00
BOOL lock_mouse = (g_ddraw->locked || g_ddraw->fullscreen) && !(dwFlags & SDM_LEAVE_FULLSCREEN);
2020-10-13 09:20:52 +02:00
mouse_unlock();
2021-06-11 20:30:43 +02:00
2020-10-13 09:20:52 +02:00
memset(&g_ddraw->render.mode, 0, sizeof(DEVMODE));
2020-10-15 01:17:40 +02:00
2020-10-13 09:20:52 +02:00
g_ddraw->render.mode.dmSize = sizeof(DEVMODE);
2021-06-11 20:30:43 +02:00
g_ddraw->render.mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2020-10-13 09:20:52 +02:00
g_ddraw->render.mode.dmPelsWidth = g_ddraw->render.width;
g_ddraw->render.mode.dmPelsHeight = g_ddraw->render.height;
2020-10-13 21:58:04 +02:00
2020-10-15 01:17:40 +02:00
if (g_ddraw->render.bpp)
2020-10-13 09:20:52 +02:00
{
g_ddraw->render.mode.dmFields |= DM_BITSPERPEL;
g_ddraw->render.mode.dmBitsPerPel = g_ddraw->render.bpp;
}
2021-06-11 20:30:43 +02:00
2020-10-13 09:20:52 +02:00
if (!g_ddraw->windowed)
{
2021-06-11 20:30:43 +02:00
/* Making sure the chosen resolution is valid */
2020-10-13 09:20:52 +02:00
int old_width = g_ddraw->render.width;
int old_height = g_ddraw->render.height;
if (ChangeDisplaySettings(&g_ddraw->render.mode, CDS_TEST) != DISP_CHANGE_SUCCESSFUL)
{
2021-06-11 20:30:43 +02:00
/* fail... compare resolutions */
if (g_ddraw->render.width > g_ddraw->mode.dmPelsWidth ||
g_ddraw->render.height > g_ddraw->mode.dmPelsHeight)
2020-10-13 09:20:52 +02:00
{
2021-06-11 20:30:43 +02:00
/* chosen game resolution higher than current resolution, use windowed mode for this case */
2020-10-13 09:20:52 +02:00
g_ddraw->windowed = TRUE;
}
else
{
2021-06-11 20:30:43 +02:00
/* Try 2x scaling */
2020-10-13 09:20:52 +02:00
g_ddraw->render.width *= 2;
g_ddraw->render.height *= 2;
g_ddraw->render.mode.dmPelsWidth = g_ddraw->render.width;
g_ddraw->render.mode.dmPelsHeight = g_ddraw->render.height;
2021-06-11 20:30:43 +02:00
if ((g_ddraw->render.width > g_ddraw->mode.dmPelsWidth ||
g_ddraw->render.height > g_ddraw->mode.dmPelsHeight) ||
2020-10-13 09:20:52 +02:00
ChangeDisplaySettings(&g_ddraw->render.mode, CDS_TEST) != DISP_CHANGE_SUCCESSFUL)
{
2021-06-11 20:30:43 +02:00
SIZE res = { 0 };
2020-10-13 09:20:52 +02:00
2021-06-11 20:30:43 +02:00
/* try to get a resolution with the same aspect ratio as the requested resolution */
2020-10-13 09:20:52 +02:00
BOOL found_res = util_get_lowest_resolution(
(float)old_width / old_height,
&res,
2021-06-11 20:30:43 +02:00
old_width + 1, /* don't return the original resolution since we tested that one already */
2020-10-13 09:20:52 +02:00
old_height + 1,
g_ddraw->mode.dmPelsWidth,
g_ddraw->mode.dmPelsHeight);
if (!found_res)
{
2021-06-11 20:30:43 +02:00
/* try to get a resolution with the same aspect ratio as the current display mode */
2020-10-13 09:20:52 +02:00
found_res = util_get_lowest_resolution(
(float)g_ddraw->mode.dmPelsWidth / g_ddraw->mode.dmPelsHeight,
&res,
old_width,
old_height,
g_ddraw->mode.dmPelsWidth,
g_ddraw->mode.dmPelsHeight);
}
g_ddraw->render.width = res.cx;
g_ddraw->render.height = res.cy;
g_ddraw->render.mode.dmPelsWidth = g_ddraw->render.width;
g_ddraw->render.mode.dmPelsHeight = g_ddraw->render.height;
2021-06-11 20:30:43 +02:00
2020-10-13 09:20:52 +02:00
if (!found_res || ChangeDisplaySettings(&g_ddraw->render.mode, CDS_TEST) != DISP_CHANGE_SUCCESSFUL)
{
2021-06-11 20:30:43 +02:00
/* try current display settings */
2020-10-13 09:20:52 +02:00
g_ddraw->render.width = g_ddraw->mode.dmPelsWidth;
g_ddraw->render.height = g_ddraw->mode.dmPelsHeight;
g_ddraw->render.mode.dmPelsWidth = g_ddraw->render.width;
g_ddraw->render.mode.dmPelsHeight = g_ddraw->render.height;
if (ChangeDisplaySettings(&g_ddraw->render.mode, CDS_TEST) != DISP_CHANGE_SUCCESSFUL)
{
2021-06-11 20:30:43 +02:00
/* everything failed, use windowed mode instead */
2020-10-13 09:20:52 +02:00
g_ddraw->render.width = old_width;
g_ddraw->render.height = old_height;
g_ddraw->render.mode.dmPelsWidth = g_ddraw->render.width;
g_ddraw->render.mode.dmPelsHeight = g_ddraw->render.height;
g_ddraw->windowed = TRUE;
}
}
}
}
}
}
g_ddraw->render.viewport.width = g_ddraw->render.width;
g_ddraw->render.viewport.height = g_ddraw->render.height;
g_ddraw->render.viewport.x = 0;
g_ddraw->render.viewport.y = 0;
2021-06-11 20:30:43 +02:00
2020-10-13 09:20:52 +02:00
if (g_ddraw->boxing)
{
g_ddraw->render.viewport.width = g_ddraw->width;
g_ddraw->render.viewport.height = g_ddraw->height;
2021-06-11 20:30:43 +02:00
for (int i = 20; i-- > 1;)
2020-10-13 09:20:52 +02:00
{
if (g_ddraw->width * i <= g_ddraw->render.width && g_ddraw->height * i <= g_ddraw->render.height)
{
g_ddraw->render.viewport.width *= i;
g_ddraw->render.viewport.height *= i;
break;
}
}
g_ddraw->render.viewport.y = g_ddraw->render.height / 2 - g_ddraw->render.viewport.height / 2;
g_ddraw->render.viewport.x = g_ddraw->render.width / 2 - g_ddraw->render.viewport.width / 2;
}
2021-06-16 05:57:19 +02:00
else if (g_ddraw->maintas)
2020-10-13 09:20:52 +02:00
{
g_ddraw->render.viewport.width = g_ddraw->render.width;
2021-06-11 20:30:43 +02:00
g_ddraw->render.viewport.height =
(int)(((float)g_ddraw->height / g_ddraw->width) * g_ddraw->render.viewport.width);
2020-10-13 09:20:52 +02:00
if (g_ddraw->render.viewport.height > g_ddraw->render.height)
{
2021-06-11 20:30:43 +02:00
g_ddraw->render.viewport.width =
2021-05-10 04:00:45 +02:00
(int)(((float)g_ddraw->render.viewport.width / g_ddraw->render.viewport.height) * g_ddraw->render.height);
2021-06-11 20:30:43 +02:00
2020-10-13 09:20:52 +02:00
g_ddraw->render.viewport.height = g_ddraw->render.height;
}
2021-06-11 20:30:43 +02:00
2020-10-13 09:20:52 +02:00
g_ddraw->render.viewport.y = g_ddraw->render.height / 2 - g_ddraw->render.viewport.height / 2;
g_ddraw->render.viewport.x = g_ddraw->render.width / 2 - g_ddraw->render.viewport.width / 2;
}
2021-06-11 20:30:43 +02:00
2020-10-13 09:20:52 +02:00
g_ddraw->render.scale_w = ((float)g_ddraw->render.viewport.width / g_ddraw->width);
g_ddraw->render.scale_h = ((float)g_ddraw->render.viewport.height / g_ddraw->height);
g_ddraw->render.unscale_w = ((float)g_ddraw->width / g_ddraw->render.viewport.width);
g_ddraw->render.unscale_h = ((float)g_ddraw->height / g_ddraw->render.viewport.height);
if (nonexclusive || (g_ddraw->nonexclusive && !g_ddraw->windowed && g_ddraw->renderer == ogl_render_main))
{
g_ddraw->render.height++;
}
2020-10-13 09:20:52 +02:00
if (g_ddraw->windowed)
{
2021-06-11 20:30:43 +02:00
MSG msg; /* workaround for "Not Responding" window problem in cnc games */
2020-10-13 09:20:52 +02:00
PeekMessage(&msg, g_ddraw->hwnd, 0, 0, PM_NOREMOVE);
if (!border)
{
2021-06-11 20:30:43 +02:00
real_SetWindowLongA(
g_ddraw->hwnd,
GWL_STYLE,
GetWindowLong(
g_ddraw->hwnd, GWL_STYLE) & ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU));
2020-10-13 09:20:52 +02:00
}
else
{
2021-06-11 20:30:43 +02:00
real_SetWindowLongA(
g_ddraw->hwnd,
GWL_STYLE,
2021-08-04 15:12:05 +02:00
(GetWindowLong(g_ddraw->hwnd, GWL_STYLE) | WS_OVERLAPPEDWINDOW) & ~WS_MAXIMIZE);
2020-10-13 09:20:52 +02:00
}
if (g_ddraw->wine)
2021-06-11 20:30:43 +02:00
{
real_SetWindowLongA(
g_ddraw->hwnd,
GWL_STYLE,
(GetWindowLong(g_ddraw->hwnd, GWL_STYLE) | WS_MINIMIZEBOX) & ~(WS_MAXIMIZEBOX | WS_THICKFRAME));
}
2020-10-13 09:20:52 +02:00
/* center the window with correct dimensions */
int cy = g_ddraw->mode.dmPelsWidth ? g_ddraw->mode.dmPelsWidth : g_ddraw->render.width;
int cx = g_ddraw->mode.dmPelsHeight ? g_ddraw->mode.dmPelsHeight : g_ddraw->render.height;
int x = (g_config.window_rect.left != -32000) ? g_config.window_rect.left : (cy / 2) - (g_ddraw->render.width / 2);
int y = (g_config.window_rect.top != -32000) ? g_config.window_rect.top : (cx / 2) - (g_ddraw->render.height / 2);
2021-06-11 20:30:43 +02:00
2020-10-13 09:20:52 +02:00
RECT dst = { x, y, g_ddraw->render.width + x, g_ddraw->render.height + y };
2021-06-11 20:30:43 +02:00
2020-10-13 09:20:52 +02:00
AdjustWindowRect(&dst, GetWindowLong(g_ddraw->hwnd, GWL_STYLE), FALSE);
real_SetWindowPos(g_ddraw->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
real_MoveWindow(g_ddraw->hwnd, dst.left, dst.top, (dst.right - dst.left), (dst.bottom - dst.top), TRUE);
BOOL d3d9_active = FALSE;
2020-10-13 11:29:52 +02:00
2020-10-13 09:20:52 +02:00
if (g_ddraw->renderer == d3d9_render_main)
{
d3d9_active = d3d9_create();
2020-10-13 11:29:52 +02:00
2020-10-13 09:20:52 +02:00
if (!d3d9_active)
{
d3d9_release();
g_ddraw->show_driver_warning = TRUE;
g_ddraw->renderer = gdi_render_main;
}
}
if (lock_mouse)
mouse_lock();
}
else
{
LONG style = GetWindowLong(g_ddraw->hwnd, GWL_STYLE);
if ((style & WS_CAPTION))
{
2021-06-11 20:30:43 +02:00
real_SetWindowLongA(
g_ddraw->hwnd,
GWL_STYLE,
style & ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU));
2020-10-13 09:20:52 +02:00
}
BOOL d3d9_active = FALSE;
2020-10-13 11:29:52 +02:00
2020-10-13 09:20:52 +02:00
if (g_ddraw->renderer == d3d9_render_main)
{
d3d9_active = d3d9_create();
2020-10-13 11:29:52 +02:00
2020-10-13 09:20:52 +02:00
if (!d3d9_active)
{
d3d9_release();
g_ddraw->show_driver_warning = TRUE;
g_ddraw->renderer = gdi_render_main;
}
}
if (!d3d9_active && ChangeDisplaySettings(&g_ddraw->render.mode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
g_ddraw->render.run = FALSE;
g_ddraw->windowed = TRUE;
2021-07-03 18:07:38 +02:00
return dd_SetDisplayMode(dwWidth, dwHeight, dwBPP, dwFlags);
2020-10-13 09:20:52 +02:00
}
if (g_ddraw->wine)
2020-10-13 11:29:52 +02:00
{
2020-10-13 09:20:52 +02:00
real_SetWindowLongA(g_ddraw->hwnd, GWL_STYLE, GetWindowLong(g_ddraw->hwnd, GWL_STYLE) | WS_MINIMIZEBOX);
2020-10-13 11:29:52 +02:00
}
2020-10-13 09:20:52 +02:00
2021-06-11 20:30:43 +02:00
real_SetWindowPos(
g_ddraw->hwnd,
HWND_TOPMOST,
0,
0,
g_ddraw->render.width,
g_ddraw->render.height,
SWP_SHOWWINDOW);
2020-10-13 09:20:52 +02:00
g_ddraw->last_set_window_pos_tick = timeGetTime();
mouse_lock();
}
2021-06-11 20:30:43 +02:00
2020-10-13 11:29:52 +02:00
if (g_ddraw->render.viewport.x != 0 || g_ddraw->render.viewport.y != 0)
2020-10-13 09:20:52 +02:00
{
RedrawWindow(g_ddraw->hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE);
2021-08-05 00:39:06 +02:00
InterlockedExchange(&g_ddraw->render.clear_screen, TRUE);
2020-10-13 09:20:52 +02:00
}
2020-10-13 11:29:52 +02:00
if (g_ddraw->render.thread == NULL)
2020-10-13 09:20:52 +02:00
{
InterlockedExchange(&g_ddraw->render.palette_updated, TRUE);
InterlockedExchange(&g_ddraw->render.surface_updated, TRUE);
ReleaseSemaphore(g_ddraw->render.sem, 1, NULL);
g_ddraw->render.thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)g_ddraw->renderer, NULL, 0, NULL);
}
2021-07-03 18:07:38 +02:00
if (dwFlags & SDM_MODE_SET_BY_GAME)
2020-10-13 09:20:52 +02:00
{
2021-06-04 03:34:35 +02:00
real_SendMessageA(g_ddraw->hwnd, WM_SIZE_DDRAW, 0, MAKELPARAM(g_ddraw->width, g_ddraw->height));
real_SendMessageA(g_ddraw->hwnd, WM_MOVE_DDRAW, 0, MAKELPARAM(0, 0));
real_SendMessageA(g_ddraw->hwnd, WM_DISPLAYCHANGE_DDRAW, g_ddraw->bpp, MAKELPARAM(g_ddraw->width, g_ddraw->height));
2020-10-13 09:20:52 +02:00
}
return DD_OK;
}
HRESULT dd_SetCooperativeLevel(HWND hwnd, DWORD dwFlags)
{
PIXELFORMATDESCRIPTOR pfd;
2020-10-13 21:58:04 +02:00
if (hwnd == NULL)
2020-10-13 09:20:52 +02:00
{
return DD_OK;
}
if (g_ddraw->hwnd == NULL)
{
g_ddraw->hwnd = hwnd;
}
if (!g_ddraw->wndproc)
{
hook_init();
2021-03-02 22:50:06 +01:00
g_ddraw->wndproc = (WNDPROC)real_SetWindowLongA(g_ddraw->hwnd, GWL_WNDPROC, (LONG)fake_WndProc);
2020-10-13 09:20:52 +02:00
if (!g_ddraw->render.hdc)
{
g_ddraw->render.hdc = GetDC(g_ddraw->hwnd);
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
2020-10-17 04:52:31 +02:00
2020-10-13 09:20:52 +02:00
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
2021-06-11 20:30:43 +02:00
pfd.dwFlags =
PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER | (g_ddraw->renderer == ogl_render_main ? PFD_SUPPORT_OPENGL : 0);
2020-10-13 09:20:52 +02:00
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = g_ddraw->render.bpp ? g_ddraw->render.bpp : g_ddraw->mode.dmBitsPerPel;
pfd.iLayerType = PFD_MAIN_PLANE;
2020-10-13 21:58:04 +02:00
2020-10-13 09:20:52 +02:00
SetPixelFormat(g_ddraw->render.hdc, ChoosePixelFormat(g_ddraw->render.hdc, &pfd), &pfd);
}
2021-06-19 04:28:15 +02:00
if (!g_ddraw->devmode)
{
HCURSOR cursor = real_SetCursor(LoadCursor(NULL, IDC_ARROW));
InterlockedExchange((LONG*)&g_ddraw->old_cursor, (LONG)cursor);
}
2021-06-17 04:12:05 +02:00
int cursor_count = real_ShowCursor(TRUE) - 1;
2021-06-17 06:13:16 +02:00
InterlockedExchange((LONG*)&g_ddraw->show_cursor_count, cursor_count);
2021-06-17 04:12:05 +02:00
real_ShowCursor(FALSE);
2021-06-16 05:57:19 +02:00
/* Make sure the cursor is visible in windowed mode initially */
2021-06-19 15:19:22 +02:00
if (g_ddraw->windowed && !g_ddraw->fullscreen && !g_ddraw->devmode && cursor_count < 0)
2020-10-13 09:20:52 +02:00
{
2021-06-19 04:28:15 +02:00
while (real_ShowCursor(TRUE) < 0);
2021-06-16 05:57:19 +02:00
}
2020-10-13 09:20:52 +02:00
GetWindowText(g_ddraw->hwnd, (LPTSTR)&g_ddraw->title, sizeof(g_ddraw->title));
g_ddraw->isredalert = strcmp(g_ddraw->title, "Red Alert") == 0;
g_ddraw->iscnc1 = strcmp(g_ddraw->title, "Command & Conquer") == 0;
g_ddraw->iskkndx = strcmp(g_ddraw->title, "KKND Xtreme") == 0;
2020-10-13 09:20:52 +02:00
if (g_ddraw->iskkndx)
{
g_ddraw->upscale_hack_width = 640;
g_ddraw->upscale_hack_height = 480;
}
else if (g_ddraw->isredalert || g_ddraw->iscnc1)
{
g_ddraw->upscale_hack_width = 640;
g_ddraw->upscale_hack_height = 400;
}
if (g_ddraw->vhack && !g_ddraw->isredalert && !g_ddraw->iscnc1 && !g_ddraw->iskkndx)
2020-10-13 11:29:52 +02:00
{
2020-10-13 09:20:52 +02:00
g_ddraw->vhack = 0;
2020-10-13 11:29:52 +02:00
}
2020-10-13 09:20:52 +02:00
}
return DD_OK;
}
2021-06-11 20:30:43 +02:00
HRESULT dd_WaitForVerticalBlank(DWORD dwFlags, HANDLE hEvent)
2020-10-13 09:20:52 +02:00
{
2021-02-19 03:24:11 +01:00
if (g_ddraw->maxgameticks == -2)
{
2021-02-22 09:19:09 +01:00
if (fpsl_dwm_flush() || fpsl_wait_for_vblank(g_ddraw->render.maxfps >= 0 && !g_ddraw->vsync))
2021-02-19 03:24:11 +01:00
return DD_OK;
}
2020-10-13 09:20:52 +02:00
if (!g_ddraw->flip_limiter.tick_length)
return DD_OK;
if (g_ddraw->flip_limiter.htimer)
{
FILETIME last_flip_ft = { 0 };
GetSystemTimeAsFileTime(&last_flip_ft);
if (!g_ddraw->flip_limiter.due_time.QuadPart)
{
memcpy(&g_ddraw->flip_limiter.due_time, &last_flip_ft, sizeof(LARGE_INTEGER));
}
else
{
while (CompareFileTime((FILETIME*)&g_ddraw->flip_limiter.due_time, &last_flip_ft) == -1)
g_ddraw->flip_limiter.due_time.QuadPart += g_ddraw->flip_limiter.tick_length_ns;
SetWaitableTimer(g_ddraw->flip_limiter.htimer, &g_ddraw->flip_limiter.due_time, 0, NULL, NULL, FALSE);
WaitForSingleObject(g_ddraw->flip_limiter.htimer, g_ddraw->flip_limiter.tick_length * 2);
}
}
else
{
static DWORD next_game_tick;
2020-10-13 11:29:52 +02:00
2020-10-13 09:20:52 +02:00
if (!next_game_tick)
{
next_game_tick = timeGetTime();
return DD_OK;
}
2020-10-13 11:29:52 +02:00
2020-10-13 09:20:52 +02:00
next_game_tick += g_ddraw->flip_limiter.tick_length;
DWORD tick_count = timeGetTime();
int sleep_time = next_game_tick - tick_count;
2020-10-13 11:29:52 +02:00
2020-10-13 09:20:52 +02:00
if (sleep_time <= 0 || sleep_time > g_ddraw->flip_limiter.tick_length)
2020-10-13 11:29:52 +02:00
{
2020-10-13 09:20:52 +02:00
next_game_tick = tick_count;
2020-10-13 11:29:52 +02:00
}
2020-10-13 09:20:52 +02:00
else
2020-10-13 11:29:52 +02:00
{
2020-10-13 09:20:52 +02:00
Sleep(sleep_time);
2020-10-13 11:29:52 +02:00
}
2020-10-13 09:20:52 +02:00
}
return DD_OK;
}
ULONG dd_AddRef()
{
return ++g_ddraw->ref;
}
ULONG dd_Release()
{
g_ddraw->ref--;
if (g_ddraw->ref == 0)
{
if (g_ddraw->bpp)
2020-10-15 01:17:40 +02:00
{
2020-10-13 09:20:52 +02:00
cfg_save();
2020-10-15 01:17:40 +02:00
}
2020-10-13 09:20:52 +02:00
2020-10-15 01:17:40 +02:00
if (g_ddraw->render.run)
2020-10-13 09:20:52 +02:00
{
EnterCriticalSection(&g_ddraw->cs);
g_ddraw->render.run = FALSE;
ReleaseSemaphore(g_ddraw->render.sem, 1, NULL);
LeaveCriticalSection(&g_ddraw->cs);
if (g_ddraw->render.thread)
{
WaitForSingleObject(g_ddraw->render.thread, INFINITE);
g_ddraw->render.thread = NULL;
}
if (g_ddraw->renderer == d3d9_render_main)
{
d3d9_release();
}
else if (!g_ddraw->windowed)
{
ChangeDisplaySettings(NULL, 0);
}
}
2020-10-13 11:29:52 +02:00
if (g_ddraw->render.hdc)
2020-10-13 09:20:52 +02:00
{
ReleaseDC(g_ddraw->hwnd, g_ddraw->render.hdc);
g_ddraw->render.hdc = NULL;
}
if (g_ddraw->ticks_limiter.htimer)
{
CancelWaitableTimer(g_ddraw->ticks_limiter.htimer);
CloseHandle(g_ddraw->ticks_limiter.htimer);
g_ddraw->ticks_limiter.htimer = NULL;
}
if (g_ddraw->flip_limiter.htimer)
{
CancelWaitableTimer(g_ddraw->flip_limiter.htimer);
CloseHandle(g_ddraw->flip_limiter.htimer);
g_ddraw->flip_limiter.htimer = NULL;
}
if (g_fpsl.htimer)
2020-10-13 09:20:52 +02:00
{
CancelWaitableTimer(g_fpsl.htimer);
CloseHandle(g_fpsl.htimer);
g_fpsl.htimer = NULL;
2020-10-13 09:20:52 +02:00
}
2021-05-29 20:52:57 +02:00
if (g_ddraw->real_dd)
{
g_ddraw->real_dd->lpVtbl->Release(g_ddraw->real_dd);
}
2020-10-13 09:20:52 +02:00
DeleteCriticalSection(&g_ddraw->cs);
/* restore old wndproc, subsequent ddraw creation will otherwise fail */
real_SetWindowLongA(g_ddraw->hwnd, GWL_WNDPROC, (LONG)g_ddraw->wndproc);
2020-10-13 11:29:52 +02:00
2020-10-13 09:20:52 +02:00
HeapFree(GetProcessHeap(), 0, g_ddraw);
g_ddraw = NULL;
2020-10-13 11:29:52 +02:00
2020-10-13 09:20:52 +02:00
return 0;
}
return g_ddraw->ref;
}
HRESULT dd_GetAvailableVidMem(LPDDSCAPS lpDDCaps, LPDWORD lpdwTotal, LPDWORD lpdwFree)
2020-10-13 09:20:52 +02:00
{
2021-08-02 17:13:31 +02:00
if (lpdwTotal)
*lpdwTotal = 16777216;
if (lpdwFree)
*lpdwFree = 16777216;
2020-10-13 09:20:52 +02:00
return DD_OK;
}
HRESULT dd_GetVerticalBlankStatus(LPBOOL lpbIsInVB)
{
*lpbIsInVB = TRUE;
return DD_OK;
}
2020-10-15 05:13:37 +02:00
HRESULT dd_CreateEx(GUID* lpGuid, LPVOID* lplpDD, REFIID iid, IUnknown* pUnkOuter)
{
if (!g_ddraw)
{
2021-06-11 20:30:43 +02:00
g_ddraw = (CNCDDRAW*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CNCDDRAW));
g_ddraw->ref++;
InitializeCriticalSection(&g_ddraw->cs);
2020-10-15 05:13:37 +02:00
g_ddraw->render.sem = CreateSemaphore(NULL, 0, 1, NULL);
g_ddraw->wine = GetProcAddress(GetModuleHandleA("ntdll.dll"), "wine_get_version") != 0;
cfg_load();
g_ddraw->ref--;
}
2020-10-15 05:13:37 +02:00
IDirectDrawImpl* dd = (IDirectDrawImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawImpl));
2021-06-11 20:30:43 +02:00
2020-10-15 05:13:37 +02:00
if (iid && IsEqualGUID(&IID_IDirectDraw, iid))
{
2021-06-11 20:30:43 +02:00
TRACE(" GUID = %08X (IID_IDirectDraw), ddraw = %p\n", ((GUID*)iid)->Data1, dd);
2020-10-15 05:13:37 +02:00
dd->lpVtbl = &g_dd_vtbl1;
}
else
{
2021-06-11 20:30:43 +02:00
TRACE(" GUID = %08X (IID_IDirectDrawX), ddraw = %p\n", iid ? ((GUID*)iid)->Data1 : 0, dd);
2020-10-15 05:13:37 +02:00
dd->lpVtbl = &g_dd_vtblx;
}
IDirectDraw_AddRef(dd);
*lplpDD = (LPVOID)dd;
return DD_OK;
}