codepad
[
create a new paste
]
login
|
about
Language:
C
C++
D
Haskell
Lua
OCaml
PHP
Perl
Plain Text
Python
Ruby
Scheme
Tcl
#ifdef PRECOMPILEDHEADERS #include "Utils All.h" #include "interface control.h" #else #include <windows.h> #include <mmsystem.h> #include <string.h> #include "stdlib.h" #include "debug.h" #include "Timer Control.h" #include "overhead.h" #include "handle items.h" #include "worlddef.h" #include "renderworld.h" #include "interface control.h" #include "keymap.h" #endif #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include "Soldier Control.h" void SetFastForwardPeriod(DOUBLE value); void SetFastForwardKey(INT32 key); void SetFastForwardMode(BOOLEAN enable); BOOLEAN IsFastForwardKeyPressed(); BOOLEAN IsFastForwardMode(); BOOLEAN IsHiSpeedClockMode(); void SetHiSpeedClockMode(BOOLEAN enable); static INT32 BASETIMESLICE = 10; // Base resolution of callback timer const INT32 FASTFORWARDTIMESLICE = 1000; const LONGLONG FREQUENCY_CONST = 1000000; static INT32 MIN_NOTIFY_TIME = 16000; static INT32 UPDATETIMESLICE = 10000; INT32 giClockTimer = -1; INT32 giTimerDiag = 0; UINT32 guiBaseJA2Clock = 0; UINT32 guiBaseJA2NoPauseClock = 0; BOOLEAN gfPauseClock = FALSE; BOOLEAN gfHispeedClockMode = FALSE; const inline UINT32 TIME_US_TO_MS(UINT32 value) { return value / 1000; } const inline UINT32 TIME_MS_TO_US(UINT32 value) { return value * 1000; } UINT32 giFastForwardPeriod = FASTFORWARDTIMESLICE; BOOLEAN giFastForwardMode = FALSE; INT32 giFastForwardKey = 0; UINT32 guiTimeSlice = 0; FLOAT gfClockSpeedPercent = 1.0; LARGE_INTEGER gliPerfFreq = { 0 }; LARGE_INTEGER gliPerfCount = { 0 }; LARGE_INTEGER gliPerfCountNext = { 0 }; INT32 giTimerIntervals[NUMTIMERS] = { 5, // Tactical Overhead 20, // NEXTSCROLL 200, // Start Scroll 200, // Animate tiles 1000, // FPS Counter 80, // PATH FIND COUNTER 150, // CURSOR TIMER 250, // RIGHT CLICK FOR MENU 300, // LEFT 30, // SLIDING TEXT 200, // TARGET REFINE TIMER 150, // CURSOR/AP FLASH 60, // FADE MERCS OUT 160, // PANEL SLIDE 1000, // CLOCK UPDATE DELAY 20, // PHYSICS UPDATE 100, // FADE ENEMYS 20, // STRATEGIC OVERHEAD 40, 500, // NON GUN TARGET REFINE TIMER 250, // IMPROVED CURSOR FLASH 500, // 2nd CURSOR FLASH 400, // RADARMAP BLINK AND OVERHEAD MAP BLINK SHOUDL BE THE SAME 400, 10, // Music Overhead 100, // Rubber band start delay }; // TIMER COUNTERS INT32 giTimerCounters[NUMTIMERS]; INT32 giTimerAirRaidQuote = 0; INT32 giTimerAirRaidDiveStarted = 0; INT32 giTimerAirRaidUpdate = 0; INT32 giTimerCustomizable = 0; INT32 giTimerTeamTurnUpdate = 0; CUSTOMIZABLE_TIMER_CALLBACK gpCustomizableTimerCallback = NULL; // Clock Callback event ID MMRESULT gTimerID; TIMECAPS gtc; HANDLE ghClockThread; DWORD gdwClockThreadId; HANDLE ghClockThreadShutdown; HANDLE ghNotifyThread; DWORD gdwNotifyThreadId; HANDLE ghNotifyThreadEvent; HANDLE ghNotifyThreadShutdownComplete; // GLOBALS FOR CALLBACK UINT32 gCNT; SOLDIERTYPE *gPSOLDIER; // GLobal for displaying time diff ( DIAG ) UINT32 guiClockDiff = 0; UINT32 guiClockStart = 0; // BOB: made global to help track freeze issue LONGLONG gliTimestampDiff = 0; LONGLONG gliWaitTime = 0; LONGLONG giIncrement = 0; UINT32 giSleepTime = 0; extern UINT32 guiCompressionStringBaseTime; extern INT32 giFlashHighlightedItemBaseTime; //extern INT32 giCompatibleItemBaseTime;//Moa:removed (see HandleMouseInCompatableItemForMapSectorInventory) extern INT32 giAnimateRouteBaseTime; extern INT32 giPotHeliPathBaseTime; // extern INT32 giPotMilitiaPathBaseTime; extern INT32 giClickHeliIconBaseTime; extern INT32 giExitToTactBaseTime; extern UINT32 guiSectorLocatorBaseTime; extern INT32 giCommonGlowBaseTime; extern INT32 giFlashAssignBaseTime; extern INT32 giFlashContractBaseTime; extern UINT32 guiFlashCursorBaseTime; extern INT32 giPotCharPathBaseTime; typedef void(*TIMER_NOTIFY_CALLBACK) (INT32 timer, PTR state); struct TIMER_NOTIFY_ITEM { TIMER_NOTIFY_CALLBACK callback; PTR state; }; typedef std::list<TIMER_NOTIFY_ITEM> TIMER_NOTIFY_ITEM_LIST; typedef TIMER_NOTIFY_ITEM_LIST::iterator TIMER_NOTIFY_ITEM_ITERATOR; static TIMER_NOTIFY_ITEM_LIST glNotifyCallbacks; static CRITICAL_SECTION gcsNotifyLock; static bool HasTimerNotifyCallbacks(); static void BroadcastTimerNotify(INT32); static BOOLEAN UpdateTimeCounter(INT32 &counter, INT32 &iTimeLeft); static BOOLEAN UpdateCounter(INT32 counter, INT32 &iTimeLeft); static void UpdateTimer(); void ResetJA2ClockGlobalTimers(void); UINT32 InitializeJA2TimerCallback(UINT32 uiDelay, LPTIMECALLBACK TimerProc, UINT32 uiUser); // CALLBACKS void CALLBACK FlashItem(UINT uiID, UINT uiMsg, DWORD uiUser, DWORD uiDw1, DWORD uiDw2); void CALLBACK TimeProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) { static BOOLEAN fInFunction = FALSE; //SOLDIERTYPE *pSoldier; if (!fInFunction) { fInFunction = TRUE; BOOLEAN timerDone = FALSE; BOOLEAN tickTime = FALSE; INT32 iTimeLeft = 0; // Use QPC to check if BASETIMESLICE (in ms) has passed if (IsHiSpeedClockMode()) { // Only advance time when sufficient time has passed to exceed next time QueryPerformanceCounter(&gliPerfCount); if (gliPerfCount.QuadPart > gliPerfCountNext.QuadPart) { INT32 iNext = IsFastForwardMode() ? giFastForwardPeriod : UPDATETIMESLICE; giIncrement = (iNext * gliPerfFreq.QuadPart) / FREQUENCY_CONST; gliPerfCountNext.QuadPart = gliPerfCount.QuadPart + giIncrement; iTimeLeft = iNext; timerDone = IsFastForwardMode(); tickTime = TRUE; } } else { // When using millisecond timer, advance time everytime this function is called tickTime = TRUE; timerDone = !IsFastForwardMode(); } if (tickTime) { guiBaseJA2NoPauseClock += BASETIMESLICE; if (!gfPauseClock) { guiBaseJA2Clock += BASETIMESLICE; for (gCNT = 0; gCNT < NUMTIMERS; gCNT++) { timerDone |= UpdateCounter(gCNT, iTimeLeft); } // Update some specialized countdown timers... timerDone |= UpdateTimeCounter(giTimerAirRaidQuote, iTimeLeft); timerDone |= UpdateTimeCounter(giTimerAirRaidDiveStarted, iTimeLeft); timerDone |= UpdateTimeCounter(giTimerAirRaidUpdate, iTimeLeft); timerDone |= UpdateTimeCounter(giTimerTeamTurnUpdate, iTimeLeft); if (gpCustomizableTimerCallback) { timerDone |= UpdateTimeCounter(giTimerCustomizable, iTimeLeft); } #ifndef BOUNDS_CHECKER // If mapscreen... if (guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN) { // IN Mapscreen, loop through player's team..... for (gCNT = gTacticalStatus.Team[gbPlayerNum].bFirstID; gCNT <= gTacticalStatus.Team[gbPlayerNum].bLastID; gCNT++) { gPSOLDIER = MercPtrs[gCNT]; timerDone |= UpdateTimeCounter(gPSOLDIER->timeCounters.PortraitFlashCounter, iTimeLeft); timerDone |= UpdateTimeCounter(gPSOLDIER->timeCounters.PanelAnimateCounter, iTimeLeft); } } else { // Set update flags for soldiers //////////////////////////// for (gCNT = 0; gCNT < guiNumMercSlots; gCNT++) { gPSOLDIER = MercSlots[gCNT]; if (gPSOLDIER != NULL) { timerDone |= UpdateTimeCounter(gPSOLDIER->timeCounters.UpdateCounter, iTimeLeft); timerDone |= UpdateTimeCounter(gPSOLDIER->timeCounters.DamageCounter, iTimeLeft); timerDone |= UpdateTimeCounter(gPSOLDIER->timeCounters.ReloadCounter, iTimeLeft); timerDone |= UpdateTimeCounter(gPSOLDIER->timeCounters.FlashSelCounter, iTimeLeft); timerDone |= UpdateTimeCounter(gPSOLDIER->timeCounters.BlinkSelCounter, iTimeLeft); timerDone |= UpdateTimeCounter(gPSOLDIER->timeCounters.PortraitFlashCounter, iTimeLeft); timerDone |= UpdateTimeCounter(gPSOLDIER->timeCounters.AICounter, iTimeLeft); timerDone |= UpdateTimeCounter(gPSOLDIER->timeCounters.FadeCounter, iTimeLeft); timerDone |= UpdateTimeCounter(gPSOLDIER->timeCounters.NextTileCounter, iTimeLeft); timerDone |= UpdateTimeCounter(gPSOLDIER->timeCounters.PanelAnimateCounter, iTimeLeft); #ifdef JA2UB timerDone |= UpdateTimeCounter(gPSOLDIER->GetupFromJA25StartCounter, iTimeLeft); #endif } } } #endif } } if (timerDone) SetEvent(ghNotifyThreadEvent); fInFunction = FALSE; } } static UINT32 MIN_TIMER(UINT32 timer, UINT32 other) { UINT32 value = TIME_MS_TO_US(timer); return (value && value < other ? value : other); } // checks if the clock based on QueryPerformanceCounter is using sane values static inline bool TimerSanityCheck() { // quick and drity check for messed up gliPerfCountNext - if the high part is ahead by more than 2, something very bad is going on. return !(gliPerfCountNext.HighPart > gliPerfCount.HighPart + 1L); } // Returns the smallest time interval for a counter currently in use UINT32 GetNextCounterDoneTime(void) { QueryPerformanceCounter(&gliPerfCount); gliTimestampDiff = gliPerfCountNext.QuadPart - gliPerfCount.QuadPart; gliWaitTime = (gliTimestampDiff * FREQUENCY_CONST) / gliPerfFreq.QuadPart; // if the wait time is too long, or the "missed" step gets too long, re-evaluate the timer and try waiting 125ms if (gliWaitTime > 15000 || gliWaitTime < -15000) { gliWaitTime = 125; // in mili-seconds QueryPerformanceFrequency(&gliPerfFreq); gliPerfCountNext.QuadPart = gliPerfCount.QuadPart + ((125 * gliPerfFreq.QuadPart) / FREQUENCY_CONST); } return (UINT32)((gliWaitTime > 0) ? gliWaitTime : 0); } // Function to test if there are any outstanding timers. Used in fast forward routines BOOLEAN IsTimerActive(void) { return GetNextCounterDoneTime() <= FASTFORWARDTIMESLICE ? TRUE : FALSE; } DWORD WINAPI JA2ClockThread(LPVOID lpParam) { __try { for (;;) { TimeProc(0, 0, 0, 0, 0); DWORD dwResult = WaitForSingleObject(ghClockThreadShutdown, 0); if (dwResult == WAIT_OBJECT_0 || dwResult == WAIT_ABANDONED) break; YieldProcessor(); // Sleep for a couple of milliseconds if not in fast forward mode if (!IsFastForwardMode()) { giSleepTime = TIME_US_TO_MS(GetNextCounterDoneTime()); // monitor the returned sleep times, if we try to sleep for more than 2 secs then somehing must be very wrong. if (giSleepTime > 2000) { giSleepTime = 250; } Sleep(giSleepTime); } } } __except (EXCEPTION_EXECUTE_HANDLER) { // Unhandled exception just exit __debugbreak(); } return 0L; } DWORD WINAPI JA2NotifyThread(LPVOID lpParam) { HANDLE waitHandles[] = { ghClockThreadShutdown, ghNotifyThreadEvent }; for (;;) { DWORD dwResult = WaitForSingleObject(ghClockThreadShutdown, 0); if (dwResult == WAIT_OBJECT_0 || dwResult == WAIT_ABANDONED) break; DWORD waitTime = (!IsFastForwardMode()) ? max(TIME_US_TO_MS(MIN_NOTIFY_TIME), TIME_US_TO_MS(GetNextCounterDoneTime())) : 0; dwResult = WaitForMultipleObjectsEx(_countof(waitHandles), waitHandles, FALSE, waitTime, FALSE); if (dwResult == WAIT_OBJECT_0) break; if (dwResult >= WAIT_ABANDONED_0 && dwResult <= (WAIT_ABANDONED_0 + _countof(waitHandles))) break; if (dwResult == WAIT_FAILED || dwResult == WAIT_TIMEOUT || (dwResult - WAIT_OBJECT_0) == 1) { if (HasTimerNotifyCallbacks()) { BroadcastTimerNotify(-1); } } else { // unexpected failure DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "JA2NotifyThread failed!"); __debugbreak(); } } SetEvent(ghNotifyThreadShutdownComplete); return 0L; } BOOLEAN InitializeJA2Clock() { #ifdef CALLBACKTIMER MMRESULT mmResult; INT32 cnt; // Init timer delays for (cnt = 0; cnt < NUMTIMERS; cnt++) { giTimerCounters[cnt] = giTimerIntervals[cnt]; } // First get timer resolutions mmResult = timeGetDevCaps(>c, sizeof(gtc)); if (mmResult != TIMERR_NOERROR) { DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "Could not get timer properties"); } if (!QueryPerformanceFrequency(&gliPerfFreq)) { DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "Could not get performance frequency"); } if (!QueryPerformanceCounter(&gliPerfCount)) { DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "Could not get performance frequency"); } timeBeginPeriod(gtc.wPeriodMin); InitializeCriticalSection(&gcsNotifyLock); if (IsHiSpeedClockMode()) { ghClockThreadShutdown = CreateEvent(NULL, TRUE, FALSE, NULL); ghNotifyThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL); ghNotifyThreadShutdownComplete = CreateEvent(NULL, TRUE, FALSE, NULL); ghClockThread = CreateThread( NULL, // default security attributes 0, // use default stack size JA2ClockThread, // thread function NULL, // argument to thread function 0, // use default creation flags &gdwClockThreadId);// returns the thread identifier ghNotifyThread = CreateThread( NULL, // default security attributes 0, // use default stack size JA2NotifyThread, // thread function NULL, // argument to thread function 0, // use default creation flags &gdwNotifyThreadId);// returns the thread identifier } else { UpdateTimer(); } #endif return TRUE; } void ShutdownJA2Clock(void) { if (IsHiSpeedClockMode()) { SetEvent(ghClockThreadShutdown); WaitForSingleObject(ghNotifyThreadShutdownComplete, 2000); HANDLE waitHandles[] = { ghClockThread, ghNotifyThread }; WaitForMultipleObjects(_countof(waitHandles), waitHandles, TRUE, 1000); CloseHandle(ghClockThreadShutdown); CloseHandle(ghClockThread); CloseHandle(ghNotifyThreadEvent); CloseHandle(ghNotifyThread); // During ungraceful shutdowns notify lock may be in use in notify thread if (TryEnterCriticalSection(&gcsNotifyLock)) { LeaveCriticalSection(&gcsNotifyLock); DeleteCriticalSection(&gcsNotifyLock); } } else { // Make sure we kill the timer #ifdef CALLBACKTIMER timeKillEvent(gTimerID); #endif } timeEndPeriod(gtc.wPeriodMin); } UINT32 InitializeJA2TimerCallback(UINT32 uiDelay, LPTIMECALLBACK TimerProc, UINT32 uiUser) { MMRESULT mmResult; MMRESULT TimerID; // First get timer resolutions mmResult = timeGetDevCaps(>c, sizeof(gtc)); if (mmResult != TIMERR_NOERROR) { __debugbreak(); DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "Could not get timer properties"); } // Set timer at lowest resolution. Could use middle of lowest/highest, we'll see how this performs first TimerID = timeSetEvent((UINT)uiDelay, (UINT)uiDelay, TimerProc, (DWORD)uiUser, TIME_PERIODIC); if (!TimerID) { __debugbreak(); DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "Could not create timer callback"); } return ((UINT32)TimerID); } void RemoveJA2TimerCallback(UINT32 uiTimer) { timeKillEvent(uiTimer); } UINT32 InitializeJA2TimerID(UINT32 uiDelay, UINT32 uiCallbackID, UINT32 uiUser) { switch (uiCallbackID) { case ITEM_LOCATOR_CALLBACK: return(InitializeJA2TimerCallback(uiDelay, FlashItem, uiUser)); break; } // invalid callback id Assert(FALSE); return(0); } ////////////////////////////////////////////////////////////////////////////////////////////// // TIMER CALLBACK S ////////////////////////////////////////////////////////////////////////////////////////////// void CALLBACK FlashItem(UINT uiID, UINT uiMsg, DWORD uiUser, DWORD uiDw1, DWORD uiDw2) { } void PauseTime(BOOLEAN fPaused) { gfPauseClock = fPaused; } void SetCustomizableTimerCallbackAndDelay(INT32 iDelay, CUSTOMIZABLE_TIMER_CALLBACK pCallback, BOOLEAN fReplace) { if (gpCustomizableTimerCallback) { if (!fReplace) { // replace callback but call the current callback first gpCustomizableTimerCallback(); } } RESETTIMECOUNTER(giTimerCustomizable, iDelay); gpCustomizableTimerCallback = pCallback; } void CheckCustomizableTimer(void) { if (gpCustomizableTimerCallback) { if (TIMECOUNTERDONE(giTimerCustomizable, 0)) { // set the callback to a temp variable so we can reset the global variable // before calling the callback, so that if the callback sets up another // instance of the timer, we don't reset it afterwards CUSTOMIZABLE_TIMER_CALLBACK pTempCallback; pTempCallback = gpCustomizableTimerCallback; gpCustomizableTimerCallback = NULL; pTempCallback(); } } } void ResetJA2ClockGlobalTimers(void) { UINT32 uiCurrentTime = GetJA2Clock(); guiCompressionStringBaseTime = uiCurrentTime; giFlashHighlightedItemBaseTime = uiCurrentTime; //giCompatibleItemBaseTime = uiCurrentTime;//Moa: removed (see HandleMouseInCompatableItemForMapSectorInventory) giAnimateRouteBaseTime = uiCurrentTime; giPotHeliPathBaseTime = uiCurrentTime; // giPotMilitiaPathBaseTime = uiCurrentTime; giClickHeliIconBaseTime = uiCurrentTime; giExitToTactBaseTime = uiCurrentTime; guiSectorLocatorBaseTime = uiCurrentTime; giCommonGlowBaseTime = uiCurrentTime; giFlashAssignBaseTime = uiCurrentTime; giFlashContractBaseTime = uiCurrentTime; guiFlashCursorBaseTime = uiCurrentTime; giPotCharPathBaseTime = uiCurrentTime; } void SetTileAnimCounter(INT32 iTime) { giTimerIntervals[ANIMATETILES] = iTime; } void SetFastForwardPeriod(DOUBLE value) { giFastForwardPeriod = (UINT32)(value); if (giFastForwardPeriod <= 1) giFastForwardPeriod = 1; } void SetFastForwardKey(INT32 key) { giFastForwardKey = key; } BOOLEAN IsFastForwardKeyPressed() { return giFastForwardKey && _KeyDown(giFastForwardKey); } void SetFastForwardMode(BOOLEAN enable) { giFastForwardMode = enable; UpdateTimer(); } BOOLEAN IsFastForwardMode() { return FALSE; // giFastForwardMode || IsFastForwardKeyPressed(); } LONGLONG GetJA2Microseconds() { return gliPerfCount.QuadPart * FREQUENCY_CONST / gliPerfFreq.QuadPart; } void AddTimerNotifyCallback(TIMER_NOTIFY_CALLBACK callback, PTR state) { EnterCriticalSection(&gcsNotifyLock); BOOL addItem = TRUE; for (TIMER_NOTIFY_ITEM_ITERATOR itr = glNotifyCallbacks.begin(); itr != glNotifyCallbacks.end(); ++itr) { if (callback == (*itr).callback && state == (*itr).state) { addItem = FALSE; break; } } if (addItem) { TIMER_NOTIFY_ITEM item; item.callback = callback; item.state = state; glNotifyCallbacks.push_back(item); } LeaveCriticalSection(&gcsNotifyLock); } void RemoveTimerNotifyCallback(TIMER_NOTIFY_CALLBACK callback, PTR state) { EnterCriticalSection(&gcsNotifyLock); for (TIMER_NOTIFY_ITEM_ITERATOR itr = glNotifyCallbacks.begin(); itr != glNotifyCallbacks.end();) { if (callback == (*itr).callback && state == (*itr).state) itr = glNotifyCallbacks.erase(itr); else ++itr; } LeaveCriticalSection(&gcsNotifyLock); } void ClearTimerNotifyCallbacks() { // If we cannot get the lock it is likely due to exception while handling notification and we are shutting down if (TryEnterCriticalSection(&gcsNotifyLock)) { glNotifyCallbacks.clear(); LeaveCriticalSection(&gcsNotifyLock); } } static bool HasTimerNotifyCallbacks() { return !glNotifyCallbacks.empty(); } // Call timer notify routine // Separate the callback notifies with normal try/catch // as SEH __try/__except are incompatible with C++ exceptions static void InnerTimerNotify(INT32 timer) { try { for (TIMER_NOTIFY_ITEM_ITERATOR itr = glNotifyCallbacks.begin(); itr != glNotifyCallbacks.end(); ++itr) { if (NULL != (*itr).callback) (*itr).callback(timer, (*itr).state); } } catch (...) { __debugbreak(); DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "InnerTimerNotify Failed!"); } } static void BroadcastTimerNotify(INT32 timer) { EnterCriticalSection(&gcsNotifyLock); __try { __try { InnerTimerNotify(timer); } __except (EXCEPTION_EXECUTE_HANDLER) { /* Not sure. exit? */ __debugbreak(); DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "BroadcastTimerNotify Failed!"); } } __finally { LeaveCriticalSection(&gcsNotifyLock); } } BOOLEAN UpdateTimeCounter(INT32 &counter, INT32 &iTimeLeft) { if (counter == 0) { return FALSE; } else if ((counter - BASETIMESLICE) < 0) { counter = 0; return TRUE; } else { counter -= BASETIMESLICE; if (counter < iTimeLeft) iTimeLeft = counter; return FALSE; } return FALSE; } BOOLEAN UpdateCounter(INT32 counterIdx, INT32 &iTimeLeft) { INT32& counter = giTimerCounters[counterIdx]; return UpdateTimeCounter(counter, iTimeLeft); } BOOLEAN UpdateCounter(INT32 counterIdx) { INT32 iDummy = 0; return UpdateCounter(counterIdx, iDummy); } void ResetCounter(INT32 counterIdx) { giTimerCounters[counterIdx] = giTimerIntervals[counterIdx]; } BOOLEAN CounterDone(INT32 counterIdx) { return (giTimerCounters[counterIdx] == 0) ? TRUE : FALSE; } void ResetTimerCounter(INT32 &timer, INT32 value) { timer = value; } BOOLEAN TimeCounterDone(INT32 timer) { return (timer == 0) ? TRUE : FALSE; } void ZeroTimeCounter(INT32& timer) { timer = 0; } BOOLEAN IsJA2TimerThread() { return (GetCurrentThreadId() == gdwClockThreadId); } #ifndef GetJA2Clock UINT32 GetJA2Clock() { return guiBaseJA2Clock; } #endif #ifndef GetJA2NoPauseClock UINT32 GetJA2NoPauseClock() { return guiBaseJA2NoPauseClock; } #endif void SetHiSpeedClockMode(BOOLEAN enable) { gfHispeedClockMode = enable; } BOOLEAN IsHiSpeedClockMode() { return gfHispeedClockMode; } void SetNotifyFrequencyKey(INT32 value) { MIN_NOTIFY_TIME = value; } void SetClockSpeedPercent(FLOAT value) { gfClockSpeedPercent = value; UPDATETIMESLICE = (UINT32)((FLOAT)TIME_MS_TO_US(BASETIMESLICE) * 100.0f / value); UpdateTimer(); } void UpdateTimer() { // Set timer at lowest resolution. Could use middle of lowest/highest, we'll see how this performs first if (!IsHiSpeedClockMode()) { UINT uiTimeSlice = giFastForwardMode ? gtc.wPeriodMin : max(gtc.wPeriodMin, TIME_US_TO_MS(UPDATETIMESLICE)); if (uiTimeSlice != guiTimeSlice) { guiTimeSlice = uiTimeSlice; if (gTimerID != 0) timeKillEvent(gTimerID); gTimerID = timeSetEvent(uiTimeSlice, uiTimeSlice, TimeProc, (DWORD)0, TIME_PERIODIC); if (!gTimerID) { __debugbreak(); DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "Could not create timer callback"); } } } }
Private
[
?
]
Run code
Submit