From 0b52adcc2b3e9a2f5fdb73f1b33f9bee11d2b8f3 Mon Sep 17 00:00:00 2001 From: gho tik Date: Mon, 16 Sep 2013 12:38:17 -0400 Subject: [PATCH] v2_02_34_src Former-commit-id: d8d2c00dadd24ffc53cc6d189f0edd44f1abd949 --- Include/dxwnd.h | 4 +- build/{dxwnd.ini => dxwnd.2.ini} | 52 +- build/dxwnd.dll | 4 +- build/dxwnd.exe | 2 +- build/readme-relnotes.txt | 13 + dll/ddraw.cpp | 922 ++++++++++++++++--------------- dll/dxhelper.cpp | 4 +- dll/dxhook.cpp | 68 ++- dll/dxwcore.cpp | 64 ++- dll/dxwcore.hpp | 2 + dll/dxwnd.cpp | 4 +- dll/dxwnd.vs2008.suo | Bin 207872 -> 207872 bytes dll/hd3d.cpp | 16 +- dll/kernel32.cpp | 145 ++++- dll/syslibs.h | 13 + dll/user32.cpp | 56 +- host/Resource.h | 4 +- host/TabCompat.cpp | 1 + host/TargetDlg.cpp | 3 +- host/TargetDlg.h | 1 + host/dxwndhost.aps | Bin 163380 -> 163524 bytes host/dxwndhost.rc | 10 +- host/dxwndhost.vs2008.suo | Bin 303104 -> 308736 bytes host/dxwndhostView.cpp | 2 + 24 files changed, 867 insertions(+), 523 deletions(-) rename build/{dxwnd.ini => dxwnd.2.ini} (95%) diff --git a/Include/dxwnd.h b/Include/dxwnd.h index 08d7196..5efc826 100644 --- a/Include/dxwnd.h +++ b/Include/dxwnd.h @@ -99,6 +99,7 @@ #define FONTBYPASS 0x00020000 // bypass font unsupported API #define YUV2RGB 0x00040000 // Simulate YUV to RGB color conversion #define RGB2YUV 0x00080000 // Simulate RGB to YUV color conversion +#define BUFFEREDIOFIX 0x00100000 // fix buffered IO incompatibilities between pre-Win98 and post-WinNT // logging Tflags DWORD: #define OUTTRACE 0x00000001 // enables tracing to dxwnd.log in general @@ -203,6 +204,7 @@ extern WNDPROC WhndGetWindowProc(HWND ); typedef enum { DXW_SET_COORDINATES = 0, + DXW_DESKTOP_CENTER, DXW_DESKTOP_WORKAREA, - DXW_DESKTOP_CENTER + DXW_DESKTOP_FULL } Coordinates_Types; diff --git a/build/dxwnd.ini b/build/dxwnd.2.ini similarity index 95% rename from build/dxwnd.ini rename to build/dxwnd.2.ini index 4c98059..2ff451e 100644 --- a/build/dxwnd.ini +++ b/build/dxwnd.2.ini @@ -331,7 +331,7 @@ flag14=402653218 flagg14=134217728 flagh14=1044 flagi14=0 -tflag14=2 +tflag14=259 initx14=0 inity14=0 minx14=0 @@ -1080,8 +1080,54 @@ sizx46=800 sizy46=600 maxfps46=0 initts46=0 +title47=age3.exe +path47=D:\Games\Age of Empires III\age3.exe +module47= +opengllib47= +ver47=0 +coord47=0 +flag47=-394125278 +flagg47=134217728 +flagh47=20 +flagi47=0 +tflag47=64 +initx47=0 +inity47=0 +minx47=0 +miny47=0 +maxx47=0 +maxy47=0 +posx47=50 +posy47=50 +sizx47=800 +sizy47=600 +maxfps47=0 +initts47=0 +title48=road.exe +path48=D:\Games\Vangers\road.exe +module48= +opengllib48= +ver48=1 +coord48=0 +flag48=134217762 +flagg48=134217728 +flagh48=20 +flagi48=0 +tflag48=323 +initx48=0 +inity48=0 +minx48=0 +miny48=0 +maxx48=0 +maxy48=0 +posx48=50 +posy48=50 +sizx48=800 +sizy48=600 +maxfps48=0 +initts48=0 [window] -posx=908 -posy=205 +posx=1435 +posy=210 sizx=320 sizy=420 diff --git a/build/dxwnd.dll b/build/dxwnd.dll index bbeb1ab..c3b90e9 100644 --- a/build/dxwnd.dll +++ b/build/dxwnd.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:12040e25e1b8e234164832361e51d6470456a3050a15ae43f29a78b3636d0f70 -size 404992 +oid sha256:996722440a942e7241f3ee9fc60589c3dee97d84b8487c8c319ebf8962da3105 +size 406016 diff --git a/build/dxwnd.exe b/build/dxwnd.exe index a5f5acc..29a59a1 100644 --- a/build/dxwnd.exe +++ b/build/dxwnd.exe @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1fbd3ed5ac2b5db41671b9b4f80688c59abc1d894b408912f5c19c06c4a18063 +oid sha256:0ccd2bbf780cc35a20ef2cd852c3b1a5934717b1d477906c67b3d3a9ad156e19 size 524800 diff --git a/build/readme-relnotes.txt b/build/readme-relnotes.txt index 17ea5ca..ae2bc15 100644 --- a/build/readme-relnotes.txt +++ b/build/readme-relnotes.txt @@ -241,6 +241,19 @@ GUI added controls for new core features defaulted ddraw emulation mode to surface emulation +v2.02.34 +CORE: +Much better surface description in log +Completely revised CreateSurface hook: emulated and direct code are merged as much as possible, and reference counter are kept accurate. Now most games can work both in emulated and direct mode. +Fixed surface capabilities for "Vangers", "The Sims" (now working in emulated mode again) +Updated "Fixed aspect ratio" option: now uses the x,y size declared in the configuration instead of the fixed 800 x 600 standard one. +Added virtual fullscreen "Desktop" mode. +Completely revised the Peek/GetMessage handling: now it uses the standard SetWindowHook API instead of the address redirection, making the handling more reliable and accurate: now "Age of Empires III" works at last! +GUI: +Added virtual fullscreen "Desktop" mode. +Added "Fix buffered IO after Win98" flag: this is meant to fix an incompatibility in the ReadFile kernel32 API that must read from block boundaries, where a block was smaller up to Win98 and bigger after it. +As a result, games like "Dylan Dog Horror Luna Park" show IO errors while reading data from the CD. Unfortunately, this is not the only problem of this game, so Dylan Dog fans will have to wait further. +Maybe some other programs suffer of this problem, and I will strongly appreciate if anyone finds some. diff --git a/dll/ddraw.cpp b/dll/ddraw.cpp index ab8e390..d28f439 100644 --- a/dll/ddraw.cpp +++ b/dll/ddraw.cpp @@ -231,7 +231,6 @@ void *EmuScreenBuffer = NULL; // to implement pitch bug fix DWORD rPitch = 0; LPVOID rSurface = NULL; static char *SetPixFmt(LPDDSURFACEDESC2); -int FlipChainLength=0; FARPROC Remap_ddraw_ProcAddress(LPCSTR proc, HMODULE hModule) { @@ -263,6 +262,18 @@ FARPROC Remap_ddraw_ProcAddress(LPCSTR proc, HMODULE hModule) // auxiliary (static) functions /* ------------------------------------------------------------------------------ */ +static void RefProbe(INTERFACE *obj, char *op, int line) +{ + obj->AddRef(); + OutTrace("### COM obj=%x op=%s refcount=%d at %d ###\n", obj, op, (*pReleaseS)((LPDIRECTDRAWSURFACE)obj), line); +} + +#ifdef REFPROVE_TEST +#define REFPROBE(obj, op) RefProbe((INTERFACE *)(obj), op, __LINE__) +#else +#define REFPROBE(obj, op) +#endif + static char *sFourCC(DWORD fcc) { static char sRet[5]; @@ -277,6 +288,7 @@ static char *sFourCC(DWORD fcc) *t = 0; return sRet; } + static void LogSurfaceAttributes(LPDDSURFACEDESC lpddsd, char *label, int line) { OutTraceD("SurfaceDesc: %s Flags=%x(%s)", @@ -285,6 +297,7 @@ static void LogSurfaceAttributes(LPDDSURFACEDESC lpddsd, char *label, int line) if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) OutTraceD(" BackBufferCount=%d", lpddsd->dwBackBufferCount); if (lpddsd->dwFlags & DDSD_WIDTH) OutTraceD(" Width=%d", lpddsd->dwWidth); if (lpddsd->dwFlags & DDSD_HEIGHT) OutTraceD(" Height=%d", lpddsd->dwHeight); + if (lpddsd->dwFlags & DDSD_PITCH) OutTraceD(" Pitch=%d", lpddsd->lPitch); if (lpddsd->dwFlags & DDSD_CAPS) { OutTraceD(" Caps=%x(%s)", lpddsd->ddsCaps.dwCaps, ExplainDDSCaps(lpddsd->ddsCaps.dwCaps)); if(lpddsd->dwSize==sizeof(DDSURFACEDESC2)){ @@ -299,13 +312,34 @@ static void LogSurfaceAttributes(LPDDSURFACEDESC lpddsd, char *label, int line) if (lpddsd->dwFlags & DDSD_CKSRCOVERLAY ) OutTraceD(" CKSrcOverlay=(%x,%x)", lpddsd->ddckCKSrcOverlay.dwColorSpaceLowValue, lpddsd->ddckCKSrcOverlay.dwColorSpaceHighValue); if (lpddsd->dwFlags & DDSD_PIXELFORMAT ){ DWORD flags=lpddsd->ddpfPixelFormat.dwFlags; - OutTraceD(" PixelFormat flags=%x(%s)", flags, ExplainPixelFormatFlags(flags)); - if (flags & DDPF_RGB) OutTraceD(" BPP=%d RGBA=(%x,%x,%x,%x)", - lpddsd->ddpfPixelFormat.dwRGBBitCount, + OutTraceD(" PixelFormat flags=%x(%s) BPP=%d", flags, ExplainPixelFormatFlags(flags), lpddsd->ddpfPixelFormat.dwRGBBitCount); + if (flags & DDPF_RGB) OutTraceD(" RGBA=(%x,%x,%x,%x)", lpddsd->ddpfPixelFormat.dwRBitMask, lpddsd->ddpfPixelFormat.dwGBitMask, lpddsd->ddpfPixelFormat.dwBBitMask, lpddsd->ddpfPixelFormat.dwRGBAlphaBitMask); + if (flags & DDPF_YUV) OutTraceD(" YUVA=(%x,%x,%x,%x)", + lpddsd->ddpfPixelFormat.dwYBitMask, + lpddsd->ddpfPixelFormat.dwUBitMask, + lpddsd->ddpfPixelFormat.dwVBitMask, + lpddsd->ddpfPixelFormat.dwYUVAlphaBitMask); + if (flags & DDPF_ZBUFFER) OutTraceD(" SdZSbL=(%x,%x,%x,%x)", + lpddsd->ddpfPixelFormat.dwStencilBitDepth, + lpddsd->ddpfPixelFormat.dwZBitMask, + lpddsd->ddpfPixelFormat.dwStencilBitMask, + lpddsd->ddpfPixelFormat.dwLuminanceAlphaBitMask); + if (flags & DDPF_ALPHA) OutTraceD(" LBdBlZ=(%x,%x,%x,%x)", + lpddsd->ddpfPixelFormat.dwLuminanceBitMask, + lpddsd->ddpfPixelFormat.dwBumpDvBitMask, + lpddsd->ddpfPixelFormat.dwBumpLuminanceBitMask, + lpddsd->ddpfPixelFormat.dwRGBZBitMask); + if (flags & DDPF_LUMINANCE) OutTraceD(" BMbMF=(%x,%x,%x,%x)", + lpddsd->ddpfPixelFormat.dwBumpDuBitMask, + lpddsd->ddpfPixelFormat.MultiSampleCaps.wBltMSTypes, + lpddsd->ddpfPixelFormat.MultiSampleCaps.wFlipMSTypes, + lpddsd->ddpfPixelFormat.dwYUVZBitMask); + if (flags & DDPF_BUMPDUDV) OutTraceD(" O=(%x)", + lpddsd->ddpfPixelFormat.dwOperations); if (flags & DDPF_FOURCC) OutTraceD(" FourCC=%x(%s)", lpddsd->ddpfPixelFormat.dwFourCC, sFourCC(lpddsd->ddpfPixelFormat.dwFourCC)); } if (lpddsd->dwFlags & DDSD_LPSURFACE) OutTraceD(" Surface=%x", lpddsd->lpSurface); @@ -318,6 +352,30 @@ static void DumpSurfaceAttributes(LPDDSURFACEDESC lpddsd, char *label, int line) LogSurfaceAttributes(lpddsd, label, line); } +static void DescribeSurface(LPDIRECTDRAWSURFACE lpdds, int dxversion, char *label, int line) +{ + DDSURFACEDESC2 ddsd; + HRESULT res; + int dwSize = (dxversion<4)?sizeof(DDSURFACEDESC):sizeof(DDSURFACEDESC2); + memset(&ddsd, 0, dwSize); + ddsd.dwSize = dwSize; + if(dxversion<4){ + if (pGetSurfaceDesc1) + res=(*pGetSurfaceDesc1)(lpdds, (LPDDSURFACEDESC)&ddsd); + else + res=lpdds->GetSurfaceDesc((LPDDSURFACEDESC)&ddsd); + } + else { + if (pGetSurfaceDesc4) + res=(*pGetSurfaceDesc4)((LPDIRECTDRAWSURFACE2)lpdds, &ddsd); + else + res=lpdds->GetSurfaceDesc((LPDDSURFACEDESC)&ddsd); + } + if(res)return; + OutTrace("Surface %s: ddsd=%x dxversion=%d ", lpdds, dxversion); + DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, label, line); +} + #define CAPSHASHSIZE 113 typedef struct { @@ -326,7 +384,7 @@ typedef struct { DWORD Caps; DDPIXELFORMAT PixelFormat; } CapsHash_Type; -static CapsHash_Type *CapsHash; +static CapsHash_Type *CapsHash=NULL; static void PushCaps(LPDDSURFACEDESC2 lpddsd, LPDIRECTDRAWSURFACE lpdds) { @@ -361,7 +419,9 @@ static void PushCaps(LPDDSURFACEDESC2 lpddsd, LPDIRECTDRAWSURFACE lpdds) static int PopCaps(LPDDSURFACEDESC2 lpddsd, LPDIRECTDRAWSURFACE lpdds) { - int i; + UINT i; + if(!CapsHash) return FALSE; // not initialized yet! + i = ((DWORD)lpdds >> 3) % CAPSHASHSIZE; if(lpdds != CapsHash[i].lpdds){ char sMsg[80]; @@ -1210,15 +1270,6 @@ static void HookDDSurfacePrim(LPDIRECTDRAWSURFACE *lplpdds, int dxversion) SetHook((void *)(**(DWORD **)lplpdds + 136), extUpdateOverlayDisplayProxy, (void **)&pUpdateOverlayDisplay, "UpdateOverlayDisplay(S)"); // IDirectDrawSurface::UpdateOverlayZOrder SetHook((void *)(**(DWORD **)lplpdds + 140), extUpdateOverlayZOrderProxy, (void **)&pUpdateOverlayZOrder, "UpdateOverlayZOrder(S)"); - if (!(dxw.dwFlags1 & (EMULATESURFACE|EMULATEBUFFER))){ - // IDirectDrawSurface::Lock - SetHook((void *)(**(DWORD **)lplpdds + 100), extLock, (void **)&pLock, "Lock(S)"); - // IDirectDrawSurface::Unlock - if (dxversion < 4) - SetHook((void *)(**(DWORD **)lplpdds + 128), extUnlock1, (void **)&pUnlock1, "Unlock(S)"); - else - SetHook((void *)(**(DWORD **)lplpdds + 128), extUnlock4, (void **)&pUnlock4, "Unlock(S)"); - } } static void HookDDSurfaceGeneric(LPDIRECTDRAWSURFACE *lplpdds, int dxversion) @@ -1870,6 +1921,8 @@ HRESULT WINAPI extSetCooperativeLevel(void *lpdd, HWND hwnd, DWORD dwflags) static char *FixSurfaceCaps(LPDDSURFACEDESC2 lpddsd) { + // OutTrace("FixSurfaceCaps DEBUG: flags=%x(%s) caps=%x(%s)\n", + // lpddsd->dwFlags, ExplainFlags(lpddsd->dwFlags), lpddsd->ddsCaps.dwCaps, ExplainDDSCaps(lpddsd->ddsCaps.dwCaps)); // experimental part: switch (lpddsd->dwFlags){ case DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH: @@ -1910,26 +1963,16 @@ static char *FixSurfaceCaps(LPDDSURFACEDESC2 lpddsd) //lpddsd->ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY|DDSCAPS_ZBUFFER; identical ... return "ZBUFFER"; break; -#if 0 - case DDSCAPS_TEXTURE: - // Descent 3 cursors & other graphics - OutTrace("FixSurfaceCaps: Texture for Descent 3\n"); - lpddsd->ddsCaps.dwCaps = DDSCAPS_TEXTURE|DDSCAPS_SYSTEMMEMORY|DDSCAPS_OFFSCREENPLAIN; - SetPixFmt(lpddsd); - return "TEXTURE1"; - break; - case DDSCAPS_TEXTURE|DDSCAPS_VIDEOMEMORY: - // Descent 3 cursors & other graphics - OutTrace("FixSurfaceCaps: VideoMemory Texture for Descent 3\n"); - lpddsd->ddsCaps.dwCaps = DDSCAPS_TEXTURE|DDSCAPS_SYSTEMMEMORY|DDSCAPS_OFFSCREENPLAIN; - SetPixFmt(lpddsd); - return "TEXTURE2"; - break; -#endif } break; case DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH: switch (lpddsd->ddsCaps.dwCaps){ + case DDSCAPS_BACKBUFFER|DDSCAPS_SYSTEMMEMORY: + // Vangers + OutTrace("FixSurfaceCaps: backbuffer\n"); + lpddsd->ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY; + return("backbuf"); + break; case DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY: // Alien Nations OutTrace("FixSurfaceCaps: Alien Nations (1)\n"); @@ -1984,28 +2027,362 @@ static char *FixSurfaceCaps(LPDDSURFACEDESC2 lpddsd) return SetPixFmt(lpddsd); } -HRESULT WINAPI extCreateSurfaceEmu(int dxversion, CreateSurface_Type pCreateSurface, LPDIRECTDRAW lpdd, DDSURFACEDESC2 *lpddsd, +static void ClearSurfaceDesc(void *ddsd, int dxversion) +{ + int size; + size = (dxversion < 4) ? sizeof(DDSURFACEDESC) : sizeof(DDSURFACEDESC2); + memset(ddsd, 0, size); // Clean all + ((LPDDSURFACEDESC)ddsd)->dwSize = size; +} + +static HRESULT BuildPrimaryEmu(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu) +{ + DDSURFACEDESC2 ddsd; + HRESULT res; + + // emulated primary surface + ClearSurfaceDesc((void *)&ddsd, dxversion); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; + ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; + if (lpddsd->dwFlags & DDSD_CKDESTBLT) ddsd.dwFlags|=DDSD_CKDESTBLT; + if (lpddsd->dwFlags & DDSD_CKDESTOVERLAY) ddsd.dwFlags|=DDSD_CKDESTOVERLAY; + if (lpddsd->dwFlags & DDSD_CKSRCBLT) ddsd.dwFlags|=DDSD_CKSRCBLT; + if (lpddsd->dwFlags & DDSD_CKSRCOVERLAY) ddsd.dwFlags|=DDSD_CKSRCOVERLAY; + ddsd.dwWidth = dxw.GetScreenWidth(); + ddsd.dwHeight = dxw.GetScreenHeight(); + SetPixFmt((LPDDSURFACEDESC2)&ddsd); + + // create Primary surface + DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Primary]" , __LINE__); + res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0); + if(res){ + if (res==DDERR_PRIMARYSURFACEALREADYEXISTS){ + LPDIRECTDRAWSURFACE lpPrim; + OutTraceE("CreateSurface: CreateSurface DDERR_PRIMARYSURFACEALREADYEXISTS workaround\n"); + (*pGetGDISurface)(lpPrimaryDD, &lpPrim); + while ((*pReleaseS)(lpPrim)); + res = (*pCreateSurface)(lpdd, &ddsd, lplpdds, 0); + } + /* fall through */ + if(res){ + OutTraceE("CreateSurface: ERROR on DDSPrim res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__); + if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd); + return res; + } + } + + OutTraceD("CreateSurface: created PRIMARY DDSPrim=%x\n", *lplpdds); + if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSPrim", __LINE__); + dxw.MarkPrimarySurface(*lplpdds); + HookDDSurfacePrim(lplpdds, dxversion); + + if(lpDDSEmu_Prim==NULL){ + ClearSurfaceDesc((void *)&ddsd, dxversion); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + SetPixFmt(&ddsd); + DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[EmuPrim]" , __LINE__); + + res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSEmu_Prim, 0); + if(res==DDERR_PRIMARYSURFACEALREADYEXISTS){ + OutTraceD("CreateSurface: ASSERT DDSEmu_Prim already exists\n"); + res=(*pGetGDISurface)(lpdd, &lpDDSEmu_Prim); // ok only if the previous surface has the good properties!!! + (*pReleaseS)(lpDDSEmu_Prim); + } + if(res){ + OutTraceE("CreateSurface: ERROR on DDSEmu_Prim res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__); + if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd); + return res; + } + OutTraceD("CreateSurface: created new DDSEmu_Prim=%x\n",lpDDSEmu_Prim); + if(IsDebug) DescribeSurface(lpDDSEmu_Prim, dxversion, "DDSEmu_Prim", __LINE__); + InitDSScreenParameters(lpDDSEmu_Prim); + dxw.UnmarkPrimarySurface(lpDDSEmu_Prim); + // can't hook lpDDSEmu_Prim as generic, since the Flip method is unimplemented for a PRIMARY surface! + // better avoid it or hook just useful methods. + //if (dxw.dwTFlags & OUTPROXYTRACE) HookDDSurfaceGeneric(&lpDDSEmu_Prim, dxw.dwDDVersion); + } + + if(lpDDSEmu_Back==NULL){ + ClearSurfaceDesc((void *)&ddsd, dxversion); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = dxw.GetScreenWidth(); + ddsd.dwHeight = dxw.GetScreenHeight(); + DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[EmuBack]" , __LINE__); + + res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSEmu_Back, 0); + if(res){ + OutTraceE("CreateSurface: CreateSurface ERROR on DDSEmuBack : res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__); + if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd); + return res; + } + OutTraceD("CreateSurface: created new DDSEmu_Back=%x\n", lpDDSEmu_Back); + if(IsDebug) DescribeSurface(lpDDSEmu_Back, dxversion, "DDSEmu_Back", __LINE__); + dxw.UnmarkPrimarySurface(lpDDSEmu_Back); + if (dxw.dwTFlags & OUTPROXYTRACE) HookDDSurfaceGeneric(&lpDDSEmu_Back, dxversion); + } + + return DD_OK; +} + +static HRESULT BuildPrimaryDir(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu) +{ + DDSURFACEDESC2 ddsd; + HRESULT res; + + // genuine primary surface + memcpy((void *)&ddsd, lpddsd, lpddsd->dwSize); + ddsd.dwFlags &= ~(DDSD_WIDTH|DDSD_HEIGHT|DDSD_BACKBUFFERCOUNT|DDSD_REFRESHRATE|DDSD_PIXELFORMAT); + ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_FLIP | DDSCAPS_COMPLEX); + + // create Primary surface + DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Primary]" , __LINE__); + res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0); + if(res){ + if (res==DDERR_PRIMARYSURFACEALREADYEXISTS){ + LPDIRECTDRAWSURFACE lpPrim; + OutTraceE("CreateSurface: CreateSurface DDERR_PRIMARYSURFACEALREADYEXISTS workaround\n"); + (*pGetGDISurface)(lpPrimaryDD, &lpPrim); + while ((*pReleaseS)(lpPrim)); + res = (*pCreateSurface)(lpdd, &ddsd, lplpdds, 0); + } + /* fall through */ + if(res){ + OutTraceE("CreateSurface: ERROR on DDSPrim res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__); + if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd); + return res; + } + } + + OutTraceD("CreateSurface: created PRIMARY DDSPrim=%x\n", *lplpdds); + if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSPrim", __LINE__); + + if(dxw.dwFlags1 & EMULATEBUFFER){ + lpDDSEmu_Prim = *lplpdds; + dxw.UnmarkPrimarySurface(lpDDSEmu_Prim); + RenewClipper(lpdd, lpDDSEmu_Prim); + + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; + // warning: can't create zero sized backbuffer surface !!!! + ddsd.dwWidth = dxw.GetScreenWidth(); + ddsd.dwHeight = dxw.GetScreenHeight(); + ddsd.ddsCaps.dwCaps = 0; + if (dxversion >= 4) ddsd.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN; + DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Dir FixBuf]" , __LINE__); + res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0); + if(res){ + OutTraceE("CreateSurface: ERROR on DDSPrim res=%x(%s) at %d\n",res, ExplainDDError(res), __LINE__); + return res; + } + OutTraceD("CreateSurface: created FIX DDSPrim=%x\n", *lplpdds); + if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSPrim(2)", __LINE__); + } + + dxw.MarkPrimarySurface(*lplpdds); + HookDDSurfacePrim(lplpdds, dxversion); + if(dxw.dwFlags1 & CLIPCURSOR) dxw.SetClipCursor(); + + return DD_OK; +} + +static HRESULT BuildBackBufferEmu(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu) +{ + DDSURFACEDESC2 ddsd; + HRESULT res; + + // create BackBuffer surface + ClearSurfaceDesc((void *)&ddsd, dxversion); + ddsd.dwFlags = DDSD_CAPS|DDSD_PIXELFORMAT|DDSD_HEIGHT|DDSD_WIDTH; + ddsd.ddsCaps.dwCaps=DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = dxw.GetScreenWidth(); + ddsd.dwHeight = dxw.GetScreenHeight(); + SetPixFmt(&ddsd); + DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Backbuf]" , __LINE__); + res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0); + if(res) { + OutTraceE("CreateSurface ERROR: res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__); + if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd); + return res; + } + if (dxw.dwFlags3 & SAVECAPS) { + ddsd.ddsCaps.dwCaps=DDSCAPS_VIDEOMEMORY; + PushCaps(&ddsd, *lplpdds); + } + OutTraceD("CreateSurface: created BACK DDSBack=%x\n", *lplpdds); + if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSBack", __LINE__); + dxw.UnmarkPrimarySurface(*lplpdds); + HookDDSurfaceGeneric(lplpdds, dxversion); // added !!! + lpBackBufferDD = lpdd; // v2.02.31 + iBakBufferVersion=dxversion; // v2.02.31 + + return DD_OK; +} + +static HRESULT BuildBackBufferDir(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu) +{ + DDSURFACEDESC2 ddsd; + HRESULT res; + + // create BackBuffer surface + ClearSurfaceDesc((void *)&ddsd, dxversion); + ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH; + ddsd.ddsCaps.dwCaps=DDSCAPS_SYSTEMMEMORY; + if (dxversion >= 4) ddsd.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = dxw.GetScreenWidth(); + ddsd.dwHeight = dxw.GetScreenHeight(); + if (dxw.dwFlags2 & BACKBUFATTACH) { + LPDIRECTDRAWSURFACE lpPrim; + DDSURFACEDESC2 prim; + (*pGetGDISurface)(lpPrimaryDD, &lpPrim); + res=lpPrim->GetSurfaceDesc((DDSURFACEDESC *)&prim); + (*pReleaseS)(lpPrim); + ddsd.dwWidth = prim.dwWidth; + ddsd.dwHeight = prim.dwHeight; + OutTraceD("BMX FIX: res=%x(%s) wxh=(%dx%d)\n", res, ExplainDDError(res),ddsd.dwWidth, ddsd.dwHeight); + } + DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Backbuf]" , __LINE__); + res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0); + if(res) { + OutTraceE("CreateSurface ERROR: res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__); + if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd); + return res; + } + if (dxw.dwFlags3 & SAVECAPS) { + ddsd.ddsCaps.dwCaps=DDSCAPS_VIDEOMEMORY; + PushCaps(&ddsd, *lplpdds); + } + OutTraceD("CreateSurface: created BACK DDSBack=%x\n", *lplpdds); + if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSBack", __LINE__); + dxw.UnmarkPrimarySurface(*lplpdds); + HookDDSurfaceGeneric(lplpdds, dxversion); // added !!! + lpBackBufferDD = lpdd; // v2.02.31 + iBakBufferVersion=dxversion; // v2.02.31 + + return DD_OK; +} + +static HRESULT BuildGenericEmu(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu) +{ + DDSURFACEDESC2 ddsd; + HRESULT res; + + memcpy(&ddsd, lpddsd, lpddsd->dwSize); // Copy over .... + FixSurfaceCaps(&ddsd); + DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Emu Generic]" , __LINE__); + res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, pu); + if(res){ + // v2.1.81: retry on system memory may fix not only the DDERR_OUTOFVIDEOMEMORY + // error, but the DDERR_INVALIDPIXELFORMAT (see "The Sims ???") + if ((dxw.dwFlags1 & SWITCHVIDEOMEMORY) && + ((res==DDERR_OUTOFVIDEOMEMORY) || (res==DDERR_INVALIDPIXELFORMAT))){ + OutTraceD("CreateSurface: CreateSurface ERROR err=%x(%s) at %d, retry in SYSTEMMEMORY\n", + res, ExplainDDError(res), __LINE__); + ddsd.dwFlags |= DDSD_CAPS; + ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY; + ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; + DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Emu Generic2]" , __LINE__); + res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0); + } + } + if (res) { + OutTraceE("CreateSurface: ERROR on Emu_Generic res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__); + return res; + } + + OutTraceD("CreateSurface: created Emu_Generic dds=%x\n", *lplpdds); + if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSEmu_Generic", __LINE__); + // diagnostic hooks .... + HookDDSurfaceGeneric(lplpdds, dxversion); + // unmark this as possible primary + dxw.UnmarkPrimarySurface(*lplpdds); + + return DD_OK; +} + +static HRESULT BuildGenericDir(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu) +{ + HRESULT res; + + DumpSurfaceAttributes((LPDDSURFACEDESC)lpddsd, "[Dir Generic]" , __LINE__); + res = (*pCreateSurface)(lpdd, lpddsd, lplpdds, 0); + if(res){ + if ((dxw.dwFlags1 & SWITCHVIDEOMEMORY) && (res==DDERR_OUTOFVIDEOMEMORY)){ + OutTraceD("CreateSurface ERROR: res=%x(%s) at %d, retry\n", res, ExplainDDError(res), __LINE__); + lpddsd->ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY; + lpddsd->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; + res = (*pCreateSurface)(lpdd, lpddsd, lplpdds, 0); + } + if(res){ + OutTraceE("CreateSurface: CreateSurface ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__); + return res; + } + } + OutTraceD("CreateSurface: created GENERIC surface dds=%x flags=%x(%s) caps=%x(%s)\n", + *lplpdds, lpddsd->dwFlags, ExplainFlags(lpddsd->dwFlags), lpddsd->ddsCaps.dwCaps, ExplainDDSCaps(lpddsd->ddsCaps.dwCaps)); + + // hooks .... + HookDDSurfaceGeneric(lplpdds, dxversion); + dxw.UnmarkPrimarySurface(*lplpdds); + + OutTraceD("CreateSurface: created lpdds=%x type=Generic ret=%x\n", *lplpdds, res); + if(IsDebug) DescribeSurface(lpDDSBack, dxversion, "Generic", __LINE__); + + return DD_OK; +} + +static HRESULT WINAPI extCreateSurface(int dxversion, CreateSurface_Type pCreateSurface, LPDIRECTDRAW lpdd, DDSURFACEDESC2 *lpddsd, LPDIRECTDRAWSURFACE *lplpdds, void *pu) { HRESULT res; - DDSURFACEDESC2 ddsd; + DDSURFACEDESC2 ddsd, SavedDDSD; LPDIRECTDRAWSURFACE lpDDSPrim; - char *pfmt; - DWORD CurFlags, CurSize; + DWORD CurFlags; + int TargetSize; + typedef HRESULT (*BuildSurface_Type)(LPDIRECTDRAW, CreateSurface_Type, LPDDSURFACEDESC2, int, LPDIRECTDRAWSURFACE *, void *); + BuildSurface_Type BuildPrimary; + BuildSurface_Type BuildBackBuffer; + BuildSurface_Type BuildGeneric; - if((lpddsd->dwSize != sizeof(DDSURFACEDESC2)) && (lpddsd->dwSize != sizeof(DDSURFACEDESC))){ + if (dxw.dwFlags1 & EMULATESURFACE){ + BuildPrimary = BuildPrimaryEmu; + BuildBackBuffer = BuildBackBufferEmu; + BuildGeneric = BuildGenericEmu; + } + else { + BuildPrimary = BuildPrimaryDir; + BuildBackBuffer = BuildBackBufferDir; + BuildGeneric = BuildGenericDir; + } + + if(IsTraceD){ + OutTrace("CreateSurface: Version=%d lpdd=%x ", dxversion, lpdd); + LogSurfaceAttributes((LPDDSURFACEDESC)lpddsd, "[CreateSurface]", __LINE__); + } + + // check for lpddsd->dwSize value + TargetSize=(dxversion<4)?sizeof(DDSURFACEDESC):sizeof(DDSURFACEDESC2); + if(lpddsd->dwSize != TargetSize){ char sMsg[81]; - sprintf_s(sMsg,80, "CreateSurface: ASSERT bad dwSize=%d\n", lpddsd->dwSize); + sprintf_s(sMsg,80, "CreateSurface: ASSERT bad dwSize=%d dxversion=%d\n", + lpddsd->dwSize, dxversion); OutTraceD(sMsg); if(IsAssertEnabled) MessageBox(0, sMsg, "CreateSurface", MB_OK | MB_ICONEXCLAMATION); return DDERR_INVALIDPARAMS; } - memset(&ddsd, 0, sizeof(ddsd)); // Clean all - memcpy(&ddsd, lpddsd, lpddsd->dwSize); // Copy - CurSize = (dxversion < 4) ? sizeof(DDSURFACEDESC) : sizeof(DDSURFACEDESC2); - ddsd.dwSize = CurSize; + //GHO workaround (needed for WarWind, Rogue Spear): + if (lpddsd->dwFlags && !(lpddsd->dwFlags & 0x1)){ + OutTraceD("CreateSurface: fixing illegal dwFlags value: %x -> %x\n", + lpddsd->dwFlags, lpddsd->dwFlags+1); + lpddsd->dwFlags++; + } + if (dxw.dwFlags3 & SAVECAPS) SavedDDSD=*lpddsd; + + memcpy(&ddsd, lpddsd, lpddsd->dwSize); // Copy + + // creation of the primary surface.... if(ddsd.dwFlags & DDSD_CAPS && ddsd.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE){ GetHookInfo()->Height=(short)dxw.GetScreenHeight(); GetHookInfo()->Width=(short)dxw.GetScreenWidth(); @@ -2030,7 +2407,7 @@ HRESULT WINAPI extCreateSurfaceEmu(int dxversion, CreateSurface_Type pCreateSurf lpDDSEmu_Back=NULL; lpDDSEmu_Prim=NULL; - int BBCount=1; + int BBCount=0; // or 1 ?? if (ddsd.dwFlags & DDSD_BACKBUFFERCOUNT) BBCount=ddsd.dwBackBufferCount; if ((BBCount > 0) && (iBakBufferVersion < 4)){ lpDDSBack=NULL; @@ -2047,389 +2424,65 @@ HRESULT WINAPI extCreateSurfaceEmu(int dxversion, CreateSurface_Type pCreateSurf BBCount = MAXBACKBUFFERS; } - // emulated primary surface - ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; - ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; - if (lpddsd->dwFlags & DDSD_CKDESTBLT) ddsd.dwFlags|=DDSD_CKDESTBLT; - if (lpddsd->dwFlags & DDSD_CKDESTOVERLAY) ddsd.dwFlags|=DDSD_CKDESTOVERLAY; - if (lpddsd->dwFlags & DDSD_CKSRCBLT) ddsd.dwFlags|=DDSD_CKSRCBLT; - if (lpddsd->dwFlags & DDSD_CKSRCOVERLAY) ddsd.dwFlags|=DDSD_CKSRCOVERLAY; - ddsd.dwWidth = dxw.GetScreenWidth(); - ddsd.dwHeight = dxw.GetScreenHeight(); - pfmt=SetPixFmt(&ddsd); + // build emulated primary surface, real primary and backbuffer surfaces CurFlags=ddsd.dwFlags; - - // create Primary surface - DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Primary]" , __LINE__); - res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0); - if(res){ - if (res==DDERR_PRIMARYSURFACEALREADYEXISTS){ - LPDIRECTDRAWSURFACE lpPrim; - OutTraceE("CreateSurface: CreateSurface DDERR_PRIMARYSURFACEALREADYEXISTS workaround\n"); - (*pGetGDISurface)(lpPrimaryDD, &lpPrim); - while ((*pReleaseS)(lpPrim)); - res = (*pCreateSurface)(lpdd, &ddsd, lplpdds, 0); - } - /* fall through */ - if(res){ - OutTraceE("CreateSurface ERROR: res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__); - if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd); - return res; - } - } + res=BuildPrimary(lpdd, pCreateSurface, lpddsd, dxversion, lplpdds, NULL); + if(res) return res; lpDDSPrim = *lplpdds; - OutTraceD("CreateSurface: created PRIMARY DDSPrim=%x\n", lpDDSPrim); - dxw.MarkPrimarySurface(*lplpdds); - HookDDSurfacePrim(lplpdds, dxversion); - //if (dxw.dwFlags3 & SAVECAPS) PushCaps(&ddsd, lpDDSPrim); handled outside .... if (BBCount){ - // create BackBuffer surface - memset(&ddsd, 0, sizeof(ddsd)); // Clean all - ddsd.dwSize = CurSize; - ddsd.dwFlags = CurFlags; - ddsd.ddsCaps.dwCaps=DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; - ddsd.dwWidth = dxw.GetScreenWidth(); - ddsd.dwHeight = dxw.GetScreenHeight(); - pfmt=SetPixFmt(&ddsd); - //ddsd.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER; - DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Backbuf]" , __LINE__); - res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSBack, 0); - if(res){ - OutTraceE("CreateSurface ERROR: res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__); - if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd); - return res; - } - if (dxw.dwFlags3 & SAVECAPS) { - ddsd.ddsCaps.dwCaps=DDSCAPS_VIDEOMEMORY; - PushCaps(&ddsd, lpDDSBack); - } - OutTraceD("CreateSurface: created BACK DDSBack=%x\n", lpDDSBack); - dxw.UnmarkPrimarySurface(lpDDSBack); - HookDDSurfaceGeneric(&lpDDSBack, dxversion); // added !!! - lpBackBufferDD = lpdd; // v2.02.31 - iBakBufferVersion=dxversion; // v2.02.31 + // build emulated backbuffer surface + res=BuildBackBuffer(lpdd, pCreateSurface, lpddsd, dxversion, &lpDDSBack, NULL); + if(res) return res; + + // V2.1.85/V2.2.34: tricky !!!! + // When a real backbuffer is created, it has a reference to its frontbuffer. + // some games (Monopoly 3D) may depend on this setting - i.e. they could close + // the exceeding references - so this is better be replicated adding an initial + // reference to the zero count. But you don't have to do this if the backbuffer + // is created independently by the primary surface. + lpDDSBack->AddRef(); // should it be repeated BBCount times???? } - FlipChainLength=BBCount; - // V2.1.85: tricky !!!! - // When a real backbuffer is created, it has a reference to its frontbuffer. - // some games (Monopoly 3D) may depend on this setting - i.e. they could close - // the exceeding references - so this is better be replicated adding an initial - // reference to the zero count. - if (lpDDSBack) lpDDSBack->AddRef(); // should it be repeated BBCount times???? - - // rebuild emulated primary surface - - if(lpDDSEmu_Prim==NULL){ - memset(&ddsd, 0, sizeof(ddsd)); // Clean all - ddsd.dwSize = CurSize; - ddsd.dwFlags = DDSD_CAPS; - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - pfmt=SetPixFmt(&ddsd); - DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[EmuPrim]" , __LINE__); - res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSEmu_Prim, 0); - if(res==DDERR_PRIMARYSURFACEALREADYEXISTS){ - OutTraceD("CreateSurface: ASSERT DDSEmu_Prim already exists\n"); - res=(*pGetGDISurface)(lpdd, &lpDDSEmu_Prim); // ok only if the oprevious surface has the good properties!!! - //while((*pReleaseS)(lpDDSEmu_Prim)); - //res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSEmu_Prim, 0); - } - if(res){ - OutTraceE("CreateSurface: CreateSurface ERROR on DDSEmu_Prim res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__); - if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd); - return res; - } - OutTraceD("CreateSurface: created new DDSEmu_Prim=%x\n",lpDDSEmu_Prim); - InitDSScreenParameters(lpDDSEmu_Prim); + if(IsTraceD){ + OutTrace("CreateSurface: created DDSPrim=%x DDSBack=%x", lpDDSPrim, lpDDSBack); + if(dxw.dwFlags1 & (EMULATESURFACE|EMULATEBUFFER)) OutTrace(" DDSEmu_Prim=%x", lpDDSEmu_Prim); + if(dxw.dwFlags1 & EMULATESURFACE) OutTrace(" DDSEmu_Back=%x", lpDDSEmu_Back); + OutTrace("\n"); } - + + // rebuild the clipper area if (lpDDC==NULL) RenewClipper(lpdd, lpDDSEmu_Prim); - - dxw.UnmarkPrimarySurface(lpDDSEmu_Prim); - // can't hook lpDDSEmu_Prim as generic, since the Flip method is unimplemented for a PRIMARY surface! - // better avoid it or hook just useful methods. - //if (dxw.dwTFlags & OUTPROXYTRACE) HookDDSurfaceGeneric(&lpDDSEmu_Prim, dxw.dwDDVersion); - - // rebuild emulated primary backbuffer surface - - if(lpDDSEmu_Back==NULL){ - memset(&ddsd, 0, sizeof(ddsd)); // Clean all - ddsd.dwSize = CurSize; - ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; - ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; - ddsd.dwWidth = dxw.GetScreenWidth(); - ddsd.dwHeight = dxw.GetScreenHeight(); - //pfmt=SetPixFmt(&ddsd); - DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[EmuBack]" , __LINE__); - - res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSEmu_Back, 0); - if(res){ - OutTraceE("CreateSurface: CreateSurface ERROR on DDSEmuBack : res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__); - if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd); - return res; - } - OutTraceD("CreateSurface: created new DDSEmu_Back=%x\n", lpDDSEmu_Back); - } - - dxw.UnmarkPrimarySurface(lpDDSEmu_Back); - if (dxw.dwTFlags & OUTPROXYTRACE) HookDDSurfaceGeneric(&lpDDSEmu_Back, dxversion); - - OutTraceD("CreateSurface: created DDSEmu_Prim=%x DDSEmu_Back=%x DDSPrim=%x DDSBack=%x\n", - lpDDSEmu_Prim, lpDDSEmu_Back, lpDDSPrim, lpDDSBack); - - // creation of lpDDSHDC service surface moved to GetDC method - if(dxw.dwFlags1 & CLIPCURSOR) dxw.SetClipCursor(); - return 0; + REFPROBE(*lplpdds, "CREATED"); + return DD_OK; } - pfmt=FixSurfaceCaps(&ddsd); - - DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Emu Generic]" , __LINE__); - DumpPixFmt(&ddsd); - //OutTrace("pCreateSurface=%x lpdd=%x &ddsd=%x lplpdds=%x pu=%x\n",pCreateSurface, lpdd, &ddsd, lplpdds, pu); - res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, pu); - if(res){ - // v2.1.81: retry on system memory may fix not only the DDERR_OUTOFVIDEOMEMORY - // error, but the DDERR_INVALIDPIXELFORMAT (see "The Sims ???") - if ((dxw.dwFlags1 & SWITCHVIDEOMEMORY) && - ((res==DDERR_OUTOFVIDEOMEMORY) || (res==DDERR_INVALIDPIXELFORMAT))){ - OutTraceD("CreateSurface: CreateSurface ERROR err=%x(%s) at %d, retry in SYSTEMMEMORY\n", - res, ExplainDDError(res), __LINE__); - ddsd.dwFlags |= DDSD_CAPS; - ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY; - ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; - DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Emu Generic2]" , __LINE__); - res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0); + // a request for a separate (not complex) backbuffer to attach later on, maybe. + if ((ddsd.dwFlags & DDSD_CAPS) && (ddsd.ddsCaps.dwCaps & DDSCAPS_BACKBUFFER)){ + if (lpDDSBack) { + OutTraceD("CreateSurface: returning current DDSBack=%x\n", lpDDSBack); + *lplpdds = lpDDSBack; + REFPROBE(*lplpdds, "CREATED"); + return DD_OK; } - } - if (res) { - OutTraceE("CreateSurface: CreateSurface ERROR res=%x(%s) pfmt=%s at %d\n", res, ExplainDDError(res), pfmt, __LINE__); - //if((res==DDERR_INVALIDPIXELFORMAT) || (res && (ddsd.dwFlags & DDSD_PIXELFORMAT))) DumpPixFmt(&ddsd); - DumpPixFmt(&ddsd); // why Pandemonium2 fails ??? + + res=BuildBackBuffer(lpdd, pCreateSurface, lpddsd, dxversion, lplpdds, NULL); + lpDDSBack = *lplpdds; + REFPROBE(*lplpdds, "CREATED"); return res; } - // diagnostic hooks .... - HookDDSurfaceGeneric(lplpdds, dxversion); - // unmark this as possible primary - dxw.UnmarkPrimarySurface(*lplpdds); - OutTraceD("CreateSurface: created EMU_GENERIC dds=%x type=%s\n", *lplpdds, pfmt); + // if nothing else, it's a generic surface + res=BuildGeneric(lpdd, pCreateSurface, lpddsd, dxversion, lplpdds, pu); - return 0; -} + if (dxw.dwFlags3 & SAVECAPS) PushCaps(&SavedDDSD, *lplpdds); -HRESULT WINAPI extCreateSurfaceDir(int dxversion, CreateSurface_Type pCreateSurface, LPDIRECTDRAW lpdd, DDSURFACEDESC2 *lpddsd, - LPDIRECTDRAWSURFACE *lplpdds, void *pu) -{ - HRESULT res; - DDSURFACEDESC2 ddsd; - LPDIRECTDRAWSURFACE lpDDSPrim; - int dwSize; - - memset(&ddsd, 0, sizeof(ddsd)); // Clean all - memcpy(&ddsd, lpddsd, lpddsd->dwSize); // Copy - dwSize = (dxversion < 4) ? sizeof(DDSURFACEDESC) : sizeof(DDSURFACEDESC2); - ddsd.dwSize = dwSize; - - if(ddsd.dwFlags & DDSD_CAPS && ddsd.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE){ - GetHookInfo()->Height=(short)dxw.GetScreenHeight(); - GetHookInfo()->Width=(short)dxw.GetScreenWidth(); - GetHookInfo()->ColorDepth=(short)dxw.VirtualPixelFormat.dwRGBBitCount; - GetHookInfo()->DXVersion=dxversion; - dxw.dwPrimarySurfaceCaps = ddsd.ddsCaps.dwCaps; - dxw.dwBackBufferCount = (ddsd.dwFlags & DDSD_BACKBUFFERCOUNT) ? ddsd.dwBackBufferCount : 0; - lpPrimaryDD = lpdd; // v2.1.87 - - // clean up service objects - // beware of the different behaviour between older and newer directdraw releases... - if(dxversion >= 4){ - if (lpDDC){ - __try { while(lpDDC && lpDDC->Release()); } - __except(EXCEPTION_EXECUTE_HANDLER){ - OutTraceD("Release(lpDDC): exception caught at %d\n", __LINE__); - lpDDC=NULL; - } - } - if (lpDDSBack){ - __try { while(lpDDSBack && lpDDSBack->Release()); } - __except(EXCEPTION_EXECUTE_HANDLER){ - OutTraceD("Release(lpDDSBack): exception caught at %d\n", __LINE__); - lpDDSBack=NULL; - } - } - } - lpDDC=NULL; - - int BBCount=1; - if (ddsd.dwFlags & DDSD_BACKBUFFERCOUNT) BBCount=ddsd.dwBackBufferCount; - // beware: a previously allocated backbuffer should be cleared or not depending on - // the ddraw version of the backbuffer surface, not the current one! - //if(0){ // ok for Silent Hunter II - //if(1){ // ok for Dark Vengeance - if ((BBCount > 0) && (iBakBufferVersion < 4)){ - lpDDSBack=NULL; - OutTraceD("CreateSurface: BackBufferCount=%d\n", BBCount); - } - - if((dxw.dwFlags1 & EMULATEBUFFER) && lpDDSEmu_Prim){ - __try { while(lpDDSEmu_Prim && lpDDSEmu_Prim->Release()); } - __except(EXCEPTION_EXECUTE_HANDLER){ - OutTraceD("Release(lpDDSEmu_Prim): exception caught at %d\n", __LINE__); - lpDDSEmu_Prim=NULL; - } - } - - // genuine primary surface - ddsd.dwFlags &= ~(DDSD_WIDTH|DDSD_HEIGHT|DDSD_BACKBUFFERCOUNT|DDSD_REFRESHRATE|DDSD_PIXELFORMAT); - ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_FLIP | DDSCAPS_COMPLEX); - DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Dir Primary]" , __LINE__); - res = (*pCreateSurface)(lpdd, &ddsd, &lpDDSPrim, pu); - if(res){ - if (res==DDERR_PRIMARYSURFACEALREADYEXISTS){ - LPDIRECTDRAWSURFACE lpPrim; - OutTraceE("CreateSurface: CreateSurface DDERR_PRIMARYSURFACEALREADYEXISTS workaround\n"); - (*pGetGDISurface)(lpPrimaryDD, &lpPrim); - while ((*pReleaseS)(lpPrim)); - res = (*pCreateSurface)(lpdd, &ddsd, &lpDDSPrim, pu); - } - /* fall through */ - if ((dxw.dwFlags1 & SWITCHVIDEOMEMORY) && (res==DDERR_OUTOFVIDEOMEMORY)){ - OutTraceD("CreateSurface: CreateSurface DDERR_OUTOFVIDEOMEMORY ERROR at %d, retry in SYSTEMMEMORY\n", __LINE__); - ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY; // try ... - ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; // try ... - res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0); - } - if(res){ - OutTraceE("CreateSurface: CreateSurface ERROR on DDSPrim res=%x(%s) at %d\n", - res, ExplainDDError(res), __LINE__); - return res; - } - } - - if(dxw.dwFlags1 & EMULATEBUFFER){ - lpDDSEmu_Prim = lpDDSPrim; - dxw.UnmarkPrimarySurface(lpDDSEmu_Prim); - OutTraceD("CreateSurface: created PRIMARY DDSPrim=%x flags=%x(%s) caps=%x(%s)\n", - lpDDSPrim, ddsd.dwFlags, ExplainFlags(ddsd.dwFlags), ddsd.ddsCaps.dwCaps, ExplainDDSCaps(ddsd.ddsCaps.dwCaps)); - RenewClipper(lpdd, lpDDSEmu_Prim); - - ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; - // warning: can't create zero sized backbuffer surface !!!! - ddsd.dwWidth = dxw.GetScreenWidth(); - ddsd.dwHeight = dxw.GetScreenHeight(); - ddsd.ddsCaps.dwCaps = 0; - if (dxversion >= 4) ddsd.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN; - DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Dir FixBuf]" , __LINE__); - res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSPrim, 0); - if(res){ - OutTraceE("CreateSurface: ERROR on DDSPrim res=%x(%s) at %d\n",res, ExplainDDError(res), __LINE__); - return res; - } - - *lplpdds = lpDDSPrim; - dxw.MarkPrimarySurface(lpDDSPrim); - OutTraceD("CreateSurface: created FIX DDSPrim=%x flags=%x(%s) caps=%x(%s)\n", - *lplpdds, ddsd.dwFlags, ExplainFlags(ddsd.dwFlags), ddsd.ddsCaps.dwCaps, ExplainDDSCaps(ddsd.ddsCaps.dwCaps)); - } - else{ - *lplpdds = lpDDSPrim; - dxw.MarkPrimarySurface(lpDDSPrim); - OutTraceD("CreateSurface: created PRIMARY DDSPrim=%x flags=%x(%s) caps=%x(%s)\n", - *lplpdds, ddsd.dwFlags, ExplainFlags(ddsd.dwFlags), ddsd.ddsCaps.dwCaps, ExplainDDSCaps(ddsd.ddsCaps.dwCaps)); - RenewClipper(lpdd, lpDDSPrim); - } - - HookDDSurfacePrim(&lpDDSPrim, dxversion); - if(dxw.dwFlags1 & CLIPCURSOR) dxw.SetClipCursor(); - - if (!BBCount) return 0; - FlipChainLength=BBCount; - if (lpDDSBack) return 0; // v2.02.31: if you got a previous backbuffer surface, use it! - - ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; - // warning: can't create zero sized backbuffer surface !!!! - ddsd.dwWidth = dxw.GetScreenWidth(); - ddsd.dwHeight = dxw.GetScreenHeight(); - if (dxw.dwFlags2 & BACKBUFATTACH) { - DDSURFACEDESC2 prim; - prim.dwSize = dwSize; - res=lpDDSPrim->GetSurfaceDesc((DDSURFACEDESC *)&prim); - ddsd.dwWidth = prim.dwWidth; - ddsd.dwHeight = prim.dwHeight; - OutTraceD("BMX FIX: res=%x(%s) wxh=(%dx%d)\n", res, ExplainDDError(res),ddsd.dwWidth, ddsd.dwHeight); - } - - // preserve original CAPS.... - ddsd.ddsCaps.dwCaps &= ~DDSCAPS_PRIMARYSURFACE; - if (dxversion >= 4) ddsd.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN; - DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Dir Backbuf]" , __LINE__); - res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSBack, pu); - if(res) { - if ((dxw.dwFlags1 & SWITCHVIDEOMEMORY) && (res==DDERR_OUTOFVIDEOMEMORY)){ - OutTraceD("CreateSurface: CreateSurface DDERR_OUTOFVIDEOMEMORY ERROR at %d, retry in SYSTEMMEMORY\n", __LINE__); - ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY; // try ... - ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; // try ... - res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSBack, pu); - } - if(res){ - OutTraceE("CreateSurface: CreateSurface ERROR on DDSBack res=%x(%s) caps=%x(%s) at %d\n", - res, ExplainDDError(res), ddsd.ddsCaps.dwCaps, ExplainDDSCaps(ddsd.ddsCaps.dwCaps), __LINE__); - return res; - } - } - OutTraceD("CreateSurface: created BACK DDSBack=%x flags=%x(%s) caps=%x(%s)\n", - lpDDSBack, ddsd.dwFlags, ExplainFlags(ddsd.dwFlags), ddsd.ddsCaps.dwCaps, ExplainDDSCaps(ddsd.ddsCaps.dwCaps)); - - HookDDSurfaceGeneric(&lpDDSBack, dxversion); - // V2.1.84: tricky !!!! - // When a real backbuffer is created, it has a reference to its frontbuffer. - // some games (Monopoly 3D) may depend on this setting - i.e. they could close - // the exceeding references - so this is better be replicated adding an initial - // reference to the zero count. - // Should this hold for EMULATED mode as well? Maybe, but Diablo crashes.... - lpDDSBack->AddRef(); - lpBackBufferDD = lpdd; - iBakBufferVersion=dxversion; // v2.02.31 - - return 0; - } - - //BACKBUFATTACH: needed for Syberia - if ((dxw.dwFlags2 & BACKBUFATTACH) && (lpddsd->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)){ - DDSURFACEDESC2 backbuf; - backbuf.dwSize = dwSize; - res=lpDDSBack->GetSurfaceDesc((DDSURFACEDESC *)&backbuf); - ddsd.dwWidth = backbuf.dwWidth; - ddsd.dwHeight = backbuf.dwHeight; - } - - DumpSurfaceAttributes((LPDDSURFACEDESC)lpddsd, "[Dir Generic]" , __LINE__); - res = (*pCreateSurface)(lpdd, lpddsd, lplpdds, 0); - if(res){ - if ((dxw.dwFlags1 & SWITCHVIDEOMEMORY) && (res==DDERR_OUTOFVIDEOMEMORY)){ - OutTraceD("CreateSurface ERROR: res=%x(%s) at %d, retry\n", res, ExplainDDError(res), __LINE__); - lpddsd->ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY; - lpddsd->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; - res = (*pCreateSurface)(lpdd, lpddsd, lplpdds, 0); - } - if(res){ - OutTraceE("CreateSurface: CreateSurface ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__); - return res; - } - } - OutTraceD("CreateSurface: created GENERIC surface dds=%x flags=%x(%s) caps=%x(%s)\n", - *lplpdds, lpddsd->dwFlags, ExplainFlags(lpddsd->dwFlags), lpddsd->ddsCaps.dwCaps, ExplainDDSCaps(lpddsd->ddsCaps.dwCaps)); - - // hooks .... - HookDDSurfaceGeneric(lplpdds, dxversion); - dxw.UnmarkPrimarySurface(*lplpdds); - - OutTraceD("CreateSurface: created lpdds=%x type=GENUINE Return=%x\n", *lplpdds, res); + REFPROBE(*lplpdds, "CREATED"); return res; } + HRESULT WINAPI extCreateSurface1(LPDIRECTDRAW lpdd, DDSURFACEDESC *lpddsd, LPDIRECTDRAWSURFACE *lplpdds, void *pu) { return extCreateSurface(1, (CreateSurface_Type)pCreateSurface1, lpdd, (DDSURFACEDESC2 *)lpddsd, lplpdds, pu); @@ -2450,46 +2503,6 @@ HRESULT WINAPI extCreateSurface7(LPDIRECTDRAW lpdd, DDSURFACEDESC2 *lpddsd, LPDI return extCreateSurface(7, (CreateSurface_Type)pCreateSurface7, lpdd, (DDSURFACEDESC2 *)lpddsd, lplpdds, pu); } -HRESULT WINAPI extCreateSurface(int dxversion, CreateSurface_Type pCreateSurface, LPDIRECTDRAW lpdd, DDSURFACEDESC2 *lpddsd, - LPDIRECTDRAWSURFACE *lplpdds, void *pu) -{ - HRESULT res; - DDSURFACEDESC2 ddsd; - - if(IsTraceD){ - // beware: incomplete trace lines - must be line terminated below! - OutTrace("CreateSurface: Version=%d lpdd=%x Flags=%x(%s)", dxversion, lpdd, lpddsd->dwFlags, ExplainFlags(lpddsd->dwFlags)); - if (lpddsd->dwFlags & DDSD_CAPS && lpddsd->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) OutTrace(" VirtualScreen=(%d,%d)", dxw.GetScreenWidth(), dxw.GetScreenHeight()); - if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) OutTrace(" BackBufferCount=%d", lpddsd->dwBackBufferCount); - if (lpddsd->dwFlags & DDSD_WIDTH) OutTrace(" Width=%d", lpddsd->dwWidth); - if (lpddsd->dwFlags & DDSD_HEIGHT) OutTrace(" Height=%d", lpddsd->dwHeight); - if (lpddsd->dwFlags & DDSD_CAPS) OutTrace(" Caps=%x(%s)", lpddsd->ddsCaps.dwCaps, ExplainDDSCaps(lpddsd->ddsCaps.dwCaps)); - if (lpddsd->dwFlags & DDSD_CKDESTBLT ) OutTrace(" CKDestBlt=(%x,%x)", lpddsd->ddckCKDestBlt.dwColorSpaceLowValue, lpddsd->ddckCKDestBlt.dwColorSpaceHighValue); - if (lpddsd->dwFlags & DDSD_CKDESTOVERLAY ) OutTrace(" CKDestOverlay=(%x,%x)", lpddsd->ddckCKDestOverlay.dwColorSpaceLowValue, lpddsd->ddckCKDestOverlay.dwColorSpaceHighValue); - if (lpddsd->dwFlags & DDSD_CKSRCBLT ) OutTrace(" CKSrcBlt=(%x,%x)", lpddsd->ddckCKSrcBlt.dwColorSpaceLowValue, lpddsd->ddckCKSrcBlt.dwColorSpaceHighValue); - if (lpddsd->dwFlags & DDSD_CKSRCOVERLAY ) OutTrace(" CKSrcOverlay=(%x,%x)", lpddsd->ddckCKSrcOverlay.dwColorSpaceLowValue, lpddsd->ddckCKSrcOverlay.dwColorSpaceHighValue); - OutTrace("\n"); - if (lpddsd->dwFlags & DDSD_PIXELFORMAT) DumpPixFmt(lpddsd); - } - - //GHO workaround (needed for WarWind, Rogue Spear): - if (lpddsd->dwFlags && !(lpddsd->dwFlags & 0x1)){ - OutTraceD("CreateSurface: fixing illegal dwFlags value: %x -> %x\n", - lpddsd->dwFlags, lpddsd->dwFlags+1); - lpddsd->dwFlags++; - } - - if (dxw.dwFlags3 & SAVECAPS) ddsd=*lpddsd; - - if (dxw.dwFlags1 & EMULATESURFACE) - res= extCreateSurfaceEmu(dxversion, pCreateSurface, lpdd, lpddsd, lplpdds, pu); - else - res= extCreateSurfaceDir(dxversion, pCreateSurface, lpdd, lpddsd, lplpdds, pu); - - if (dxw.dwFlags3 & SAVECAPS) PushCaps(&ddsd, *lplpdds); - - return res; -} HRESULT WINAPI extGetAttachedSurface(int dxversion, GetAttachedSurface_Type pGetAttachedSurface, LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS lpddsc, LPDIRECTDRAWSURFACE *lplpddas) @@ -2628,6 +2641,7 @@ HRESULT WINAPI sBlt(char *api, LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect, BOOL ToPrim, FromPrim, ToScreen, FromScreen; //CkArg arg; + ToPrim=dxw.IsAPrimarySurface(lpdds); FromPrim=dxw.IsAPrimarySurface(lpddssrc); ToScreen=ToPrim && !(dxw.dwFlags1 & EMULATESURFACE); @@ -2970,6 +2984,7 @@ HRESULT WINAPI extBltFast(LPDIRECTDRAWSURFACE lpdds, DWORD dwx, DWORD dwy, HRESULT ret; BOOL ToPrim, FromPrim; + REFPROBE(lpdds, "BLTFAST"); ToPrim=dxw.IsAPrimarySurface(lpdds); FromPrim=dxw.IsAPrimarySurface(lpddssrc); @@ -3243,6 +3258,7 @@ HRESULT WINAPI extLockDir(LPDIRECTDRAWSURFACE lpdds, LPRECT lprect, LPDIRECTDRAW } (*pGetGDISurface)(lpPrimaryDD, &lpDDSPrim); + (*pReleaseS)(lpDDSPrim); if(lpdds==lpDDSPrim){ if(dxw.dwFlags1 & LOCKEDSURFACE){ DDSURFACEDESC2 ddsd; @@ -3341,7 +3357,7 @@ HRESULT WINAPI extUnlockDir(int dxversion, Unlock4_Type pUnlock, LPDIRECTDRAWSUR IsPrim=dxw.IsAPrimarySurface(lpdds); - if ((dxversion == 4) && lprect) CleanRect(&lprect,__LINE__); + if ((dxversion >= 4) && lprect) CleanRect(&lprect,__LINE__); if(IsTraceD){ OutTrace("Unlock: lpdds=%x%s ", lpdds, (IsPrim ? "(PRIM)":"")); @@ -3356,8 +3372,9 @@ HRESULT WINAPI extUnlockDir(int dxversion, Unlock4_Type pUnlock, LPDIRECTDRAWSUR OutTrace("lpvoid=%x\n", lprect); } + if(dxw.dwFlags1 & LOCKEDSURFACE){ (*pGetGDISurface)(lpPrimaryDD, &lpDDSPrim); - if((lpdds==lpDDSPrim) && (dxw.dwFlags1 & LOCKEDSURFACE)){ + if(lpdds==lpDDSPrim){ RECT client; POINT upleft={0,0}; (*pGetClientRect)(dxw.GethWnd(), &client); @@ -3369,9 +3386,10 @@ HRESULT WINAPI extUnlockDir(int dxversion, Unlock4_Type pUnlock, LPDIRECTDRAWSUR if(lpDDSBuffer) (*pReleaseS)((LPDIRECTDRAWSURFACE)lpDDSBuffer); lpDDSBuffer = NULL; } - else{ - res=(*pUnlock)(lpdds, lprect); + (*pReleaseS)(lpDDSPrim); // to leave a correct refcount } + + res=(*pUnlock)(lpdds, lprect); if (res) OutTraceE("Unlock ERROR res=%x(%s) at %d\n",res, ExplainDDError(res), __LINE__); if (IsPrim && res==DD_OK) sBlt("Unlock", lpdds, NULL, lpdds, NULL, NULL, 0, FALSE); if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=0; @@ -3686,6 +3704,7 @@ HRESULT WINAPI extReleaseS(LPDIRECTDRAWSURFACE lpdds) BOOL IsPrim; BOOL IsClosed; OutTraceD("Release(S): DEBUG - lpdds=%x\n", lpdds); + REFPROBE(lpdds, "RELEASE"); IsPrim=dxw.IsAPrimarySurface(lpdds); @@ -3712,8 +3731,9 @@ HRESULT WINAPI extReleaseS(LPDIRECTDRAWSURFACE lpdds) if(IsPrim) dxw.UnmarkPrimarySurface(lpdds); // service surfaces cleanup if(lpdds==lpDDSBack) { - OutTraceD("Release(S): NOT Clearing lpDDSBack pointer\n"); - //lpDDSBack=NULL; + //OutTraceD("Release(S): NOT Clearing lpDDSBack pointer\n"); + OutTraceD("Release(S): Clearing lpDDSBack pointer\n"); + lpDDSBack=NULL; } if (dxw.dwFlags1 & EMULATESURFACE) { if(lpdds==lpDDSEmu_Prim) { diff --git a/dll/dxhelper.cpp b/dll/dxhelper.cpp index e5ebe2d..5d511c3 100644 --- a/dll/dxhelper.cpp +++ b/dll/dxhelper.cpp @@ -120,7 +120,7 @@ char *ExplainDDSCaps2(DWORD c) if (c & DDSCAPS2_EXTENDEDFORMATPRIMARY) strcat(eb, "EXTENDEDFORMATPRIMARY+"); if (c & DDSCAPS2_ADDITIONALPRIMARY) strcat(eb, "ADDITIONALPRIMARY+"); l=strlen(eb); - if (l>strlen("DDCAPS2_")) eb[l-1]=0; // delete last '+' if any + if (l>strlen("DDSCAPS2_")) eb[l-1]=0; // delete last '+' if any else eb[0]=0; return(eb); } @@ -144,7 +144,7 @@ char *ExplainDDSCaps3(DWORD c) strcat(eb, sQuality); } l=strlen(eb); - if (l>strlen("DDCAPS3_")) eb[l-1]=0; // delete last '+' if any + if (l>strlen("DDSCAPS3_")) eb[l-1]=0; // delete last '+' if any else eb[0]=0; return(eb); } diff --git a/dll/dxhook.cpp b/dll/dxhook.cpp index 2d3d113..014885e 100644 --- a/dll/dxhook.cpp +++ b/dll/dxhook.cpp @@ -59,7 +59,7 @@ static char *Flag3Names[32]={ "SAVECAPS", "SINGLEPROCAFFINITY", "EMULATEREGISTRY", "CDROMDRIVETYPE", "NOWINDOWMOVE", "DISABLEHAL", "LOCKSYSCOLORS", "EMULATEDC", "FULLSCREENONLY", "FONTBYPASS", "YUV2RGB", "RGB2YUV", - "Flags3:21", "Flags3:22", "Flags3:23", "Flags3:24", + "BUFFEREDIOFIX", "Flags3:22", "Flags3:23", "Flags3:24", "Flags3:25", "Flags3:26", "Flags3:27", "Flags3:28", "Flags3:29", "Flags3:30", "Flags3:31", "Flags3:32", }; @@ -569,21 +569,10 @@ void CalculateWindowPos(HWND hwnd, DWORD width, DWORD height, LPWINDOWPOS wp) case DXW_DESKTOP_WORKAREA: SystemParametersInfo(SPI_GETWORKAREA, NULL, &workarea, 0); rect = workarea; - if ((dxw.dwFlags2 & KEEPASPECTRATIO) && !(dxw.dwFlags3 & FIXD3DFRAME)) { - int w, h, b; // width, height and border - w = workarea.right - workarea.left; - h = workarea.bottom - workarea.top; - if ((w * 600) > (h * 800)){ - b = (w - (h * 800 / 600))/2; - rect.left = workarea.left + b; - rect.right = workarea.right - b; - } - else { - b = (h - (w * 600 / 800))/2; - rect.top = workarea.top + b; - rect.bottom = workarea.bottom - b; - } - } + break; + case DXW_DESKTOP_FULL: + (*pGetClientRect)((*pGetDesktopWindow)(), &workarea); + rect = workarea; break; case DXW_SET_COORDINATES: default: @@ -648,7 +637,17 @@ void AdjustWindowFrame(HWND hwnd, DWORD width, DWORD height) dxw.SetScreenSize(width, height); if (hwnd==NULL) return; - style = ((dxw.dwFlags2 & MODALSTYLE) || (dxw.Coordinates == DXW_DESKTOP_WORKAREA)) ? 0 : WS_OVERLAPPEDWINDOW; + switch(dxw.Coordinates){ + case DXW_SET_COORDINATES: + case DXW_DESKTOP_CENTER: + style = (dxw.dwFlags2 & MODALSTYLE) ? 0 : WS_OVERLAPPEDWINDOW; + break; + case DXW_DESKTOP_WORKAREA: + case DXW_DESKTOP_FULL: + style = 0; + break; + } + (*pSetWindowLong)(hwnd, GWL_STYLE, style); (*pSetWindowLong)(hwnd, GWL_EXSTYLE, 0); (*pShowWindow)(hwnd, SW_SHOWNORMAL); @@ -1324,6 +1323,27 @@ void SetSingleProcessAffinity(void) OutTraceE("SetProcessAffinityMask: ERROR err=%d\n", GetLastError()); } +extern HHOOK hMouseHook; + +LRESULT CALLBACK MessageHook(int code, WPARAM wParam, LPARAM lParam) +{ + if(code == HC_ACTION){ + if(dxw.IsFullScreen()){ + MSG *msg; + msg = (MSG *)lParam; + OutTraceC("MessageHook: message=%d(%s) remove=%d pt=(%d,%d)\n", + msg->message, ExplainWinMessage(msg->message), msg->wParam, msg->pt.x, msg->pt.y); + msg->pt=dxw.FixMessagePt(dxw.GethWnd(), msg->pt); + // beware: needs fix for mousewheel? + if((msg->message <= WM_MOUSELAST) && (msg->message >= WM_MOUSEFIRST)) msg->lParam = MAKELPARAM(msg->pt.x, msg->pt.y); + OutTraceC("MessageHook: fixed lparam/pt=(%d,%d)\n", msg->pt.x, msg->pt.y); + GetHookInfo()->CursorX=(short)msg->pt.x; + GetHookInfo()->CursorY=(short)msg->pt.y; + } + } + return CallNextHookEx(hMouseHook, code, wParam, lParam); +} + void HookInit(TARGETMAP *target, HWND hwnd) { HMODULE base; @@ -1404,17 +1424,15 @@ void HookInit(TARGETMAP *target, HWND hwnd) if(dxw.dwFlags2 & RECOVERSCREENMODE) RecoverScreenMode(); if(dxw.dwFlags3 & FORCE16BPP) SwitchTo16BPP(); + if (dxw.dwFlags1 & MESSAGEPROC){ + extern HINSTANCE hInst; + hMouseHook=SetWindowsHookEx(WH_GETMESSAGE, MessageHook, hInst, GetCurrentThreadId()); + if(hMouseHook==NULL) OutTraceE("SetWindowsHookEx WH_GETMESSAGE failed: error=%d\n", GetLastError()); + } + InitScreenParameters(); if (IsDebug) OutTraceD("MoveWindow: target pos=(%d,%d) size=(%d,%d)\n", dxw.iPosX, dxw.iPosY, dxw.iSizX, dxw.iSizY); //v2.02.09 - //if(dxw.dwFlags1 & FIXPARENTWIN){ - // CalculateWindowPos(hwnd, dxw.iSizX, dxw.iSizY, &wp); - // if (IsDebug) OutTraceD("MoveWindow: dxw.hParentWnd=%x pos=(%d,%d) size=(%d,%d)\n", dxw.hParentWnd, wp.x, wp.y, wp.cx, wp.cy); - // res=(*pMoveWindow)(dxw.hParentWnd, wp.x, wp.y, wp.cx, wp.cy, FALSE); - // if(!res) OutTraceE("MoveWindow ERROR: dxw.hParentWnd=%x err=%d at %d\n", dxw.hParentWnd, GetLastError(), __LINE__); - //} - - //return 0; } LPCSTR ProcToString(LPCSTR proc) diff --git a/dll/dxwcore.cpp b/dll/dxwcore.cpp index 55fdf06..74c3782 100644 --- a/dll/dxwcore.cpp +++ b/dll/dxwcore.cpp @@ -209,14 +209,14 @@ POINT dxwCore::FixCursorPos(POINT prev) w = rect.right - rect.left; h = rect.bottom - rect.top; - if ((dxw.Coordinates == DXW_DESKTOP_WORKAREA) && (dxw.dwFlags2 & KEEPASPECTRATIO)) { - if ((w * 600) > (h * 800)){ - b = (w - (h * 800 / 600))/2; + if (dxw.dwFlags2 & KEEPASPECTRATIO) { + if ((w * iSizY) > (h * iSizX)){ + b = (w - (h * iSizX / iSizY))/2; curr.x -= b; w -= 2*b; } else { - b = (h - (w * 600 / 800))/2; + b = (h - (w * iSizY / iSizX))/2; curr.y -= b; h -= 2*b; } @@ -326,6 +326,23 @@ void dxwCore::SethWnd(HWND hwnd) hWndFPS=hwnd; } +void dxwCore::FixWorkarea(LPRECT workarea) +{ + int w, h, b; // width, height and border + w = workarea->right - workarea->left; + h = workarea->bottom - workarea->top; + if ((w * iSizY) > (h * iSizX)){ + b = (w - (h * iSizX / iSizY))/2; + workarea->left += b; + workarea->right -= b; + } + else { + b = (h - (w * iSizY / iSizX))/2; + workarea->top += b; + workarea->bottom -= b; + } +} + RECT dxwCore::MapWindowRect(LPRECT lpRect) { POINT UpLeft={0,0}; @@ -341,14 +358,14 @@ RECT dxwCore::MapWindowRect(LPRECT lpRect) } RetRect=ClientRect; bx = by = 0; - if ((dxw.Coordinates == DXW_DESKTOP_WORKAREA) && (dwFlags2 & KEEPASPECTRATIO)){ + if (dwFlags2 & KEEPASPECTRATIO){ w = RetRect.right - RetRect.left; h = RetRect.bottom - RetRect.top; - if ((w * 600) > (h * 800)){ - bx = (w - (h * 800 / 600))/2; + if ((w * iSizY) > (h * iSizX)){ + bx = (w - (h * iSizX / iSizY))/2; } else { - by = (h - (w * 600 / 800))/2; + by = (h - (w * iSizY / iSizX))/2; } OutTraceB("bx=%d by=%d\n", bx, by); } @@ -375,6 +392,37 @@ RECT dxwCore::MapWindowRect(LPRECT lpRect) return RetRect; } +POINT dxwCore::FixMessagePt(HWND hwnd, POINT point) +{ + RECT rect; + static POINT curr; + curr=point; + + if(!(*pScreenToClient)(hwnd, &curr)){ + OutTraceE("ScreenToClient ERROR=%d hwnd=%x at %d\n", GetLastError(), hwnd, __LINE__); + curr.x = curr.y = 0; + } + + if (!(*pGetClientRect)(hwnd, &rect)) { + OutTraceE("GetClientRect ERROR=%d hwnd=%x at %d\n", GetLastError(), hwnd, __LINE__); + curr.x = curr.y = 0; + } + +#ifdef ISDEBUG + if(IsDebug) OutTrace("FixMessagePt point=(%d,%d) hwnd=%x win pos=(%d,%d) size=(%d,%d)\n", + point.x, point.y, hwnd, point.x-curr.x, point.y-curr.y, rect.right, rect.bottom); +#endif + + if (curr.x < 0) curr.x=0; + if (curr.y < 0) curr.y=0; + if (curr.x > rect.right) curr.x=rect.right; + if (curr.y > rect.bottom) curr.y=rect.bottom; + if (rect.right) curr.x = (curr.x * dxw.GetScreenWidth()) / rect.right; + if (rect.bottom) curr.y = (curr.y * dxw.GetScreenHeight()) / rect.bottom; + + return curr; +} + void dxwCore::MapClient(LPRECT rect) { RECT client; diff --git a/dll/dxwcore.hpp b/dll/dxwcore.hpp index 88f3c75..4b2f522 100644 --- a/dll/dxwcore.hpp +++ b/dll/dxwcore.hpp @@ -41,6 +41,8 @@ public: // methods void MapWindow(LPPOINT); void MapWindow(LPRECT); void MapWindow(int *, int *, int *, int *); + void FixWorkarea(LPRECT); + POINT FixMessagePt(HWND, POINT); RECT GetScreenRect(void); RECT GetWindowRect(RECT); RECT GetClientRect(RECT); diff --git a/dll/dxwnd.cpp b/dll/dxwnd.cpp index 4fdb87d..89dfac1 100644 --- a/dll/dxwnd.cpp +++ b/dll/dxwnd.cpp @@ -24,7 +24,7 @@ along with this program. If not, see . #include "dxwnd.h" #include "dxwcore.hpp" -#define VERSION "2.02.33" +#define VERSION "2.02.34" #define DDTHREADLOCK 1 @@ -32,6 +32,7 @@ LRESULT CALLBACK HookProc(int ncode, WPARAM wparam, LPARAM lparam); HINSTANCE hInst; HHOOK hHook; +HHOOK hMouseHook; HANDLE hMapping; TARGETMAP *pMapping; DXWNDSTATUS *pStatus; @@ -111,6 +112,7 @@ int StartHook(void) int EndHook(void) { UnhookWindowsHookEx(hHook); + UnhookWindowsHookEx(hMouseHook); HookStatus=DXW_IDLE; return 0; } diff --git a/dll/dxwnd.vs2008.suo b/dll/dxwnd.vs2008.suo index d6d0d609399d1424ef9f4636b50d253753c1d168..c09b79abee443986d77925dcaec942f9d0d1b314 100644 GIT binary patch delta 25515 zcmd6v2Xqxx`|f8CX@n311PGy>By>WNCWMwo6Fxdph0p{MX#!F`5kVADfg=nygoxN7 z2omrU#qQ^)6vc)O3w9Be&x+(e&zxs)OzJ;vCm8#&Pm+-Y}R8d+p(NRlh%bvYfm=KoeL>u4@EX-Bm^LBS8n%Zu9u&IwAMvgn z<2K@GgU-7a_5FReyEcB;{QaL7niB6)*VM1L8HcvOJa2_-vP@~&gRU9g;(~docuQ1& z7XEXbwcgT8%%xsTzRC1*dzw@)x3ft#&AcC4n}#TL6SLhLpJN(&#qDsc^a_*Wwf=`m zFiX8b1)ytsnI!LUYttZdVD3<}*ZX*(sqY;hfZB~6U{WiNM+WSnuF(Ube3R}CTwv18 zNYCV(LEg{;Gnjue*%+zb=F3fDB=>@3Z(xCG;1z8!Exjc@phCZ!Y;%`4yAN_KEd+gj z08S~o*Q9x~+L&bHde02Nq1MBYMs^`ub#5OV_e(ruxv61h@YF1Cb2gG`?LE`S^z|ND zftnn+0yRnV4@N@o*6>O%HgVp;3r&h?;@96R?T!?a+M+@3XMz3trh03pf!66|8kn}; z_*B!>lzFDNS>YY%WeTIUL9?`uHtCu?_@3=+Qevl~9s2uqhiZhk5%%9=-xFRin!3z}(nU(?PzKF+i>H+ePtnd_9mRGgaJ4?XF3 z1q$z%rlnUj37NOm6U{hSpU| zGSj22hYm{fN(Z2QD@NNF6;Jna^G&jMV1S8SrgF& zJ%^%2Fci9YMQu^|q@nn;WU@)C(AH_^t=(aUY$0mJ5Iu!al8&k zVyf4mt?B2TZf!D=pFbAUtY*R>NH;fIqaPrK*F@Fm=tHZedZ!-O=xfYt_QGhb2-)We zrgHT3H4Bixe>L^~dkgrvq*$GSvZi|J%TZRhJ%&NiOQyA%9qm#7iaD3#wrH#P&~Jfz zt!Bb7&xsUON%OAhU^+%Z$=P0h2ek6>y)``ls=e;qpi1(#U!r!N?-zr87Rh{}rFqQy zxGyz2x9m|XPs=v3(OC*Jg+F(t8RLx`itC}MS37f&RUx!fn)hT!R4AB?a7E>Z%mgKM zyoooX6FN28H7&B^+v8&H?Mx~wA7IenkL6=UA zV54>7l$&M-dU+Y9zG)lD*jJOcg~Tc|aBsTWnyPoPHU<80OSB4)o=f+hYJ*8C-|B;Y zIRIPE&C;pf_1$=(bjR!&%#Jm@*L!33iH^@aQ+2~M6I0f2gxT#zUhkF~Trr82&nt&l zYqVKv{^4bCM)glUcT*@!9%Futtv<<_ggeU|XC`jg3sHPdd~^JM=kg-jx25MwdPk(> z+vd??`nR8RshQ@{#t*%lZJPS0>ni1yboIG@7tF&|8G6$+GxOACm#2HLUWl11Ua6#J zn*o}`^GvoTKFplnj3Fk3i55-kPw%+ACSWl5_e0Eo+0pst)NpvV9Etl{&LoV{%}1MI zzW47(XoCKcq7}_>oVQH>D)ld}>60;F{2P^jX=55q^y-n#os8)emvslu;r`W{Y#xdh z4KurDsVUz6huoE>C|WM?q)5xWkh$FIcMe+4N8YL_NRT&@$b>tx&2G!Z&pBmn0{I<_jhsAr`7&5W|pbhA0ZOBjv0>cAqmUu;^8<0Nw}mCj{iEttL9dN=_~ z#{{pq4cdf#iy1U=&wO*6iOIr3$=i6f3H9QV@l;%N>G&h!|G-YeO5yP{;zo#nMNGfn z5r2x$XY~0j;&PZ1??kRWdXd+%5ciH7qiuC+DmurSV50*#fj!rOD~U9J){G7h|6-Ws z{V>ghz2a7;URk|G=97x?(XmUw|v+YG|=;V%b+ibW@~3O8VZ z{q)@0+aALrBY(7+{kP5fG{izZssKYCGmtL|l@iP+{I<7Rf!3=D~S8Y143J?5R%K}Ntv21llrnGrE3@Tu(i zGSjZAyCk{n_kWrG)y?DQwYxX>BXiU|`8Rgl9Evl0k?)J=9VnaovFTSkb-L5mX=6>z zKhi7>kD zfK7riTnQs%m=TSfV#H)Qe(!J|h-o(H@*lmyce|~;YnxT*Q}?huxE!ZuI0EBW7{{AE z$<)NRfFr$ebHwU2CaH8@e=jA*E#2^(J2yNCC;bDygAp?q>IO^*VZ0dmROmK{FBi*! zo*=(DVr-17#I}p^+$W(MAl@%F8hS_6FYLTxIUa>Bz`=LKMnV5O>gfC_#*gusu=r&z z0WmYkhMkpPRWZ(I)u0*biKRo=7i;FTuz%cXE|@LHSm4gkO!HzfX4D@VUpSqCVm$sT zG;4lHEED=8=(>oHTkN#hf5ezxesT;3HbenpfU>Z07n+z6klq>BEt)(MY8Gr1Y${8f7*!MWE2=RE>0N6=@wIC*i_i%uq$BmVbft(!e+o`!WO~KdTT4VjnkGu za>QIiggA`&TG*Z#x7b8N^XhrqMw|4=t8=G%P3B?7EFFzm6swGWWvk=d-Em%KYm*yB z-JE`?OB&*V(K`7(GzK~YY^)f+-?yMM!elY-CR_&1FiWgH^lY)PSZ%OkvDIQs@8%dM z+MRa`f;pSyxJ8Ut;=|C55I;=7Bj!%j;2HP+8 zEMg8gp3@VCMK^bYye-`@Q|UWh!k!ejIHm!|Vw6WB#CZ)>XCCEOV* z2S(2>h`YkN!Mek8VR^88SOKgM)&tfP)(dt$tPkvBSYKE_*Z^367}Fbwco1wTY>3z} z#FxN^!$!no0FHzh1se?;1G^M97B&u61RD>V0GkM#1e*-I3^oNe6?Qpn8te+#bl8=! z8L*kKS+Lo#Ik2l>b7Avf^I=!R7Q|!nSqQNRwivbqwiI>^EDS4#ZL8rnNd9Y+sOf<( zx0P_lt$pcA!4P7sFZ{3pf0aR0J<0KSuq#! zi~iCFUm@%5>Eh0h+G!|gi+ul!AuQMP%6Ta@7y?{L$-J7&9$yk%{$Xu>znnC*$% z?_oWvW9jQ>(E@Qro`_Jz8x(d2dAAHPsgaWTS`nVxL@Hag*q!gjkHHXL;9Tuh$v4%# z+?~;Ff>7jmel`~7(e0YV8j+uS)~J9|N5Z?tVHMgv_7uCtb-e=*xy2hcxi80HDE_q*>z&@@4u~`RQN(Beww$@gUF~|g54)+}ZR_1^ z(=U=YKZ9GZxn9W`>@ZE>HpbK|urkBMp2Er4+gV~-R2b%5<#nHDYK2R&AIqvEbX+=0 zbB*JKmQcIrK0D*!@Dhy9Lty)044=cu*ei(;7a^{Un5--83m8KiG4fvcGXZgL<23di zIcnPS2*M?nV-YlWdnXz1>@qjg3vG4pjWgRoo;bf5PH%OSOjo9m47(1ZH{$D+)D-C9 zJczJXjD981tjkui^S%tEm#x|6wyqGq5J%VP%u<~RX6t+Vq9__7yChs=l*CMFR##KctsDnMV$1VPH1F0vaK)1A6|C-#K^~rjT2+NbD$Zn z6k7~ELo6&d5Ug12Q8C`OxV~d3b1~;J1H!$6N95QP>~*oq7-00{e3Hz;hL9yjei8JQ zh&zd00o_1;y)3_>(7Y`T6C25!es4KW6zl|tNn-OXHec*Uu@3NCCAQUK_ldnEHWGd> zi+v*25bRSjw*OCp&7ir^V`zXYgf(NwHq_P9T#SvvHD3sEp%{I8K~F;5UyObep@$+4 z)=5nMYOn!_7b50D&Clo_eBj-CGva`4gJw6}FIEM*6EwpcVq6Oy6$_RtJpQ5BNAlyj z--`YI7YjQHx}#S?%#5eOs*2SY8w?f_<8p+4oCLTeVJH;i_1;5lv>1KILUUDFB*vB= zn=W!;lafr)OKo%f~LTfM_=?_HZ@x^F0T zPsjcdhg>5IH#YV{%iN){-{a#5el+bOTY6;0K818&IB)u?^b=e*vI3Z1%_LLHYk9_G znp>^!{{9~9J^F6`bc0CJ`~>VTVlSs5x5iVWU-G%1i{HGwZW(5tzm6T z!Z{&QyfK75l8j~UkhmX^^Q!pBqK%DAdz7xRdH%eT#b(5-F4&@F;a@@#C!XgL_ZyPv z8RI8$5q%P#gU@-lpV(jEGRkj)PJXtrw<6ghfQA)1I<5VLU&cwVoR@IyB{=I#IbG-% zuKsxraiieSCKfq2Kr(IoloRTMt;6Uq>sG~#bq9Tlk8D_8BZHA?24XJ70>%{*S0r2+ z1?(Q^Jh07TO`y4r!0^vV-WRpQjiEloQI3v}<<$uKduWdRAI1D!u~6s_HXJc?U~2nu zoFObW2f7%VVY$Uth}|f56^^e;@Fx?;xy6FF$}u9=1di*)_KPv|m!WeJAF|kS=)Pbd zi}izk8k*r(vDwhSiT#;?$&85+o)vVl1PWLMEr;SQmLQfSR)}*ei`5ky1XfQhTZ}E( z7rGwefnrrTnGVGV9vmaculhw|lf-y@6LcTM_gbtJnp4eAF&6v;bW_Bii}BnTtR2{$ z6%o^CGOQ(zGk>SMAZOa)(4416SZp*j=czGbOkleFW{Ppz$%STEA;wvJrPvxVo_iZ~ zFT@)Xkv{?LaX@CgSB~AG*FiHJ72{3!EwP`)hJ*bg7F#Kr7SD-;W{4N#SLOt<46(sZ zuH$41b{Aw}hC^o|9wl}SbgulyT7H*R+Vhm_CWdoxe2O@`W1M^!S-$I``Hgmi7{6UC zmf!7SQ^4*JD-$aK+bi~@#rBImQwg_R7MkH%!58J22lkTK*J4cYn_UanO>zBO=|1f6 zu*^>&W->Ej_d_$hAl4K5Md^Q8>=o(PEOt=(h+_8i>(Xyp?5)bW`i}`VgyT2R4Bv}2 zhkj420v4()U_LCCi&lgxVmvopte#j$u&QEB#dt0BgyssTSF)~t_Czx|PLLyzGf`}^ z7{~KvVhhDC0b3-tT8xFf6?z2X4Pq={2{f;<`@}l)>bn^q7-uSA?As32;BqCd4IFm zDCmvydsnOh*fBBwTEv2IE0`-J2CO8av)>YY;Lk=3{JDsZ?213dOnj6r19PDn;=~$3 z$BU(iac7~5Sbed^U?H&X*zL3b^22hs^M25U-=P}@ z-%9^r7$CH*y~heojnVU+xYKYcA`F*f_r;RhE#w{Tqy-97fijA1DwK5L42U z@TW22WHH`&EAjwBHL+&UsbZO89P?SmAMuWJp&+Zp?Ffd8#Hc%pbrR!8Y*F}I34O%I zf#vW3La0Wm+P!aj!Jy61DTFq?tD3^4pG$ZdyT#QqfH@v~wTFbXI+1GR-_^R^RP z1s%gtf>0>N8&5B>p<+B|nCnl8m<9wn>c_~j7_mQUBN@5Pt>?T#;cIc(EQ4JKuR|P>UXOSK%!Bcgyd8E2>`vHSu)ASAhhHA> z#i53?1)>CYFKjF9KG-(zhg7$D<(-g^!FIuR6BVqTHLJ(R`1A>kseFd`1nhIz7qBm3 zU%|eHeFOUz_8sgbj9)rV!G3`K$kaMlo`t3A96fsR|LlRcVYn;?qc0eyz}VTfboXMa6ODH9kvq2a1)G-BXl*)zY(oLOi0@Z<7|4T zK641)2jfQ1{T6!!n&0`hi`79~3gbw9T8#PtECcp3jOpjY*1{ML!}1APyCX2_<1lny zIihogaxrIJhR-qn+!d|iA4&AU;<&Om3r}`=3wrYjxc`rz9?bTh?~4b${_j6I81JDO z@XNk;WSXhwoxH|P^DaAz=PPnM;nBWx&!>3XufY~P9)d~p_%Mq%^cpwYJN}^CGVTGt z9ld@z?gwFiar0|@wCR&^ARXUL*)8>g7&;A_Atc7WuPK%(R+SFWnTWE)_=CeANSmRd z#hO5KQPni~QcTD0f;}w9UShp1cClDLF;1xi#0FV@L&S!O)rQ{)u`z)ku14o7!FiVB z0sUFu^+`wi?R8Cfo7q96-(x96o>Uvd%$4hgOdn1KFBH}W&s(v@xe?kuviT-F7g7u z`eGSk%s5lJndQgLk_zm9ZcgyzELbb)HkM;MI^tLdixrCX6k{g+pxIje#W=0!Lo)=s zFl^P4@*9QN|5{uNaF`%>V_29BSg<2=xfnB<2%U|1rp4w!GhAgc?)20Ln=8iSOQBhj z@Lw$K+$G2@pP&gJ5!)`tQgd0%@Px&l6nj;S1w15n#PWL+n)jHuEx%*X&DsC&S?~iN zVw+Hm8GZuIQh#Ro{Rqv$`jZ%&dJ#0kFJjagiTH&caVBC`juqh+6kC^DNd6*~@Hd=v z4$83z4$NeNb@D=J_VFSy)_957QZXRsPG}bTZZYQZ2sAIn?G_7{3huPvZZYmtvD7tT zd&J7bc$IMfiV5x$gLIySX2#E3>}9c6#MoLJp%KE)LCf)o9N!S*9rr!x3lM)O#*9A_ z`$UWdJSP2_VqWK;OMj=B1M++6Gk%QzC;U?|QTs-`5mkb2jJUEGGfoyu5kusp;}2_8 zTa4XUO}egPb`v+>njy{-W1$;|^&wj^OWjJktz!0FBWM;hV35v5U~KA6mR~n$Ue3V| zAN}&>S13QSK4Rg%g3M$PGzZrZF_wCSSg<`vzhPimh)2s0(&1Ji3sWS<9s@&7TU*Z<=XhSfe`YkT^qaF=l)bbQA0If;3=kw6 zEH=bq3!rhKI7`KtU@j+ZWm+a?hw0Ej0N13gbRnY-zCVC40Q zF2|LC&xfpIpFwjvJt4+~KNtJL@;eKCA&!+>etf!*%phi-%qvzp(PAO!&Nvp%5M(Bq zf>~m0A$~XDqO*Y*6YK(g5#p|5Jhz)zcQIa`O`&;it{5--JZOe~Q5JTX$vAxAq%mHO zWD~_Ei?JITLvw$2s^xbTGz&9Vj0Ic)-5v4uVl3cFu^Ys=x?WcqS4JGfRzYTRB{VO? z`^1{}W>9ekTs8vLXqHgY+swV+rU~5~E)=`BfJSGvgX^OcO-p)W@HO zh(luZ%Mi;HL*#VF9~L@SjDC4y`C=%i(;S+i(DLiyuS@~Q3esT)G;2Idj5VGD&3(st zVu+ku@P`HDzI;&QHDYVU5ILLihZEQqF&2>f_GI@4KN!$)H~z3$AGaL$h?R*Ua$dk6 zp8TR16MRYRWidp~yZGbxu^9chm+yD6SatT<6Uh!A|6dWa?br=}^7$>U9Q``gK+O7c zIPyjs)RR*YFD!0Bka1e%#YJB(RmhNo-##r6bJ`0ScNbVqf0jVZVsV}&YYT&4*gu&U z70cQ&3VlazSCHk1F~dQyF|fg6>}_6r48vf|n3?dxWta{N3d6k@PJeU6=yw%&YzVmt zLq{gK5XNvFEJ$#Po+Z*kCM128@ly5VQ$9ic>2?K8$|3umTvvP#75l+lOHUjI1GSB#dD!jBE#N9E@Qq z3=Fdt!sY(o=(Y_VS%4*Cs}YkiuzeV|z{uFKB`}8Vu;5%~#PAY~EChQQ#_%PKjNvPP z+(Dd#5psBb4`c9B&YD({mW%6oUzNC*c;nBS-WV{|o%p!hT-;U5%U`n|%6oJN_rd%S zdSu7n_tvY2f5IVVz!IPK-SD%KSbM~Oh*f|S{b=#{!y(Eobbe+t#!w&xTkO2oTp(6g ze%-+8iDgGw*#DKFg<$ZM9}@~5=xe8w=~93{y%86RvCrD`0Ky^`E`@H=Huhd$cC@cs!msh#ZNBTdmh5$8F+oD{!q+ zRgSF?^E{@@+B0z4BdZ4+4r90m7O?2GjO{5gp6kIFo`D5^&-#Q{UzB0K4m)29p0ymy z#hT$vo*aTTr$FFOK9u!g{Mm9A{9c36L$86|{&=(_~ zB*v5ZD-FYJF=oPde;AgEvH7nN`&o?L%SSkQRq#p8pfF)R%h?5RxCKW-vjC&SszdWp z&O*dfEOrw#uZp!6D}iPv4~d1Ke^Fsd#n{q2p%KE))0X3bD0EJWu@K*jm5VjtX_|AZ zB4$l8Vb#Pk#Inf6E)ipE4HsMBv%b-l1)t$$xL%GNAS=a!$2Qrl4~XrTA2WUm`cGW= zXV;GJ8^a$M`L*bg=&zaw<;TJt(z$$NgoVz4{VG-$mo6FYCTP}qvshE;de98p#8?)- z_`&d)7{3khy$^<`Vx4$RM&9<$ZVuK6JExe&|L6ZOKs|42i96i?M?-j5oLK+AzX!5P zF4y*XKb4KP4Ok$ zfp=chh2LlYS9e|{;(BkLH4mQuJNW-jIp>F+dyow?Wb8}a1tY5hdj^&V3)UY@?`7Bk*g+Wmcqwj$F&u#zu7yGnM`7&Pw_tSSBJT?r*_SXf zCdlcNj5BB8$7KZPhcjaI`%^5KSwlRA6L<%85%XMzINk(Uy95jJB>^(7G4Q`1s*BYW zO98ETBH@qlz2Ff{|B(JGbWDLu3Hyb< zlTf9c=fz$W3&HOtX}gO=YR={JIxFnHDSC0b4)Z|NXQ__o-)VnELO&@AAG zVp-51Nq=hjeJ;N*#hCV2(kIXPq5V(E@kc@S`w3`<;O$-i19D}?F8&0yt0We@CBmlW zo4j09)si36t1VX7Vj(j2f2IWspm_%`ve*PME+?2V6Xa{a-4M?bV+&p-eYIjBXCXBH zcNUAKLobnDhS*=r((!tH!2iw-I>=0d*G+B_qaW8T^oxk`in&et4#jMRHFQF_Q;d2u zG;zsaEbKfi_^4n89JWjE{>#zXBfq_3A^7c+4%S1wN;ZKp9MCc9=b(vS5UUUUqOZ~Z zuL;tTFGJ&h=ZF{!^SboginGAplm1XK?@z~|yCV)52k=K?pUID{`Yv=F;uB=-e}=E{ z0slMS5F%~>`&Rk~#cWpI-FqSqSQ2zG1}iV)ALR$>@NI4U@BAXhbGaJiz%;n;2jeIl zgAaspf{;!nXr5eIj3*~T^Abw2{J4CiUv)7KLcTr3??ZfZh?%ez8i_R)V|sj}2yxiC z&~j`Og-%Dyu`_fUPUtDdOh!VtN6Z)cf=ot>@s({dW-<<%VY*ldny+Q^_>mo;(wpfoocxz;KiN@Xq!*wo&X3F&1z)bVJ0Ci?J2uk+<_Hf!)s6CL?Z z6WN<`oW#)@ybr}pxPoH{UdyI#gLBw|?Q||#ff(P53R{Gti&3kk3LKT~8A2-8UJig$~ zn3)`b?u__#F+|QAVn@a3_l4M(Vu+lt#J(0|AMq`8hHu4qy`GW|ms^mH%|cwDn3<$N zv$Imgm=?E?$@u6r{aL&3ae#f6F2>oWu5|EdH5nhR<~i-6adh9eJwDV2?4*OtBuA{9 z7&GY&&1Mar%Z7A@fU)z3$*&UhrO<5Zv0^-zuTL@KBE=lpgW_}zULgqP%z|cue2$wZ z&~Y&|!?l**D*3GzV$p7%=!a@rdcj zZ~-(Et0Tr&#>qmk;DPZhF%Gy!(#;h!kA{5tpPLUhYy}4vCSQ&$ApcbXvVVwi zAn_jxARA|~iDHv1Hbsp8Pyh?abNPTd&%HVx{ZGgNw?L5p7yubd$bSrgj>Te-{^PA| z1wKAYKZbju$?g+lCJ#V!wtCQFd|WmQ>>)A#-7P*xOZadAp>Ks|cvOsq;q$oclI<3I zi~yljtP}JL&@A+eV(j;q#r|!v*P#8!)DBwkh#X%R;~MJ?v7=(0!QK>mON=e}w%9vj zY=!rs+aTtnyg~DyfbI&0M|S^uOzkw_hsl36>8H?a(i37#>`Q2FV0|Tq$VtNOs4?Qo zh=Z<77P~-9K>Gu+YbS{NvVaADZPq8mFZnA;S}^g`>xn> zycU{lnHZ$A0-B{>DaMR%kX~c42sAIb+r*ghda(_b-yP7r-QSsFUH^9p-fcNPF1AOE z36_cNwftU#=7>IM`5h8FZ27$n&GGh5;K%#VyMo6o$B&^oGky{{LVqgundSEzG+XO; z%kK}dGnQW!+?#oSsERnaN~%GJ2~!2xthJ#zU)Ql5>x$L0{2D^D2^(2{jm4T+ej}k- zz)_apXt6O>bp12qnS!${$Jt_Y#OQYqbSuQ0Ex#>dC1U($@(eU5$LB1+=b;n8UOeZA z_CF}c!!Y~nBX5`XT*S<3b=i;F#I4&V$9@bXwH(G#i~IYXpXHdVvu2HD?YG< z+XR`(ZaF?K#=`6oE3^Dw6nn|?ds*yXmftaGw$^)=-}^p8`+s0Lo|NPFmg6b0A1uGK z(5y+h<;Q0g$qZsPH7k+=&5Wyvu_9H)s*$n(=@`NXo}6JhW{PEr(XS0O6KrewwG(S^ z`Q=0N=2Kw#6^iw+{K7*8hgpu7hz%EGe~yCY2%aVe>0AlTuA6DGC1TfzvCylaGZ5b- z##UGzWnt%L%kd6qUfXwCj(3UOZTUR}%>*B|{2mc|)be{m?4Oq3lVbaQhW1D7Eao4C zr+pah67IWm<}!%cpDeX2RzZv{Qv;f}+mIM*+zp!D*XwMv@2p8jXs(btiLt4> zLvx197h?enptBJ7@cuZ1A2?W#)j(X6+-$ksB6h17{Wd{!V!g-m+bp)l^4kmD7JmCI zzbC~0Y55(jj>(mdhb+g#ay%l&+sjkX3~z{0zXQ!SI3`Ayig-+cZO{-g+l8!&ShiRj zuvTKNYlQ!DY$MoFj%?H%vCbCjD%Ra%`C>gS)<>+b7{_;iu>oS$k-sxga8Llj28#_5 zW6up08z#mAj)883_);;}xJYcg#U_bOw%7=0=I=}q#0YcVVhRYe#n|u5pqbfqVl2#Z zu@#ozI%tlgh~;;i*m}#a44UJ7Zw)Q3nBYFaCoIQzpc~@YyJGY^Cib2f3-&EE!$~nN zMdm`YE-AS5ITl!vd}wA|AQsDisiIJ@hvhgzY~(pd++M^+*Ypmwz`wTUrkI}I_01|Q Ky1)1)WBvzyT1Kt_ delta 31962 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 diff --git a/dll/hd3d.cpp b/dll/hd3d.cpp index 774e533..03a717c 100644 --- a/dll/hd3d.cpp +++ b/dll/hd3d.cpp @@ -627,21 +627,7 @@ HRESULT WINAPI extCreateDevice(void *lpd3d, UINT adapter, D3DDEVTYPE devicetype, RECT workarea; GetClassName(dxw.GethWnd(), ClassName, 80); (*pGetClientRect)(dxw.GethWnd(), &workarea); - if ((dxw.dwFlags2 & KEEPASPECTRATIO) && (dxw.Coordinates == DXW_DESKTOP_WORKAREA)) { - int w, h, b; // width, height and border - w = workarea.right - workarea.left; - h = workarea.bottom - workarea.top; - if ((w * 600) > (h * 800)){ - b = (w - (h * 800 / 600))/2; - workarea.left += b; - workarea.right -= b; - } - else { - b = (h - (w * 600 / 800))/2; - workarea.top += b; - workarea.bottom -= b; - } - } + if (dxw.dwFlags2 & KEEPASPECTRATIO) dxw.FixWorkarea(&workarea); hfocuswindow=(*pCreateWindowExA)( 0, ClassName, "child", WS_CHILD|WS_VISIBLE, diff --git a/dll/kernel32.cpp b/dll/kernel32.cpp index 59e3872..d79620f 100644 --- a/dll/kernel32.cpp +++ b/dll/kernel32.cpp @@ -17,6 +17,14 @@ static HookEntry_Type Hooks[]={ {0, NULL, 0, 0} // terminator }; +static HookEntry_Type FixIOHooks[]={ + {"ReadFile", (FARPROC)NULL, (FARPROC *)&pReadFile, (FARPROC)extReadFile}, + {"CreateFileA", (FARPROC)NULL, (FARPROC *)&pCreateFile, (FARPROC)extCreateFile}, + {"SetFilePointer", (FARPROC)NULL, (FARPROC *)&pSetFilePointer, (FARPROC)extSetFilePointer}, + {"CloseHandle", (FARPROC)NULL, (FARPROC *)&pCloseHandle, (FARPROC)extCloseHandle}, + {0, NULL, 0, 0} // terminator +}; + static HookEntry_Type LimitHooks[]={ {"GetDiskFreeSpaceA", (FARPROC)GetDiskFreeSpaceA, (FARPROC *)&pGetDiskFreeSpaceA, (FARPROC)extGetDiskFreeSpaceA}, {"GlobalMemoryStatus", (FARPROC)GlobalMemoryStatus, (FARPROC *)&pGlobalMemoryStatus, (FARPROC)extGlobalMemoryStatus}, @@ -45,6 +53,7 @@ static char *libname = "kernel32.dll"; void HookKernel32(HMODULE module) { HookLibrary(module, Hooks, libname); + if(dxw.dwFlags3 & BUFFEREDIOFIX) HookLibrary(module, FixIOHooks, libname); if(dxw.dwFlags2 & LIMITRESOURCES) HookLibrary(module, LimitHooks, libname); if(dxw.dwFlags2 & TIMESTRETCH) HookLibrary(module, TimeHooks, libname); if(dxw.dwFlags2 & FAKEVERSION) HookLibrary(module, VersionHooks, libname); @@ -64,6 +73,9 @@ FARPROC Remap_kernel32_ProcAddress(LPCSTR proc, HMODULE hModule) if (addr=RemapLibrary(proc, hModule, Hooks)) return addr; + if(dxw.dwFlags3 & BUFFEREDIOFIX) + if (addr=RemapLibrary(proc, hModule, FixIOHooks)) return addr; + if(dxw.dwFlags2 & LIMITRESOURCES) if (addr=RemapLibrary(proc, hModule, LimitHooks)) return addr; @@ -494,4 +506,135 @@ UINT WINAPI extGetDriveType(LPCTSTR lpRootPathName) OutTraceD("GetDriveType: path=\"%s\"\n", lpRootPathName); if (dxw.dwFlags3 & CDROMDRIVETYPE) return DRIVE_CDROM; return (*pGetDriveType)(lpRootPathName); -} \ No newline at end of file +} + +static HANDLE LastFile=NULL; +static int Where=0; +static DWORD FileLength; +static DWORD IOHeapSize; +static HANDLE IOHeap; + +BOOL WINAPI extReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) +{ + BOOL ret; + static char *IOBuffer=NULL; + DWORD BytesRead; + DWORD Cursor; + OutTrace("ReadFile: hFile=%x Buffer=%x BytesToRead=%d\n", hFile, lpBuffer, nNumberOfBytesToRead); + +#define SECTOR_SIZE 4096 + + if(!IOBuffer) { // initial allocation + IOHeap=HeapCreate(0, 0, 0); + IOHeapSize = SECTOR_SIZE*200; + if(IOHeap==NULL) OutTraceE("HeapCreate ERROR: err=%d at %d\n", GetLastError(), __LINE__); + IOBuffer=(char *)HeapAlloc(IOHeap, 0, IOHeapSize); + if(IOBuffer==0) OutTraceE("HeapAlloc ERROR: err=%d at %d\n", GetLastError(), __LINE__); + OutTrace("ReadFile: Heap=%x Buffer=%x\n", IOHeap, IOBuffer); + } + + // if reading current cached file .... + if(hFile==LastFile){ + OutTrace("ReadFile: BUFFERED BEFORE BytesRequested=%d FileSize=%d where=%d\n", + nNumberOfBytesToRead, FileLength, Where); + if((Where+nNumberOfBytesToRead)<=FileLength) + *lpNumberOfBytesRead=nNumberOfBytesToRead; + else + *lpNumberOfBytesRead=FileLength-Where; + if (*lpNumberOfBytesRead < 0) *lpNumberOfBytesRead=0; + memcpy(lpBuffer, IOBuffer+Where, nNumberOfBytesToRead); + OutTrace("ReadFile: BUFFERED READ BytesRequested=%d BytesRead=%d where=%d\n", + nNumberOfBytesToRead, *lpNumberOfBytesRead, Where); + Where += (*lpNumberOfBytesRead); + return TRUE; + } + + LastFile=hFile; + Where=Cursor=0; + // get the whole file + Where=(*pSetFilePointer)(hFile, 0, 0, FILE_CURRENT); + if(Where==INVALID_SET_FILE_POINTER){ + OutTraceE("SetFilePointer ERROR: err=%d at %d\n", GetLastError(), __LINE__); + return FALSE; + } + if((*pSetFilePointer)(hFile, 0, 0, FILE_BEGIN)==INVALID_SET_FILE_POINTER){ + OutTraceE("SetFilePointer ERROR: err=%d at %d\n", GetLastError(), __LINE__); + return FALSE; + } + do {// try to read it all + // when space is not enough, let's grow! + if((DWORD)(IOBuffer+Cursor+SECTOR_SIZE) > (DWORD)IOHeapSize){ + IOHeapSize += 200*SECTOR_SIZE; + IOBuffer=(char *)HeapReAlloc(IOHeap, 0, IOBuffer, IOHeapSize); + if(IOBuffer==0) OutTraceE("HeapReAlloc ERROR: err=%d at %d\n", GetLastError(), __LINE__); + } + ret=(*pReadFile)(hFile, IOBuffer+Cursor, SECTOR_SIZE, &BytesRead, lpOverlapped); // read one block + Cursor+=BytesRead; + if (ret && BytesRead == 0) ret=FALSE; // eof + } while(ret); + OutTrace("ReadFIle: BUFFERED FileSize=%d\n", Cursor); + FileLength=Cursor; + + // recurse ... + return extReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); +} + +HANDLE WINAPI extCreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) +{ + HANDLE ret; + OutTrace("CreateFile: FileName=%s DesiredAccess=%x SharedMode=%x Disposition=%x Flags=%x\n", + lpFileName, dwDesiredAccess, dwShareMode, dwCreationDisposition, dwFlagsAndAttributes); + + ret=(*pCreateFile)(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); + if(ret && (ret != (HANDLE)INVALID_SET_FILE_POINTER)) + OutTrace("CreateFile: ret=%x\n", ret); + else + OutTraceE("CreateFile ERROR: err=%d\n", GetLastError()); + return ret; +} + +BOOL WINAPI extCloseHandle(HANDLE hObject) +{ + if (hObject==LastFile) LastFile=0; // invalidate cache + + return (*pCloseHandle)(hObject); +} + +DWORD WINAPI extSetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) +{ + DWORD ret; + OutTrace("SetFilePointer: hFile=%x DistanceToMove=%ld DistanceToMoveHigh=%x MoveMethod=%x\n", + hFile, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod); + + // if cached file ... + if(LastFile==hFile){ + if(!lpDistanceToMoveHigh){ + OutTrace("SetFilePointer: buffered move\n"); + switch(dwMoveMethod){ + case FILE_BEGIN: Where=lDistanceToMove; break; + case FILE_CURRENT: Where+=lDistanceToMove; break; + case FILE_END: Where=FileLength-lDistanceToMove; break; + } + OutTrace("SetFilePointer: ret=%x\n", Where); + return Where; + } + } + + // proxy + ret=(*pSetFilePointer)(hFile, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod); + if(lpDistanceToMoveHigh){ + if(ret) + OutTrace("SetFilePointer: DistanceToMoveHigh=%x\n", *lpDistanceToMoveHigh); + else + OutTraceE("SetFilePointer ERROR: err=%d\n", GetLastError()); + } + else{ + if(ret==INVALID_SET_FILE_POINTER) + OutTraceE("SetFilePointer ERROR: err=%d\n", GetLastError()); + else + OutTrace("SetFilePointer: ret=%x\n", ret); + } + return ret; +} diff --git a/dll/syslibs.h b/dll/syslibs.h index 21705e6..8374288 100644 --- a/dll/syslibs.h +++ b/dll/syslibs.h @@ -104,6 +104,7 @@ typedef HMODULE (WINAPI *LoadLibraryA_Type)(LPCTSTR); typedef HMODULE (WINAPI *LoadLibraryExA_Type)(LPCTSTR, HANDLE, DWORD); typedef HMODULE (WINAPI *LoadLibraryW_Type)(LPCWSTR); typedef HMODULE (WINAPI *LoadLibraryExW_Type)(LPCWSTR, HANDLE, DWORD); +typedef BOOL (WINAPI *ReadFile_Type)(HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED); typedef LPTOP_LEVEL_EXCEPTION_FILTER (WINAPI *SetUnhandledExceptionFilter_Type)(LPTOP_LEVEL_EXCEPTION_FILTER); typedef void (WINAPI *Sleep_Type)(DWORD); @@ -112,6 +113,9 @@ typedef BOOL (WINAPI *CreateScalableFontResourceA_Type)(DWORD, LPCTSTR, LPCTSTR, typedef int (WINAPI *AddFontResourceA_Type)(LPCTSTR); typedef BOOL (WINAPI *CreateScalableFontResourceW_Type)(DWORD, LPCWSTR, LPCWSTR, LPCWSTR); typedef int (WINAPI *AddFontResourceW_Type)(LPCWSTR); +typedef HANDLE (WINAPI *CreateFile_Type)(LPCTSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE); +typedef DWORD (WINAPI *SetFilePointer_Type)(HANDLE, LONG, PLONG, DWORD); +typedef BOOL (WINAPI *CloseHandle_Type)(HANDLE); // ole32.dll: typedef HRESULT (STDAPICALLTYPE *CoCreateInstance_Type)(REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID FAR*); @@ -281,9 +285,13 @@ DXWEXTERN LoadLibraryA_Type pLoadLibraryA DXWINITIALIZED; DXWEXTERN LoadLibraryExA_Type pLoadLibraryExA DXWINITIALIZED; DXWEXTERN LoadLibraryW_Type pLoadLibraryW DXWINITIALIZED; DXWEXTERN LoadLibraryExW_Type pLoadLibraryExW DXWINITIALIZED; +DXWEXTERN ReadFile_Type pReadFile DXWINITIALIZED; DXWEXTERN SetUnhandledExceptionFilter_Type pSetUnhandledExceptionFilter DXWINITIALIZED; DXWEXTERN Sleep_Type pSleep DXWINITIALIZED; DXWEXTERN SleepEx_Type pSleepEx DXWINITIALIZED; +DXWEXTERN CreateFile_Type pCreateFile DXWINITIALIZED; +DXWEXTERN SetFilePointer_Type pSetFilePointer DXWINITIALIZED; +DXWEXTERN CloseHandle_Type pCloseHandle DXWINITIALIZED; // ole32.dll: DXWEXTERN CoCreateInstance_Type pCoCreateInstance DXWINITIALIZED; @@ -449,9 +457,13 @@ extern HMODULE WINAPI extLoadLibraryA(LPCTSTR); extern HMODULE WINAPI extLoadLibraryExA(LPCTSTR, HANDLE, DWORD); extern HMODULE WINAPI extLoadLibraryW(LPCWSTR); extern HMODULE WINAPI extLoadLibraryExW(LPCWSTR, HANDLE, DWORD); +extern BOOL WINAPI extReadFile(HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED); extern LPTOP_LEVEL_EXCEPTION_FILTER WINAPI extSetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER); extern void WINAPI extSleep(DWORD); extern DWORD WINAPI extSleepEx(DWORD, BOOL); +extern HANDLE WINAPI extCreateFile(LPCTSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE); +extern DWORD WINAPI extSetFilePointer(HANDLE, LONG, PLONG, DWORD); +extern BOOL WINAPI extCloseHandle(HANDLE); // ole32.dll: extern HRESULT STDAPICALLTYPE extCoCreateInstance(REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID FAR*); @@ -491,6 +503,7 @@ extern BOOL WINAPI extDDInvalidateRect(HWND, RECT *, BOOL); extern int WINAPI extMapWindowPoints(HWND, HWND, LPPOINT, UINT); extern BOOL WINAPI extMoveWindow(HWND, int, int, int, int, BOOL); extern BOOL WINAPI extPeekMessage(LPMSG, HWND, UINT, UINT, UINT); +extern BOOL WINAPI extPeekAnyMessage(LPMSG, HWND, UINT, UINT, UINT); extern ATOM WINAPI extRegisterClassExA(WNDCLASSEXA *); extern int WINAPI extDDReleaseDC(HWND, HDC); extern int WINAPI extGDIReleaseDC(HWND, HDC); diff --git a/dll/user32.cpp b/dll/user32.cpp index 9ee20e8..b5fc384 100644 --- a/dll/user32.cpp +++ b/dll/user32.cpp @@ -74,8 +74,14 @@ static HookEntry_Type RemapHooks[]={ }; static HookEntry_Type MessageHooks[]={ - {"PeekMessageA", (FARPROC)PeekMessageA, (FARPROC *)&pPeekMessage, (FARPROC)extPeekMessage}, - {"GetMessageA", (FARPROC)GetMessageA, (FARPROC *)&pGetMessage, (FARPROC)extGetMessage}, + //{"PeekMessageA", (FARPROC)PeekMessageA, (FARPROC *)&pPeekMessage, (FARPROC)extPeekMessage}, + //{"GetMessageA", (FARPROC)GetMessageA, (FARPROC *)&pGetMessage, (FARPROC)extGetMessage}, + {0, NULL, 0, 0} // terminator +}; + +static HookEntry_Type PeekAllHooks[]={ + {"PeekMessageA", (FARPROC)NULL, (FARPROC *)&pPeekMessage, (FARPROC)extPeekAnyMessage}, + {"PeekMessageW", (FARPROC)NULL, (FARPROC *)&pPeekMessage, (FARPROC)extPeekAnyMessage}, {0, NULL, 0, 0} // terminator }; @@ -112,14 +118,17 @@ FARPROC Remap_user32_ProcAddress(LPCSTR proc, HMODULE hModule) if (addr=RemapLibrary(proc, hModule, (dxw.dwFlags1 & MAPGDITOPRIMARY) ? DDHooks : GDIHooks)) return addr; if (dxw.dwFlags1 & CLIENTREMAPPING) if (addr=RemapLibrary(proc, hModule, RemapHooks)) return addr; - if (dxw.dwFlags1 & MESSAGEPROC) - if (addr=RemapLibrary(proc, hModule, MessageHooks)) return addr; + // commented out since message processing was given to SetWindowHook callback + // if (dxw.dwFlags1 & MESSAGEPROC) + // if (addr=RemapLibrary(proc, hModule, MessageHooks)) return addr; if(dxw.dwFlags1 & MODIFYMOUSE) if (addr=RemapLibrary(proc, hModule, MouseHooks)) return addr; if (dxw.dwFlags1 & (PREVENTMAXIMIZE|FIXWINFRAME|LOCKWINPOS|LOCKWINSTYLE)) if (addr=RemapLibrary(proc, hModule, WinHooks)) return addr; if((dxw.dwFlags1 & (MODIFYMOUSE|SLOWDOWN|KEEPCURSORWITHIN)) || (dxw.dwFlags2 & KEEPCURSORFIXED)) if (addr=RemapLibrary(proc, hModule, MouseHooks2)) return addr; + if(FALSE) + if (addr=RemapLibrary(proc, hModule, PeekAllHooks)) return addr; return NULL; } @@ -132,10 +141,11 @@ void HookUser32(HMODULE hModule) HookLibrary(hModule, EmulateHooks, libname); HookLibrary(hModule, (dxw.dwFlags1 & MAPGDITOPRIMARY) ? DDHooks : GDIHooks, libname); if (dxw.dwFlags1 & CLIENTREMAPPING) HookLibrary(hModule, RemapHooks, libname); - if (dxw.dwFlags1 & MESSAGEPROC) HookLibrary(hModule, MessageHooks, libname); + //if (dxw.dwFlags1 & MESSAGEPROC) HookLibrary(hModule, MessageHooks, libname); if(dxw.dwFlags1 & MODIFYMOUSE)HookLibrary(hModule, MouseHooks, libname); if (dxw.dwFlags1 & (PREVENTMAXIMIZE|FIXWINFRAME|LOCKWINPOS|LOCKWINSTYLE))HookLibrary(hModule, WinHooks, libname); if((dxw.dwFlags1 & (MODIFYMOUSE|SLOWDOWN|KEEPCURSORWITHIN)) || (dxw.dwFlags2 & KEEPCURSORFIXED)) HookLibrary(hModule, MouseHooks2, libname); + if(FALSE) HookLibrary(hModule, PeekAllHooks, libname); return; } @@ -770,6 +780,28 @@ BOOL WINAPI extSetCursorPos(int x, int y) return res; } +BOOL WINAPI extPeekAnyMessage(LPMSG lpMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg) +{ + BOOL res; + + if(wMsgFilterMin || wMsgFilterMax){ + while (TRUE){ + res=(*pPeekMessage)(lpMsg, hwnd, 0, 0, wRemoveMsg); + if((lpMsg->message >= wMsgFilterMin) && (lpMsg->message <= wMsgFilterMax)) break; + if(!wRemoveMsg)(*pPeekMessage)(lpMsg, hwnd, 0, 0, TRUE); + } + } + else + res=(*pPeekMessage)(lpMsg, hwnd, 0, 0, wRemoveMsg); + + OutTraceW("PeekMessage: lpmsg=%x hwnd=%x filter=(%x-%x) remove=%x msg=%x(%s) wparam=%x, lparam=%x pt=(%d,%d) res=%x\n", + lpMsg, lpMsg->hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg, + lpMsg->message, ExplainWinMessage(lpMsg->message & 0xFFFF), + lpMsg->wParam, lpMsg->lParam, lpMsg->pt.x, lpMsg->pt.y, res); + + return res; +} + BOOL WINAPI extPeekMessage(LPMSG lpMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg) { BOOL res; @@ -791,7 +823,7 @@ BOOL WINAPI extPeekMessage(LPMSG lpMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsg // fix to avoid crash in Warhammer Final Liberation, that evidently intercepts mouse position by // peeking & removing messages from window queue and considering the lParam parameter. - // v2.1.100 - never alter the mlMsg, otherwise the message is duplicated in the queue! Work on a copy of it. + // v2.1.100 - never alter the lpMsg, otherwise the message is duplicated in the queue! Work on a copy of it. if(wRemoveMsg){ static MSG MsgCopy; MsgCopy=*lpMsg; @@ -1127,9 +1159,19 @@ static HWND WINAPI extCreateWindowCommon( y=0; nWidth=workarea.right; nHeight=workarea.bottom; - dwStyle=(dxw.dwFlags2 & MODALSTYLE) ? 0 : WS_OVERLAPPEDWINDOW; + dwStyle=0; OutTraceD("%s: WORKAREA win pos=(%d,%d) size=(%d,%d)\n", ApiName, x, y, nWidth, nHeight); } + else if(dxw.Coordinates==DXW_DESKTOP_FULL){ + RECT workarea; + (*pGetClientRect)((*pGetDesktopWindow)(), &workarea); + x=0; + y=0; + nWidth=workarea.right; + nHeight=workarea.bottom; + dwStyle=0; + OutTraceD("%s: FULLDESKTOP win pos=(%d,%d) size=(%d,%d)\n", ApiName, x, y, nWidth, nHeight); + } } if(!dxw.IsFullScreen()){ // v2.1.63: needed for "Monster Truck Madness" diff --git a/host/Resource.h b/host/Resource.h index 5becd67..e18d3b4 100644 --- a/host/Resource.h +++ b/host/Resource.h @@ -147,7 +147,7 @@ #define IDC_HOOKDLLS 1104 #define IDC_HOOKENABLED 1105 #define IDC_DESKTOPWORKAREA 1106 -#define IDC_FIXD3DFRAME 1107 +#define IDC_DESKTOPFULL 1107 #define IDC_TIMESLIDER 1108 #define IDC_BLACKWHITE 1109 #define IDC_SAVECAPS 1110 @@ -167,6 +167,8 @@ #define IDC_FONTBYPASS 1124 #define IDC_YUV2RGB 1125 #define IDC_RGB2YUV 1126 +#define IDC_FIXD3DFRAME 1127 +#define IDC_BUFFEREDIOFIX 1128 #define ID_MODIFY 32771 #define ID_DELETE 32772 #define ID_ADD 32773 diff --git a/host/TabCompat.cpp b/host/TabCompat.cpp index b102458..09ee744 100644 --- a/host/TabCompat.cpp +++ b/host/TabCompat.cpp @@ -36,6 +36,7 @@ void CTabCompat::DoDataExchange(CDataExchange* pDX) DDX_Check(pDX, IDC_SUPPRESSD3DEXT, cTarget->m_SuppressD3DExt); DDX_Check(pDX, IDC_CDROMDRIVETYPE, cTarget->m_CDROMDriveType); DDX_Check(pDX, IDC_FONTBYPASS, cTarget->m_FontBypass); + DDX_Check(pDX, IDC_BUFFEREDIOFIX, cTarget->m_BufferedIOFix); } BEGIN_MESSAGE_MAP(CTabCompat, CDialog) diff --git a/host/TargetDlg.cpp b/host/TargetDlg.cpp index ebdfc70..6357e12 100644 --- a/host/TargetDlg.cpp +++ b/host/TargetDlg.cpp @@ -34,7 +34,7 @@ CTargetDlg::CTargetDlg(CWnd* pParent /*=NULL*/) m_HandleExceptions = FALSE; m_SuppressIME = FALSE; m_SuppressD3DExt = FALSE; - m_SetCompatibility = FALSE; + m_SetCompatibility = TRUE; m_DisableHAL = FALSE; m_LockSysColors = FALSE; m_ForceYUVtoRGB = FALSE; @@ -44,6 +44,7 @@ CTargetDlg::CTargetDlg(CWnd* pParent /*=NULL*/) m_LimitResources = FALSE; m_CDROMDriveType = FALSE; m_FontBypass = FALSE; + m_BufferedIOFix = FALSE; m_UnNotify = FALSE; m_Windowize = TRUE; // default true !! m_HookDLLs = TRUE; // default true !! diff --git a/host/TargetDlg.h b/host/TargetDlg.h index b62f1ee..103d7d4 100644 --- a/host/TargetDlg.h +++ b/host/TargetDlg.h @@ -105,6 +105,7 @@ public: BOOL m_LimitResources; BOOL m_CDROMDriveType; BOOL m_FontBypass; + BOOL m_BufferedIOFix; BOOL m_SuppressIME; BOOL m_SetCompatibility; BOOL m_DisableHAL; diff --git a/host/dxwndhost.aps b/host/dxwndhost.aps index 2339bdcf821c2af0ad9635f4ad1c33f59ef09925..1e474f397fca8d90554c6698a914f6c2916c0721 100644 GIT binary patch delta 2296 zcmZXUdr;I>6vxlKJmNKm5a=!lq&=t%f4d8^7?~@(D!IBl`v8`#%>o1*F$jXn5-TT`; z5WD|o>^gf&MI(obX$$NvrF9hxn$1DY9JJ(Od&xL9u&aL6m=#6AfWO4-nLQIsCUYKa z0VuW?1t~TYmuxD$D_L-!%U(Py02Xt8z6rJ}WOq0nK8HeP*rt%pZdb7dwyW4t=61R~ zVNEW)r_fKI~S^XY=6O~nSyKR22T&Y#dgHHixY)nu4ES&Y&0zr?%>kF^ks#)Q4z!e))`4@n1ZA=-z zU&*|-5{JB-EMd~%O8~4dNlurM3BFPids*pxJKaP{%Yk=zVhO* zSM`$aSr)yKCZFfWyV`kv7N2C4u5rs*7Sb)<%NteslS%=q)E zDeQJMUC2l0=^Rc4+fLU?bMdrCn!+>6tUL3VjC#*Zyai~J&qDwg{*sK7yW{k@RK@P@ zIFf}Hbe~|+KGKn&d$xqJE`0giL+k_|JXb`|>DHd>IHx}$b}RHi5aPg#$IqpN`1#8j zd}s)JZ!}>0Knza58WU<5C}U{+Z49ow8i_qOXX2ZeW3cOL9BP9(IQ42G)(u9pO1yu- zfUgc}iX0(QCCREQgCAZQWI0W2Kul=lck|sItn*|<*(Lz=h?+(|iP^;~()5a5jXX2D z%>yub8GhTG5gkvP?Kyz+59CCplAA6THt`AK;U=ESs-WaiegP&mI^4W=hAL#8j6_tKPA9h|dil?N% zzYmRlMzK!%*?;46e^F`aXZ4Fc%XkLQ9>C{r(5%F0{Jv#8Gopht@f%|gMrGdt@RJC% zP}|A(iPjd9H(JDIvNX+J!VxV+OdOrb4AEN>09N}%ztlJv3ga_8BciNDYYApoaj}Aes6qDZIS3FA#KpGoGOp6;bLhu6@drE*^NA8~z0_eA8+G delta 2072 zcmYjPTToM16g}qzA|eHpmjncSFe0`X604!(3rUn{BrypHXua5i0=6nD4;8H=t%D3R zrL)yTr;dZueyBx@#@0s>A5{xVeKJU`j83(!Vig>*ts^zv=jK99KGxc6t-JTW=bm%_ z4nER1xW*XLwuX`1cNQ7T7Oco!RHBo#I!UjG&lZHywnIe~{vS#6tVZ*!ETY#OzP#@)-M>y0gv$7 ztR!+!Xp?T}6K2C$yKu#05vm=z9A>iH-5_(pSIg&F>qMK-xs3kwZ=AjXx=VZ&6xggDm z>&ljnoQFe0Bk2VU1jDYKe)LD^9y)w@vm6!YB-xVF9iBduNDD*{3!@j|>CO;(3FZw8 z)3nM#d2#bRo7L_VZFO4m6M-3g__WKiZNu-;Z|TStkEVPCgHBJb5+Wtr9FpEBrC8IP zcB{of5=lFOYwM%fO#+oXnspH9-Wo-J25ng+z2%x8v@Ds%!g1#|D&J36cKSx@q0pVN zM`jn4dS&J#g{{uYQrNw$RE4EvPf-}pZlQYDl7%r$5k7zSv4^>KFTOV*E_tTdU%l6) z*z4c7^$-6wcf4Z9=9Me#c;174wzNuN3zvNX!}7;@Ds=}PL)>m?C=P>F`SBi+ZUI+6 zS647O&|Mq?fdzp|U=Sn~j8(V~tdsf3f{}2xU<9g5kkP_OWP1um!HmKPCFuui3u6`j z1{@yX{?IeP10Z3!l7a5RAyBfs|LLKw{mW0N@tpEjf9XYYU~uVZdcyTqX~{6xscjW3 zC@VcfXP-TjBqk;%5k?6mp)j>NA_z4ddZ^>=P;^IivFo2|i$8?pST=@@$beTtnC;jBDFHO8au92b*AjNw%^L2c(ot> zGM!$9@wZdxEm(Q`g{!vn_b5gPZ0=jlB&(~pZz*MFBP@DlXBIOwyqd>q{J>f^mQ~wfr#(s?JA#lSPH1vQd2gkJ5I&-q zji&WHxtK+(bL@mXC;|V{DD@EZ%3I)IOM*HSX=4j-DrP$B!=Dy2J&S9F6|EXRql9_U zRoqm1z(5k>l%Jn*o6Nk?7cVO$qkK~4I;#= z9pda%*YS8nT*kZ(qYq|ME~U_L^B6`HEbPRiY#G~8P}8OU2iB$7WwP!0EH{8Mk{ zX$vYm6jSpU zKb6PA2UVk3i$%av7VbR-3w+0o_>Of;c@+ln1ovU7s?2BHosUh33NK>;??R8YeZYM; rAy$9L;}KOpD;WQ11vcG+eSC_rD8eTy@y^y4@hXvUu3`Mr8W#Q^rwgD@ diff --git a/host/dxwndhost.rc b/host/dxwndhost.rc index e24db61..218996b 100644 --- a/host/dxwndhost.rc +++ b/host/dxwndhost.rc @@ -263,15 +263,16 @@ BEGIN CONTROL "Optimize CPU (DirectX1 - 7)",IDC_SAVELOAD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,170,160,109,10 CONTROL "Intercept Alt-F4 key",IDC_HANDLEALTF4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,136,109,10 CONTROL "Run in Window",IDC_WINDOWIZE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,148,124,10 - GROUPBOX "Generic",IDC_STATIC,7,103,286,88 + GROUPBOX "Generic",IDC_STATIC,7,103,286,84 CONTROL "No banner",IDC_NOBANNER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,170,124,108,10 CONTROL "use DLL Injection",IDC_STARTDEBUG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,170,136,100,10 CONTROL "Remap Client Rect",IDC_CLIENTREMAPPING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,170,112,115,10 CONTROL "Hook all DLLs",IDC_HOOKDLLS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,160,124,10 CONTROL "Hook enabled",IDC_HOOKENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,112,124,10 - CONTROL "X,Y coordinates",IDC_COORDINATES,"Button",BS_AUTORADIOBUTTON | WS_GROUP,170,198,95,10 - CONTROL "Desktop work area",IDC_DESKTOPWORKAREA,"Button",BS_AUTORADIOBUTTON,170,208,95,10 - CONTROL "Desktop center",IDC_DESKTOPCENTER,"Button",BS_AUTORADIOBUTTON,170,218,95,10 + CONTROL "X,Y coordinates",IDC_COORDINATES,"Button",BS_AUTORADIOBUTTON | WS_GROUP,170,190,95,10 + CONTROL "Desktop center",IDC_DESKTOPCENTER,"Button",BS_AUTORADIOBUTTON,170,200,95,10 + CONTROL "Desktop work area",IDC_DESKTOPWORKAREA,"Button",BS_AUTORADIOBUTTON,170,210,95,10 + CONTROL "Desktop",IDC_DESKTOPFULL,"Button",BS_AUTORADIOBUTTON,170,220,95,10 CONTROL "Hook child WindowProc",IDC_HOOKCHILDWIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,170,148,114,10 CONTROL "Emulate Registry",IDC_EMULATEREGISTRY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,172,124,10 CONTROL "Fullscreen only",IDC_FULLSCREENONLY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,170,172,114,10 @@ -434,6 +435,7 @@ BEGIN "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,164,109,12 CONTROL "Set CDROM Drive Type",IDC_CDROMDRIVETYPE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,152,109,12 CONTROL "Bypass font unsupported api",IDC_FONTBYPASS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,140,109,12 + CONTROL "Fix buffered IO after Win98",IDC_BUFFEREDIOFIX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,128,109,12 END IDD_TAB_GDI DIALOGEX 0, 0, 300, 240 diff --git a/host/dxwndhost.vs2008.suo b/host/dxwndhost.vs2008.suo index ad316851092fc7f25e9f209253ef9e62f3b4854b..f751908ec45944359137e8c40be0537560e7de95 100644 GIT binary patch delta 3294 zcmd5;e^AuN75~2d?j6UEgY!5KL_EHNA`ryGLyW)hFvJ?LN(f@gFb0e@{;HzVfHcO# zX&Hk=BO7@pCW`k5+C)3(DPN;j5lw6S(NM;*HPfa@jng<8wGPb~W2A47Ge?}H?VsJ5 z&v$n}yZd(cz4v`@Jsnoh7uGl2U^|$5f$@ArQG`XcnF^@!u)n`wq^nay%c!%AutKa> zU7^dVb(D}N4ydOhExx*gF}^>5N{qW$)bjHt3pHtJKX&a>Q$&Y}`)UjY2BTsmJ`~|L zJR$nR<{DuF^+Wvqrcjy_UZ5I5t}_SbM0S}X28+tKF-3_ECyI(uF)09wa)UPhhTtUb z()(G~+YfK`OFohM;|U>;@qN^f0$+~Bz{HuTO!Q0zE^4d=;tbEkHjQz(?)%C*7DR7J zoX>4r!h|>9E>7B;gm=Ev=ZVQI0y-n+g7pMJViE0z_bCP0Ej*1ZHPEn zu^YBkR(PA4_w6{`V^9-(2|KOZf_q*No`(*f<6*BV)@--?> z(UJliAtu=0lnN2BY+!CjD%fF&97}CagQ$=sPe_XzCf)NCQ^<_|^5lUTJkV6M{WJ9O znNY-rn~5q?eyXe>R48ld`-(DOS*om5T>5SoRD|K7e?mHz=YUnuu|X%ax`DUm027tn z@p^n7T!;2qU`-%LO2e+j5RcEl1p8WN($N!;Td~r_Y(6b3NUE2gbDsD7@15a*% z8Q8HB?7F=kZh~lWa4f9lcGT)P>AVptRbl;T7HY3UtX|#(EeY7Y9+LDkTVWa#?vIU4 zo4Kgm9@)GCBK71$P#c1shanMPsV2*7Z<%!W3Ft8BEgwKR6J5uw_`6l|9-UBYXgv=R zV&m2{aVu4WVG=6HCID&8j9mlPr49IXDYCy8?M?`(I$MQS>g26_fMh z@Mr9$7^Es=3LD9iWFA#4g7|QJLkwH zIg4e2H;}Dx!Hi42ybUS_GasrShZtc2Ee-d_FTLuL`p$%T1r%3j5q?C-AqFXR~%1b>XkWVp=FE#Tv>9XVfp7_56 z3zWWuZJYQwxh@_5xSALLH~+&qYxogLD`_}(EiceLYq`fLn(TI>(&3=U-0_s?=#AIk zT)-Eo&F^yhyh@cZtS5W;MUXR4tLLK(d&#c)AoWz$^F|m? zS#Uk+BXhhfi*k?>{JVZI01lilu`mroU*n}4zITPp-GkGuOw=O?V;|$GtE3WA9^>n% zzlC6ZjE|xI7=nC=49K?+^fMM<%gRoPnpN5cKZ6{x3EEx9;?JJ5b6P)mL` zLAuMF0GCF!^eb5k335&b;aP$#^9YiYYf1>RloH6TpkL4VtNNl*Tv(RSyc1;5zjj{D zMSh!7ZpS|)At+<>_oh5}S@gIx^xS|votN?lD*Oq-0n?kmfOtce;!?5(%yWu%`Y@;% zW_x6w34U7`hm*S9AWoa73nvf9vzz%;(PefLZ2k_qUuBWeGUDYgPuVYzD&1cp&z9N9 z^k@LfZ-EoLD_9xs_#78)D861nZ`6M XKfxkVdy|h5zc)_`Xhdq|`;ho=Jbtq* delta 2655 zcma)8eNa@_6@TZxyC3W>urAAr8^q^|xDbLH1hmnRO|l_Yjb?0W8HbS%Q({u9h-ev- zhOLuf9Eyls;%QA)X8$0WXd2AoUPo+7jGdu=(ABZVIJDU@#y^^jQcE3UQt5e10z0&s z_-1~)=bm@(x#ykpyXV~C7mnb7qr(qrM;<@J_`R{QF=1Do=4FbaEGLM3bxG3CNO*~` zUTjepBn3!1M%XCcQU92t$UC3op&?L7Gw_sX;-}4NB$Aymj2=+EV!+J9jfUk0BN$1a zjBpbk6r+|^Mx~g>rueusiRM_BtKvicuoz8=ih#qn%*hnRYNa{!7!|VuFfPxeKR@Bz zp(4l4dpE{(y@|$|gy~cCx+`;(aH-wE@WVN*P;7IoG(r+-ZSjqI0cQ9E?P8CwF;>v>vIF6}Gu)e!QplEx;1vJdnKn0>q;x_m z!A_V)a1hc6dT4dHXy&RTbrle5wTY??_2K&8v;%JZkLnBi`l1lp=MF`fs5+h<&OSa2 zp<@hs!!S4op%b>yX&ZXGcqVE;fIM;F&t~DfXb!Kr{5FIxF~QDdVDxElg$u4+Frohg z$Usd6b66XVLFlSObnY$@md~8wWp^SFy3MfO3LcF8m@Nsf`#J=nyG+!-?vgGB|A4(N z$O>oOyQ=nZ;5`;#A~+*cW}4v|;OgV>9Qtpm4q5Ajeb8eAv+xYMG38~*mZha|5<17S zWR?pW?EpB_3lHMS94H5l56pvpJ))1G-3vQlMuK8zF4({_K6@Y+T#%-}%#Gwhs%f6d z*u^Y5rT)c~Z#bYVdgnZ+G{hh6a9qZHn|Z4ococGg)ki!%YzG`+R_sM*5fB1 zYU+SKq>Mg9L?apa`)Q!bMH^rcB1^$BOZU!;L$#2F)gP;ZHFW>YbEN!5;OET)Pb^Rr~0iDfX%-VPdSyLgGbk;EJfwEz^N zT?IRKyvDgKyUh**b{U`!d#^ArUR%d6M{LZm!n63RRJKs~qGk*xGmq|gp74KZmKRf5 z{&lP|5zAwhd>F(N5n{w0R>Z-NM;?N7jJ=_{WW(1iI^VF6c)Bi8o3CCpLVluVfqHQd z)Fx{Fr2fTZRH|vIHC||B!#VYL#rb;CSW30`11_uRuTe)J=LdrIA4oY z)H3KBICl3_85pVN92=~9L`o=-9Zj6*=1+%|NDUw4@MeM&qqTg637=>Lho#!{`7S++ zRLCnfaiK>-!!N!9Gsc44sPkbp&adam?(aU9c(;xpjUOt}+iJv_n|Y=0yJzd%`5*pd zPVxswJ^}|8Z{^Ez(;2YNy)OpgntF11hRw}^stm(;p=Oif;)Jg+>WR44(ZQTYjub@17!weW1iAxhVK2?1OE?RuyBfA@68Vorgp~; z(sdJN5EAXIqH%U5{iIKMVW;$H1lKou4E~xEsamOyJh{3Mx3%&g!TXcJz|mIztT@Ge zhS$xCQYAh}eoXkd4Fm7;CAg!MlIdvU1sJq42QNSN!{@Q;=PZC%1k-T1f@M+rxLpYI zsNK+!d=yJ}@h1(m|KanvvW+*1;4dg??ffkj4o_}rJ4RFV2CYAMzLvVoxlP=ob8r#% z@8VC10&N;AEcMy7MPo7g%q9g zj~cw}^dW!x0M=o}m80`l<2Kh2Z{; z9NL^{m_LimitResources) t->flags2 |= LIMITRESOURCES; if(dlg->m_CDROMDriveType) t->flags3 |= CDROMDRIVETYPE; if(dlg->m_FontBypass) t->flags3 |= FONTBYPASS; + if(dlg->m_BufferedIOFix) t->flags3 |= BUFFEREDIOFIX; if(dlg->m_SuppressIME) t->flags2 |= SUPPRESSIME; if(dlg->m_SuppressD3DExt) t->flags3 |= SUPPRESSD3DEXT; if(dlg->m_SetCompatibility) t->flags2 |= SETCOMPATIBILITY; @@ -279,6 +280,7 @@ static void SetDlgFromTarget(TARGETMAP *t, CTargetDlg *dlg) dlg->m_LimitResources = t->flags2 & LIMITRESOURCES ? 1 : 0; dlg->m_CDROMDriveType = t->flags3 & CDROMDRIVETYPE ? 1 : 0; dlg->m_FontBypass = t->flags3 & FONTBYPASS ? 1 : 0; + dlg->m_BufferedIOFix = t->flags3 & BUFFEREDIOFIX ? 1 : 0; dlg->m_SaveLoad = t->flags & SAVELOAD ? 1 : 0; dlg->m_SlowDown = t->flags & SLOWDOWN ? 1 : 0; dlg->m_BlitFromBackBuffer = t->flags & BLITFROMBACKBUFFER ? 1 : 0;