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