implement EnumDisplayModes and BltFast - Fixes DDBLT_COLORFILL with NULL rect - support resolution changes during runtime (AoE2)

This commit is contained in:
FunkyFr3sh 2018-10-26 05:27:10 +02:00
parent 25627134e7
commit cbc66c3bc2
5 changed files with 132 additions and 58 deletions

View file

@ -102,6 +102,7 @@ typedef struct IDirectDrawImpl
BOOL maintas;
BOOL fakecursorpos;
BOOL noactivateapp;
BOOL hidemouse;
char shader[MAX_PATH];
BOOL wine;
int sleep;

View file

@ -145,9 +145,41 @@ HRESULT __stdcall ddraw_DuplicateSurface(IDirectDrawImpl *This, LPDIRECTDRAWSURF
return DD_OK;
}
HRESULT __stdcall ddraw_EnumDisplayModes(IDirectDrawImpl *This, DWORD a, LPDDSURFACEDESC b, LPVOID c, LPDDENUMMODESCALLBACK d)
HRESULT __stdcall ddraw_EnumDisplayModes(IDirectDrawImpl *This, DWORD dwFlags, LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext, LPDDENUMMODESCALLBACK lpEnumModesCallback)
{
printf("DirectDraw::EnumDisplayModes(This=%p, ...)\n", This);
DWORD i = 0;
DEVMODE m;
DDSURFACEDESC s;
printf("DirectDraw::EnumDisplayModes(This=%p, dwFlags=%d, lpDDSurfaceDesc=%p, lpContext=%p, lpEnumModesCallback=%p)\n", This, (unsigned int)dwFlags, lpDDSurfaceDesc, lpContext, lpEnumModesCallback);
if (lpDDSurfaceDesc != NULL)
{
return DDERR_UNSUPPORTED;
}
while (EnumDisplaySettings(NULL, i, &m))
{
printf(" %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));
s.dwSize = sizeof(DDSURFACEDESC);
s.dwFlags = DDSD_HEIGHT | DDSD_REFRESHRATE | DDSD_WIDTH | DDSD_PIXELFORMAT;
s.dwHeight = m.dmPelsHeight;
s.dwWidth = m.dmPelsWidth;
s.dwRefreshRate = m.dmDisplayFrequency;
s.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
s.ddpfPixelFormat.dwFlags = m.dmBitsPerPel == 8 ? DDPF_PALETTEINDEXED8 : DDPF_RGB;
s.ddpfPixelFormat.dwRGBBitCount = m.dmBitsPerPel;
if (lpEnumModesCallback(&s, lpContext) == DDENUMRET_CANCEL)
{
printf(" DDENUMRET_CANCEL returned, stopping\n");
break;
}
i++;
}
return DD_OK;
}
@ -283,6 +315,8 @@ HRESULT __stdcall ddraw_SetDisplayMode(IDirectDrawImpl *This, DWORD width, DWORD
{
printf("DirectDraw::SetDisplayMode(This=%p, width=%d, height=%d, bpp=%d)\n", This, (unsigned int)width, (unsigned int)height, (unsigned int)bpp);
if (!This->mode.dmPelsWidth)
{
This->mode.dmSize = sizeof(DEVMODE);
This->mode.dmDriverExtra = 0;
@ -291,6 +325,12 @@ HRESULT __stdcall ddraw_SetDisplayMode(IDirectDrawImpl *This, DWORD width, DWORD
/* not expected */
return DDERR_UNSUPPORTED;
}
}
else //resolution changed twice during runtime, disable stretching for these cases for now
{
This->render.width = 0;
This->render.height = 0;
}
This->width = width;
This->height = height;

View file

@ -134,11 +134,17 @@ BOOL WINAPI fake_ClipCursor(const RECT *lpRect)
int WINAPI fake_ShowCursor(BOOL bShow)
{
if (ddraw && !ddraw->hidemouse)
return ShowCursor(bShow);
return TRUE;
}
HCURSOR WINAPI fake_SetCursor(HCURSOR hCursor)
{
if (ddraw && !ddraw->hidemouse)
return SetCursor(hCursor);
return NULL;
}
@ -211,7 +217,9 @@ void mouse_lock()
if (ddraw->devmode)
{
if (ddraw->hidemouse)
while(ShowCursor(FALSE) > 0);
return;
}
@ -255,7 +263,9 @@ void mouse_lock()
SetCapture(ddraw->hWnd);
ClipCursor(&rc);
if (ddraw->hidemouse)
while(ShowCursor(FALSE) > 0);
ddraw->locked = TRUE;
}
}
@ -266,7 +276,9 @@ void mouse_unlock()
if (ddraw->devmode)
{
if (ddraw->hidemouse)
while(ShowCursor(TRUE) < 0);
return;
}
@ -289,8 +301,11 @@ void mouse_unlock()
ClientToScreen(ddraw->hWnd, &pt2);
SetRect(&rc, pt.x, pt.y, pt2.x, pt2.y);
if (ddraw->hidemouse)
{
while (ShowCursor(TRUE) < 0);
SetCursor(LoadCursor(NULL, IDC_ARROW));
}
ClipCursor(NULL);
ReleaseCapture();

View file

@ -41,6 +41,7 @@ void Settings_Load()
ddraw->fakecursorpos = GetBool("fakecursorpos", TRUE);
ddraw->noactivateapp = GetBool("noactivateapp", FALSE);
ddraw->vhack = GetBool("vhack", FALSE);
ddraw->hidemouse = GetBool("hidemouse", TRUE);
ddraw->sleep = GetInt("sleep", 0);
ddraw->render.maxfps = GetInt("maxfps", 125);
@ -184,6 +185,8 @@ static void CreateSettingsIni()
"shader=\n"
"; Sleep for X ms after drawing each frame (Slows down scrollrate on C&C95 / Prevents visual glitches on Carmageddon)\n"
"sleep=0\n"
"; Hide/Show the mouse cursor on lock/unlock (Ctrl+Tab)\n"
"hidemouse=true\n"
"\n"
"[CARMA95]\n"
"fakecursorpos=false\n"
@ -193,6 +196,11 @@ static void CreateSettingsIni()
"[C&C95]\n"
"sleep=10\n"
"\n"
"[EMPIRES2]\n"
"renderer=gdi\n"
"hidemouse=false\n"
"border=false\n"
"\n"
, fh);
fclose(fh);

View file

@ -104,42 +104,24 @@ HRESULT __stdcall ddraw_surface_Blt(IDirectDrawSurfaceImpl *This, LPRECT lpDestR
if (This->surface && (dwFlags & DDBLT_COLORFILL))
{
int dst_w = lpDestRect->right - lpDestRect->left;
int dst_h = lpDestRect->bottom - lpDestRect->top;
int dst_w = lpDestRect ? lpDestRect->right - lpDestRect->left : This->width;
int dst_h = lpDestRect ? lpDestRect->bottom - lpDestRect->top : This->height;
int dst_x = lpDestRect ? lpDestRect->left : 0;
int dst_y = lpDestRect ? lpDestRect->top : 0;
int y, x;
for (y = 0; y < dst_h; y++)
{
int ydst = This->width * (y + lpDestRect->top);
int ydst = This->width * (y + dst_y);
for (x = 0; x < dst_w; x++)
{
((unsigned char *)This->surface)[x + lpDestRect->left + ydst] = lpDDBltFx->dwFillColor;
((unsigned char *)This->surface)[x + dst_x + ydst] = lpDDBltFx->dwFillColor;
}
}
}
if (Source)
{
//BitBlt(This->hDC, lpDestRect->left, lpDestRect->top, lpDestRect->right, lpDestRect->bottom,
// Source->hDC, lpSrcRect->left, lpSrcRect->top, SRCCOPY);
int dst_w = lpDestRect->right - lpDestRect->left;
int dst_h = lpDestRect->bottom - lpDestRect->top;
int src_w = lpSrcRect->right - lpSrcRect->left;
int src_h = lpSrcRect->bottom - lpSrcRect->top;
if (dst_w != src_w || dst_h != src_h)
{
StretchBlt(This->hDC, lpDestRect->left, lpDestRect->top, lpDestRect->right, lpDestRect->bottom,
Source->hDC, lpSrcRect->left, lpSrcRect->top, lpSrcRect->right, lpSrcRect->bottom, SRCCOPY);
}
else if (dst_w == This->width && dst_h == This->height &&
src_w == Source->width && src_h == Source->height)
{
memcpy(This->surface, Source->surface, This->width * This->height * This->lXPitch);
}
else
{
int dx = 0, dy = 0;
if (lpDestRect)
@ -166,8 +148,6 @@ HRESULT __stdcall ddraw_surface_Blt(IDirectDrawSurfaceImpl *This, LPRECT lpDestR
}
}
}
if(This->caps & DDSCAPS_PRIMARYSURFACE && !(This->flags & DDSD_BACKBUFFERCOUNT) && ddraw->render.run)
{
InterlockedExchange(&ddraw->render.surfaceUpdated, TRUE);
@ -195,9 +175,38 @@ HRESULT __stdcall ddraw_surface_BltBatch(IDirectDrawSurfaceImpl *This, LPDDBLTBA
return DD_OK;
}
HRESULT __stdcall ddraw_surface_BltFast(IDirectDrawSurfaceImpl *This, DWORD a, DWORD b, LPDIRECTDRAWSURFACE c, LPRECT d, DWORD e)
HRESULT __stdcall ddraw_surface_BltFast(IDirectDrawSurfaceImpl *This, DWORD x, DWORD y, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DWORD flags)
{
printf("IDirectDrawSurface::BltFast(This=%p, ...)\n", This);
IDirectDrawSurfaceImpl *Source = (IDirectDrawSurfaceImpl *)lpDDSrcSurface;
if (Source)
{
int x0 = 0, y0 = 0, x1 = Source->width, y1 = Source->height;
if (lpSrcRect)
{
x0 = max(x0, lpSrcRect->left);
x1 = min(x1, lpSrcRect->right);
y0 = max(y0, lpSrcRect->top);
y1 = min(y1, lpSrcRect->bottom);
}
unsigned char* to = (unsigned char *)This->surface + y*This->width + x;
unsigned char* from = (unsigned char *)Source->surface + y0*Source->width + x0;
int s = x1 - x0;
int y;
for (y = y0; y < y1; ++y, to += This->width, from += Source->width)
{
memcpy(to, from, s);
}
}
if (This->caps & DDSCAPS_PRIMARYSURFACE && !(This->flags & DDSD_BACKBUFFERCOUNT) && ddraw->render.run)
{
InterlockedExchange(&ddraw->render.surfaceUpdated, TRUE);
ReleaseSemaphore(ddraw->render.sem, 1, NULL);
}
return DD_OK;
}
@ -317,6 +326,7 @@ HRESULT __stdcall ddraw_surface_GetColorKey(IDirectDrawSurfaceImpl *This, DWORD
HRESULT __stdcall ddraw_surface_GetDC(IDirectDrawSurfaceImpl *This, HDC FAR *a)
{
printf("IDirectDrawSurface::GetDC(This=%p, ...)\n", This);
*a = This->hDC;
return DD_OK;
}