From 90d46c7aa01ee29da01941f06ca9e2f29ad4b3a5 Mon Sep 17 00:00:00 2001 From: gho tik Date: Sun, 26 Apr 2015 12:40:41 -0400 Subject: [PATCH] v2_03_19_src Former-commit-id: e667ce58160f0f24e6455d26ee8ac7225d5e8ae0 --- Include/dxwnd.h | 9 +- build/dxwnd.dll | 4 +- build/dxwnd.exe | 4 +- build/readme-relnotes.txt | 9 + dll/ddblit.cpp | 7 +- dll/ddraw.cpp | 20 +- dll/dxhelper.cpp | 2 +- dll/dxhook.cpp | 14 +- dll/dxwcore.cpp | 23 ++- dll/dxwcore.hpp | 2 + dll/dxwnd.cpp | 2 +- dll/dxwnd.vs2008.suo | Bin 112128 -> 151040 bytes dll/gdiblt.cpp | 59 +----- dll/hd3d.cpp | 22 +++ dll/syslibs.h | 5 - dll/user32.cpp | 383 +++++++++++++++----------------------- dll/winmm.cpp | 10 + host/TabDirect3D.cpp | 4 + host/TargetDlg.cpp | 2 + host/TargetDlg.h | 2 + host/dxwndhost.aps | Bin 129084 -> 129696 bytes host/dxwndhost.rc | Bin 97634 -> 98878 bytes host/dxwndhost.vs2008.suo | Bin 203776 -> 206848 bytes host/dxwndhostView.cpp | 20 +- host/resource | Bin 33944 -> 34496 bytes 25 files changed, 290 insertions(+), 313 deletions(-) diff --git a/Include/dxwnd.h b/Include/dxwnd.h index 0c33993..c39728d 100644 --- a/Include/dxwnd.h +++ b/Include/dxwnd.h @@ -8,9 +8,11 @@ #define MAXTARGETS 256 #define ONEPIXELFIX 1 +#define HOOKDDRAWNONE 12 +#define HANDLEFLIPTOGDI 1 // first flags DWORD dwFlags1: -#define UNNOTIFY 0x00000001 +#define UNNOTIFY 0x00000001 #define EMULATESURFACE 0x00000002 #define CLIPCURSOR 0x00000004 // Force cursor clipping within window #define RESETPRIMARY 0x00000008 // reset emulated primary surface when reopening DDRaw object @@ -179,6 +181,9 @@ #define UNLOCKZORDER 0x40000000 // Inhibit attempts to keep the main win on top of ZORDER by stripping BringWindowToTop and SetForegroundWindow calls #define EASPORTSHACK 0X80000000 // Hack to intercept and neutralize some of the hooks set internally by EA Sports games +// sixth flags DWORD dxw.dwFlags6: +#define FORCESWAPEFFECT 0x00000001 // in D3D8/9, forces the SwapEffect value in CreateDevice/Reset operations + // logging Tflags DWORD: #define OUTTRACE 0x00000001 // enables tracing to dxwnd.log in general #define OUTDDRAWTRACE 0x00000002 // traces DxWnd directdraw screen handling @@ -214,6 +219,7 @@ typedef struct TARGETMAP int flags3; int flags4; int flags5; + int flags6; int tflags; short initx; short inity; @@ -229,6 +235,7 @@ typedef struct TARGETMAP short InitTS; short FakeVersionId; short MaxScreenRes; + short SwapEffect; }TARGETMAP; typedef struct diff --git a/build/dxwnd.dll b/build/dxwnd.dll index 5c3db29..4761121 100644 --- a/build/dxwnd.dll +++ b/build/dxwnd.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2e7c1adfbd594089e1c8eb7040b06037ae1f239498a09399e82ef4e52023c080 -size 576512 +oid sha256:30f6a78ea3b87ee01aff8159e37ade8c64528ce94e51299d3f5e5b3f7c7e8276 +size 575488 diff --git a/build/dxwnd.exe b/build/dxwnd.exe index 74d412c..3002862 100644 --- a/build/dxwnd.exe +++ b/build/dxwnd.exe @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a512e18dc9a004e3cb5f8f08eca94a0b06c8e5d935689eac885ba75f5636cde1 -size 538624 +oid sha256:292da547aea629cb8b159cd7ac8c768bdc915cdd4ecd294dbc0ec14097ec869c +size 539648 diff --git a/build/readme-relnotes.txt b/build/readme-relnotes.txt index 7f73f80..6443c63 100644 --- a/build/readme-relnotes.txt +++ b/build/readme-relnotes.txt @@ -785,3 +785,12 @@ fix: eliminated InvalidateRect calls in ddrow Unlock hooker: this is not the rig fix: DirectDrawEnumerateEx log fix: cursor is hidden in fullscreen mode only fix: CoCreateInstance & CoCreateInstanceEx wrappers. Now "Crusaders of Might & Magic" is playable in window + +v2.03.19: +fix: scaling of movie coordinates rendered through MciSendString +fix: doubled rendering to screen with fast 2x bilinear filtering +fix: crash when setting "showFPS overlay" with DirectX "hybrid mode" +fix: "keep aspect ratio" with DirectX "GDI mode" +fix: when ddraw hook is set to "none", no hook operations are performed on ddraw +add: possibility to control the D3D8/9 SwapEffect field with the "force swap effect" flag +fix: revised handling of GDI device context shared with DirectDraw primary surface, improved behaviour of "Star trek Armada" \ No newline at end of file diff --git a/dll/ddblit.cpp b/dll/ddblit.cpp index ec66120..15f61e5 100644 --- a/dll/ddblit.cpp +++ b/dll/ddblit.cpp @@ -10,7 +10,6 @@ extern LPDIRECTDRAWSURFACE lpDDSBack; extern LPDIRECTDRAWSURFACE lpDDSEmu_Prim; -extern LPDIRECTDRAWSURFACE lpDDSEmu_Back; extern LPDIRECTDRAW lpPrimaryDD; extern Blt_Type pBlt; extern ReleaseS_Type pReleaseS; @@ -290,6 +289,10 @@ static HRESULT sBltToPrimary(char *api, LPDIRECTDRAWSURFACE lpdds, LPRECT lpdest if(lpDDSEmu_Prim->IsLost()) lpDDSEmu_Prim->Restore(); dxw.ShowOverlay(lpDDSSource); + if(dxw.dwFlags4 & BILINEAR2XFILTER){ + emurect.right <<= 1; + emurect.bottom <<= 1; + } if (IsDebug) BlitTrace("BACK2PRIM", &emurect, &destrect, __LINE__); res=(*pPrimaryBlt)(lpDDSEmu_Prim, &destrect, lpDDSSource, &emurect); @@ -364,7 +367,7 @@ HRESULT WINAPI sBlt(char *api, LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect, OutTrace(sLog); } - if(ToPrim) + if(ToPrim) res = sBltToPrimary(api, lpdds, lpdestrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx, isFlipping); else res = sBltNoPrimary(api, lpdds, lpdestrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx); diff --git a/dll/ddraw.cpp b/dll/ddraw.cpp index 927cec0..b0b511f 100644 --- a/dll/ddraw.cpp +++ b/dll/ddraw.cpp @@ -23,6 +23,11 @@ DWORD dwBackBufferCaps; extern void TextureHandling(LPDIRECTDRAWSURFACE); ColorConversion_Type pColorConversion = NULL; +#ifdef HANDLEFLIPTOGDI +HDC hFlippedDC = NULL; +BOOL bFlippedDC = FALSE; +#endif + // DirectDraw API HRESULT WINAPI extDirectDrawCreate(GUID FAR *, LPDIRECTDRAW FAR *, IUnknown FAR *); HRESULT WINAPI extDirectDrawCreateEx(GUID FAR *, LPDIRECTDRAW FAR *, REFIID, IUnknown FAR *); @@ -283,6 +288,7 @@ static HookEntry_Type ddHooks[]={ FARPROC Remap_ddraw_ProcAddress(LPCSTR proc, HMODULE hModule) { FARPROC addr; + if (dxw.dwTargetDDVersion == HOOKDDRAWNONE) return NULL; if (addr=RemapLibrary(proc, hModule, ddHooks)) return addr; return NULL; } @@ -2367,6 +2373,8 @@ static HRESULT BuildPrimaryEmu(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurf if (dxw.dwTFlags & OUTPROXYTRACE) HookDDSurfaceGeneric(&lpDDSEmu_Back, dxversion); } + bFlippedDC = TRUE; + return DD_OK; } @@ -3696,7 +3704,6 @@ HRESULT WINAPI extLockDir(LPDIRECTDRAWSURFACE lpdds, LPRECT lprect, LPDDSURFACED HRESULT WINAPI extUnlock(int dxversion, Unlock4_Type pUnlock, LPDIRECTDRAWSURFACE lpdds, LPRECT lprect) { HRESULT res; - //RECT screen, rect; BOOL IsPrim; BOOL IsBack; @@ -3858,13 +3865,17 @@ HRESULT WINAPI extReleaseDC(LPDIRECTDRAWSURFACE lpdds, HDC FAR hdc) HRESULT WINAPI extFlipToGDISurface(LPDIRECTDRAW lpdd) { - //HRESULT res; + // HRESULT res; OutTraceDDRAW("FlipToGDISurface: lpdd=%x\n", lpdd); // to revise: so far, it seems the best thing to do is NOTHING, just return 0. - //res=(*pFlipToGDISurface)(lpdd); - //if (res) OutTraceE("FlipToGDISurface: ERROR res=%x(%s), skipping\n", res, ExplainDDError(res)); + // res=(*pFlipToGDISurface)(lpdd); + // if (res) OutTraceE("FlipToGDISurface: ERROR res=%x(%s), skipping\n", res, ExplainDDError(res)); // pretend you flipped anyway.... +#ifdef HANDLEFLIPTOGDI + bFlippedDC = TRUE; +#endif + return 0; } @@ -3876,6 +3887,7 @@ HRESULT WINAPI extGetGDISurface(LPDIRECTDRAW lpdd, LPDIRECTDRAWSURFACE *w) // in EMULATED mode, should not return the actual ddraw primary surface, but the virtual one. if(dxw.dwFlags1 & EMULATESURFACE){ *w=dxw.GetPrimarySurface(); + OutTraceDW("GetGDISurface: EMULATED lpdd=%x w=%x\n", lpdd, *w); return DD_OK; } diff --git a/dll/dxhelper.cpp b/dll/dxhelper.cpp index c97a6f0..2dfb051 100644 --- a/dll/dxhelper.cpp +++ b/dll/dxhelper.cpp @@ -968,7 +968,7 @@ char *ExplainGUID(GUID FAR *lpguid) case DDCREATE_HARDWAREONLY: return "DDCREATE_HARDWAREONLY"; break; case DDCREATE_EMULATIONONLY: return "DDCREATE_EMULATIONONLY"; break; } - switch ((*(DWORD *)lpguid)){ + switch (lpguid->Data1){ case 0x00000000: sguid="IID_IUnknown"; break; case 0x6C14DB80: sguid="IID_IDirectDraw"; break; case 0xB3A6F3E0: sguid="IID_IDirectDraw2"; break; diff --git a/dll/dxhook.cpp b/dll/dxhook.cpp index 06afaf3..9d41a14 100644 --- a/dll/dxhook.cpp +++ b/dll/dxhook.cpp @@ -102,6 +102,17 @@ static char *Flag5Names[32]={ "GSKYHACK", "LOCKRESERVEDPALETTE", "UNLOCKZORDER", "EASPORTSHACK", }; +static char *Flag6Names[32]={ + "FORCESWAPEFFECT", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", +}; + static char *TFlagNames[32]={ "OUTTRACE", "OUTDDRAWTRACE", "OUTWINMESSAGES", "OUTCURSORTRACE", "OUTPROXYTRACE", "DXPROXED", "ASSERTDIALOG", "OUTIMPORTTABLE", @@ -149,6 +160,7 @@ static void OutTraceHeader(FILE *fp) for(i=0, dword=dxw.dwFlags3; i<32; i++, dword>>=1) if(dword & 0x1) fprintf(fp, "%s ", Flag3Names[i]); for(i=0, dword=dxw.dwFlags4; i<32; i++, dword>>=1) if(dword & 0x1) fprintf(fp, "%s ", Flag4Names[i]); for(i=0, dword=dxw.dwFlags5; i<32; i++, dword>>=1) if(dword & 0x1) fprintf(fp, "%s ", Flag5Names[i]); + for(i=0, dword=dxw.dwFlags6; i<32; i++, dword>>=1) if(dword & 0x1) fprintf(fp, "%s ", Flag6Names[i]); for(i=0, dword=dxw.dwTFlags; i<32; i++, dword>>=1) if(dword & 0x1) fprintf(fp, "%s ", TFlagNames[i]); fprintf(fp, "***\n"); } @@ -1344,7 +1356,7 @@ void HookModule(HMODULE base, int dxversion) //if(dxw.dwFlags2 & SUPPRESSIME) HookImeLib(module); HookGDI32(base); if(dxw.dwFlags1 & HOOKDI) HookDirectInput(base, dxversion); - HookDirectDraw(base, dxversion); + if(dxw.dwTargetDDVersion != HOOKDDRAWNONE) HookDirectDraw(base, dxversion); HookDirect3D(base, dxversion); HookDirect3D7(base, dxversion); if(dxw.dwFlags2 & HOOKOPENGL) HookOpenGLLibs(base, dxw.CustomOpenGLLib); diff --git a/dll/dxwcore.cpp b/dll/dxwcore.cpp index 7958352..0869d6e 100644 --- a/dll/dxwcore.cpp +++ b/dll/dxwcore.cpp @@ -6,6 +6,7 @@ #include "syslibs.h" #include "dxhelper.h" #include "resource.h" +#include "d3d9.h" /* ------------------------------------------------------------------ */ // Internal function pointers @@ -81,6 +82,7 @@ void dxwCore::InitTarget(TARGETMAP *target) dwFlags3 = target->flags3; dwFlags4 = target->flags4; dwFlags5 = target->flags5; + dwFlags6 = target->flags6; dwTFlags = target->tflags; Windowize = (dwFlags2 & WINDOWIZE) ? TRUE : FALSE; if(dwFlags3 & FULLSCREENONLY) FullScreen=TRUE; @@ -98,6 +100,13 @@ void dxwCore::InitTarget(TARGETMAP *target) FakeVersionId = target->FakeVersionId; MaxScreenRes = target->MaxScreenRes; Coordinates = target->coordinates; + switch(target->SwapEffect){ + case 0: SwapEffect = D3DSWAPEFFECT_DISCARD; break; + case 1: SwapEffect = D3DSWAPEFFECT_FLIP; break; + case 2: SwapEffect = D3DSWAPEFFECT_COPY; break; + case 3: SwapEffect = D3DSWAPEFFECT_OVERLAY; break; + case 4: SwapEffect = D3DSWAPEFFECT_FLIPEX; break; + } MustShowOverlay=((dwFlags2 & SHOWFPSOVERLAY) || (dwFlags4 & SHOWTIMESTRETCH)); if(dwFlags4 & FINETIMING){ pTimeShifter = TimeShifterFine; @@ -722,11 +731,11 @@ RECT dxwCore::MapClientRect(LPRECT lpRect) LONG Width, Height; Width = ClientRect.right - (2*bx); Height = ClientRect.bottom - (2*by); - // v2.03.15 - fixed right & bottom values + // v2.03.18 - fixed right & bottom values RetRect.left = bx + (lpRect->left * Width / dwScreenWidth); - RetRect.right = RetRect.left + Width; + RetRect.right = bx + (lpRect->right * Width / dwScreenWidth); RetRect.top = by + (lpRect->top * Height / dwScreenHeight); - RetRect.bottom = RetRect.top + Height; + RetRect.bottom = by + (lpRect->bottom * Height / dwScreenHeight); } else{ RetRect.left = ClientRect.left + bx; @@ -1327,11 +1336,15 @@ void dxwCore::ShowOverlay() void dxwCore::ShowOverlay(LPDIRECTDRAWSURFACE lpdds) { + typedef HRESULT (WINAPI *GetDC_Type) (LPDIRECTDRAWSURFACE, HDC FAR *); + typedef HRESULT (WINAPI *ReleaseDC_Type)(LPDIRECTDRAWSURFACE, HDC); + extern GetDC_Type pGetDC; + extern ReleaseDC_Type pReleaseDC; if (MustShowOverlay) { HDC hdc; // the working dc int h, w; if(!lpdds) return; - if (FAILED(lpdds->GetDC(&hdc))) return; + if (FAILED((*pGetDC)(lpdds, &hdc))) return; w = this->GetScreenWidth(); h = this->GetScreenHeight(); if(this->dwFlags4 & BILINEAR2XFILTER) { @@ -1339,7 +1352,7 @@ void dxwCore::ShowOverlay(LPDIRECTDRAWSURFACE lpdds) h <<=1; } this->ShowOverlay(hdc, w, h); - lpdds->ReleaseDC(hdc); + (*pReleaseDC)(lpdds, hdc); } } diff --git a/dll/dxwcore.hpp b/dll/dxwcore.hpp index 31ec851..4d84035 100644 --- a/dll/dxwcore.hpp +++ b/dll/dxwcore.hpp @@ -139,12 +139,14 @@ public: // simple data variables DWORD dwFlags3; DWORD dwFlags4; DWORD dwFlags5; + DWORD dwFlags6; DWORD dwTFlags; HWND hParentWnd; HWND hChildWnd; BOOL bActive; BOOL bDInputAbs; DWORD MaxFPS; + DWORD SwapEffect; char *gsModules; int TimeShift; LPDIRECTDRAWSURFACE lpDDSPrimHDC; diff --git a/dll/dxwnd.cpp b/dll/dxwnd.cpp index 7b88850..cf8a001 100644 --- a/dll/dxwnd.cpp +++ b/dll/dxwnd.cpp @@ -27,7 +27,7 @@ along with this program. If not, see . #include "TlHelp32.h" -#define VERSION "2.03.18" +#define VERSION "2.03.19" #define DDTHREADLOCK 1 //#define LOCKTHREADS diff --git a/dll/dxwnd.vs2008.suo b/dll/dxwnd.vs2008.suo index 65f237b8c12c25f7b65fd5edbe32411519feedaf..6f7ec42d910632c9066259a6f28712735eb82bea 100644 GIT binary patch literal 151040 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
4y>x@7JB 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 delta 12668 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 A(f|Me diff --git a/dll/gdiblt.cpp b/dll/gdiblt.cpp index e3f7816..4775915 100644 --- a/dll/gdiblt.cpp +++ b/dll/gdiblt.cpp @@ -18,52 +18,6 @@ extern GetDC_Type pGetDC; extern ReleaseDC_Type pReleaseDC; extern Unlock1_Type pUnlock1; -//#define HDC_CACHE_OPTIMIZED - -#ifdef HDC_CACHE_OPTIMIZED -void BlitToWindow(HWND w, LPDIRECTDRAWSURFACE s) -{ - static HDC thdc = NULL; - HDC shdc; - static HWND LastWindow = NULL; - RECT client; - HRESULT res; - BOOL ret; - - if(!s) return; // for surface color fill - ret=(*pGetClientRect)(w, &client); - if(!ret) OutTrace("GetClientRect error=%d\n", GetLastError()); - res=(*pGetDC)(s, &shdc); - if(res) OutTrace("ddraw GetDC error lpdds=%x res=%x(%s)\n", s, res, ExplainDDError(res)); - if(w != LastWindow){ - if(LastWindow){ - ret=(*pGDIReleaseDC)(LastWindow, thdc); - if(!ret) OutTrace("GDI ReleaseDC error=%d\n", GetLastError()); - } - LastWindow = w; - thdc=(*pGDIGetDC)(w); - if(!thdc) OutTrace("GDI GetDC error=%d\n", GetLastError()); - } - if(dxw.dwFlags5 & CENTERTOWIN){ - int x, y; - x = (client.right - dxw.GetScreenWidth()) >> 1; // right-shift 1 bit means divide by 2! - y = (client.bottom - dxw.GetScreenHeight()) >> 1; - ret=(*pGDIBitBlt)(thdc, x, y, dxw.GetScreenWidth(), dxw.GetScreenHeight(), shdc, 0, 0, SRCCOPY); - if(!ret) OutTrace("BitBlt error=%d\n", GetLastError()); - } - else{ - if(dxw.dwFlags5 & BILINEARFILTER) { - ret=SetStretchBltMode(thdc, HALFTONE); - if((!ret) || (ret==ERROR_INVALID_PARAMETER)) OutTrace("GDI SetStretchBltMode error=%d\n", GetLastError()); - } - ret=(*pGDIStretchBlt)(thdc, 0, 0, client.right, client.bottom, shdc, 0, 0, dxw.GetScreenWidth(), dxw.GetScreenHeight(), SRCCOPY); - if(!ret) OutTrace("GDI StretchBlt error=%d\n", GetLastError()); - } - dxw.ShowOverlay(thdc); - res=(*pReleaseDC)(s, shdc); - if(res) OutTrace("ddraw ReleaseDC error lpdds=%x res=%x(%s)\n", s, res, ExplainDDError(res)); -} -#else void BlitToWindow(HWND w, LPDIRECTDRAWSURFACE s) { HDC shdc, thdc; @@ -72,16 +26,15 @@ void BlitToWindow(HWND w, LPDIRECTDRAWSURFACE s) BOOL ret; if(!s) return; // for surface color fill - ret=(*pGetClientRect)(w, &client); - if(!ret) OutTrace("GetClientRect error=%d\n", GetLastError()); res=(*pGetDC)(s, &shdc); if(res) OutTrace("ddraw GetDC error lpdds=%x res=%x(%s)\n", s, res, ExplainDDError(res)); thdc=(*pGDIGetDC)(w); if(!thdc) OutTrace("GDI GetDC error=%d\n", GetLastError()); + client = dxw.MapClientRect(NULL); if(dxw.dwFlags5 & CENTERTOWIN){ int x, y; - x = (client.right - dxw.GetScreenWidth()) >> 1; // right-shift 1 bit means divide by 2! - y = (client.bottom - dxw.GetScreenHeight()) >> 1; + x = (client.left + client.right - dxw.GetScreenWidth()) >> 1; // right-shift 1 bit means divide by 2! + y = (client.top + client.bottom - dxw.GetScreenHeight()) >> 1; ret=(*pGDIBitBlt)(thdc, x, y, dxw.GetScreenWidth(), dxw.GetScreenHeight(), shdc, 0, 0, SRCCOPY); if(!ret) OutTrace("BitBlt error=%d\n", GetLastError()); } @@ -90,7 +43,9 @@ void BlitToWindow(HWND w, LPDIRECTDRAWSURFACE s) ret=SetStretchBltMode(thdc, HALFTONE); if((!ret) || (ret==ERROR_INVALID_PARAMETER)) OutTrace("GDI SetStretchBltMode error=%d\n", GetLastError()); } - ret=(*pGDIStretchBlt)(thdc, 0, 0, client.right, client.bottom, shdc, 0, 0, dxw.GetScreenWidth(), dxw.GetScreenHeight(), SRCCOPY); + ret=(*pGDIStretchBlt)(thdc, + client.left, client.top, client.right-client.left, client.bottom-client.top, + shdc, 0, 0, dxw.GetScreenWidth(), dxw.GetScreenHeight(), SRCCOPY); if(!ret) OutTrace("GDI StretchBlt error=%d\n", GetLastError()); } dxw.ShowOverlay(thdc); @@ -99,4 +54,4 @@ void BlitToWindow(HWND w, LPDIRECTDRAWSURFACE s) ret=(*pGDIReleaseDC)(w, thdc); if(!ret) OutTrace("GDI ReleaseDC error=%d\n", GetLastError()); } -#endif + diff --git a/dll/hd3d.cpp b/dll/hd3d.cpp index 24d2757..7beab3c 100644 --- a/dll/hd3d.cpp +++ b/dll/hd3d.cpp @@ -282,6 +282,7 @@ AddRef_Type pAddRef9 = 0; Release_Type pRelease9 = 0; DWORD dwD3DVersion; +DWORD dwD3DSwapEffect; static HookEntry_Type d3d8Hooks[]={ {HOOK_HOT_CANDIDATE, "Direct3DCreate8", (FARPROC)NULL, (FARPROC *)&pDirect3DCreate8, (FARPROC)extDirect3DCreate8}, @@ -327,6 +328,7 @@ static HookEntry_Type d3d11Hooks[]={ FARPROC Remap_d3d8_ProcAddress(LPCSTR proc, HMODULE hModule) { FARPROC addr; + //if (dxw.dwTargetDDVersion == HOOKDDRAWNONE) return NULL; if (addr=RemapLibrary(proc, hModule, d3d8Hooks)) return addr; return NULL; } @@ -334,6 +336,7 @@ FARPROC Remap_d3d8_ProcAddress(LPCSTR proc, HMODULE hModule) FARPROC Remap_d3d9_ProcAddress(LPCSTR proc, HMODULE hModule) { FARPROC addr; + //if (dxw.dwTargetDDVersion == HOOKDDRAWNONE) return NULL; if (addr=RemapLibrary(proc, hModule, d3d9Hooks)) return addr; if (dxw.dwFlags3 & SUPPRESSD3DEXT) if (addr=RemapLibrary(proc, hModule, d3d9Extra)) return addr; return NULL; @@ -342,6 +345,7 @@ FARPROC Remap_d3d9_ProcAddress(LPCSTR proc, HMODULE hModule) FARPROC Remap_d3d10_ProcAddress(LPCSTR proc, HMODULE hModule) { FARPROC addr; + //if (dxw.dwTargetDDVersion == HOOKDDRAWNONE) return NULL; if (addr=RemapLibrary(proc, hModule, d3d10Hooks)) return addr; return NULL; } @@ -349,6 +353,7 @@ FARPROC Remap_d3d10_ProcAddress(LPCSTR proc, HMODULE hModule) FARPROC Remap_d3d10_1_ProcAddress(LPCSTR proc, HMODULE hModule) { FARPROC addr; + //if (dxw.dwTargetDDVersion == HOOKDDRAWNONE) return NULL; if (addr=RemapLibrary(proc, hModule, d3d10_1Hooks)) return addr; return NULL; } @@ -356,6 +361,7 @@ FARPROC Remap_d3d10_1_ProcAddress(LPCSTR proc, HMODULE hModule) FARPROC Remap_d3d11_ProcAddress(LPCSTR proc, HMODULE hModule) { FARPROC addr; + //if (dxw.dwTargetDDVersion == HOOKDDRAWNONE) return NULL; if (addr=RemapLibrary(proc, hModule, d3d11Hooks)) return addr; return NULL; } @@ -750,6 +756,8 @@ HRESULT WINAPI extReset(void *pd3dd, D3DPRESENT_PARAMETERS* pPresParam) OutTraceD3D("GetAdapterDisplayMode FAILED! %x\n", res); return(DD_OK); } + if(dxw.dwFlags6 & FORCESWAPEFFECT) param[6] = dxw.SwapEffect; //Swap effect; + dwD3DSwapEffect = param[6]; param[7] = 0; //hDeviceWindow dxw.SetFullScreen(~param[8]?TRUE:FALSE); param[8] = 1; //Windowed @@ -769,6 +777,8 @@ HRESULT WINAPI extReset(void *pd3dd, D3DPRESENT_PARAMETERS* pPresParam) OutTraceD3D("GetAdapterDisplayMode FAILED! %x\n", res); return(DD_OK); } + if(dxw.dwFlags6 & FORCESWAPEFFECT) param[5] = dxw.SwapEffect; //Swap effect; + dwD3DSwapEffect = param[5]; param[6] = 0; //hDeviceWindow dxw.SetFullScreen(~param[7]?TRUE:FALSE); param[7] = 1; //Windowed @@ -839,8 +849,10 @@ HRESULT WINAPI extPresent(void *pd3dd, CONST RECT *pSourceRect, CONST RECT *pDes if(dxw.dwFlags2 & FULLRECTBLT) pSourceRect = pDestRect = NULL; if(dxw.Windowize){ // v2.03.15 - fix target RECT region + if ((dwD3DSwapEffect == D3DSWAPEFFECT_COPY) && (dxw.dwFlags2 & KEEPASPECTRATIO)) { RemappedDstRect=dxw.MapClientRect((LPRECT)pDestRect); pDestRect = &RemappedDstRect; + } OutTraceB("Present: FIXED DestRect=(%d,%d)-(%d,%d)\n", RemappedDstRect.left, RemappedDstRect.top, RemappedDstRect.right, RemappedDstRect.bottom); // in case of NOD3DRESET, remap source rect. Unfortunately, this doesn't work in fullscreen mode .... if((dxw.dwFlags4 & NOD3DRESET) && (pSourceRect == NULL)){ @@ -1049,6 +1061,8 @@ HRESULT WINAPI extCreateDevice(void *lpd3d, UINT adapter, D3DDEVTYPE devicetype, if(dwD3DVersion == 9){ if(dxw.Windowize){ + if(dxw.dwFlags6 & FORCESWAPEFFECT) param[6] = dxw.SwapEffect; //Swap effect; + dwD3DSwapEffect = param[6]; param[7] = 0; //hDeviceWindow dxw.SetFullScreen(~param[8]?TRUE:FALSE); param[8] = 1; //Windowed @@ -1070,6 +1084,8 @@ HRESULT WINAPI extCreateDevice(void *lpd3d, UINT adapter, D3DDEVTYPE devicetype, } else{ if(dxw.Windowize){ + if(dxw.dwFlags6 & FORCESWAPEFFECT) param[5] = dxw.SwapEffect; //Swap effect; + dwD3DSwapEffect = param[5]; param[6] = 0; //hDeviceWindow dxw.SetFullScreen(~param[7]?TRUE:FALSE); param[7] = 1; //Windowed @@ -1175,6 +1191,8 @@ HRESULT WINAPI extCreateDeviceEx(void *lpd3d, UINT adapter, D3DDEVTYPE devicetyp } if(dxw.Windowize){ + if(dxw.dwFlags6 & FORCESWAPEFFECT) param[6] = dxw.SwapEffect; //Swap effect; + dwD3DSwapEffect = param[6]; //param[7] = 0; //hDeviceWindow param[7] = (DWORD)dxw.GethWnd(); //hDeviceWindow dxw.SetFullScreen(~param[8]?TRUE:FALSE); @@ -1313,6 +1331,8 @@ HRESULT WINAPI extCreateAdditionalSwapChain(void *lpd3dd, D3DPRESENT_PARAMETERS if(dxw.Windowize){ if(dwD3DVersion == 9){ + if(dxw.dwFlags6 & FORCESWAPEFFECT) param[6] = dxw.SwapEffect; //Swap effect; + dwD3DSwapEffect = param[6]; param[7] = 0; //hDeviceWindow dxw.SetFullScreen(~param[8]?TRUE:FALSE); param[8] = 1; //Windowed @@ -1320,6 +1340,8 @@ HRESULT WINAPI extCreateAdditionalSwapChain(void *lpd3dd, D3DPRESENT_PARAMETERS param[13] = D3DPRESENT_INTERVAL_DEFAULT; //PresentationInterval } else{ + if(dxw.dwFlags6 & FORCESWAPEFFECT) param[5] = dxw.SwapEffect; //Swap effect; + dwD3DSwapEffect = param[5]; param[6] = 0; //hDeviceWindow dxw.SetFullScreen(~param[7]?TRUE:FALSE); param[7] = 1; //Windowed diff --git a/dll/syslibs.h b/dll/syslibs.h index 8b35f8e..75ec488 100644 --- a/dll/syslibs.h +++ b/dll/syslibs.h @@ -571,7 +571,6 @@ extern void STDAPICALLTYPE extCoUninitialize(void); // user32.dll: extern HDC WINAPI extBeginPaint(HWND, LPPAINTSTRUCT); -extern HDC WINAPI extEMUBeginPaint(HWND, LPPAINTSTRUCT); extern HDC WINAPI extDDBeginPaint(HWND, LPPAINTSTRUCT); extern LRESULT WINAPI extCallWindowProc(WNDPROC, HWND, UINT, WPARAM, LPARAM); extern LONG WINAPI extChangeDisplaySettingsA(DEVMODEA *, DWORD); @@ -589,7 +588,6 @@ extern LRESULT WINAPI extDefWindowProcW(HWND, UINT, WPARAM, LPARAM); extern int WINAPI extDrawTextA(HDC, LPCTSTR, int, LPRECT, UINT); extern int WINAPI extDrawTextExA(HDC, LPTSTR, int, LPRECT, UINT, LPDRAWTEXTPARAMS); extern BOOL WINAPI extEndPaint(HWND, const PAINTSTRUCT *); -extern BOOL WINAPI extEMUEndPaint(HWND, const PAINTSTRUCT *); extern BOOL WINAPI extDDEndPaint(HWND, const PAINTSTRUCT *); extern LONG WINAPI extEnumDisplaySettings(LPCTSTR, DWORD, DEVMODE *); extern int WINAPI extFillRect(HDC, const RECT *, HBRUSH); @@ -607,7 +605,6 @@ extern int WINAPI extGetSystemMetrics(int); extern HWND WINAPI extGetTopWindow(HWND); extern int WINAPI extGetUpdateRgn(HWND, HRGN, BOOL); extern HDC WINAPI extGDIGetWindowDC(HWND); -extern HDC WINAPI extEMUGetWindowDC(HWND); extern HDC WINAPI extDDGetWindowDC(HWND); extern LONG WINAPI extGetWindowLongA(HWND, int); extern LONG WINAPI extGetWindowLongW(HWND, int); @@ -621,7 +618,6 @@ extern BOOL WINAPI extRedrawWindow(HWND, const RECT *, HRGN, UINT); extern ATOM WINAPI extRegisterClassExA(WNDCLASSEXA *); extern ATOM WINAPI extRegisterClassA(WNDCLASSA *); extern int WINAPI extGDIReleaseDC(HWND, HDC); -extern int WINAPI extEMUReleaseDC(HWND, HDC); extern int WINAPI extDDReleaseDC(HWND, HDC); extern BOOL WINAPI extScreenToClient(HWND, LPPOINT); extern LRESULT WINAPI extSendMessageA(HWND, UINT, WPARAM, LPARAM); @@ -639,7 +635,6 @@ extern BOOL WINAPI extDestroyWindow(HWND); extern BOOL WINAPI extCloseWindow(HWND); extern BOOL WINAPI extSetSysColors(int, const INT *, const COLORREF *); extern HDC WINAPI extGDIGetDCEx(HWND, HRGN, DWORD); -extern HDC WINAPI extEMUGetDCEx(HWND, HRGN, DWORD); extern HDC WINAPI extDDGetDCEx(HWND, HRGN, DWORD); extern BOOL WINAPI extUpdateWindow(HWND); extern BOOL WINAPI extGetWindowPlacement(HWND, WINDOWPLACEMENT *); diff --git a/dll/user32.cpp b/dll/user32.cpp index bc35be4..e9c5e42 100644 --- a/dll/user32.cpp +++ b/dll/user32.cpp @@ -15,6 +15,10 @@ #define FIXCHILDSIZE FALSE BOOL IsChangeDisplaySettingsHotPatched = FALSE; +#define GDIMODE_STRETCHED 0 +#define GDIMODE_EMULATED 1 +#define GDIMODE_DIRECTDRAW 2 +int GDIEmulationMode = 0; //typedef BOOL (WINAPI *ValidateRect_Type)(HWND, const RECT *); //BOOL WINAPI extValidateRect(HWND, const RECT *); @@ -42,6 +46,9 @@ HRESULT WINAPI extMessageBoxTimeoutA(HWND, LPCSTR, LPCSTR, UINT, WORD, DWORD); typedef HRESULT (WINAPI *MessageBoxTimeoutW_Type)(HWND, LPCWSTR, LPCWSTR, UINT, WORD, DWORD); MessageBoxTimeoutW_Type pMessageBoxTimeoutW = NULL; HRESULT WINAPI extMessageBoxTimeoutW(HWND, LPCWSTR, LPCWSTR, UINT, WORD, DWORD); +typedef BOOL (WINAPI *IsIconic_Type)(HWND); +IsIconic_Type pIsIconic = NULL; +BOOL WINAPI extIsIconic(HWND); #ifdef TRACEPALETTE typedef UINT (WINAPI *GetDIBColorTable_Type)(HDC, UINT, UINT, RGBQUAD *); @@ -108,6 +115,8 @@ static HookEntry_Type Hooks[]={ //{HOOK_HOT_CANDIDATE, "MessageBoxTimeoutA", (FARPROC)NULL, (FARPROC *)&pMessageBoxTimeoutA, (FARPROC)extMessageBoxTimeoutA}, //{HOOK_HOT_CANDIDATE, "MessageBoxTimeoutW", (FARPROC)NULL, (FARPROC *)&pMessageBoxTimeoutW, (FARPROC)extMessageBoxTimeoutW}, + //{HOOK_HOT_CANDIDATE, "IsIconic", (FARPROC)IsIconic, (FARPROC *)&pIsIconic, (FARPROC)extIsIconic}, + {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator }; @@ -118,18 +127,19 @@ static HookEntry_Type NoGDIHooks[]={ }; static HookEntry_Type EmulateHooks[]={ - {HOOK_IAT_CANDIDATE, "BeginPaint", (FARPROC)BeginPaint, (FARPROC *)&pBeginPaint, (FARPROC)extEMUBeginPaint}, - {HOOK_IAT_CANDIDATE, "EndPaint", (FARPROC)EndPaint, (FARPROC *)&pEndPaint, (FARPROC)extEMUEndPaint}, - {HOOK_IAT_CANDIDATE, "GetDC", (FARPROC)GetDC, (FARPROC *)&pGDIGetDC, (FARPROC)extEMUGetDC}, - {HOOK_IAT_CANDIDATE, "GetDCEx", (FARPROC)GetDCEx, (FARPROC *)&pGDIGetDCEx, (FARPROC)extEMUGetDCEx}, - {HOOK_IAT_CANDIDATE, "GetWindowDC", (FARPROC)GetWindowDC, (FARPROC *)&pGDIGetWindowDC, (FARPROC)extEMUGetWindowDC}, - {HOOK_IAT_CANDIDATE, "ReleaseDC", (FARPROC)ReleaseDC, (FARPROC *)&pGDIReleaseDC, (FARPROC)extEMUReleaseDC}, + {HOOK_IAT_CANDIDATE, "BeginPaint", (FARPROC)BeginPaint, (FARPROC *)&pBeginPaint, (FARPROC)extBeginPaint}, + {HOOK_IAT_CANDIDATE, "EndPaint", (FARPROC)EndPaint, (FARPROC *)&pEndPaint, (FARPROC)extEndPaint}, + {HOOK_IAT_CANDIDATE, "GetDC", (FARPROC)GetDC, (FARPROC *)&pGDIGetDC, (FARPROC)extGDIGetDC}, + {HOOK_IAT_CANDIDATE, "GetDCEx", (FARPROC)GetDCEx, (FARPROC *)&pGDIGetDCEx, (FARPROC)extGDIGetDCEx}, + {HOOK_IAT_CANDIDATE, "GetWindowDC", (FARPROC)GetWindowDC, (FARPROC *)&pGDIGetWindowDC, (FARPROC)extGDIGetWindowDC}, + {HOOK_IAT_CANDIDATE, "ReleaseDC", (FARPROC)ReleaseDC, (FARPROC *)&pGDIReleaseDC, (FARPROC)extGDIReleaseDC}, //{HOOK_IAT_CANDIDATE, "InvalidateRect", (FARPROC)InvalidateRect, (FARPROC *)&pInvalidateRect, (FARPROC)extInvalidateRect}, {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator }; static HookEntry_Type DDHooks[]={ {HOOK_IAT_CANDIDATE, "BeginPaint", (FARPROC)BeginPaint, (FARPROC *)&pBeginPaint, (FARPROC)extDDBeginPaint}, + //{HOOK_IAT_CANDIDATE, "BeginPaint", (FARPROC)BeginPaint, (FARPROC *)&pBeginPaint, (FARPROC)extBeginPaint}, {HOOK_IAT_CANDIDATE, "EndPaint", (FARPROC)EndPaint, (FARPROC *)&pEndPaint, (FARPROC)extDDEndPaint}, {HOOK_IAT_CANDIDATE, "GetDC", (FARPROC)GetDC, (FARPROC *)&pGDIGetDC, (FARPROC)extDDGetDC}, {HOOK_IAT_CANDIDATE, "GetDCEx", (FARPROC)GetDCEx, (FARPROC *)&pGDIGetDCEx, (FARPROC)extDDGetDCEx}, @@ -232,6 +242,11 @@ static char *libname = "user32.dll"; void HookUser32(HMODULE hModule) { + GDIEmulationMode = GDIMODE_STRETCHED; // default + if (dxw.dwFlags2 & GDISTRETCHED) GDIEmulationMode = GDIMODE_STRETCHED; + if (dxw.dwFlags3 & GDIEMULATEDC) GDIEmulationMode = GDIMODE_EMULATED; + if (dxw.dwFlags1 & MAPGDITOPRIMARY) GDIEmulationMode = GDIMODE_DIRECTDRAW; + HookLibrary(hModule, Hooks, libname); if (!(dxw.dwFlags2 & GDISTRETCHED) && !(dxw.dwFlags3 & GDIEMULATEDC) && !(dxw.dwFlags1 & MAPGDITOPRIMARY)) HookLibrary(hModule, NoGDIHooks, libname); @@ -1847,216 +1862,92 @@ LONG WINAPI extChangeDisplaySettingsExW(LPCTSTR lpszDeviceName, DEVMODEW *lpDevM return (*pChangeDisplaySettingsExW)(lpszDeviceName, lpDevMode, hwnd, dwflags, lParam); } -HDC WINAPI extGDIGetDC(HWND hwnd) +static HDC WINAPI sGetDC(HWND hwnd, char *ApiName) { + // to do: add parameter and reference to pGDIGetDCEx to merge properly GetDC and GetDCEx HDC ret; HWND lochwnd; - OutTraceDW("GDI.GetDC: hwnd=%x\n", hwnd); lochwnd=hwnd; + if (dxw.IsRealDesktop(hwnd)) { - OutTraceDW("GDI.GetDC: desktop remapping hwnd=%x->%x\n", hwnd, dxw.GethWnd()); + OutTraceDW("%s: desktop remapping hwnd=%x->%x\n", ApiName, hwnd, dxw.GethWnd()); lochwnd=dxw.GethWnd(); } - ret=(*pGDIGetDC)(lochwnd); - +#ifdef HANDLEFLIPTOGDI + extern BOOL bFlippedDC; + //if(bFlippedDC && (OBJ_DC == GetObjectType(ret))) { + if(bFlippedDC) { + extern HDC hFlippedDC; + LPDIRECTDRAWSURFACE lpDDSPrim; + //extern Unlock4_Type pUnlockMethod(LPDIRECTDRAWSURFACE); + lpDDSPrim = dxw.GetPrimarySurface(); + //(*pUnlockMethod(lpDDSPrim))(lpDDSPrim, NULL); + (*pGetDC)(lpDDSPrim, &hFlippedDC); + OutTraceDW("%s: remapping flipped GDI hdc=%x\n", ApiName, hFlippedDC); + return hFlippedDC; + } +#endif + + switch(GDIEmulationMode){ + case GDIMODE_STRETCHED: + ret=(*pGDIGetDC)(lochwnd); + break; + case GDIMODE_EMULATED: + ret=dxw.AcquireEmulatedDC(lochwnd); + dxw.VirtualHDC=ret; + break; + case GDIMODE_DIRECTDRAW: + break; + } + if(ret){ - OutTraceDW("GDI.GetDC: hwnd=%x ret=%x\n", lochwnd, ret); + OutTraceDW("%s: hwnd=%x ret=%x\n", ApiName, lochwnd, ret); } else{ int err; err=GetLastError(); - OutTraceE("GDI.GetDC ERROR: hwnd=%x err=%d at %d\n", lochwnd, err, __LINE__); + OutTraceE("%s ERROR: hwnd=%x err=%d at %d\n", ApiName, lochwnd, err, __LINE__); if((err==ERROR_INVALID_WINDOW_HANDLE) && (lochwnd!=hwnd)){ ret=(*pGDIGetDC)(hwnd); if(ret) - OutTraceDW("GDI.GetDC: hwnd=%x ret=%x\n", hwnd, ret); + OutTraceDW("%s: hwnd=%x ret=%x\n", ApiName, hwnd, ret); else - OutTraceE("GDI.GetDC ERROR: hwnd=%x err=%d at %d\n", hwnd, GetLastError(), __LINE__); + OutTraceE("%s ERROR: hwnd=%x err=%d at %d\n", ApiName, hwnd, GetLastError(), __LINE__); } } return ret; } -HDC WINAPI extEMUGetDC(HWND hwnd) +HDC WINAPI extGDIGetDC(HWND hwnd) { - HDC ret; - HWND lochwnd; - OutTraceDW("GDI.GetDC: hwnd=%x\n", hwnd); - - lochwnd=hwnd; - if (dxw.IsRealDesktop(hwnd)) { - OutTraceDW("GDI.GetDC: desktop remapping hwnd=%x->%x\n", hwnd, dxw.GethWnd()); - lochwnd=dxw.GethWnd(); - } - - ret=dxw.AcquireEmulatedDC(lochwnd); - OutTraceDW("GDI.GetDC: remapping hdc=%x->%x\n", (*pGDIGetDC)(hwnd), ret); - dxw.VirtualHDC=ret; - - if(ret){ - OutTraceDW("GDI.GetDC: hwnd=%x ret=%x\n", lochwnd, ret); - } - else{ - int err; - err=GetLastError(); - OutTraceE("GDI.GetDC ERROR: hwnd=%x err=%d at %d\n", lochwnd, err, __LINE__); - if((err==ERROR_INVALID_WINDOW_HANDLE) && (lochwnd!=hwnd)){ - ret=(*pGDIGetDC)(hwnd); - if(ret) - OutTraceDW("GDI.GetDC: hwnd=%x ret=%x\n", hwnd, ret); - else - OutTraceE("GDI.GetDC ERROR: hwnd=%x err=%d at %d\n", hwnd, GetLastError(), __LINE__); - } - } - - return ret; + return sGetDC(hwnd, "GDI.GetDC"); } HDC WINAPI extGDIGetDCEx(HWND hwnd, HRGN hrgnClip, DWORD flags) { // used by Star Wars Shadow of the Empire - HDC ret; - HWND lochwnd; - OutTraceDW("GDI.GetDCEx: hwnd=%x hrgnClip=%x flags=%x(%s)\n", hwnd, hrgnClip, flags, ExplainGetDCExFlags(flags)); - lochwnd=hwnd; - if (dxw.IsRealDesktop(hwnd)) { - OutTraceDW("GDI.GetDCEx: desktop remapping hwnd=%x->%x\n", hwnd, dxw.GethWnd()); - lochwnd=dxw.GethWnd(); - } - - ret=(*pGDIGetDC)(lochwnd); - - if(ret){ - OutTraceDW("GDI.GetDCEx: hwnd=%x ret=%x\n", lochwnd, ret); - } - else{ - int err; - err=GetLastError(); - OutTraceE("GDI.GetDCEx ERROR: hwnd=%x err=%d at %d\n", lochwnd, err, __LINE__); - if((err==ERROR_INVALID_WINDOW_HANDLE) && (lochwnd!=hwnd)){ - ret=(*pGDIGetDCEx)(hwnd, hrgnClip, flags); - if(ret) - OutTraceDW("GDI.GetDCEx: hwnd=%x ret=%x\n", hwnd, ret); - else - OutTraceE("GDI.GetDCEx ERROR: hwnd=%x err=%d at %d\n", hwnd, GetLastError(), __LINE__); - } - } - - return ret; -} - -HDC WINAPI extEMUGetDCEx(HWND hwnd, HRGN hrgnClip, DWORD flags) -{ - // used by Star Wars Shadow of the Empire - HDC ret; - HWND lochwnd; - - OutTraceDW("GDI.GetDCEx: hwnd=%x hrgnClip=%x flags=%x(%s)\n", hwnd, hrgnClip, flags, ExplainGetDCExFlags(flags)); - lochwnd=hwnd; - if (dxw.IsRealDesktop(hwnd)) { - OutTraceDW("GDI.GetDCEx: desktop remapping hwnd=%x->%x\n", hwnd, dxw.GethWnd()); - lochwnd=dxw.GethWnd(); - } - - ret=dxw.AcquireEmulatedDC(lochwnd); - OutTraceDW("GDI.GetDCEx: remapping hdc=%x->%x\n", (*pGDIGetDC)(hwnd), ret); - dxw.VirtualHDC=ret; - - if(ret){ - OutTraceDW("GDI.GetDCEx: hwnd=%x ret=%x\n", lochwnd, ret); - } - else{ - int err; - err=GetLastError(); - OutTraceE("GDI.GetDCEx ERROR: hwnd=%x err=%d at %d\n", lochwnd, err, __LINE__); - if((err==ERROR_INVALID_WINDOW_HANDLE) && (lochwnd!=hwnd)){ - ret=(*pGDIGetDCEx)(hwnd, hrgnClip, flags); - if(ret) - OutTraceDW("GDI.GetDCEx: hwnd=%x ret=%x\n", hwnd, ret); - else - OutTraceE("GDI.GetDCEx ERROR: hwnd=%x err=%d at %d\n", hwnd, GetLastError(), __LINE__); - } - } - - return ret; + return sGetDC(hwnd, "GDI.GetDCEx"); } HDC WINAPI extGDIGetWindowDC(HWND hwnd) { - HDC ret; - HWND lochwnd; OutTraceDW("GDI.GetWindowDC: hwnd=%x\n", hwnd); - lochwnd=hwnd; - if (dxw.IsRealDesktop(hwnd)) { - OutTraceDW("GDI.GetWindowDC: desktop remapping hwnd=%x->%x\n", hwnd, dxw.GethWnd()); - lochwnd=dxw.GethWnd(); + + // if not fullscreen or not desktop win, just proxy the call + if(!dxw.IsFullScreen() || !dxw.IsDesktop(hwnd)){ + HDC ret; + ret=(*pGDIGetWindowDC)(hwnd); + OutTraceDW("GDI.GetWindowDC: hwnd=%x hdc=%x\n", hwnd, ret); + return ret; } - if(dxw.IsFullScreen()){ - ret=dxw.AcquireEmulatedDC(lochwnd); - OutTraceDW("GDI.GetWindowDC: remapping hdc=%x->%x\n", (*pGDIGetDC)(hwnd), ret); - dxw.VirtualHDC=ret; - } - else - ret=(*pGDIGetWindowDC)(lochwnd); - - if(ret){ - OutTraceDW("GDI.GetWindowDC: hwnd=%x ret=%x\n", lochwnd, ret); - } - else{ - int err; - err=GetLastError(); - OutTraceE("GDI.GetWindowDC ERROR: hwnd=%x err=%d at %d\n", lochwnd, err, __LINE__); - if((err==ERROR_INVALID_WINDOW_HANDLE) && (lochwnd!=hwnd)){ - ret=(*pGDIGetWindowDC)(hwnd); - if(ret) - OutTraceDW("GDI.GetWindowDC: hwnd=%x ret=%x\n", hwnd, ret); - else - OutTraceE("GDI.GetWindowDC ERROR: hwnd=%x err=%d at %d\n", hwnd, GetLastError(), __LINE__); - } - } - return ret; + return sGetDC(hwnd, "GDI.GetWindowDC"); } - -HDC WINAPI extEMUGetWindowDC(HWND hwnd) -{ - HDC ret; - HWND lochwnd; - OutTraceDW("GDI.GetWindowDC: hwnd=%x\n", hwnd); - lochwnd=hwnd; - if (dxw.IsRealDesktop(hwnd)) { - OutTraceDW("GDI.GetWindowDC: desktop remapping hwnd=%x->%x\n", hwnd, dxw.GethWnd()); - lochwnd=dxw.GethWnd(); - } - - if(dxw.IsDesktop(hwnd) && dxw.IsFullScreen()) - ret=(*pGDIGetDC)(lochwnd); - else - ret=(*pGDIGetWindowDC)(lochwnd); - - if(ret){ - OutTraceDW("GDI.GetWindowDC: hwnd=%x ret=%x\n", lochwnd, ret); - } - else{ - int err; - err=GetLastError(); - OutTraceE("GDI.GetWindowDC ERROR: hwnd=%x err=%d at %d\n", lochwnd, err, __LINE__); - if((err==ERROR_INVALID_WINDOW_HANDLE) && (lochwnd!=hwnd)){ - ret=(*pGDIGetWindowDC)(hwnd); - if(ret) - OutTraceDW("GDI.GetWindowDC: hwnd=%x ret=%x\n", hwnd, ret); - else - OutTraceE("GDI.GetWindowDC ERROR: hwnd=%x err=%d at %d\n", hwnd, GetLastError(), __LINE__); - } - } - return ret; -} - int WINAPI extGDIReleaseDC(HWND hwnd, HDC hDC) { int res; @@ -2064,22 +1955,34 @@ int WINAPI extGDIReleaseDC(HWND hwnd, HDC hDC) OutTraceDW("GDI.ReleaseDC: hwnd=%x hdc=%x\n", hwnd, hDC); if (dxw.IsRealDesktop(hwnd)) hwnd=dxw.GethWnd(); - res=(*pGDIReleaseDC)(hwnd, hDC); - if (!res) OutTraceE("GDI.ReleaseDC ERROR: err=%d at %d\n", GetLastError(), __LINE__); - return(res); -} -int WINAPI extEMUReleaseDC(HWND hwnd, HDC hDC) -{ - int res; - HDC windc; +#ifdef HANDLEFLIPTOGDI + extern BOOL bFlippedDC; + extern HDC hFlippedDC; + if(bFlippedDC && (hDC == hFlippedDC)) { + HRESULT ret; + OutTraceDW("GDI.ReleaseDC: releasing flipped GDI hdc=%x\n", hDC); + ret=(*pReleaseDC)(dxw.GetPrimarySurface(), hDC); + if (ret) OutTraceE("GDI.ReleaseDC ERROR: err=%x(%s) at %d\n", ret, ExplainDDError(ret), __LINE__); + dxw.ScreenRefresh(); + return (ret == DD_OK); + } +#endif - OutTraceDW("GDI.ReleaseDC: hwnd=%x hdc=%x\n", hwnd, hDC); + switch(GDIEmulationMode){ + case GDIMODE_STRETCHED: + res=(*pGDIReleaseDC)(hwnd, hDC); + break; + case GDIMODE_EMULATED: + HDC windc; + windc=(*pGDIGetDC)(hwnd); + res=dxw.ReleaseEmulatedDC(hwnd); + res=(*pGDIReleaseDC)(hwnd, windc); + break; + case GDIMODE_DIRECTDRAW: + break; + } - if (dxw.IsRealDesktop(hwnd)) hwnd=dxw.GethWnd(); - windc=(*pGDIGetDC)(hwnd); - res=dxw.ReleaseEmulatedDC(hwnd); - res=(*pGDIReleaseDC)(hwnd, windc); if (!res) OutTraceE("GDI.ReleaseDC ERROR: err=%d at %d\n", GetLastError(), __LINE__); return(res); } @@ -2089,45 +1992,43 @@ HDC WINAPI extBeginPaint(HWND hwnd, LPPAINTSTRUCT lpPaint) HDC hdc; OutTraceDW("GDI.BeginPaint: hwnd=%x lpPaint=%x FullScreen=%x\n", hwnd, lpPaint, dxw.IsFullScreen()); - hdc=(*pBeginPaint)(hwnd, lpPaint); // avoid access to real desktop if(dxw.IsRealDesktop(hwnd)) hwnd=dxw.GethWnd(); + hdc=(*pBeginPaint)(hwnd, lpPaint); + // if not in fullscreen mode, that's all! if(!dxw.IsFullScreen()) return hdc; // on CLIENTREMAPPING, resize the paint area to virtual screen size if(dxw.dwFlags1 & CLIENTREMAPPING) lpPaint->rcPaint=dxw.GetScreenRect(); + switch(GDIEmulationMode){ + case GDIMODE_STRETCHED: + break; + case GDIMODE_EMULATED: + HDC EmuHDC; + EmuHDC = dxw.AcquireEmulatedDC(hwnd); + lpPaint->hdc=EmuHDC; + hdc = EmuHDC; + break; + case GDIMODE_DIRECTDRAW: + (*pGDIReleaseDC)(hwnd, lpPaint->hdc); + (*pGetDC)(dxw.lpDDSPrimHDC,&PrimHDC); + lpPaint->hdc=PrimHDC; + // resize the paint area to virtual screen size (see CivIII clipped panels...) + lpPaint->rcPaint=dxw.GetScreenRect(); + OutTraceDW("GDI.BeginPaint(MAPGDITOPRIMARY): hdc=%x -> %x\n", hdc, PrimHDC); + hdc = PrimHDC; + break; + } + OutTraceDW("GDI.BeginPaint: hdc=%x rcPaint=(%d,%d)-(%d,%d)\n", hdc, lpPaint->rcPaint.left, lpPaint->rcPaint.top, lpPaint->rcPaint.right, lpPaint->rcPaint.bottom); return hdc; } -HDC WINAPI extEMUBeginPaint(HWND hwnd, LPPAINTSTRUCT lpPaint) -{ - HDC hdc; - HDC EmuHDC; - - OutTraceDW("GDI.BeginPaint(GDIEMULATEDC): hwnd=%x lpPaint=%x FullScreen=%x\n", hwnd, lpPaint, dxw.IsFullScreen()); - hdc=(*pBeginPaint)(hwnd, lpPaint); - - // avoid access to real desktop - if(dxw.IsRealDesktop(hwnd)) hwnd=dxw.GethWnd(); - - // if not in fullscreen mode, that's all! - if(!dxw.IsFullScreen()) return hdc; - - // on CLIENTREMAPPING, resize the paint area to virtual screen size - if(dxw.dwFlags1 & CLIENTREMAPPING) lpPaint->rcPaint=dxw.GetScreenRect(); - - EmuHDC = dxw.AcquireEmulatedDC(hwnd); - lpPaint->hdc=EmuHDC; - OutTraceDW("GDI.BeginPaint(GDIEMULATEDC): hdc=%x -> %x\n", hdc, EmuHDC); - return EmuHDC; -} - HDC WINAPI extDDBeginPaint(HWND hwnd, LPPAINTSTRUCT lpPaint) { HDC hdc; @@ -2179,32 +2080,34 @@ BOOL WINAPI extEndPaint(HWND hwnd, const PAINTSTRUCT *lpPaint) { BOOL ret; - OutTraceDW("GDI.EndPaint: hwnd=%x lpPaint=%x lpPaint.rcpaint=(%d,%d)-(%d-%d) lpPaint.hdc=%x\n", - hwnd, lpPaint, lpPaint->rcPaint.left, lpPaint->rcPaint.top, lpPaint->rcPaint.right, lpPaint->rcPaint.bottom, lpPaint->hdc); - ret=(*pEndPaint)(hwnd, lpPaint); - OutTraceDW("GDI.EndPaint: hwnd=%x ret=%x\n", hwnd, ret); - if(!ret) OutTraceE("GDI.EndPaint ERROR: err=%d at %d\n", GetLastError(), __LINE__); - return ret; -} + OutTraceDW("GDI.EndPaint: hwnd=%x lpPaint=%x lpPaint.hdc=%x lpPaint.rcpaint=(%d,%d)-(%d-%d)\n", + hwnd, lpPaint, lpPaint->hdc, lpPaint->rcPaint.left, lpPaint->rcPaint.top, lpPaint->rcPaint.right, lpPaint->rcPaint.bottom); -BOOL WINAPI extEMUEndPaint(HWND hwnd, const PAINTSTRUCT *lpPaint) -{ - BOOL ret; - - OutTraceDW("GDI.EndPaint: hwnd=%x lpPaint=%x lpPaint.hdc=%x\n", hwnd, lpPaint, lpPaint->hdc); - - if(dxw.IsFullScreen()){ - // avoid access to real desktop - if(dxw.IsRealDesktop(hwnd)) hwnd=dxw.GethWnd(); - OutTraceDW("GDI.EndPaint(GDIEMULATEDC): hwnd=%x\n", hwnd); - ret=dxw.ReleaseEmulatedDC(hwnd); + // if not fullscreen or not desktop win, just proxy the call + if(!dxw.IsFullScreen() || !dxw.Windowize){ + ret=(*pEndPaint)(hwnd, lpPaint); + return ret; } - else{ - // proxy part ... - ret=(*pEndPaint)(hwnd, lpPaint); + + // avoid access to real desktop + if(dxw.IsRealDesktop(hwnd)) hwnd=dxw.GethWnd(); + + switch(GDIEmulationMode){ + case GDIMODE_STRETCHED: + ret=(*pEndPaint)(hwnd, lpPaint); + break; + case GDIMODE_EMULATED: + ret=dxw.ReleaseEmulatedDC(hwnd); + break; + case GDIMODE_DIRECTDRAW: + break; } - OutTraceDW("GDI.EndPaint: hwnd=%x ret=%x\n", hwnd, ret); - if(!ret) OutTraceE("GDI.EndPaint ERROR: err=%d at %d\n", GetLastError(), __LINE__); + + if(ret) + OutTraceDW("GDI.EndPaint: hwnd=%x ret=%x\n", hwnd, ret); + else + OutTraceE("GDI.EndPaint ERROR: err=%d at %d\n", GetLastError(), __LINE__); + return ret; } @@ -3065,3 +2968,11 @@ HRESULT WINAPI extMessageBoxTimeoutW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaptio return res; } +BOOL WINAPI extIsIconic(HWND hWnd) +{ + BOOL ret; + ret = (*pIsIconic)(hWnd); + OutTrace("IsIconic: hwnd=%x ret=%x\n", hWnd, ret); + //return FALSE; + return ret; +} \ No newline at end of file diff --git a/dll/winmm.cpp b/dll/winmm.cpp index d7923b4..1028bdc 100644 --- a/dll/winmm.cpp +++ b/dll/winmm.cpp @@ -162,7 +162,12 @@ MCIERROR WINAPI extmciSendStringA(LPCTSTR lpszCommand, LPTSTR lpszReturnString, if (sscanf(lpszCommand, "put %s destination at %ld %ld %ld %ld", sMovieNickName, &(rect.left), &(rect.top), &(rect.right), &(rect.bottom))==5){ char NewCommand[256]; + // v2.03.19 height / width fix + rect.right += rect.left; // convert width to position + rect.bottom += rect.top; // convert height to position rect=dxw.MapClientRect(&rect); + rect.right -= rect.left; // convert position to width + rect.bottom -= rect.top; // convert position to height sprintf(NewCommand, "put %s destination at %d %d %d %d", sMovieNickName, rect.left, rect.top, rect.right, rect.bottom); lpszCommand=NewCommand; OutTraceDW("mciSendStringA: replaced Command=\"%s\"\n", lpszCommand); @@ -186,7 +191,12 @@ MCIERROR WINAPI extmciSendStringW(LPCWSTR lpszCommand, LPWSTR lpszReturnString, if (swscanf(lpszCommand, L"put %ls destination at %ld %ld %ld %ld", sMovieNickName, &(rect.left), &(rect.top), &(rect.right), &(rect.bottom))==5){ WCHAR NewCommand[256]; + // v2.03.19 height / width fix + rect.right += rect.left; // convert width to position + rect.bottom += rect.top; // convert height to position rect=dxw.MapClientRect(&rect); + rect.right -= rect.left; // convert position to width + rect.bottom -= rect.top; // convert position to height swprintf(NewCommand, L"put %ls destination at %d %d %d %d", sMovieNickName, rect.left, rect.top, rect.right, rect.bottom); lpszCommand=NewCommand; OutTraceDW("mciSendStringW: replaced Command=\"%ls\"\n", lpszCommand); diff --git a/host/TabDirect3D.cpp b/host/TabDirect3D.cpp index 3c3c6b5..5b9999c 100644 --- a/host/TabDirect3D.cpp +++ b/host/TabDirect3D.cpp @@ -43,6 +43,10 @@ void CTabDirect3D::DoDataExchange(CDataExchange* pDX) DDX_Check(pDX, IDC_WIREFRAME, cTarget->m_WireFrame); DDX_Check(pDX, IDC_DISABLEFOGGING, cTarget->m_DisableFogging); DDX_Check(pDX, IDC_CLEARTARGET, cTarget->m_ClearTarget); + + // Swap Effect + DDX_Check(pDX, IDC_FORCESWAPEFFECT, cTarget->m_ForcesSwapEffect); + DDX_Radio(pDX, IDC_SWAP_DISCARD, cTarget->m_SwapEffect); } BEGIN_MESSAGE_MAP(CTabDirect3D, CDialog) diff --git a/host/TargetDlg.cpp b/host/TargetDlg.cpp index b56a783..c136853 100644 --- a/host/TargetDlg.cpp +++ b/host/TargetDlg.cpp @@ -49,6 +49,7 @@ CTargetDlg::CTargetDlg(CWnd* pParent /*=NULL*/) m_NoImagehlp = FALSE; m_ReplacePrivOps = FALSE; m_ForcesHEL = FALSE; + m_ForcesSwapEffect = FALSE; m_ColorFix = FALSE; m_NoPixelFormat = FALSE; m_NoAlphaChannel = FALSE; @@ -186,6 +187,7 @@ CTargetDlg::CTargetDlg(CWnd* pParent /*=NULL*/) m_SizY = 600; m_MaxFPS = 0; m_InitTS = 8; + m_SwapEffect = 0; //}}AFX_DATA_INIT } diff --git a/host/TargetDlg.h b/host/TargetDlg.h index 3e15050..6b17882 100644 --- a/host/TargetDlg.h +++ b/host/TargetDlg.h @@ -170,6 +170,7 @@ public: BOOL m_EASportsHack; BOOL m_NoImagehlp; BOOL m_ForcesHEL; + BOOL m_ForcesSwapEffect; BOOL m_ColorFix; BOOL m_NoPixelFormat; BOOL m_NoAlphaChannel; @@ -205,6 +206,7 @@ public: int m_FakeVersionId; int m_MaxScreenRes; int m_ResTypes; + int m_SwapEffect; //}}AFX_DATA diff --git a/host/dxwndhost.aps b/host/dxwndhost.aps index e8a5659b7f3fae0fb6fe3236be848b58bcb5136d..34f53bace9046dbd10533ec732e3c33cfcba1b5d 100644 GIT binary patch delta 3347 zcmZuzdu&tZ6+g!bp@Wpy@^m0jAiSY|CAkhQ#PPjOE;zmy+j;Q3P$*psOA(-u5U3HT zS|!*<=ZZ6-waXvv1X?H2PQwzEQAFtgL4c-$4j6TitzVe)I&{Q;Td@#3;`b{4K5P&C0@nZj+O)52@h=KSP1pmk!+Q9S{Oy7WY=bqh z2_}KY==%7Lab?zwdo5?$4C~@+>I*jo^Z(eLl6Ie^>*)CFU*P`_a=6{s7=W}!y277qF(;em03M9j2A z6s=WwRKgDhVKo}69#{%)S9P@$3M8azK`p9D$OVNG@~NuS-B2WTtXPNf>k zB^LEX7F&z;U{Io7m?+VJ9@MOeL0zYD^l&!!I$#oAZ^sG6&t&)p!&of5ydIcLqqbqu zoGFqNxD|;SrX;Iiszf=lB?^$B7b?hPkK$>P_^@Xr81a zzGh84vEZCec$S{;z_KET%fv?m*hm-(!Eoh3b^U*4lFM9NK&>? zZ#0c?RQS3aP)Qd%uylHrqfQZA@YVyQVOE;lIjbSIXem!@^%WUQe#JF%EncVa%y zm+Plpo;p)>SaB)voPeg_^GT}Qk*(_$67Gsjo#3sfHMd;`Tr- zjogl9l|D%)87r*uAmz4I+*MGQP5FaHvia_6@Y8a3wW|o+FYa_$57k?GC}2R9!{Km& zM*Fv8X?0)--{RAwlJ`LU5F!%QOp_x>vJx7oZ##}hoxT@h5!t)2EN3x~d(}NGqEHv+ z*@Hv;wbo={rvn$nrMMR}eFEkI~qguF85Bd0DV3z0KLfs-!E1led<8zjZ{rU|S z3>TyumeIc%oxglY1l@0h0zN$`160C_A*9%~K|LZ{=&FL1WbWjLT19O_ShQ~^Kk#Zg z%wofup^jRk&ukD=<R@K9NZnsLeDtL)jzlH@Xf0W^)IyXs<+O5FL8Ju^nY^&P~uVkTmokTqj z*pNZ}Mx*JIjqo^OBV7?C{5VOc_oB+LH$Se&4Q+%m?$E0=F~$ebCIri8Ml82#akHag zBNzcEv{Nv~8)X}9jPVZXpq~n@lYSTDo^DT^k74aX%0G!A^d^>{#P@RW7U5~E=hszy z1teCVM#Gj=E~GGe>r?DauVa70d+GJ=vv?}KUVaW6((B{r@VWGQ^m#m&S||F?h%Lqo=RU z&oWTzzU+KAbXv@{WH!=yY?lV z*YU$a+sBE=H*n>kT9nxQ7rZv8D)ho_oS$~BrK4F|1C8iIf0}Ei^?evfYbA81FO#yA zp1On6)0~|e?qs+rv^T?1>@JR=&+qV?ot!?MxQipH@Jrq*NdTwOqA#%`txcylva}iW zX_hvVa_?p=XHi|2Hk)>3X>;h0S=!vhmBwJEcy zxgX1IpLnQU$O11N5OPKx9ToD8I=U)kYXdzLa${qBV6mMX_u03#iK^~ndH#1z;uCZj z|2;^x_p!j%-5j6SWT*YYD%cXg&g&y$?O7Ior*%Qzi~@i;77ehoZR-}Y|AXa6T~s4v zZj6=*nZKL13t786-m}Y|cW4a2Q$MF;0=oR`_^Njp$_FUurU3!ne4p(9Wclt1suA+5 z6SPdoBR%m27n9z9?V*DLdjB>Z6SD7iyzQ1fk4u3={WKt;oBd?}j^(>ZH9~%Yw2Wm= z_c)|y$6~3h;`4EIP>{cxLdOJoc?yy>nMo1pmmV4rJpLaZB|hgJJcjhIcMZTKi>^Mx$+nVHG{E+Gw`K$6pP}-9 HVflXn;~Tu- delta 2839 zcmZWreQZ=&6+fqCTU~XbOG~Gvot8>jy5-}|yeTtNu;sPywS9Cx9`n%|D(w@Cpy(2I zZ4^qsh-fw&jKoPiW@EZ0enbQ7V%*Inn+7FzBP@$xR~?nG^M`IF`9t|M$nf1>c2%U%j*D{eo|}8ndoOoKaEB{b7o#jD#U6FD#Xmrt30RVVR7Lv=xfRavmR)NG_I)NRJ<$ zl(Cg30*Dm0J6**!-zknCYCD~&dsZg|2^bGjHCAowa z@3ytsE}-j88Ym6G?uVp(ax9_j)%;6LO6mE1u7j&d&tmYS}4R-<5Kp*N=NOA zM!O~JgDS}i!j31jSguwRRMXN!Shn6RRW4$SEy|Q2)XbCf2M#C-)Y5iNsaPddzSBS&B**Qcc{4`*q~xVZO#(gdsNX4fN6wmap6>Wiz51X@z%Z@z_MZ z*8>XuVF;J6^GJg=H|2m=1+UZ5()jJl#~biAflA8`V;%bFrNdZG+YaL=u_?FSFV>sn z`cta6&60cc2Ei|=x~f2~M{XW%$9O=`UQYx>-6>yw7OL4x14(Z1&2Ns75Hlm4c1nvy7-5s5C?05`U2O5SF0vT0STrULDr{Y(q%d=<6K0zlvaMR@{yl>4Y8M5jOY>K?@}f z@bD`i%)WXAx3t)*4~hP#XkV}Bz^e? zK9$#&(}{V_MYk6y)wE&8@wsXL46ey%)zHf`Sf7t->E?oH6*au;XmzyLiRgnH_&ELI zUH+)ejd1-86So!+&&=Q_sPR2qnJ>O3Yrlub9?#yoi$BAnJxc)6^_iCX%A$QA2e{Ud zaW_^LZD95*DqZ;y-360=niY6yYvzfz%A!+`0VrB#KQHgG3pz6`U6n;|76X)qXy{*T zghZw#Sy^<9#UCW-bwPC{>59O6NtzXSHBFWGu&v;aebj%C}a^Gh>I6*A}Cnu<1;L#H_Dljxj69SJ<(rJO|3p6e8*adndFfmQ; ze=|NmO)UbgJJc`m=p7mr7y_CQI1Y4LU{?uE3mh(?M*{Uaaz9`^SVt`ax2n`Ha8RXD zfm?K%5O`Fl(+|*FIHe=qF>pQAKEx%3A93`Gfh(!)A+9L!8Pxj_-G$c-q?%5wDC*}6 z+tNWVGFdR$L9Yv3-9=Y~$ug0?vkfbXzt5%vA+8hVj9w1bhN<~K?EG<
#kB(Q5c zy~tR2H-@w^!I{lGt>bZ|iyRb9aBwR{v%+z5C(_M6CbeAvXZxsm7V8R>UsL}qx{C)I R0apK(PcemMALDlN?|%jtAVB~C diff --git a/host/dxwndhost.rc b/host/dxwndhost.rc index 9891e0c18c9b14f6ec102ba01b264401d7fb9e30..d3e311393a2cb4c3e6287cce09a0df1276119a16 100644 GIT binary patch delta 489 zcmaF#i*;WM+Xl9-$&1b!OqQ9<@ zLA1f-!so`5WlnNP76a8|*QtL|Trij+oWYSH0BE8c5V|rrPj;*io?MW^#%{u33N*=b z^2N#KlLaoYX(t2iE@DVwPy&j2GPp1}GsFYUh3Jk4@;!k(XP{X@3@(!&c7;x!@SBC% zl)-$m{d`+lH-;RBOrXoL>YZ-S!Kgj?!)G~GL!jR+K^i9i)8~-Jsu*a6KSRLe!d6wN z4hsfDkPc;khB9D)6ag(tWT?b$(d5V-hEQFW48|Z`+AxQ?GE`vK0}K=&px1x_G`Vmx i*iLRE1_N-=fC4#wS}LQ$?-D46}%ww&f{eA!Yyo diff --git a/host/dxwndhost.vs2008.suo b/host/dxwndhost.vs2008.suo index 1a31ec43faca18502b008bc67c961a1fc5c7efcf..d2f4513079daa1d6b331697d3a373b4140b11b9e 100644 GIT binary patch delta 6679 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 b{hDt&{!8P1R_T8M&*6RZ diff --git a/host/dxwndhostView.cpp b/host/dxwndhostView.cpp index 958fc4d..a02dd19 100644 --- a/host/dxwndhostView.cpp +++ b/host/dxwndhostView.cpp @@ -166,6 +166,7 @@ static void SetTargetFromDlg(TARGETMAP *t, CTargetDlg *dlg) t->flags3 = 0; t->flags4 = 0; t->flags5 = 0; + t->flags6 = 0; t->tflags = 0; if(dlg->m_UnNotify) t->flags |= UNNOTIFY; if(dlg->m_Windowize) t->flags2 |= WINDOWIZE; @@ -274,6 +275,7 @@ static void SetTargetFromDlg(TARGETMAP *t, CTargetDlg *dlg) if(dlg->m_EASportsHack) t->flags5 |= EASPORTSHACK; if(dlg->m_NoImagehlp) t->flags5 |= NOIMAGEHLP; if(dlg->m_ForcesHEL) t->flags3 |= FORCESHEL; + if(dlg->m_ForcesSwapEffect) t->flags6 |= FORCESWAPEFFECT; if(dlg->m_ColorFix) t->flags3 |= COLORFIX; if(dlg->m_NoPixelFormat) t->flags3 |= NOPIXELFORMAT; if(dlg->m_NoAlphaChannel) t->flags4 |= NOALPHACHANNEL; @@ -382,6 +384,7 @@ static void SetTargetFromDlg(TARGETMAP *t, CTargetDlg *dlg) t->InitTS = dlg->m_InitTS-8; t->FakeVersionId = dlg->m_FakeVersionId; t->MaxScreenRes = dlg->m_MaxScreenRes; + t->SwapEffect = dlg->m_SwapEffect; strcpy_s(t->module, sizeof(t->module), dlg->m_Module); strcpy_s(t->OpenGLLib, sizeof(t->OpenGLLib), dlg->m_OpenGLLib); } @@ -473,6 +476,7 @@ static void SetDlgFromTarget(TARGETMAP *t, CTargetDlg *dlg) dlg->m_EASportsHack = t->flags5 & EASPORTSHACK ? 1 : 0; dlg->m_NoImagehlp = t->flags5 & NOIMAGEHLP ? 1 : 0; dlg->m_ForcesHEL = t->flags3 & FORCESHEL ? 1 : 0; + dlg->m_ForcesSwapEffect = t->flags6 & FORCESWAPEFFECT ? 1 : 0; dlg->m_ColorFix = t->flags3 & COLORFIX ? 1 : 0; dlg->m_NoPixelFormat = t->flags3 & NOPIXELFORMAT ? 1 : 0; dlg->m_NoAlphaChannel = t->flags4 & NOALPHACHANNEL ? 1 : 0; @@ -596,6 +600,7 @@ static void SetDlgFromTarget(TARGETMAP *t, CTargetDlg *dlg) dlg->m_InitTS = t->InitTS+8; dlg->m_FakeVersionId = t->FakeVersionId; dlg->m_MaxScreenRes = t->MaxScreenRes; + dlg->m_SwapEffect = t->SwapEffect; } static void SaveConfigItem(TARGETMAP *TargetMap, PRIVATEMAP *PrivateMap, int i, char *InitPath) @@ -634,6 +639,9 @@ static void SaveConfigItem(TARGETMAP *TargetMap, PRIVATEMAP *PrivateMap, int i, sprintf_s(key, sizeof(key), "flagj%i", i); sprintf_s(val, sizeof(val), "%i", TargetMap->flags5); WritePrivateProfileString("target", key, val, InitPath); + sprintf_s(key, sizeof(key), "flagk%i", i); + sprintf_s(val, sizeof(val), "%i", TargetMap->flags6); + WritePrivateProfileString("target", key, val, InitPath); sprintf_s(key, sizeof(key), "tflag%i", i); sprintf_s(val, sizeof(val), "%i", TargetMap->tflags); WritePrivateProfileString("target", key, val, InitPath); @@ -680,6 +688,9 @@ static void SaveConfigItem(TARGETMAP *TargetMap, PRIVATEMAP *PrivateMap, int i, sprintf_s(key, sizeof(key), "maxres%i", i); sprintf_s(val, sizeof(val), "%i", TargetMap->MaxScreenRes); WritePrivateProfileString("target", key, val, InitPath); + sprintf_s(key, sizeof(key), "swapeffect%i", i); + sprintf_s(val, sizeof(val), "%i", TargetMap->SwapEffect); + WritePrivateProfileString("target", key, val, InitPath); } static void ClearTarget(int i, char *InitPath) @@ -703,6 +714,8 @@ static void ClearTarget(int i, char *InitPath) WritePrivateProfileString("target", key, 0, InitPath); sprintf_s(key, sizeof(key), "flagj%i", i); WritePrivateProfileString("target", key, 0, InitPath); + sprintf_s(key, sizeof(key), "flagk%i", i); + WritePrivateProfileString("target", key, 0, InitPath); sprintf_s(key, sizeof(key), "tflag%i", i); WritePrivateProfileString("target", key, 0, InitPath); sprintf_s(key, sizeof(key), "initx%i", i); @@ -727,6 +740,8 @@ static void ClearTarget(int i, char *InitPath) WritePrivateProfileString("target", key, 0, InitPath); sprintf_s(key, sizeof(key), "maxfps%i", i); WritePrivateProfileString("target", key, 0, InitPath); + sprintf_s(key, sizeof(key), "swapeffect%i", i); + WritePrivateProfileString("target", key, 0, InitPath); sprintf_s(key, sizeof(key), "initts%i", i); WritePrivateProfileString("target", key, 0, InitPath); @@ -770,6 +785,8 @@ static int LoadConfigItem(TARGETMAP *TargetMap, PRIVATEMAP *PrivateMap, int i, c TargetMap->flags4 = GetPrivateProfileInt("target", key, 0, InitPath); sprintf_s(key, sizeof(key), "flagj%i", i); TargetMap->flags5 = GetPrivateProfileInt("target", key, 0, InitPath); + sprintf_s(key, sizeof(key), "flagk%i", i); + TargetMap->flags6 = GetPrivateProfileInt("target", key, 0, InitPath); sprintf_s(key, sizeof(key), "tflag%i", i); TargetMap->tflags = GetPrivateProfileInt("target", key, 0, InitPath); sprintf_s(key, sizeof(key), "initx%i", i); @@ -796,7 +813,8 @@ static int LoadConfigItem(TARGETMAP *TargetMap, PRIVATEMAP *PrivateMap, int i, c TargetMap->MaxFPS = GetPrivateProfileInt("target", key, 0, InitPath); sprintf_s(key, sizeof(key), "initts%i", i); TargetMap->InitTS = GetPrivateProfileInt("target", key, 0, InitPath); - + sprintf_s(key, sizeof(key), "swapeffect%i", i); + TargetMap->SwapEffect = GetPrivateProfileInt("target", key, 0, InitPath); sprintf_s(key, sizeof(key), "winver%i", i); TargetMap->FakeVersionId = GetPrivateProfileInt("target", key, 0, InitPath); sprintf_s(key, sizeof(key), "maxres%i", i); diff --git a/host/resource b/host/resource index 162bf7c6b64393fed909348d19f6e77d8ce2a3a7..80e061a179c1c4f6cff35135338ede8a25b85e51 100644 GIT binary patch delta 213 zcmbQy$#kHXX~UuT$shPwCi59`@dh)5GdMB?Ft{?fF}O|M@2)uc0wW8f@#H{mX^!B2jX7X-{0Mb!3_c8=lP@Z3Ga5~9v{mMXm>&<+>CX@_ zd83=^WC2DNknYJvGD_@F*~$4j+HmnhwGxvr@NfvDnF(^`#E+_AtqOG#lLM02HXn(< Gq5=Ss;yF10 delta 14 WcmX@m%QT~tX~UuT&94%#sQ>^p