diff --git a/build/dxwnd.dll b/build/dxwnd.dll
index 1f0d515..fe6e70f 100644
--- a/build/dxwnd.dll
+++ b/build/dxwnd.dll
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:df99818897624e2426ed40251d25c8c8f8a50e5174746aed2c5c1be3dbfcd4a4
+oid sha256:d748f1b239ec33cab73c3a6b40b6900a093f28c33c42e1b430f2e08f499e36fd
size 262144
diff --git a/build/dxwnd.exe b/build/dxwnd.exe
index 140ea66..08ebd30 100644
--- a/build/dxwnd.exe
+++ b/build/dxwnd.exe
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:63d93b8775f8106a4ed846e49768c1ff2203c049656866b84a8f046d1c9864d9
+oid sha256:b9e5a9b8b7cadb640fa36491af117b34e6979ac7eb3cee8fa4b55b06e1a3ab9f
size 488448
diff --git a/build/readme-relnotes.txt b/build/readme-relnotes.txt
index 7a206ec..2f54251 100644
--- a/build/readme-relnotes.txt
+++ b/build/readme-relnotes.txt
@@ -12,4 +12,9 @@ code cleanup - see syslib calls hooking
new configuration flags: Hook GDI and Hook OpenGL
OpenGL custom library field
API hooking fix with module specification
-Time stratching by keyboard control (Alt F5/F6) and/or Time Slider dialog
\ No newline at end of file
+Time stretching by keyboard control (Alt F5/F6) and/or Time Slider dialog
+
+v2.02.05:
+hooked winmm timeGetTime() API: makes time stretching work for Age of Empires series
+changed time stretching grain: now it's not the coarse grained 2x, 4x,... series in 9 possible values but the fine grained series 1.5x, 2x, 3x,.... in 17 possible values
+added status and time stretching view panels to tray icon menu
\ No newline at end of file
diff --git a/dll/dxhook.cpp b/dll/dxhook.cpp
index 723f6fa..c85fe37 100644
--- a/dll/dxhook.cpp
+++ b/dll/dxhook.cpp
@@ -694,8 +694,8 @@ LRESULT CALLBACK extWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lp
case VK_F6:
if (dxw.dwFlags2 & TIMESTRETCH) {
char *sTSCaption[9]={"x16","x8","x4","x2","x1",":2",":4",":8",":16"};
- if (wparam == VK_F5 && (dxw.TimeShift < 4)) dxw.TimeShift++;
- if (wparam == VK_F6 && (dxw.TimeShift > -4)) dxw.TimeShift--;
+ if (wparam == VK_F5 && (dxw.TimeShift < 8)) dxw.TimeShift++;
+ if (wparam == VK_F6 && (dxw.TimeShift > -8)) dxw.TimeShift--;
OutTrace("Time Stretch: shift=%d speed=%s\n", dxw.TimeShift, sTSCaption[dxw.TimeShift+4]);
DxWndStatus.iTimeShift=dxw.TimeShift;
SetHookStatus(&DxWndStatus);
@@ -1017,6 +1017,8 @@ void HookSysLibs(char *module)
if(tmp) pSleepEx = (SleepEx_Type)tmp;
tmp = HookAPI(module, "user32.dll", SetTimer, "SetTimer", extSetTimer);
if(tmp) pSetTimer = (SetTimer_Type)tmp;
+ tmp = HookAPI(module, "winmm.dll", NULL, "timeGetTime", exttimeGetTime);
+ if(tmp) ptimeGetTime = (timeGetTime_Type)tmp;
}
return;
}
diff --git a/dll/dxwcore.cpp b/dll/dxwcore.cpp
index e51b646..bf50ae4 100644
--- a/dll/dxwcore.cpp
+++ b/dll/dxwcore.cpp
@@ -51,8 +51,8 @@ void dxwCore::InitTarget(TARGETMAP *target)
if(dwTargetDDVersion<0) dwTargetDDVersion=0;
if(dwTargetDDVersion>10) dwTargetDDVersion=10;
TimeShift = target->InitTS;
- if(TimeShift < -4) TimeShift = -4;
- if(TimeShift > 4) TimeShift = 4;
+ if(TimeShift < -8) TimeShift = -8;
+ if(TimeShift > 8) TimeShift = 8;
}
/* ------------------------------------------------------------------ */
@@ -378,20 +378,35 @@ BOOL dxwCore::HandleFPS()
return FALSE;
}
+static DWORD TimeShifter(DWORD val, int shift)
+{
+ int exp, reminder;
+ if (shift > 0) {
+ exp = shift >> 1;
+ reminder = shift & 0x1;
+ if (reminder) val -= (val >> 2); // val * (1-1/4) = val * 3/4
+ val >>= exp; // val * 2^exp
+ }
+ if (shift < 0) {
+ exp = (-shift) >> 1;
+ reminder = (-shift) & 0x1;
+ val <<= exp; // val / 2^exp
+ if (reminder) val += (val >> 1); // val * (1+1/2) = val * 3/2
+ }
+ return val;
+}
+
DWORD dxwCore::GetTickCount(void)
{
DWORD dwTick;
static DWORD dwLastRealTick=0;
static DWORD dwLastFakeTick=0;
DWORD dwNextRealTick;
-// extern DXWNDSTATUS *pStatus;
dwNextRealTick=(*pGetTickCount)();
dwTick=(dwNextRealTick-dwLastRealTick);
-// TimeShift=pStatus->iTimeShift;
TimeShift=GetTimeShift();
- if (TimeShift > 0) dwTick >>= TimeShift;
- if (TimeShift < 0) dwTick <<= -TimeShift;
+ dwTick = TimeShifter(dwTick, TimeShift);
dwLastFakeTick += dwTick;
dwLastRealTick = dwNextRealTick;
return dwLastFakeTick;
@@ -399,11 +414,8 @@ DWORD dxwCore::GetTickCount(void)
DWORD dxwCore::StretchTime(DWORD dwTimer)
{
- //extern DXWNDSTATUS *pStatus;
- //TimeShift=pStatus->iTimeShift;
TimeShift=GetTimeShift();
- if (TimeShift > 0) dwTimer <<= TimeShift;
- if (TimeShift < 0) dwTimer >>= -TimeShift;
+ dwTimer = TimeShifter(dwTimer, -TimeShift);
return dwTimer;
}
@@ -417,7 +429,6 @@ void dxwCore::GetSystemTime(LPSYSTEMTIME lpSystemTime)
static FILETIME StartFileTime;
extern DXWNDSTATUS *pStatus;
- //TimeShift=pStatus->iTimeShift;
if(dwStartTick==0) {
SYSTEMTIME StartingTime;
// first time through, initialize & return true time
@@ -430,8 +441,7 @@ void dxwCore::GetSystemTime(LPSYSTEMTIME lpSystemTime)
dwCurrentTick=(*pGetTickCount)();
dwTick=(dwCurrentTick-dwStartTick);
TimeShift=GetTimeShift();
- if (TimeShift > 0) dwTick >>= TimeShift;
- if (TimeShift < 0) dwTick <<= -TimeShift;
+ dwTick = TimeShifter(dwTick, TimeShift);
// From MSDN: Contains a 64-bit value representing the number of
// 100-nanosecond intervals since January 1, 1601 (UTC).
// So, since 1mSec = 10.000 * 100nSec, you still have to multiply by 10.000.
diff --git a/dll/dxwnd.cpp b/dll/dxwnd.cpp
index b73389d..7665ebc 100644
--- a/dll/dxwnd.cpp
+++ b/dll/dxwnd.cpp
@@ -23,7 +23,7 @@ along with this program. If not, see .
#include
#include "dxwnd.h"
-#define VERSION "2.02.04"
+#define VERSION "2.02.05"
LRESULT CALLBACK HookProc(int ncode, WPARAM wparam, LPARAM lparam);
diff --git a/dll/dxwnd.ws2008.suo b/dll/dxwnd.ws2008.suo
index 3e8602a..58cb1cf 100644
Binary files a/dll/dxwnd.ws2008.suo and b/dll/dxwnd.ws2008.suo differ
diff --git a/dll/syslibs.cpp b/dll/syslibs.cpp
index 4853ec9..37354db 100644
--- a/dll/syslibs.cpp
+++ b/dll/syslibs.cpp
@@ -2566,6 +2566,12 @@ DWORD WINAPI extSleepEx(DWORD dwMilliseconds, BOOL bAlertable)
return (*pSleepEx)(dwNewDelay, bAlertable);
}
+DWORD WINAPI exttimeGetTime(void)
+{
+ OutTrace("timeGetTime\n");
+ return dxw.GetTickCount();
+}
+
int WINAPI extShowCursor(BOOL bShow)
{
static int iFakeCounter;
diff --git a/dll/syslibs.h b/dll/syslibs.h
index c178e0b..a922808 100644
--- a/dll/syslibs.h
+++ b/dll/syslibs.h
@@ -93,6 +93,9 @@ typedef BOOL (WINAPI *SetWindowPos_Type)(HWND, HWND, int, int, int, int, UINT);
typedef int (WINAPI *ShowCursor_Type)(BOOL);
typedef BOOL (WINAPI *ShowWindow_Type)(HWND, int);
+// Winmm.dll:
+typedef DWORD (WINAPI *timeGetTime_Type)(void);
+
/* ===================================================================
hooked APIs real pointers
====================================================================*/
@@ -189,6 +192,9 @@ DXWEXTERN SetWindowPos_Type pSetWindowPos DXWINITIALIZED;
DXWEXTERN ShowCursor_Type pShowCursor DXWINITIALIZED;
DXWEXTERN ShowWindow_Type pShowWindow DXWINITIALIZED;
+// Winmm.dll:
+DXWEXTERN timeGetTime_Type ptimeGetTime DXWINITIALIZED;
+
/* ===================================================================
hook procedures (possibly more tnan one per each API...)
====================================================================*/
@@ -282,4 +288,7 @@ extern BOOL WINAPI extSetWindowPos(HWND, HWND, int, int, int, int, UINT);
extern int WINAPI extShowCursor(BOOL);
extern BOOL WINAPI extShowWindow(HWND, int);
+// Winmm.dll:
+extern DWORD WINAPI exttimeGetTime(void);
+
/* eof */
\ No newline at end of file
diff --git a/host/Resource.h b/host/Resource.h
index b371b00..5a7b00c 100644
--- a/host/Resource.h
+++ b/host/Resource.h
@@ -148,6 +148,10 @@
#define ID_DXAPP_EXIT 32810
#define ID_SAVEFILE 32810
#define ID_VIEW_TIMESLIDER 32811
+#define ID_DXWND_VI 32812
+#define ID_VIEW_STATUS32813 32813
+#define ID_VIEW_TIMESLIDER32814 32814
+#define ID_VIEW_STATUS3 32815
// Next default values for new objects
//
@@ -155,7 +159,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_3D_CONTROLS 1
#define _APS_NEXT_RESOURCE_VALUE 151
-#define _APS_NEXT_COMMAND_VALUE 32812
+#define _APS_NEXT_COMMAND_VALUE 32816
#define _APS_NEXT_CONTROL_VALUE 1080
#define _APS_NEXT_SYMED_VALUE 101
#endif
diff --git a/host/StatusDialog.cpp b/host/StatusDialog.cpp
index 8ed0167..d505394 100644
--- a/host/StatusDialog.cpp
+++ b/host/StatusDialog.cpp
@@ -56,8 +56,7 @@ void CStatusDialog::OnTimer(UINT_PTR nIDEvent)
GetDllVersion(DllVersion);
DxWndStatus.Status=DxStatus;
if(DxStatus==DXW_RUNNING){
- int idx;
- char *sTSCaption[9]={"x16","x8","x4","x2","x1",":2",":4",":8",":16"};
+ char *sTSCaption[17]={"x16","x12","x8","x6","x4","x3","x2","x1.5","x1",":1.5",":2",":3",":4",":6",":8",":12",":16"};
GetHookStatus(&DxWndStatus);
Target=&pTargets[DxWndStatus.TaskIdx];
@@ -76,9 +75,8 @@ void CStatusDialog::OnTimer(UINT_PTR nIDEvent)
strcat(sMsg, sMsgBuf);
}
if(Target->flags2 & TIMESTRETCH){
- idx=DxWndStatus.iTimeShift+4;
- if(idx>=0 && idx<=8){
- sprintf(sMsgBuf, "\nTime speed: %s", sTSCaption[DxWndStatus.iTimeShift+4]);
+ if(DxWndStatus.iTimeShift>=-8 && DxWndStatus.iTimeShift<=8){
+ sprintf(sMsgBuf, "\nTime speed: %s", sTSCaption[DxWndStatus.iTimeShift+8]);
strcat(sMsg, sMsgBuf);
}
}
diff --git a/host/TimeSliderDlg.cpp b/host/TimeSliderDlg.cpp
index d489502..c420dcb 100644
--- a/host/TimeSliderDlg.cpp
+++ b/host/TimeSliderDlg.cpp
@@ -12,7 +12,6 @@ IMPLEMENT_DYNAMIC(CTimeSliderDialog, CDialog)
CTimeSliderDialog::CTimeSliderDialog(CWnd* pParent /*=NULL*/)
: CDialog(CTimeSliderDialog::IDD, pParent)
{
- //m_TimeSlider.SetRange(-4, +4, TRUE);
}
CTimeSliderDialog::~CTimeSliderDialog()
@@ -41,7 +40,7 @@ void CTimeSliderDialog::OnTimer(UINT_PTR nIDEvent)
DXWNDSTATUS Status;
CSliderCtrl *Slider;
CStatic *Text;
- char *sTSCaption[9]={"x16","x8","x4","x2","x1",":2",":4",":8",":16"};
+ char *sTSCaption[17]={"x16","x12","x8","x6","x4","x3","x2","x1.5","x1",":1.5",":2",":3",":4",":6",":8",":12",":16"};
char sMsg[81];
static int iLastPos=-1;
@@ -62,13 +61,13 @@ void CTimeSliderDialog::OnTimer(UINT_PTR nIDEvent)
}
else {
// slider position changed, set the new value
- if (i_TimeSlider < -4) i_TimeSlider=-4;
- if (i_TimeSlider > 4) i_TimeSlider=4;
+ if (i_TimeSlider < -8) i_TimeSlider=-8;
+ if (i_TimeSlider > 8) i_TimeSlider= 8;
Status.iTimeShift=i_TimeSlider;
SetHookStatus(&Status);
}
iLastPos = i_TimeSlider;
- sprintf(sMsg, "Time speed: %s", sTSCaption[i_TimeSlider+4]);
+ sprintf(sMsg, "Time speed: %s", sTSCaption[i_TimeSlider+8]);
Text->SetWindowTextA(sMsg);
}
@@ -80,7 +79,7 @@ BOOL CTimeSliderDialog::OnInitDialog()
GetHookStatus(&Status);
Slider=(CSliderCtrl *)this->GetDlgItem(IDC_TIMESLIDER);
- Slider->SetRange(-4, +4, 0);
+ Slider->SetRange(-8, +8, 0);
Slider->SetTicFreq(1);
Slider->SetPos(Status.iTimeShift);
SetTimer(IDTIMER, 1000, NULL);
diff --git a/host/dxwndhost.aps b/host/dxwndhost.aps
index 5cbe54c..3592788 100644
Binary files a/host/dxwndhost.aps and b/host/dxwndhost.aps differ
diff --git a/host/dxwndhost.rc b/host/dxwndhost.rc
index cb07e96..8f415f6 100644
--- a/host/dxwndhost.rc
+++ b/host/dxwndhost.rc
@@ -146,6 +146,11 @@ BEGIN
MENUITEM "Start", ID_HOOK_START
MENUITEM "Stop", ID_HOOK_STOP
END
+ POPUP "View ..."
+ BEGIN
+ MENUITEM "Status", ID_VIEW_STATUS
+ MENUITEM "Time Slider", ID_VIEW_TIMESLIDER
+ END
MENUITEM "e&Xit", ID_DXAPP_EXIT
END
END
diff --git a/host/dxwndhost.vs2008.suo b/host/dxwndhost.vs2008.suo
index e87fc66..7ce95c6 100644
Binary files a/host/dxwndhost.vs2008.suo and b/host/dxwndhost.vs2008.suo differ