diff --git a/Include/dxwnd.h b/Include/dxwnd.h index c018474..e026e07 100644 --- a/Include/dxwnd.h +++ b/Include/dxwnd.h @@ -208,6 +208,7 @@ #define CREATEDESKTOP 0x01000000 // creates a virtual desktop window to replace the real one #define NOWINDOWHOOKS 0x02000000 // do not intercept window callback routines #define SYNCPALETTE 0x04000000 // Syncronize GDI to DDRAW palette +#define VIRTUALJOYSTICK 0x08000000 // Enables the DxWnd virtual joystick // logging Tflags DWORD: #define OUTTRACE 0x00000001 // enables tracing to dxwnd.log in general diff --git a/build/dxwnd.dll b/build/dxwnd.dll index 95f92cb..b101732 100644 --- a/build/dxwnd.dll +++ b/build/dxwnd.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aea2bada6a8f9329392fea5ab8975c3751d32c6a84c8f02924cdef0f42854dca -size 595456 +oid sha256:367c504db6f66d3f5c9e40e1a3e3aeb94f3c5a3df7b7bd9134a649379a40c8fa +size 612864 diff --git a/build/dxwnd.exe b/build/dxwnd.exe index 2f0682e..8f4f1a8 100644 --- a/build/dxwnd.exe +++ b/build/dxwnd.exe @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d242c24095ab0e76e32fe9d98821ab993f406512317a733859b531f466d160f7 +oid sha256:4b44208fd7eef222ff0861d95418c3aabb46481b83198c1b40d769bc52f6a8b4 size 545792 diff --git a/build/dxwnd.ini b/build/dxwnd.ini index e99a2ff..ce0540b 100644 --- a/build/dxwnd.ini +++ b/build/dxwnd.ini @@ -1,26 +1,26 @@ [window] -exportpath=D:\DxWnd\exports\ -posx=1231 -posy=493 +exportpath=D:\DxWnd\v2_03_43_src\build\exports\ +exepath=D:\Games\Arx Fatalis demo\ +posx=1946 +posy=567 sizx=320 sizy=200 -exepath=D:\Games\Men in Black\ [target] -title0=Fin-Fin -path0=D:\Games\Fin-Fin\v90seger\teoboot.exe -launchpath0=D:\Games\Fin-Fin\v90seger\FinFin.exe -module0= +title0=Arx Fatalis demo +path0=D:\Games\Arx Fatalis demo\ARX.exe +launchpath0= +module0=Athena opengllib0= notes0= registry0= ver0=0 coord0=0 -flag0=-1465909214 +flag0=136314918 flagg0=1207959552 -flagh0=20 -flagi0=205520900 +flagh0=65552 +flagi0=138412036 flagj0=4224 -flagk0=327680 +flagk0=65536 tflag0=0 initx0=0 inity0=0 @@ -28,7 +28,7 @@ minx0=0 miny0=0 maxx0=0 maxy0=0 -posx0=50 +posx0=150 posy0=50 sizx0=800 sizy0=600 @@ -37,28 +37,28 @@ initts0=0 winver0=0 maxres0=-1 swapeffect0=0 -title1=Men in Black -path1=D:\Games\Men in Black\MiBd.exe +title1=TieFighter 95 +path1=D:\Games\TIE95\TIE95.EXE launchpath1= -module1=RWL21 +module1= opengllib1= -notes1= +notes1=The game can be played also with no joystick using the DxWnd virtual one.\nIf you have a real joystick, the "Use DLL injection" flag is not necessary.\nUse "Unlock Z order" to avoid losing control of the window. registry1= -ver1=0 +ver1=1 coord1=0 -flag1=136314914 -flagg1=1209008128 +flag1=681574514 +flagg1=1744830464 flagh1=20 flagi1=138412036 -flagj1=4224 -flagk1=327680 -tflag1=-2147477245 +flagj1=1073746048 +flagk1=136642560 +tflag1=0 initx1=0 inity1=0 minx1=0 miny1=0 -maxx1=0 -maxy1=0 +maxx1=800 +maxy1=600 posx1=50 posy1=50 sizx1=800 @@ -68,96 +68,3 @@ initts1=0 winver1=0 maxres1=-1 swapeffect1=0 -title2=STCC Swedish TouringCar Championship -path2=D:\Games\STCC\STCC.exe -launchpath2= -module2= -opengllib2= -notes2=Still slow and choppy in emulation mode -registry2= -ver2=0 -coord2=0 -flag2=136314914 -flagg2=1207959552 -flagh2=-2147483628 -flagi2=138412036 -flagj2=268439680 -flagk2=69632 -tflag2=-2147477245 -initx2=0 -inity2=0 -minx2=0 -miny2=0 -maxx2=0 -maxy2=0 -posx2=50 -posy2=50 -sizx2=800 -sizy2=600 -maxfps2=0 -initts2=0 -winver2=0 -maxres2=-1 -swapeffect2=0 -title3=DOSBox.exe -path3=D:\Program Files (x86)\DOSBox-0.74\DOSBox.exe -launchpath3= -module3= -opengllib3= -notes3= -registry3= -ver3=0 -coord3=0 -flag3=681574434 -flagg3=1744830464 -flagh3=20 -flagi3=138412036 -flagj3=4224 -flagk3=327680 -tflag3=0 -initx3=0 -inity3=0 -minx3=0 -miny3=0 -maxx3=0 -maxy3=0 -posx3=50 -posy3=50 -sizx3=800 -sizy3=600 -maxfps3=0 -initts3=0 -winver3=0 -maxres3=-1 -swapeffect3=0 -title4=Imperialism -path4=D:\Games\Imperialism\Imperialism.exe -launchpath4= -module4= -opengllib4= -notes4=Note:\nMap zooming is currently not workind. Do not click on the magnifying glass, \nor the game will crash. -registry4= -ver4=0 -coord4=0 -flag4=1746935843 -flagg4=1209008128 -flagh4=20 -flagi4=4194308 -flagj4=128 -flagk4=0 -tflag4=0 -initx4=0 -inity4=0 -minx4=0 -miny4=0 -maxx4=0 -maxy4=0 -posx4=50 -posy4=50 -sizx4=800 -sizy4=600 -maxfps4=0 -initts4=0 -winver4=0 -maxres4=-1 -swapeffect4=0 diff --git a/build/exports/Arx Fatalis.dxw b/build/exports/Arx Fatalis.dxw new file mode 100644 index 0000000..45ee414 --- /dev/null +++ b/build/exports/Arx Fatalis.dxw @@ -0,0 +1,32 @@ +[target] +title0=Arx Fatalis +path0=D:\Games\Arx Fatalis\arx.exe +launchpath0= +module0=Athena +opengllib0= +notes0= +registry0= +ver0=0 +coord0=0 +flag0=136314918 +flagg0=1207959552 +flagh0=65552 +flagi0=138412036 +flagj0=4224 +flagk0=65536 +tflag0=0 +initx0=0 +inity0=0 +minx0=0 +miny0=0 +maxx0=0 +maxy0=0 +posx0=150 +posy0=50 +sizx0=800 +sizy0=600 +maxfps0=0 +initts0=0 +winver0=0 +maxres0=-1 +swapeffect0=0 diff --git a/build/exports/TieFighter 95.dxw b/build/exports/TieFighter 95.dxw new file mode 100644 index 0000000..bc3ffb9 --- /dev/null +++ b/build/exports/TieFighter 95.dxw @@ -0,0 +1,32 @@ +[target] +title0=TieFighter 95 +path0=D:\Games\TIE95\TIE95.EXE +launchpath0= +module0= +opengllib0= +notes0=The game can be played also with no joystick using the DxWnd virtual one.\nIf you have a real joystick, the "Use DLL injection" flag is not necessary.\nUse "Unlock Z order" to avoid losing control of the window. +registry0= +ver0=1 +coord0=0 +flag0=681574514 +flagg0=1744830464 +flagh0=20 +flagi0=138412036 +flagj0=1073746048 +flagk0=136642560 +tflag0=0 +initx0=0 +inity0=0 +minx0=0 +miny0=0 +maxx0=800 +maxy0=600 +posx0=50 +posy0=50 +sizx0=800 +sizy0=600 +maxfps0=0 +initts0=0 +winver0=0 +maxres0=-1 +swapeffect0=0 diff --git a/build/readme-relnotes.txt b/build/readme-relnotes.txt index dee4007..1bdfc3e 100644 --- a/build/readme-relnotes.txt +++ b/build/readme-relnotes.txt @@ -939,3 +939,16 @@ add: added debug flag NOWINDOWHOOKS to avoid WindowProc hook. fix: GetPaletteEntries hook returns 256 value against hpal=NULL. Let "M.I.B." run, though palette is still not ok. fix: StretchDIBits hook no longer can return an unassigned value fix: anti-recursion check in DialogBox WindowProc call + +v2.03.42 +add: option "Syncronize GDI and DDRAW palette" - fixes "Man in Black" palette problems +add: apply "Remap MCI coordinates" options also to movies rendered through MCIWndCreate: fixes "Man in Black" movie problems +fix: fixed InvalidateRect hooker logic - fixes "Imperialism" graphic. + +v2.03.43 +fix: eliminated SYSTEMMEMORY usage on DDSCAPS_3DDEVICE surfaces. Needed for "Arx Fatalis" +fix: deleted emulation of ZBUFFER attach. Needed for "Arx Fatalis" +fix: added emulation of PixelFormat in getPixelFormat hooker. Needed for "Arx Fatalis" +add: added virtual joystick feature. Required to play "Tie Fighter 95" with no real joystick +v2.03.43.fix1 +fix: recovered virtual joystick buttons \ No newline at end of file diff --git a/dll/cross.bmp b/dll/cross.bmp new file mode 100644 index 0000000..b6ea64f Binary files /dev/null and b/dll/cross.bmp differ diff --git a/dll/ddraw.cpp b/dll/ddraw.cpp index d03599d..86f3a8d 100644 --- a/dll/ddraw.cpp +++ b/dll/ddraw.cpp @@ -17,6 +17,8 @@ #include "dxhelper.h" #include "syslibs.h" +#define EMULATEZBUFFERATTACH FALSE + extern BOOL IsChangeDisplaySettingsHotPatched; DWORD dwBackBufferCaps; extern void TextureHandling(LPDIRECTDRAWSURFACE); @@ -2177,7 +2179,7 @@ static void FixSurfaceCaps(LPDDSURFACEDESC2 lpddsd, int dxversion) } if((lpddsd->dwFlags & DDSD_CAPS) && (lpddsd->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)) { // z-buffer surface - set to memory - lpddsd->ddsCaps.dwCaps = (DDSCAPS_SYSTEMMEMORY|DDSCAPS_ZBUFFER); + lpddsd->ddsCaps.dwCaps = DDSCAPS_ZBUFFER; return; } @@ -2185,7 +2187,7 @@ static void FixSurfaceCaps(LPDDSURFACEDESC2 lpddsd, int dxversion) (lpddsd->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)) // v2.02.90: added for "Zoo Tycoon" textures { // 3DDEVICE no TEXTURE: enforce PIXELFORMAT on MEMORY lpddsd->dwFlags |= DDSD_PIXELFORMAT; - lpddsd->ddsCaps.dwCaps = (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY|DDSCAPS_3DDEVICE); + lpddsd->ddsCaps.dwCaps = (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_3DDEVICE); GetPixFmt(lpddsd); return; } @@ -2703,7 +2705,6 @@ static HRESULT BuildGenericEmu(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurf // For "Risk II" it is necessary that both the primary surface and the offscreen surfaces are generated // with the same type, so that assuming an identical lPitch and memcopy-ing from one buffer to the // other is a legitimate operation. - if(ddsd.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY; // v2.03.03 !! if(dxw.dwFlags6 & POWER2WIDTH){ // v2.03.28: POWER2WIDTH to fix "Midtown Madness" in surface emulation mode if(((ddsd.dwFlags & (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH)) == (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH)) && @@ -3103,10 +3104,14 @@ HRESULT WINAPI extGetAttachedSurface(int dxversion, GetAttachedSurface_Type pGet } } // arguable utility .... - if ((IsPrim || IsBack) && lpDDZBuffer && (lpddsc->dwCaps & DDSCAPS_ZBUFFER)){ - *lplpddas = lpDDZBuffer; - OutTraceDW("GetAttachedSurface(%d): SIMULATE ZBUFFER attach to %s=%x\n", dxversion, IsPrim?"PRIM":"BACK", lpdds); - return DD_OK; + // commented out: causes "Arx Fatalis" crash assigning ZBUFFER to the wrong surface? + // would that be necessary on some game? + if(EMULATEZBUFFERATTACH){ + if ((IsPrim || IsBack) && lpDDZBuffer && (lpddsc->dwCaps & DDSCAPS_ZBUFFER)){ + *lplpddas = lpDDZBuffer; + OutTraceDW("GetAttachedSurface(%d): SIMULATE ZBUFFER attach to %s=%x\n", dxversion, IsPrim?"PRIM":"BACK", lpdds); + return DD_OK; + } } OutTraceE("GetAttachedSurface(%d): ERROR res=%x(%s) at %d\n", dxversion, res, ExplainDDError(res), __LINE__); } @@ -4487,7 +4492,9 @@ HRESULT WINAPI extGetPixelFormat(LPDIRECTDRAWSURFACE lpdds, LPDDPIXELFORMAT p) p->dwRBitMask, p->dwGBitMask, p->dwBBitMask, p->dwRGBAlphaBitMask ); } - if ((dxw.dwFlags1 & EMULATESURFACE) && IsPrim){ + // fix: virtual pixel definition is helpful not only on promary surfaces, but more in general + // on every surface that returns an error. It fixes "Arx Fatalis" crash. + if ((dxw.dwFlags1 & EMULATESURFACE) && res){ p->dwFlags = dxw.VirtualPixelFormat.dwFlags; p->dwRGBBitCount= dxw.VirtualPixelFormat.dwRGBBitCount; p->dwRBitMask = dxw.VirtualPixelFormat.dwRBitMask; @@ -4496,6 +4503,7 @@ HRESULT WINAPI extGetPixelFormat(LPDIRECTDRAWSURFACE lpdds, LPDDPIXELFORMAT p) p->dwRGBAlphaBitMask = dxw.VirtualPixelFormat.dwRGBAlphaBitMask; OutTraceDW("GetPixelFormat: EMULATED BitCount=%d RGBA=(%x,%x,%x,%x)\n", p->dwRGBBitCount, p->dwRBitMask, p->dwGBitMask, p->dwBBitMask, p->dwRGBAlphaBitMask ); + res = DD_OK; } return res; diff --git a/dll/dsound.cpp b/dll/dsound.cpp index b6d9e97..4c54339 100644 --- a/dll/dsound.cpp +++ b/dll/dsound.cpp @@ -45,7 +45,7 @@ void HookDirectSoundInit() HookLibInit(Hooks); } -void HookDirectSound(LPDIRECTSOUND *lpds) +void HookDirectSoundObj(LPDIRECTSOUND *lpds) { // IDIrectSound::SetCooperativeLevel SetHook((void *)(**(DWORD **)lpds + 24), extDSSetCooperativeLevel, (void **)&pDSSetCooperativeLevel, "SetCooperativeLevel(DSound)"); @@ -62,9 +62,10 @@ HRESULT WINAPI extDirectSoundCreate(LPGUID guid, LPDIRECTSOUND *lpds, LPUNKNOWN return res; } - HookDirectSound(lpds); + HookDirectSoundObj(lpds); return res; } + #define DSSCL_NORMAL 0x00000001 #define DSSCL_PRIORITY 0x00000002 #define DSSCL_EXCLUSIVE 0x00000003 diff --git a/dll/dxhook.cpp b/dll/dxhook.cpp index b376ba1..13126a4 100644 --- a/dll/dxhook.cpp +++ b/dll/dxhook.cpp @@ -23,6 +23,7 @@ #include "MinHook.h" #define SKIPIMEWINDOW TRUE +#define HOOKDIRECTSOUND FALSE dxwCore dxw; dxwSStack dxwss; @@ -863,7 +864,7 @@ void HookModule(HMODULE base, int dxversion) HookMSV4WLibs(base); // -- used by Aliens & Amazons demo: what for? HookAVIFil32(base); //HookSmackW32(base); - //HookDirectSound(base); + //if (HOOKDIRECTSOUND) HookDirectSound(base); //HookComDlg32(base); } diff --git a/dll/dxwnd.aps b/dll/dxwnd.aps index caed8be..ea03d65 100644 Binary files a/dll/dxwnd.aps and b/dll/dxwnd.aps differ diff --git a/dll/dxwnd.cpp b/dll/dxwnd.cpp index fda1426..dc793d8 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.42" +#define VERSION "2.03.43.fix1" #define DDTHREADLOCK 1 //#define LOCKTHREADS diff --git a/dll/dxwnd.rc b/dll/dxwnd.rc index 2705594..6d398ea 100644 --- a/dll/dxwnd.rc +++ b/dll/dxwnd.rc @@ -53,6 +53,10 @@ END // IDB_BANNER BITMAP "dxwbanner.bmp" +IDB_CROSS BITMAP "cross.bmp" +IDB_FIRE1 BITMAP "fire1.bmp" +IDB_FIRE2 BITMAP "fire2.bmp" +IDB_FIRE3 BITMAP "fire3.bmp" #endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/dll/dxwnd.vs2008.suo b/dll/dxwnd.vs2008.suo index 9f6c481..99cde0e 100644 Binary files a/dll/dxwnd.vs2008.suo and b/dll/dxwnd.vs2008.suo differ diff --git a/dll/dxwnd.vs2008.vcproj b/dll/dxwnd.vs2008.vcproj index c95764e..1549714 100644 --- a/dll/dxwnd.vs2008.vcproj +++ b/dll/dxwnd.vs2008.vcproj @@ -539,10 +539,38 @@ Name="Resource Files" Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" > + + + + + + + + + + + + + + diff --git a/dll/fire1.bmp b/dll/fire1.bmp new file mode 100644 index 0000000..be8f6f3 Binary files /dev/null and b/dll/fire1.bmp differ diff --git a/dll/fire2.bmp b/dll/fire2.bmp new file mode 100644 index 0000000..6549d79 Binary files /dev/null and b/dll/fire2.bmp differ diff --git a/dll/fire3.bmp b/dll/fire3.bmp new file mode 100644 index 0000000..6230854 Binary files /dev/null and b/dll/fire3.bmp differ diff --git a/dll/resource.h b/dll/resource.h index 7e069c5..877fd86 100644 --- a/dll/resource.h +++ b/dll/resource.h @@ -3,12 +3,17 @@ // Used by dxwnd.rc // #define IDB_BANNER 101 +#define IDB_CROSS 102 +#define IDB_FIRE1 103 +#define IDB_FIRE2 104 +#define IDB_BITMAP2 105 +#define IDB_FIRE3 105 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_RESOURCE_VALUE 106 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 diff --git a/dll/winmm.cpp b/dll/winmm.cpp index ea10616..111cbc2 100644 --- a/dll/winmm.cpp +++ b/dll/winmm.cpp @@ -6,11 +6,14 @@ #include "syslibs.h" #include "dxhook.h" #include "dxhelper.h" +#include "resource.h" #include "MMSystem.h" #include #define SUPPRESSMCIERRORS FALSE +#define EMULATEJOY TRUE +#define INVERTJOYAXIS TRUE BOOL IsWithinMCICall = FALSE; @@ -20,10 +23,19 @@ MCIDEVICEID WINAPI extmciGetDeviceIDA(LPCTSTR); typedef MCIDEVICEID (WINAPI *mciGetDeviceIDW_Type)(LPCWSTR); mciGetDeviceIDW_Type pmciGetDeviceIDW = NULL; MCIDEVICEID WINAPI extmciGetDeviceIDW(LPCWSTR); +typedef DWORD (WINAPI *joyGetNumDevs_Type)(void); +joyGetNumDevs_Type pjoyGetNumDevs = NULL; +DWORD WINAPI extjoyGetNumDevs(void); +typedef MMRESULT (WINAPI *joyGetDevCapsA_Type)(DWORD, LPJOYCAPS, UINT); +joyGetDevCapsA_Type pjoyGetDevCapsA = NULL; +MMRESULT WINAPI extjoyGetDevCapsA(DWORD, LPJOYCAPS, UINT); +typedef MMRESULT (WINAPI *joyGetPosEx_Type)(DWORD, LPJOYINFOEX); +joyGetPosEx_Type pjoyGetPosEx = NULL; +MMRESULT WINAPI extjoyGetPosEx(DWORD, LPJOYINFOEX); static HookEntry_Type Hooks[]={ - {HOOK_HOT_CANDIDATE, "mciSendCommandA", NULL, (FARPROC *)&pmciSendCommandA, (FARPROC)extmciSendCommandA}, - {HOOK_HOT_CANDIDATE, "mciSendCommandW", NULL, (FARPROC *)&pmciSendCommandW, (FARPROC)extmciSendCommandW}, + {HOOK_IAT_CANDIDATE, "mciSendCommandA", NULL, (FARPROC *)&pmciSendCommandA, (FARPROC)extmciSendCommandA}, + {HOOK_IAT_CANDIDATE, "mciSendCommandW", NULL, (FARPROC *)&pmciSendCommandW, (FARPROC)extmciSendCommandW}, {HOOK_HOT_CANDIDATE, "mciGetDeviceIDA", NULL, (FARPROC *)&pmciGetDeviceIDA, (FARPROC)extmciGetDeviceIDA}, {HOOK_HOT_CANDIDATE, "mciGetDeviceIDW", NULL, (FARPROC *)&pmciGetDeviceIDW, (FARPROC)extmciGetDeviceIDW}, {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator @@ -42,11 +54,19 @@ static HookEntry_Type RemapHooks[]={ {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator }; +static HookEntry_Type JoyHooks[]={ + {HOOK_IAT_CANDIDATE, "joyGetNumDevs", NULL, (FARPROC *)&pjoyGetNumDevs, (FARPROC)extjoyGetNumDevs}, + {HOOK_IAT_CANDIDATE, "joyGetDevCapsA", NULL, (FARPROC *)&pjoyGetDevCapsA, (FARPROC)extjoyGetDevCapsA}, + {HOOK_IAT_CANDIDATE, "joyGetPosEx", NULL, (FARPROC *)&pjoyGetPosEx, (FARPROC)extjoyGetPosEx}, + {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator +}; + void HookWinMM(HMODULE module) { HookLibrary(module, Hooks, "winmm.dll"); if(dxw.dwFlags2 & TIMESTRETCH) HookLibrary(module, TimeHooks, "winmm.dll"); if(dxw.dwFlags5 & REMAPMCI) HookLibrary(module, RemapHooks, "winmm.dll"); + if(dxw.dwFlags6 & VIRTUALJOYSTICK) HookLibrary(module, JoyHooks, "winmm.dll"); } FARPROC Remap_WinMM_ProcAddress(LPCSTR proc, HMODULE hModule) @@ -58,6 +78,8 @@ FARPROC Remap_WinMM_ProcAddress(LPCSTR proc, HMODULE hModule) if (addr=RemapLibrary(proc, hModule, TimeHooks)) return addr; if(dxw.dwFlags5 & REMAPMCI) if (addr=RemapLibrary(proc, hModule, RemapHooks)) return addr; + if(dxw.dwFlags6 & VIRTUALJOYSTICK) + if (addr=RemapLibrary(proc, hModule, JoyHooks)) return addr; return NULL; } @@ -115,7 +137,22 @@ MCIERROR WINAPI extmciSendCommand(mciSendCommand_Type pmciSendCommand, MCIDEVICE OutTraceDW("mciSendCommand: IDDevice=%x msg=%x(%s) Command=%x(%s)\n", IDDevice, uMsg, ExplainMCICommands(uMsg), fdwCommand, ExplainMCIFlags(uMsg, fdwCommand)); - if(dxw.dwFlags6 && BYPASSMCI) return 0; + if(dxw.dwFlags6 & BYPASSMCI){ + if((uMsg == MCI_STATUS) && (fdwCommand == MCI_STATUS_ITEM)){ + // fix for Tie Fighter 95: when bypassing, let the caller know you have no CD tracks + // otherwise you risk an almost endless loop going through the unassigned returned + // number of ghost tracks + MCI_STATUS_PARMS *p = (MCI_STATUS_PARMS *)dwParam; + p->dwItem = 0; + p->dwTrack = 0; + p->dwReturn = 0; + OutTraceDW("mciSendCommand: BYPASS fixing MCI_STATUS\n"); + } + else{ + OutTraceDW("mciSendCommand: BYPASS\n"); + } + return 0; + } if(dxw.IsFullScreen()){ switch(uMsg){ @@ -157,6 +194,15 @@ MCIERROR WINAPI extmciSendCommand(mciSendCommand_Type pmciSendCommand, MCIDEVICE ret=(*pmciSendCommand)(IDDevice, uMsg, fdwCommand, dwParam); + if(ret == 0){ + switch(uMsg){ + case MCI_STATUS: + MCI_STATUS_PARMS *p = (MCI_STATUS_PARMS *)dwParam; + OutTrace("mciSendCommand: Item=%d Track=%d return=%x\n", p->dwItem, p->dwTrack, p->dwReturn); + break; + } + } + if(dxw.IsFullScreen() && uMsg==MCI_PUT) pr->rc=saverect; if (ret) OutTraceE("mciSendCommand: ERROR res=%d\n", ret); return ret; @@ -245,4 +291,148 @@ MCIDEVICEID WINAPI extmciGetDeviceIDW(LPCWSTR lpszDevice) ret = (*pmciGetDeviceIDW)(lpszDevice); OutTraceDW("mciGetDeviceIDW: device=\"%ls\" ret=%x\n", lpszDevice, ret); return ret; -} \ No newline at end of file +} + +DWORD WINAPI extjoyGetNumDevs(void) +{ + OutTraceDW("joyGetNumDevs: emulate joystick ret=1\n"); + return 1; +} + +#define XSPAN 128 +#define YSPAN 128 +static void ShowJoystick(LONG, LONG, DWORD); + +MMRESULT WINAPI extjoyGetDevCapsA(DWORD uJoyID, LPJOYCAPS pjc, UINT cbjc) +{ + OutTraceDW("joyGetDevCaps: joyid=%d size=%d\n", uJoyID, cbjc); + if((uJoyID != -1) && (uJoyID != 0)) return MMSYSERR_NODRIVER; + if(cbjc != sizeof(JOYCAPS)) return MMSYSERR_INVALPARAM; + uJoyID = 0; // always first (unique) one ... + + // set Joystick capability structure + memset(pjc, 0, sizeof(JOYCAPS)); + strncpy(pjc->szPname, "DxWnd Joystick Emulator", MAXPNAMELEN); + pjc->wXmin = 0; + pjc->wXmax = XSPAN; + pjc->wYmin = 0; + pjc->wYmax = YSPAN; + pjc->wNumButtons = 2; + pjc->wMaxButtons = 2; + pjc->wPeriodMin = 60; + pjc->wPeriodMax = 600; + pjc->wCaps = 0; + pjc->wMaxAxes = 2; + pjc->wNumAxes = 2; + + return JOYERR_NOERROR; +} + +MMRESULT WINAPI extjoyGetPosEx(DWORD uJoyID, LPJOYINFOEX pji) +{ + OutTraceDW("joyGetPosEx: joyid=%d\n", uJoyID); + if(uJoyID != 0) return JOYERR_PARMS; + LONG x, y; + HWND hwnd; + DWORD dwButtons; + + dwButtons = 0; + if (GetKeyState(VK_LBUTTON) < 0) dwButtons |= JOY_BUTTON1; + if (GetKeyState(VK_RBUTTON) < 0) dwButtons |= JOY_BUTTON2; + POINT pt; + if(hwnd=dxw.GethWnd()){ + RECT client; + POINT upleft = {0,0}; + (*pGetClientRect)(hwnd, &client); + (*pClientToScreen)(hwnd, &upleft); + (*pGetCursorPos)(&pt); + pt.x -= upleft.x; + pt.y -= upleft.y; + if(pt.x < client.left) pt.x = client.left; + if(pt.x > client.right) pt.x = client.right; + if(pt.y < client.top) pt.y = client.top; + if(pt.y > client.bottom) pt.y = client.bottom; + x = (pt.x * XSPAN) / client.right; + if(INVERTJOYAXIS) + y = ((client.bottom - pt.y) * YSPAN) / client.bottom; // inverted y axis + else + pt.y = (pt.y * YSPAN) / dxw.GetScreenHeight(); + ShowJoystick(pt.x, pt.y, dwButtons); + } + else { + x=(XSPAN>>1); + y=(YSPAN>>1); + } + + // set Joystick info structure + memset(pji, 0, sizeof(JOYINFOEX)); + pji->dwSize = sizeof(JOYINFOEX); + pji->dwFlags = 0; + pji->dwXpos = x; + pji->dwYpos = y; + pji->dwButtons = dwButtons; + pji->dwFlags = JOY_RETURNX|JOY_RETURNY|JOY_RETURNBUTTONS; + + OutTraceDW("joyGetPosEx: joyid=%d pos=(%d,%d)\n", uJoyID, pji->dwXpos, pji->dwYpos); + return JOYERR_NOERROR; +} + +static void ShowJoystick(LONG x, LONG y, DWORD dwButtons) +{ + static BOOL JustOnce=FALSE; + extern HMODULE hInst; + BITMAP bm; + HDC hClientDC; + static HBITMAP g_hbmJoyCross; + static HBITMAP g_hbmJoyFire1; + static HBITMAP g_hbmJoyFire2; + static HBITMAP g_hbmJoyFire3; + HBITMAP g_hbmJoy; + RECT client; + RECT win; + POINT PrevViewPort; + int StretchMode; + + // don't show when system cursor is visible + CURSORINFO ci; + ci.cbSize = sizeof(CURSORINFO); + GetCursorInfo(&ci); + if(ci.flags == CURSOR_SHOWING) return; + + hClientDC=(*pGDIGetDC)(dxw.GethWnd()); + (*pGetClientRect)(dxw.GethWnd(), &client); + + if(!JustOnce){ + g_hbmJoyCross = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_CROSS)); + g_hbmJoyFire1 = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_FIRE1)); + g_hbmJoyFire2 = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_FIRE2)); + g_hbmJoyFire3 = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_FIRE3)); + JustOnce=TRUE; + } + + HDC hdcMem = CreateCompatibleDC(hClientDC); + switch(dwButtons){ + case 0: g_hbmJoy = g_hbmJoyCross; break; + case JOY_BUTTON1: g_hbmJoy = g_hbmJoyFire1; break; + case JOY_BUTTON2: g_hbmJoy = g_hbmJoyFire2; break; + default: g_hbmJoy = g_hbmJoyFire3; break; + } + HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, g_hbmJoy); + GetObject(g_hbmJoy, sizeof(bm), &bm); + + (*pGetWindowRect)(dxw.GethWnd(), &win); + + //if(!pSetViewportOrgEx) pSetViewportOrgEx=SetViewportOrgEx; + (*pSetViewportOrgEx)(hClientDC, 0, 0, &PrevViewPort); + StretchMode=GetStretchBltMode(hClientDC); + SetStretchBltMode(hClientDC, HALFTONE); + int w, h; + w=36; + h=36; + (*pGDIStretchBlt)(hClientDC, x-(w>>1), y-(h>>1), w, h, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); + + SetStretchBltMode(hClientDC, StretchMode); + (*pSetViewportOrgEx)(hClientDC, PrevViewPort.x, PrevViewPort.y, NULL); + SelectObject(hdcMem, hbmOld); + DeleteDC(hdcMem); +} diff --git a/host/TabInput.cpp b/host/TabInput.cpp index f2abdab..5513149 100644 --- a/host/TabInput.cpp +++ b/host/TabInput.cpp @@ -40,6 +40,7 @@ void CTabInput::DoDataExchange(CDataExchange* pDX) DDX_Check(pDX, IDC_FIXNCHITTEST, cTarget->m_FixNCHITTEST); DDX_Check(pDX, IDC_SLOW, cTarget->m_SlowDown); DDX_Check(pDX, IDC_RELEASEMOUSE, cTarget->m_ReleaseMouse); + DDX_Check(pDX, IDC_VIRTUALJOYSTICK, cTarget->m_VirtualJoystick); //DDX_Check(pDX, IDC_FRAMECOMPENSATION, cTarget->m_FrameCompensation); // DirectInput DDX_Check(pDX, IDC_HOOKDI, cTarget->m_HookDI); diff --git a/host/TargetDlg.cpp b/host/TargetDlg.cpp index b11eac2..318ec37 100644 --- a/host/TargetDlg.cpp +++ b/host/TargetDlg.cpp @@ -29,6 +29,7 @@ CTargetDlg::CTargetDlg(CWnd* pParent /*=NULL*/) m_TextureHandling = 0; m_HookDI = FALSE; m_ModifyMouse = TRUE; // default true !! + m_VirtualJoystick = FALSE; m_LogEnabled = FALSE; m_OutProxyTrace = FALSE; m_OutDebug = FALSE; diff --git a/host/TargetDlg.h b/host/TargetDlg.h index ed76f55..a9db998 100644 --- a/host/TargetDlg.h +++ b/host/TargetDlg.h @@ -34,6 +34,7 @@ public: int m_SonProcessMode; BOOL m_HookDI; BOOL m_ModifyMouse; + BOOL m_VirtualJoystick; BOOL m_OutProxyTrace; BOOL m_OutDebug; BOOL m_CursorTrace; diff --git a/host/dxwndhost.aps b/host/dxwndhost.aps index f5fd762..39a7981 100644 Binary files a/host/dxwndhost.aps and b/host/dxwndhost.aps differ diff --git a/host/dxwndhost.rc b/host/dxwndhost.rc index 5035f2f..45864e2 100644 Binary files a/host/dxwndhost.rc and b/host/dxwndhost.rc differ diff --git a/host/dxwndhost.vs2008.suo b/host/dxwndhost.vs2008.suo index c76dae1..9b0926d 100644 Binary files a/host/dxwndhost.vs2008.suo and b/host/dxwndhost.vs2008.suo differ diff --git a/host/dxwndhostView.cpp b/host/dxwndhostView.cpp index cb749f4..fd9dd14 100644 --- a/host/dxwndhostView.cpp +++ b/host/dxwndhostView.cpp @@ -248,6 +248,7 @@ static void SetTargetFromDlg(TARGETMAP *t, CTargetDlg *dlg) if(dlg->m_HookDI) t->flags |= HOOKDI; if(dlg->m_ModifyMouse) t->flags |= MODIFYMOUSE; + if(dlg->m_VirtualJoystick) t->flags6 |= VIRTUALJOYSTICK; if(dlg->m_OutProxyTrace) t->tflags |= OUTPROXYTRACE; if(dlg->m_OutDebug) t->tflags |= OUTDEBUG; if(dlg->m_CursorTrace) t->tflags |= OUTCURSORTRACE; @@ -488,6 +489,7 @@ static void SetDlgFromTarget(TARGETMAP *t, CTargetDlg *dlg) dlg->m_HookDI = t->flags & HOOKDI ? 1 : 0; dlg->m_ModifyMouse = t->flags & MODIFYMOUSE ? 1 : 0; + dlg->m_VirtualJoystick = t->flags6 & VIRTUALJOYSTICK ? 1 : 0; dlg->m_OutProxyTrace = t->tflags & OUTPROXYTRACE ? 1 : 0; dlg->m_OutDebug = t->tflags & OUTDEBUG ? 1 : 0; dlg->m_CursorTrace = t->tflags & OUTCURSORTRACE ? 1 : 0; diff --git a/host/host.aps b/host/host.aps index 6500e13..e615e8b 100644 Binary files a/host/host.aps and b/host/host.aps differ diff --git a/host/resource b/host/resource index 8de7c61..918f057 100644 Binary files a/host/resource and b/host/resource differ