2020-10-13 09:20:52 +02:00
|
|
|
#include <windows.h>
|
2020-10-15 05:13:37 +02:00
|
|
|
#include "IDirectDraw.h"
|
2020-10-13 09:20:52 +02:00
|
|
|
#include "ddraw.h"
|
|
|
|
#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 "debug.h"
|
|
|
|
#include "utils.h"
|
|
|
|
|
|
|
|
|
|
|
|
cnc_ddraw *g_ddraw = NULL;
|
|
|
|
|
|
|
|
HRESULT dd_EnumDisplayModes(DWORD dwFlags, LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext, LPDDENUMMODESCALLBACK lpEnumModesCallback)
|
|
|
|
{
|
|
|
|
DWORD i = 0;
|
|
|
|
DDSURFACEDESC s;
|
|
|
|
|
|
|
|
// Some games crash when you feed them with too many resolutions...
|
|
|
|
|
|
|
|
if (g_ddraw->bpp)
|
|
|
|
{
|
|
|
|
dprintf(" g_ddraw->bpp=%u\n", g_ddraw->bpp);
|
|
|
|
|
|
|
|
//set up some filters to keep the list short
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
dprintfex(" %d: %dx%d@%d %d bpp\n", (int)i, (int)m.dmPelsWidth, (int)m.dmPelsHeight, (int)m.dmDisplayFrequency, (int)m.dmBitsPerPel);
|
|
|
|
|
|
|
|
memset(&s, 0, sizeof(DDSURFACEDESC));
|
2020-10-15 01:17:40 +02:00
|
|
|
|
2020-10-13 09:20:52 +02:00
|
|
|
s.dwSize = sizeof(DDSURFACEDESC);
|
|
|
|
s.dwFlags = DDSD_HEIGHT | DDSD_REFRESHRATE | DDSD_WIDTH | DDSD_PIXELFORMAT;
|
|
|
|
s.dwHeight = m.dmPelsHeight;
|
|
|
|
s.dwWidth = m.dmPelsWidth;
|
|
|
|
s.dwRefreshRate = 60;
|
|
|
|
s.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
|
|
|
|
|
|
|
|
s.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
|
|
|
|
s.ddpfPixelFormat.dwRGBBitCount = 8;
|
|
|
|
|
|
|
|
if (g_ddraw->bpp == 16)
|
|
|
|
{
|
|
|
|
s.ddpfPixelFormat.dwFlags = DDPF_RGB;
|
|
|
|
s.ddpfPixelFormat.dwRGBBitCount = 16;
|
|
|
|
s.ddpfPixelFormat.dwRBitMask = 0xF800;
|
|
|
|
s.ddpfPixelFormat.dwGBitMask = 0x07E0;
|
|
|
|
s.ddpfPixelFormat.dwBBitMask = 0x001F;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lpEnumModesCallback(&s, lpContext) == DDENUMRET_CANCEL)
|
|
|
|
{
|
2020-10-13 21:58:04 +02:00
|
|
|
dprintf(" DDENUMRET_CANCEL returned, stopping\n");
|
2020-10-13 09:20:52 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
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++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SIZE resolutions[] =
|
|
|
|
{
|
|
|
|
{ 320, 200 },
|
|
|
|
{ 320, 240 },
|
|
|
|
{ 640, 400 },
|
|
|
|
{ 640, 480 },
|
|
|
|
{ 800, 600 },
|
|
|
|
{ 1024, 768 },
|
|
|
|
{ 1280, 1024 },
|
|
|
|
{ 1280, 720 },
|
|
|
|
{ 1920, 1080 },
|
|
|
|
};
|
|
|
|
|
|
|
|
for (i = 0; i < sizeof(resolutions) / sizeof(resolutions[0]); i++)
|
|
|
|
{
|
|
|
|
memset(&s, 0, sizeof(DDSURFACEDESC));
|
2020-10-15 01:17:40 +02:00
|
|
|
|
2020-10-13 09:20:52 +02:00
|
|
|
s.dwSize = sizeof(DDSURFACEDESC);
|
|
|
|
s.dwFlags = DDSD_HEIGHT | DDSD_REFRESHRATE | DDSD_WIDTH | DDSD_PIXELFORMAT;
|
|
|
|
s.dwHeight = resolutions[i].cy;
|
|
|
|
s.dwWidth = resolutions[i].cx;
|
|
|
|
s.dwRefreshRate = 60;
|
|
|
|
s.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
|
|
|
|
s.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
|
|
|
|
s.ddpfPixelFormat.dwRGBBitCount = 8;
|
|
|
|
|
|
|
|
if (lpEnumModesCallback(&s, lpContext) == DDENUMRET_CANCEL)
|
|
|
|
{
|
2020-10-13 21:58:04 +02:00
|
|
|
dprintf(" DDENUMRET_CANCEL returned, stopping\n");
|
2020-10-13 09:20:52 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
s.ddpfPixelFormat.dwFlags = DDPF_RGB;
|
|
|
|
s.ddpfPixelFormat.dwRGBBitCount = 16;
|
|
|
|
s.ddpfPixelFormat.dwRBitMask = 0xF800;
|
|
|
|
s.ddpfPixelFormat.dwGBitMask = 0x07E0;
|
|
|
|
s.ddpfPixelFormat.dwBBitMask = 0x001F;
|
|
|
|
|
|
|
|
if (lpEnumModesCallback(&s, lpContext) == DDENUMRET_CANCEL)
|
|
|
|
{
|
2020-10-13 21:58:04 +02:00
|
|
|
dprintf(" DDENUMRET_CANCEL returned, stopping\n");
|
2020-10-13 09:20:52 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT dd_GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDEmulCaps)
|
|
|
|
{
|
2020-10-14 11:08:37 +02:00
|
|
|
if(lpDDDriverCaps)
|
2020-10-13 09:20:52 +02:00
|
|
|
{
|
|
|
|
lpDDDriverCaps->dwSize = sizeof(DDCAPS);
|
|
|
|
lpDDDriverCaps->dwCaps = DDCAPS_BLT | DDCAPS_PALETTE | DDCAPS_BLTCOLORFILL | DDCAPS_BLTSTRETCH | DDCAPS_CANCLIP;
|
|
|
|
lpDDDriverCaps->dwCKeyCaps = 0;
|
|
|
|
lpDDDriverCaps->dwPalCaps = DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE;
|
|
|
|
lpDDDriverCaps->dwVidMemTotal = 16777216;
|
|
|
|
lpDDDriverCaps->dwVidMemFree = 16777216;
|
|
|
|
lpDDDriverCaps->dwMaxVisibleOverlays = 0;
|
|
|
|
lpDDDriverCaps->dwCurrVisibleOverlays = 0;
|
|
|
|
lpDDDriverCaps->dwNumFourCCCodes = 0;
|
|
|
|
lpDDDriverCaps->dwAlignBoundarySrc = 0;
|
|
|
|
lpDDDriverCaps->dwAlignSizeSrc = 0;
|
|
|
|
lpDDDriverCaps->dwAlignBoundaryDest = 0;
|
|
|
|
lpDDDriverCaps->dwAlignSizeDest = 0;
|
|
|
|
lpDDDriverCaps->ddsCaps.dwCaps = DDSCAPS_FLIP;
|
|
|
|
}
|
|
|
|
|
2020-10-14 11:08:37 +02:00
|
|
|
if(lpDDEmulCaps)
|
2020-10-13 09:20:52 +02:00
|
|
|
{
|
2020-10-14 11:08:37 +02:00
|
|
|
lpDDEmulCaps->dwSize = 0;
|
2020-10-13 09:20:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT dd_SetDisplayMode(DWORD width, DWORD height, DWORD bpp)
|
|
|
|
{
|
|
|
|
if (bpp != 8 && bpp != 16)
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const int IDR_MYMENU = 93;
|
|
|
|
|
|
|
|
const HANDLE hbicon = LoadImage(GetModuleHandle(0), MAKEINTRESOURCE(IDR_MYMENU), IMAGE_ICON, real_GetSystemMetrics(SM_CXICON), real_GetSystemMetrics(SM_CYICON), 0);
|
|
|
|
if (hbicon)
|
|
|
|
real_SendMessageA(g_ddraw->hwnd, WM_SETICON, ICON_BIG, (LPARAM)hbicon);
|
|
|
|
|
|
|
|
const HANDLE hsicon = LoadImage(GetModuleHandle(0), MAKEINTRESOURCE(IDR_MYMENU), IMAGE_ICON, real_GetSystemMetrics(SM_CXSMICON), real_GetSystemMetrics(SM_CYSMICON), 0);
|
|
|
|
if (hsicon)
|
|
|
|
real_SendMessageA(g_ddraw->hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hsicon);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_ddraw->altenter)
|
|
|
|
{
|
|
|
|
g_ddraw->altenter = FALSE;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
//temporary fix: center window for games that keep changing their resolution
|
|
|
|
if (g_ddraw->width &&
|
|
|
|
(g_ddraw->width != width || g_ddraw->height != height) &&
|
|
|
|
(width > g_config.window_rect.right || height > g_config.window_rect.bottom))
|
|
|
|
{
|
|
|
|
g_config.window_rect.left = -32000;
|
|
|
|
g_config.window_rect.top = -32000;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_ddraw->width = width;
|
|
|
|
g_ddraw->height = height;
|
|
|
|
g_ddraw->bpp = bpp;
|
|
|
|
|
|
|
|
g_ddraw->cursor.x = width / 2;
|
|
|
|
g_ddraw->cursor.y = height / 2;
|
|
|
|
|
|
|
|
BOOL border = g_ddraw->border;
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
if (g_ddraw->windowed) //windowed-fullscreen aka borderless
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
|
|
|
// prevent OpenGL from going automatically into fullscreen exclusive mode
|
|
|
|
if (g_ddraw->renderer == ogl_render_main)
|
|
|
|
g_ddraw->render.height++;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
BOOL lock_mouse = g_ddraw->locked || g_ddraw->fullscreen;
|
|
|
|
mouse_unlock();
|
|
|
|
|
|
|
|
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 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL maintas = g_ddraw->maintas;
|
|
|
|
|
|
|
|
if (!g_ddraw->windowed)
|
|
|
|
{
|
|
|
|
// Making sure the chosen resolution is valid
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
// fail... compare resolutions
|
|
|
|
if (g_ddraw->render.width > g_ddraw->mode.dmPelsWidth || g_ddraw->render.height > g_ddraw->mode.dmPelsHeight)
|
|
|
|
{
|
|
|
|
// chosen game resolution higher than current resolution, use windowed mode for this case
|
|
|
|
g_ddraw->windowed = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Try 2x scaling
|
|
|
|
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;
|
|
|
|
|
|
|
|
if ((g_ddraw->render.width > g_ddraw->mode.dmPelsWidth || g_ddraw->render.height > g_ddraw->mode.dmPelsHeight) ||
|
|
|
|
ChangeDisplaySettings(&g_ddraw->render.mode, CDS_TEST) != DISP_CHANGE_SUCCESSFUL)
|
|
|
|
{
|
|
|
|
SIZE res = {0};
|
|
|
|
|
|
|
|
//try to get a resolution with the same aspect ratio as the requested resolution
|
|
|
|
BOOL found_res = util_get_lowest_resolution(
|
|
|
|
(float)old_width / old_height,
|
|
|
|
&res,
|
|
|
|
old_width + 1, //don't return the original resolution since we tested that one already
|
|
|
|
old_height + 1,
|
|
|
|
g_ddraw->mode.dmPelsWidth,
|
|
|
|
g_ddraw->mode.dmPelsHeight);
|
|
|
|
|
|
|
|
if (!found_res)
|
|
|
|
{
|
|
|
|
//try to get a resolution with the same aspect ratio as the current display mode
|
|
|
|
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);
|
|
|
|
|
|
|
|
if (found_res)
|
|
|
|
maintas = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
if (!found_res || ChangeDisplaySettings(&g_ddraw->render.mode, CDS_TEST) != DISP_CHANGE_SUCCESSFUL)
|
|
|
|
{
|
|
|
|
// try current display settings
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
// everything failed, use windowed mode instead
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
maintas = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-13 11:29:52 +02:00
|
|
|
if (g_ddraw->nonexclusive && !g_ddraw->windowed && g_ddraw->renderer == ogl_render_main)
|
|
|
|
{
|
2020-10-13 09:20:52 +02:00
|
|
|
g_ddraw->render.height++;
|
2020-10-13 11:29:52 +02:00
|
|
|
}
|
2020-10-13 09:20:52 +02:00
|
|
|
|
|
|
|
if (!g_ddraw->handlemouse)
|
2020-10-13 11:29:52 +02:00
|
|
|
{
|
2020-10-13 09:20:52 +02:00
|
|
|
g_ddraw->boxing = maintas = FALSE;
|
2020-10-13 11:29:52 +02:00
|
|
|
}
|
|
|
|
|
2020-10-13 09:20:52 +02:00
|
|
|
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;
|
|
|
|
|
|
|
|
if (g_ddraw->boxing)
|
|
|
|
{
|
|
|
|
g_ddraw->render.viewport.width = g_ddraw->width;
|
|
|
|
g_ddraw->render.viewport.height = g_ddraw->height;
|
|
|
|
|
|
|
|
int i;
|
|
|
|
for (i = 20; i-- > 1;)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
else if (maintas)
|
|
|
|
{
|
|
|
|
g_ddraw->render.viewport.width = g_ddraw->render.width;
|
|
|
|
g_ddraw->render.viewport.height = ((float)g_ddraw->height / g_ddraw->width) * g_ddraw->render.viewport.width;
|
|
|
|
|
|
|
|
if (g_ddraw->render.viewport.height > g_ddraw->render.height)
|
|
|
|
{
|
|
|
|
g_ddraw->render.viewport.width =
|
|
|
|
((float)g_ddraw->render.viewport.width / g_ddraw->render.viewport.height) * g_ddraw->render.height;
|
|
|
|
|
|
|
|
g_ddraw->render.viewport.height = g_ddraw->render.height;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
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 (g_ddraw->windowed)
|
|
|
|
{
|
|
|
|
MSG msg; // workaround for "Not Responding" window problem in cnc games
|
|
|
|
PeekMessage(&msg, g_ddraw->hwnd, 0, 0, PM_NOREMOVE);
|
|
|
|
|
|
|
|
if (!border)
|
|
|
|
{
|
|
|
|
real_SetWindowLongA(g_ddraw->hwnd, GWL_STYLE, GetWindowLong(g_ddraw->hwnd, GWL_STYLE) & ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
real_SetWindowLongA(g_ddraw->hwnd, GWL_STYLE, (GetWindowLong(g_ddraw->hwnd, GWL_STYLE) | WS_OVERLAPPEDWINDOW) & ~WS_MAXIMIZEBOX);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_ddraw->wine)
|
|
|
|
real_SetWindowLongA(g_ddraw->hwnd, GWL_STYLE, (GetWindowLong(g_ddraw->hwnd, GWL_STYLE) | WS_MINIMIZEBOX) & ~(WS_MAXIMIZEBOX | WS_THICKFRAME));
|
|
|
|
|
|
|
|
/* 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);
|
2020-10-13 11:29:52 +02:00
|
|
|
|
2020-10-13 09:20:52 +02:00
|
|
|
RECT dst = { x, y, g_ddraw->render.width + x, g_ddraw->render.height + y };
|
2020-10-13 11:29:52 +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))
|
|
|
|
{
|
|
|
|
real_SetWindowLongA(g_ddraw->hwnd, GWL_STYLE, style & ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU));
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
return dd_SetDisplayMode(width, height, bpp);
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
real_SetWindowPos(g_ddraw->hwnd, HWND_TOPMOST, 0, 0, g_ddraw->render.width, g_ddraw->render.height, SWP_SHOWWINDOW);
|
|
|
|
g_ddraw->last_set_window_pos_tick = timeGetTime();
|
|
|
|
|
|
|
|
mouse_lock();
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_ddraw->sierrahack)
|
|
|
|
{
|
|
|
|
PostMessageA(g_ddraw->hwnd, WM_MOVE, 0, MAKELPARAM(-32000, -32000));
|
|
|
|
PostMessageA(g_ddraw->hwnd, WM_DISPLAYCHANGE, g_ddraw->bpp, MAKELPARAM(g_ddraw->width, g_ddraw->height));
|
|
|
|
}
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT dd_SetCooperativeLevel(HWND hwnd, DWORD dwFlags)
|
|
|
|
{
|
|
|
|
PIXELFORMATDESCRIPTOR pfd;
|
|
|
|
|
|
|
|
/* Red Alert for some weird reason does this on Windows XP */
|
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();
|
|
|
|
|
|
|
|
g_ddraw->wndproc = (LRESULT(CALLBACK *)(HWND, UINT, WPARAM, LPARAM))GetWindowLong(hwnd, GWL_WNDPROC);
|
|
|
|
|
|
|
|
real_SetWindowLongA(g_ddraw->hwnd, GWL_WNDPROC, (LONG)fake_WndProc);
|
|
|
|
|
|
|
|
if (!g_ddraw->render.hdc)
|
|
|
|
{
|
|
|
|
g_ddraw->render.hdc = GetDC(g_ddraw->hwnd);
|
|
|
|
|
|
|
|
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
|
|
|
|
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
|
|
|
pfd.nVersion = 1;
|
|
|
|
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER | (g_ddraw->renderer == ogl_render_main ? PFD_SUPPORT_OPENGL : 0);
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_ddraw->handlemouse && g_ddraw->windowed)
|
|
|
|
{
|
|
|
|
while (real_ShowCursor(FALSE) > 0); //workaround for direct input games
|
|
|
|
while (real_ShowCursor(TRUE) < 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
real_SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
if (g_ddraw->vhack && !g_ddraw->isredalert && !g_ddraw->iscnc1)
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT dd_WaitForVerticalBlank(DWORD dwFlags, HANDLE h)
|
|
|
|
{
|
|
|
|
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_ddraw->fps_limiter.htimer)
|
|
|
|
{
|
|
|
|
CancelWaitableTimer(g_ddraw->fps_limiter.htimer);
|
|
|
|
CloseHandle(g_ddraw->fps_limiter.htimer);
|
|
|
|
g_ddraw->fps_limiter.htimer = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
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(void* lpDDCaps, LPDWORD lpdwTotal, LPDWORD lpdwFree)
|
|
|
|
{
|
|
|
|
*lpdwTotal = 16777216;
|
|
|
|
*lpdwFree = 16777216;
|
|
|
|
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)
|
|
|
|
{
|
2020-10-15 07:22:48 +02:00
|
|
|
/* Passthrough required for WIN XP - FIXME: check the calling module before passing the call! */
|
2020-10-15 05:13:37 +02:00
|
|
|
if (iid && IsEqualGUID(&IID_IDirectDraw, iid) && g_ddraw->DirectDrawCreate)
|
|
|
|
{
|
|
|
|
return g_ddraw->DirectDrawCreate(lpGuid, (LPDIRECTDRAW*)lplpDD, pUnkOuter);
|
|
|
|
}
|
|
|
|
|
|
|
|
return DDERR_DIRECTDRAWALREADYCREATED;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_ddraw = (cnc_ddraw*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(cnc_ddraw));
|
|
|
|
|
|
|
|
IDirectDrawImpl* dd = (IDirectDrawImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawImpl));
|
|
|
|
|
|
|
|
if (iid && IsEqualGUID(&IID_IDirectDraw, iid))
|
|
|
|
{
|
|
|
|
dprintf(" GUID = %08X (IID_IDirectDraw), ddraw = %p\n", ((GUID*)iid)->Data1, dd);
|
|
|
|
|
|
|
|
dd->lpVtbl = &g_dd_vtbl1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dprintf(" GUID = %08X (IID_IDirectDrawX), ddraw = %p\n", iid ? ((GUID*)iid)->Data1 : NULL, dd);
|
|
|
|
|
|
|
|
dd->lpVtbl = &g_dd_vtblx;
|
|
|
|
}
|
|
|
|
|
|
|
|
IDirectDraw_AddRef(dd);
|
|
|
|
|
|
|
|
*lplpDD = (LPVOID)dd;
|
|
|
|
|
|
|
|
if (!g_ddraw->real_dll)
|
|
|
|
{
|
|
|
|
g_ddraw->real_dll = LoadLibrary("system32\\ddraw.dll");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_ddraw->real_dll && !g_ddraw->DirectDrawCreate)
|
|
|
|
{
|
|
|
|
g_ddraw->DirectDrawCreate =
|
|
|
|
(HRESULT(WINAPI*)(GUID FAR*, LPDIRECTDRAW FAR*, IUnknown FAR*))GetProcAddress(g_ddraw->real_dll, "DirectDrawCreate");
|
|
|
|
|
|
|
|
if (g_ddraw->DirectDrawCreate == DirectDrawCreate)
|
|
|
|
g_ddraw->DirectDrawCreate = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
InitializeCriticalSection(&g_ddraw->cs);
|
|
|
|
|
|
|
|
g_ddraw->render.sem = CreateSemaphore(NULL, 0, 1, NULL);
|
|
|
|
g_ddraw->wine = GetProcAddress(GetModuleHandleA("ntdll.dll"), "wine_get_version") != 0;
|
|
|
|
|
|
|
|
cfg_load();
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|