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