diff --git a/Credits.cpp b/Credits.cpp index 3dab0450..a2416143 100644 --- a/Credits.cpp +++ b/Credits.cpp @@ -417,7 +417,11 @@ void GetCreditScreenUserInput() { InputAtom Event; +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&Event, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while( DequeueEvent( &Event ) ) +#endif { if( Event.usEvent == KEY_DOWN ) { diff --git a/Editor/messagebox.cpp b/Editor/messagebox.cpp index 2a2b5eaf..89207a0c 100644 --- a/Editor/messagebox.cpp +++ b/Editor/messagebox.cpp @@ -76,7 +76,12 @@ BOOLEAN MessageBoxHandled() { InputAtom DummyEvent; +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&DummyEvent, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while( DequeueEvent( &DummyEvent ) ) +#endif + { if ( DummyEvent.usEvent == KEY_DOWN ) { diff --git a/Editor/popupmenu.cpp b/Editor/popupmenu.cpp index d80cab2f..e20ffde3 100644 --- a/Editor/popupmenu.cpp +++ b/Editor/popupmenu.cpp @@ -397,7 +397,13 @@ void PopupMenuHandle() return; } //Use keyboard input as well. + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&InputEvent, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while( DequeueEvent( &InputEvent ) ) +#endif + { switch(InputEvent.usEvent) { diff --git a/GameInitOptionsScreen.cpp b/GameInitOptionsScreen.cpp index a462778d..b6b6626b 100644 --- a/GameInitOptionsScreen.cpp +++ b/GameInitOptionsScreen.cpp @@ -2578,7 +2578,11 @@ void GetGIOScreenUserInput() { InputAtom Event; +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&Event, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while( DequeueEvent( &Event ) ) +#endif { if( Event.usEvent == KEY_DOWN ) { @@ -5398,7 +5402,11 @@ void GetGIOScreenUserInput() { InputAtom Event; +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&Event, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while( DequeueEvent( &Event ) ) +#endif { if( Event.usEvent == KEY_DOWN ) { diff --git a/GameSettings.cpp b/GameSettings.cpp index cce439d1..19e40576 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -38,8 +38,11 @@ #include "InterfaceItemImages.h" #endif -#include "KeyMap.h" -#include "Timer Control.h" +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + #include "KeyMap.h" + #include "Timer Control.h" +#endif + #include "Text.h" #include "connect.h" #include "sgp_logger.h" @@ -240,6 +243,7 @@ BOOLEAN LoadGameSettings() gGameSettings.fOptions[TOPTION_QUIET_REPAIRING] = iniReader.ReadBoolean("JA2 Game Settings","TOPTION_QUIET_REPAIRING" , FALSE ); gGameSettings.fOptions[TOPTION_QUIET_DOCTORING] = iniReader.ReadBoolean("JA2 Game Settings","TOPTION_QUIET_DOCTORING" , FALSE ); +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER if (!is_networked) gGameSettings.fOptions[TOPTION_AUTO_FAST_FORWARD_MODE] = iniReader.ReadBoolean("JA2 Game Settings","TOPTION_AUTO_FAST_FORWARD_MODE" , FALSE ); else @@ -248,6 +252,7 @@ BOOLEAN LoadGameSettings() // The "HIGHSPEED_TIMER" property from the ja2.ini is not set, disable the option if (!IsHiSpeedClockMode()) gGameSettings.fOptions[TOPTION_AUTO_FAST_FORWARD_MODE] = FALSE; +#endif gGameSettings.fOptions[TOPTION_ZOMBIES] = iniReader.ReadBoolean("JA2 Game Settings","TOPTION_ZOMBIES" , FALSE ); @@ -407,7 +412,11 @@ BOOLEAN SaveGameSettings() settings << "TOPTION_QUIET_TRAINING = " << (gGameSettings.fOptions[TOPTION_QUIET_TRAINING] ? "TRUE" : "FALSE" ) << endl; settings << "TOPTION_QUIET_REPAIRING = " << (gGameSettings.fOptions[TOPTION_QUIET_REPAIRING] ? "TRUE" : "FALSE" ) << endl; settings << "TOPTION_QUIET_DOCTORING = " << (gGameSettings.fOptions[TOPTION_QUIET_DOCTORING] ? "TRUE" : "FALSE" ) << endl; + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER settings << "TOPTION_AUTO_FAST_FORWARD_MODE = " << (gGameSettings.fOptions[TOPTION_AUTO_FAST_FORWARD_MODE] ? "TRUE" : "FALSE" ) << endl; +#endif + settings << "TOPTION_ZOMBIES = " << (gGameSettings.fOptions[TOPTION_ZOMBIES] ? "TRUE" : "FALSE" ) << endl; settings << "TOPTION_CHEAT_MODE_OPTIONS_HEADER = " << (gGameSettings.fOptions[TOPTION_CHEAT_MODE_OPTIONS_HEADER] ? "TRUE" : "FALSE" ) << endl; settings << "TOPTION_FORCE_BOBBY_RAY_SHIPMENTS = " << (gGameSettings.fOptions[TOPTION_FORCE_BOBBY_RAY_SHIPMENTS] ? "TRUE" : "FALSE" ) << endl; @@ -535,7 +544,11 @@ void InitGameSettings() gGameSettings.fOptions[ TOPTION_QUIET_TRAINING ] = FALSE; gGameSettings.fOptions[ TOPTION_QUIET_REPAIRING ] = FALSE; gGameSettings.fOptions[ TOPTION_QUIET_DOCTORING ] = FALSE; + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER gGameSettings.fOptions[ TOPTION_AUTO_FAST_FORWARD_MODE ] = FALSE; +#endif + gGameSettings.fOptions[ TOPTION_ZOMBIES ] = FALSE; // Flugente Zombies 1.0 @@ -1794,6 +1807,7 @@ void LoadGameExternalOptions() gGameExternalOptions.fEnableInventoryPoolQ = FALSE; #endif +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER ////////// CLOCK SETTINGS ////////// // Key to artificially alter the clock so turns run faster @@ -1804,6 +1818,7 @@ void LoadGameExternalOptions() gGameExternalOptions.iFastForwardPeriod = (FLOAT)iniReader.ReadDouble("Clock Settings","FAST_FORWARD_PERIOD", 500, 1, 10000); gGameExternalOptions.fClockSpeedPercent = (FLOAT)iniReader.ReadDouble("Clock Settings","CLOCK_SPEED_PERCENT", 150, 100, 300); gGameExternalOptions.iNotifyFrequency = iniReader.ReadInteger("Clock Settings","UPDATE_FREQUENCY", 16000, 1000, 20000); +#endif } diff --git a/GameSettings.h b/GameSettings.h index 9b3354a9..2dbc12b3 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -90,7 +90,11 @@ enum TOPTION_QUIET_TRAINING, //Madd: mercs don't say gained experience quote while training TOPTION_QUIET_REPAIRING, //Madd: mercs don't say gained experience quote while repairing items TOPTION_QUIET_DOCTORING, //Madd: mercs don't say gained experience quote while doctoring + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER TOPTION_AUTO_FAST_FORWARD_MODE, // automatically fast forward through AI turns +#endif + TOPTION_ZOMBIES, // Flugente Zombies 1.0: allow zombies // arynn: Debug/Cheat @@ -1083,6 +1087,7 @@ typedef struct INT32 iInitialMercArrivalLocation; +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER // Keyboard shortcut (as VK) for fastforward key. See Utils/KeyMap INT32 iFastForwardKey; // Turn on fast forward whenever ui is disabled. @@ -1093,6 +1098,7 @@ typedef struct INT32 iNotifyFrequency; // Frequency that the screen is updated FLOAT fClockSpeedPercent; +#endif // Flugente FTW 1: Weapon Overheating BOOLEAN fDisplayOverheatThermometer; // Should a 'thermometer' for guns and replacable barrels be displayed? diff --git a/GameVersion.cpp b/GameVersion.cpp index 680966d5..4016d1ed 100644 --- a/GameVersion.cpp +++ b/GameVersion.cpp @@ -15,9 +15,9 @@ #ifdef JA2EDITOR #ifdef JA2UB - CHAR16 zVersionLabel[256] = { L"Unfinished Business - Map Editor v1.13.5353 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Unfinished Business - Map Editor v1.13.5354 (Development Build)" }; #else - CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.5353 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.5354 (Development Build)" }; #endif // ------------------------------ @@ -27,11 +27,11 @@ //DEBUG BUILD VERSION #ifdef JA2UB - CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.5353 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.5354 (Development Build)" }; #elif defined (JA113DEMO) || defined (JA113NODEMO) - CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.5353 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.5354 (Development Build)" }; #else - CHAR16 zVersionLabel[256] = { L"Debug: v1.13.5353 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Debug: v1.13.5354 (Development Build)" }; #endif #elif defined CRIPPLED_VERSION @@ -46,16 +46,16 @@ //RELEASE BUILD VERSION #ifdef JA2UB - CHAR16 zVersionLabel[256] = { L"Release Unfinished Business - v1.13.5353 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Release Unfinished Business - v1.13.5354 (Development Build)" }; #elif defined (JA113DEMO) || defined (JA113NODEMO) - CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.5353 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.5354 (Development Build)" }; #else - CHAR16 zVersionLabel[256] = { L"Release v1.13.5353 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Release v1.13.5354 (Development Build)" }; #endif #endif -CHAR8 czVersionNumber[16] = { "Build 19.06.12" }; //YY.MM.DD +CHAR8 czVersionNumber[16] = { "Build 25.06.12" }; //YY.MM.DD CHAR16 zTrackingNumber[16] = { L"Z" }; // SAVE_GAME_VERSION is defined in header, change it there diff --git a/Laptop/AimMembers.cpp b/Laptop/AimMembers.cpp index 8721e322..82e1e7bf 100644 --- a/Laptop/AimMembers.cpp +++ b/Laptop/AimMembers.cpp @@ -5020,7 +5020,12 @@ void HandleAimMemberKeyBoardInput() { InputAtom InputEvent; +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&InputEvent, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while (DequeueEvent(&InputEvent) == TRUE) +#endif + {//!HandleTextInput( &InputEvent ) && if( InputEvent.usEvent == KEY_DOWN ) { diff --git a/Laptop/BobbyRGuns.cpp b/Laptop/BobbyRGuns.cpp index 1ec33fdc..440e5a63 100644 --- a/Laptop/BobbyRGuns.cpp +++ b/Laptop/BobbyRGuns.cpp @@ -4053,10 +4053,12 @@ void HandleBobbyRGunsKeyBoardInput() break; } } +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER else { extern void HandleDefaultEvent(InputAtom *Event); HandleDefaultEvent(&InputEvent); } +#endif } } diff --git a/Laptop/BriefingRoom.cpp b/Laptop/BriefingRoom.cpp index 49dc1149..f0df185d 100644 --- a/Laptop/BriefingRoom.cpp +++ b/Laptop/BriefingRoom.cpp @@ -426,7 +426,11 @@ void GetPlayerKeyBoardInputForBriefingRoomHomePage( void ) GetCursorPos(&MousePos); ScreenToClient(ghWindow, &MousePos); // In window coords! +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&InputEvent, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while (DequeueEvent(&InputEvent) == TRUE) +#endif { // HOOK INTO MOUSE HOOKS /* diff --git a/Laptop/BriefingRoomM.cpp b/Laptop/BriefingRoomM.cpp index 4bcaef4a..2ac211d8 100644 --- a/Laptop/BriefingRoomM.cpp +++ b/Laptop/BriefingRoomM.cpp @@ -493,7 +493,11 @@ void GetPlayerKeyBoardInputForBriefingRoomEnterHomePage( void ) GetCursorPos(&MousePos); ScreenToClient(ghWindow, &MousePos); // In window coords! +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&InputEvent, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while (DequeueEvent(&InputEvent) == TRUE) +#endif { // HOOK INTO MOUSE HOOKS /* diff --git a/Laptop/IMP Begin Screen.cpp b/Laptop/IMP Begin Screen.cpp index 3df5b16e..c6151d0b 100644 --- a/Laptop/IMP Begin Screen.cpp +++ b/Laptop/IMP Begin Screen.cpp @@ -455,7 +455,11 @@ void GetPlayerKeyBoardInputForIMPBeginScreen( void ) ScreenToClient(ghWindow, &MousePos); // In window coords! // handle input events +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&InputEvent, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while( DequeueEvent(&InputEvent) ) +#endif { if( !HandleTextInput( &InputEvent ) && (InputEvent.usEvent == KEY_DOWN || InputEvent.usEvent == KEY_REPEAT) ) { diff --git a/Laptop/IMP HomePage.cpp b/Laptop/IMP HomePage.cpp index 0db4b321..8dd8a1df 100644 --- a/Laptop/IMP HomePage.cpp +++ b/Laptop/IMP HomePage.cpp @@ -266,7 +266,11 @@ void GetPlayerKeyBoardInputForIMPHomePage( void ) GetCursorPos(&MousePos); ScreenToClient(ghWindow, &MousePos); // In window coords! +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&InputEvent, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while (DequeueEvent(&InputEvent) == TRUE) +#endif { if( !HandleTextInput( &InputEvent ) && (InputEvent.usEvent == KEY_DOWN || InputEvent.usEvent == KEY_REPEAT || InputEvent.usEvent == KEY_UP ) ) { diff --git a/Laptop/florist Order Form.cpp b/Laptop/florist Order Form.cpp index b77a6478..882945fc 100644 --- a/Laptop/florist Order Form.cpp +++ b/Laptop/florist Order Form.cpp @@ -1257,7 +1257,11 @@ void HandleFloristOrderKeyBoardInput() { InputAtom InputEvent; +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&InputEvent, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while (DequeueEvent(&InputEvent) == TRUE) +#endif { if( !HandleTextInput( &InputEvent ) && InputEvent.usEvent == KEY_DOWN ) { diff --git a/Laptop/mercs Files.cpp b/Laptop/mercs Files.cpp index 83bc74ac..9839f9a5 100644 Binary files a/Laptop/mercs Files.cpp and b/Laptop/mercs Files.cpp differ diff --git a/Laptop/personnel.cpp b/Laptop/personnel.cpp index 6e29350d..4b18ce7a 100644 --- a/Laptop/personnel.cpp +++ b/Laptop/personnel.cpp @@ -6419,7 +6419,11 @@ void HandlePersonnelKeyboard( void ) GetCursorPos(&MousePos); ScreenToClient(ghWindow, &MousePos); // In window coords! +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&InputEvent, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while (DequeueEvent(&InputEvent) == TRUE) +#endif { if ( (InputEvent.usEvent == KEY_DOWN ) && (InputEvent.usParam >= '0' ) && ( InputEvent.usParam <= '9') ) { diff --git a/MPChatScreen.cpp b/MPChatScreen.cpp index 1eac5143..3f247fcb 100644 --- a/MPChatScreen.cpp +++ b/MPChatScreen.cpp @@ -757,7 +757,12 @@ UINT32 MPChatScreenHandle( ) // carter, need key shortcuts for clearing up message boxes // Check for esc bool bHandled; + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&InputEvent, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while (DequeueEvent(&InputEvent) == TRUE) +#endif { bHandled = false; if(InputEvent.usEvent == KEY_DOWN ) diff --git a/MPConnectScreen.cpp b/MPConnectScreen.cpp index 1b2ca83a..cafad384 100644 --- a/MPConnectScreen.cpp +++ b/MPConnectScreen.cpp @@ -418,7 +418,11 @@ void GetMPCScreenUserInput() // GetCursorPos(&MousePos); +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&Event, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while( DequeueEvent( &Event ) ) +#endif { // check if this event is swallowed by text input, otherwise process key if( Event.usEvent == KEY_DOWN ) diff --git a/MPHostScreen.cpp b/MPHostScreen.cpp index 17de7c7c..a1883c97 100644 --- a/MPHostScreen.cpp +++ b/MPHostScreen.cpp @@ -2740,7 +2740,11 @@ void GetMPHScreenUserInput() // GetCursorPos(&MousePos); +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&Event, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while( DequeueEvent( &Event ) ) +#endif { // check if this event is swallowed by text input, otherwise process key if( !HandleTextInput( &Event ) && Event.usEvent == KEY_DOWN ) diff --git a/MPJoinScreen.cpp b/MPJoinScreen.cpp index 9b2b6112..42ebad0d 100644 --- a/MPJoinScreen.cpp +++ b/MPJoinScreen.cpp @@ -665,7 +665,11 @@ void GetMPJScreenUserInput() { InputAtom Event; +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&Event, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while( DequeueEvent( &Event ) ) +#endif { // check if this event is swallowed by text input, otherwise process key if( !HandleTextInput( &Event ) && Event.usEvent == KEY_DOWN ) diff --git a/MPScoreScreen.cpp b/MPScoreScreen.cpp index b3c64214..e3ab8e7d 100644 --- a/MPScoreScreen.cpp +++ b/MPScoreScreen.cpp @@ -536,7 +536,11 @@ void GetMPSScreenUserInput() { InputAtom Event; +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&Event, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while( DequeueEvent( &Event ) ) +#endif { // check if this event is swallowed by text input, otherwise process key if( !HandleTextInput( &Event ) && Event.usEvent == KEY_DOWN ) diff --git a/MainMenuScreen.cpp b/MainMenuScreen.cpp index 32ce4178..acc07de5 100644 --- a/MainMenuScreen.cpp +++ b/MainMenuScreen.cpp @@ -484,7 +484,11 @@ void HandleMainMenuInput() InputAtom InputEvent; // Check for esc +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&InputEvent, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while (DequeueEvent(&InputEvent) == TRUE) +#endif { if( InputEvent.usEvent == KEY_UP ) { @@ -533,7 +537,11 @@ void HandleHelpScreenInput() InputAtom InputEvent; // Check for key +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&InputEvent, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while (DequeueEvent(&InputEvent) == TRUE) +#endif { switch( InputEvent.usEvent ) { diff --git a/MessageBoxScreen.cpp b/MessageBoxScreen.cpp index 55ba137a..dda3ca1d 100644 --- a/MessageBoxScreen.cpp +++ b/MessageBoxScreen.cpp @@ -1306,7 +1306,11 @@ UINT32 MessageBoxScreenHandle( ) // carter, need key shortcuts for clearing up message boxes // Check for esc +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&InputEvent, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while (DequeueEvent(&InputEvent) == TRUE) +#endif { if( !HandleTextInput( &InputEvent ) && InputEvent.usEvent == KEY_DOWN ) { diff --git a/Options Screen.cpp b/Options Screen.cpp index d50096f9..31d59831 100644 Binary files a/Options Screen.cpp and b/Options Screen.cpp differ diff --git a/SaveLoadGame.cpp b/SaveLoadGame.cpp index b75c2c4f..3bf81903 100644 --- a/SaveLoadGame.cpp +++ b/SaveLoadGame.cpp @@ -3937,7 +3937,9 @@ BOOLEAN LoadSavedGame( int ubSavedGameID ) ShutdownNPCQuotes(); +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER SetFastForwardMode(FALSE); // FF can sometimes be active if quick-load during AI turn transition +#endif //very small TODO //Bugfix = Stop the chopter sound diff --git a/Standard Gaming Platform/input.cpp b/Standard Gaming Platform/input.cpp index 8b6ba921..ca8569bd 100644 --- a/Standard Gaming Platform/input.cpp +++ b/Standard Gaming Platform/input.cpp @@ -111,7 +111,9 @@ BOOLEAN gfCurrentStringInputState; StringInput *gpCurrentStringDescriptor; // Thread -static CRITICAL_SECTION gcsInputQueueLock; +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + static CRITICAL_SECTION gcsInputQueueLock; +#endif // Local function headers @@ -280,7 +282,9 @@ BOOLEAN InitializeInputManager(void) // ghKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) KeyboardHandler, (HINSTANCE) 0, GetCurrentThreadId()); // DbgMessage(TOPIC_INPUT, DBG_LEVEL_2, String("Set keyboard hook returned %d", ghKeyboardHook)); +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER InitializeCriticalSection(&gcsInputQueueLock); +#endif ghMouseHook = SetWindowsHookEx(WH_MOUSE, (HOOKPROC) MouseHandler, (HINSTANCE) 0, GetCurrentThreadId()); DbgMessage(TOPIC_INPUT, DBG_LEVEL_2, String("Set mouse hook returned %d", ghMouseHook)); @@ -294,7 +298,11 @@ void ShutdownInputManager(void) UnRegisterDebugTopic(TOPIC_INPUT, "Input Manager"); // UnhookWindowsHookEx(ghKeyboardHook); UnhookWindowsHookEx(ghMouseHook); + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER DeleteCriticalSection(&gcsInputQueueLock); +#endif + } void QueuePureEvent(UINT16 ubInputEvent, UINT32 usParam, UINT32 uiParam) @@ -335,7 +343,11 @@ void QueuePureEvent(UINT16 ubInputEvent, UINT32 usParam, UINT32 uiParam) } } -void InternalQueueEvent(UINT16 ubInputEvent, UINT32 usParam, UINT32 uiParam) +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + void InternalQueueEvent(UINT16 ubInputEvent, UINT32 usParam, UINT32 uiParam) +#else + void QueueEvent(UINT16 ubInputEvent, UINT32 usParam, UINT32 uiParam) +#endif { UINT32 uiTimer; UINT16 usKeyState; @@ -458,20 +470,45 @@ void InternalQueueEvent(UINT16 ubInputEvent, UINT32 usParam, UINT32 uiParam) } } -void QueueEvent(UINT16 ubInputEvent, UINT32 usParam, UINT32 uiParam) -{ - EnterCriticalSection(&gcsInputQueueLock); - __try { - InternalQueueEvent(ubInputEvent, usParam, uiParam); - }__finally { - LeaveCriticalSection(&gcsInputQueueLock); +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + void QueueEvent(UINT16 ubInputEvent, UINT32 usParam, UINT32 uiParam) + { + EnterCriticalSection(&gcsInputQueueLock); + __try { + InternalQueueEvent(ubInputEvent, usParam, uiParam); + }__finally { + LeaveCriticalSection(&gcsInputQueueLock); + } } -} +#endif -BOOLEAN DequeueSpecificEvent(InputAtom *Event, UINT32 uiMaskFlags ) -{ - EnterCriticalSection(&gcsInputQueueLock); - __try +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + BOOLEAN DequeueSpecificEvent(InputAtom *Event, UINT32 uiMaskFlags ) + { + EnterCriticalSection(&gcsInputQueueLock); + __try + { + // Is there an event to dequeue + if (gusQueueCount > 0) + { + memcpy( Event, &( gEventQueue[gusHeadIndex] ), sizeof( InputAtom ) ); + + // Check if it has the masks! + if ( ( Event->usEvent & uiMaskFlags ) ) + { + return( DequeueEvent( Event) ); + } + } + + return( FALSE ); + } + __finally + { + LeaveCriticalSection(&gcsInputQueueLock); + } + } +#else + BOOLEAN DequeueSpecificEvent(InputAtom *Event, UINT32 uiMaskFlags ) { // Is there an event to dequeue if (gusQueueCount > 0) @@ -487,13 +524,13 @@ BOOLEAN DequeueSpecificEvent(InputAtom *Event, UINT32 uiMaskFlags ) return( FALSE ); } - __finally - { - LeaveCriticalSection(&gcsInputQueueLock); - } -} +#endif -BOOLEAN InternalDequeueEvent(InputAtom *Event) +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + BOOLEAN InternalDequeueEvent(InputAtom *Event) +#else + BOOLEAN DequeueEvent(InputAtom *Event) +#endif { HandleSingleClicksAndButtonRepeats( ); @@ -524,18 +561,21 @@ BOOLEAN InternalDequeueEvent(InputAtom *Event) return FALSE; } } -BOOLEAN DequeueEvent(InputAtom *Event) -{ - __try + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + BOOLEAN DequeueEvent(InputAtom *Event) { - EnterCriticalSection(&gcsInputQueueLock); - return InternalDequeueEvent(Event); + __try + { + EnterCriticalSection(&gcsInputQueueLock); + return InternalDequeueEvent(Event); + } + __finally + { + LeaveCriticalSection(&gcsInputQueueLock); + } } - __finally - { - LeaveCriticalSection(&gcsInputQueueLock); - } -} +#endif void KeyChange(UINT32 usParam, UINT32 uiParam, UINT8 ufKeyState) { diff --git a/Standard Gaming Platform/sgp.cpp b/Standard Gaming Platform/sgp.cpp index ee5eeff6..d2932869 100644 --- a/Standard Gaming Platform/sgp.cpp +++ b/Standard Gaming Platform/sgp.cpp @@ -56,8 +56,8 @@ #define USE_CONSOLE 0 #include - #include + #include "ExceptionHandling.h" #include "dbt.h" @@ -146,16 +146,18 @@ extern BOOLEAN CheckIfGameCdromIsInCDromDrive(); extern void QueueEvent(UINT16 ubInputEvent, UINT32 usParam, UINT32 uiParam); // Prototype Declarations -INT32 FAR PASCAL SyncWindowProcedure(HWND hWindow, UINT16 Message, WPARAM wParam, LPARAM lParam); INT32 FAR PASCAL WindowProcedure(HWND hWindow, UINT16 Message, WPARAM wParam, LPARAM lParam); BOOLEAN InitializeStandardGamingPlatform(HINSTANCE hInstance, int sCommandShow); void ShutdownStandardGamingPlatform(void); -void CreateStandardGamingPlatform(HWND hWindow); void GetRuntimeSettings( ); -void SafeSGPExit(void); -static bool CallGameLoop(bool wait); -static CRITICAL_SECTION gcsGameLoop; +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + INT32 FAR PASCAL SyncWindowProcedure(HWND hWindow, UINT16 Message, WPARAM wParam, LPARAM lParam); + void CreateStandardGamingPlatform(HWND hWindow); + void SafeSGPExit(void); + static bool CallGameLoop(bool wait); + static CRITICAL_SECTION gcsGameLoop; +#endif int PASCAL HandledWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCommandLine, int sCommandShow); @@ -214,14 +216,16 @@ BOOLEAN gfIgnoreMessages=FALSE; // GLOBAL VARIBLE, SET TO DEFAULT BUT CAN BE CHANGED BY THE GAME IF INIT FILE READ UINT8 gbPixelDepth = PIXEL_DEPTH; -INT32 FAR PASCAL SyncWindowProcedure(HWND hWindow, UINT16 Message, WPARAM wParam, LPARAM lParam) -{ - INT32 retval; - EnterCriticalSection(&gcsGameLoop); - retval = WindowProcedure(hWindow, Message, wParam, lParam); - LeaveCriticalSection(&gcsGameLoop); - return retval; -} +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + INT32 FAR PASCAL SyncWindowProcedure(HWND hWindow, UINT16 Message, WPARAM wParam, LPARAM lParam) + { + INT32 retval; + EnterCriticalSection(&gcsGameLoop); + retval = WindowProcedure(hWindow, Message, wParam, lParam); + LeaveCriticalSection(&gcsGameLoop); + return retval; + } +#endif bool s_bExportStrings = false; extern bool g_bUseXML_Strings;// = false; @@ -531,7 +535,10 @@ INT32 FAR PASCAL WindowProcedure(HWND hWindow, UINT16 Message, WPARAM wParam, LP break; case WM_CREATE: + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER CreateStandardGamingPlatform(hWindow); +#endif break; case WM_DESTROY: @@ -660,7 +667,11 @@ BOOLEAN InitializeStandardGamingPlatform(HINSTANCE hInstance, int sCommandShow) FontTranslationTable *pFontTable; // now required by all (even JA2) in order to call ShutdownSGP +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER atexit(SafeSGPExit); +#else + atexit(SGPExit); +#endif // First, initialize the registry keys. InitializeRegistryKeys( "Wizardry8", "Wizardry8key" ); @@ -721,7 +732,9 @@ BOOLEAN InitializeStandardGamingPlatform(HINSTANCE hInstance, int sCommandShow) return FALSE; } +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER InitializeCriticalSection(&gcsGameLoop); +#endif FastDebugMsg("Initializing Video Manager"); // Initialize DirectDraw (DirectX 2) @@ -748,6 +761,11 @@ BOOLEAN InitializeStandardGamingPlatform(HINSTANCE hInstance, int sCommandShow) return FALSE; } +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER +#else + InitializeJA2Clock(); +#endif + //InitializeJA2TimerID(); #ifdef USE_VFS @@ -897,24 +915,26 @@ BOOLEAN InitializeStandardGamingPlatform(HINSTANCE hInstance, int sCommandShow) return TRUE; } -static void TimerActivatedCallback(INT32 timer, PTR state) -{ - if (gfApplicationActive && gfProgramIsRunning) +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + static void TimerActivatedCallback(INT32 timer, PTR state) { - if (CallGameLoop(false)) - YieldProcessor(); + if (gfApplicationActive && gfProgramIsRunning) + { + if (CallGameLoop(false)) + YieldProcessor(); + } } -} -void CreateStandardGamingPlatform(HWND hWindow) -{ - InitializeJA2Clock(); + void CreateStandardGamingPlatform(HWND hWindow) + { + InitializeJA2Clock(); - if (!IsHiSpeedClockMode()) - SetTimer( hWindow, 0, 1, NULL); - else - AddTimerNotifyCallback(TimerActivatedCallback, hWindow); -} + if (!IsHiSpeedClockMode()) + SetTimer( hWindow, 0, 1, NULL); + else + AddTimerNotifyCallback(TimerActivatedCallback, hWindow); + } +#endif void ShutdownStandardGamingPlatform(void) { @@ -938,7 +958,10 @@ void ShutdownStandardGamingPlatform(void) // // Shut down the different components of the SGP // + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER ClearTimerNotifyCallbacks(); +#endif // TEST SoundServiceStreams(); @@ -986,7 +1009,9 @@ void ShutdownStandardGamingPlatform(void) // down the debugging layer UnRegisterDebugTopic(TOPIC_SGP, "Standard Gaming Platform"); +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER DeleteCriticalSection(&gcsGameLoop); +#endif ShutdownDebugManager(); @@ -1252,6 +1277,12 @@ int PASCAL HandledWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pC FastDebugMsg("Running Game"); +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER +#else + // 0verhaul: Use the smallest available timer to make sure all animation updates happen at the speed they're supposed to + SetTimer( ghWindow, uiTimer, 1, NULL); +#endif + // At this point the SGP is set up, which means all I/O, Memory, tools, etc... are available. All we need to do is // attend to the gaming mechanics themselves Message.wParam = 0; @@ -1325,6 +1356,11 @@ int PASCAL HandledWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pC } #endif +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER +#else + KillTimer( ghWindow, uiTimer); +#endif + // This is the normal exit point FastDebugMsg("Exiting Game"); PostQuitMessage(0); @@ -1685,26 +1721,29 @@ void GetRuntimeSettings( ) s_CodePage = oProps.getStringProperty(L"Ja2 Settings", L"CODE_PAGE"); #endif // USE_CODE_PAGE +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER // get timer/clock initialization state SetHiSpeedClockMode( oProps.getBoolProperty("Ja2 Settings", "HIGHSPEED_TIMER", false) ? TRUE : FALSE ); #endif + +#endif } - -void SafeSGPExit(void) -{ - // SGPExit tends to use resources that are already uninitialized so handle - __try +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + void SafeSGPExit(void) { - SGPExit(); + // SGPExit tends to use resources that are already uninitialized so handle + __try + { + SGPExit(); + } + __except( EXCEPTION_EXECUTE_HANDLER ) + { + // The application is in exit and best effort to clean up + // has failed so just ignore and continue silently + } } - __except( EXCEPTION_EXECUTE_HANDLER ) - { - // The application is in exit and best effort to clean up - // has failed so just ignore and continue silently - } -} - +#endif void ShutdownWithErrorBox(CHAR8 *pcMessage) { @@ -1899,69 +1938,70 @@ static LONG __stdcall SGPExceptionFilter(int exceptionCount, EXCEPTION_POINTERS* return EXCEPTION_EXECUTE_HANDLER; } -static void SGPGameLoop() -{ - try +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + static void SGPGameLoop() { - GameLoop(); - } - catch(sgp::Exception &ex) - { - SGP_ERROR(ex.what()); - SHOWEXCEPTION(ex); - } - catch(vfs::Exception &ex) - { - SGP_ERROR(ex.what()); - SHOWEXCEPTION(ex); - } - catch(std::exception &ex) - { - sgp::Exception nex(ex.what()); - SGP_ERROR(nex.what()); - SHOWEXCEPTION(nex); - } - catch(const char* msg) - { - sgp::Exception ex(msg); - SGP_ERROR(ex.what()); - SHOWEXCEPTION(ex); - } -} - -static bool CallGameLoop(bool wait) -{ - static int numUnsuccessfulTries = 0; - if (wait) - { - EnterCriticalSection(&gcsGameLoop); - } - else - { - if ( !TryEnterCriticalSection(&gcsGameLoop) ) - return false; + try + { + GameLoop(); + } + catch(sgp::Exception &ex) + { + SGP_ERROR(ex.what()); + SHOWEXCEPTION(ex); + } + catch(vfs::Exception &ex) + { + SGP_ERROR(ex.what()); + SHOWEXCEPTION(ex); + } + catch(std::exception &ex) + { + sgp::Exception nex(ex.what()); + SGP_ERROR(nex.what()); + SHOWEXCEPTION(nex); + } + catch(const char* msg) + { + sgp::Exception ex(msg); + SGP_ERROR(ex.what()); + SHOWEXCEPTION(ex); + } } - __try + static bool CallGameLoop(bool wait) { + static int numUnsuccessfulTries = 0; + if (wait) + { + EnterCriticalSection(&gcsGameLoop); + } + else + { + if ( !TryEnterCriticalSection(&gcsGameLoop) ) + return false; + } + __try { - SGPGameLoop(); - numUnsuccessfulTries = 0; + __try + { + SGPGameLoop(); + numUnsuccessfulTries = 0; + } + __except( SGPExceptionFilter(++numUnsuccessfulTries, GetExceptionInformation()) ) + { + } } - __except( SGPExceptionFilter(++numUnsuccessfulTries, GetExceptionInformation()) ) + __finally { + LeaveCriticalSection(&gcsGameLoop); } + + // Give it several attempts to recover from random exceptions and to display error screen + if (numUnsuccessfulTries > 5) + ShutdownWithErrorBox("Unhandled exception. Unable to recover."); + + return true; } - __finally - { - LeaveCriticalSection(&gcsGameLoop); - } - - // Give it several attempts to recover from random exceptions and to display error screen - if (numUnsuccessfulTries > 5) - ShutdownWithErrorBox("Unhandled exception. Unable to recover."); - - return true; -} - +#endif diff --git a/Strategic/AI Viewer.cpp b/Strategic/AI Viewer.cpp index 1a15c9d0..fdb6cc2a 100644 --- a/Strategic/AI Viewer.cpp +++ b/Strategic/AI Viewer.cpp @@ -932,7 +932,12 @@ void HandleViewerInput() { SECTORINFO *pSector; InputAtom Event; + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while( DequeueSpecificEvent(&Event, KEY_DOWN|KEY_UP) ) +#else + while( DequeueEvent( &Event ) ) +#endif { if( !HandleTextInput( &Event ) && Event.usEvent == KEY_DOWN ) { diff --git a/Strategic/Auto Resolve.cpp b/Strategic/Auto Resolve.cpp index 016e9755..646c585c 100644 --- a/Strategic/Auto Resolve.cpp +++ b/Strategic/Auto Resolve.cpp @@ -3410,7 +3410,12 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Autoresolve3"); InputAtom InputEvent; BOOLEAN fResetAutoResolve = FALSE; + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while( DequeueSpecificEvent(&InputEvent, KEY_DOWN|KEY_UP|KEY_REPEAT) ) +#else + while( DequeueEvent( &InputEvent ) ) +#endif { if( InputEvent.usEvent == KEY_DOWN || InputEvent.usEvent == KEY_REPEAT ) { diff --git a/Strategic/Quest Debug System.cpp b/Strategic/Quest Debug System.cpp index ec2ae91a..dff6bb76 100644 --- a/Strategic/Quest Debug System.cpp +++ b/Strategic/Quest Debug System.cpp @@ -1311,7 +1311,11 @@ void GetUserInput() GetCursorPos(&MousePos); ScreenToClient(ghWindow, &MousePos); // In window coords! +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while( DequeueSpecificEvent(&Event, KEY_DOWN|KEY_UP|KEY_REPEAT) ) +#else + while( DequeueEvent( &Event ) ) +#endif { if( !HandleTextInput( &Event ) && Event.usEvent == KEY_DOWN ) { diff --git a/Strategic/mapscreen.cpp b/Strategic/mapscreen.cpp index 54b5df09..ef75a6d2 100644 --- a/Strategic/mapscreen.cpp +++ b/Strategic/mapscreen.cpp @@ -6811,6 +6811,7 @@ void InitializeWorldSize(INT16 sSectorX, INT16 sSectorY , INT8 bSectorZ) void GetMapKeyboardInput( UINT32 *puiNewEvent ) { InputAtom InputEvent; + POINT MousePos; INT8 bSquadNumber; UINT8 ubGroupId = 0; BOOLEAN fCtrl, fAlt; @@ -6822,9 +6823,37 @@ void GetMapKeyboardInput( UINT32 *puiNewEvent ) fCtrl = _KeyDown( CTRL ); fAlt = _KeyDown( ALT ); -// while( DequeueEvent( &InputEvent ) ) - while( DequeueSpecificEvent( &InputEvent, KEY_DOWN|KEY_UP|KEY_REPEAT ) ) // doesn't work for some reason -- MM: fixed? it works better for me like this + while( DequeueEvent( &InputEvent ) ) { + #ifdef USE_HIGHSPEED_GAMELOOP_TIMER + #else + GetCursorPos(&MousePos); + ScreenToClient(ghWindow, &MousePos); // In window coords! + + // HOOK INTO MOUSE HOOKS + switch(InputEvent.usEvent) + { + case LEFT_BUTTON_DOWN: + MouseSystemHook(LEFT_BUTTON_DOWN, (INT16)MousePos.x, (INT16)MousePos.y,_LeftButtonDown, _RightButtonDown); + break; + case LEFT_BUTTON_UP: + MouseSystemHook(LEFT_BUTTON_UP, (INT16)MousePos.x, (INT16)MousePos.y ,_LeftButtonDown, _RightButtonDown); + break; + case RIGHT_BUTTON_DOWN: + MouseSystemHook(RIGHT_BUTTON_DOWN, (INT16)MousePos.x, (INT16)MousePos.y,_LeftButtonDown, _RightButtonDown); + break; + case RIGHT_BUTTON_UP: + MouseSystemHook(RIGHT_BUTTON_UP, (INT16)MousePos.x, (INT16)MousePos.y,_LeftButtonDown, _RightButtonDown); + break; + case RIGHT_BUTTON_REPEAT: + MouseSystemHook(RIGHT_BUTTON_REPEAT, (INT16)MousePos.x, (INT16)MousePos.y,_LeftButtonDown, _RightButtonDown); + break; + case LEFT_BUTTON_REPEAT: + MouseSystemHook(LEFT_BUTTON_REPEAT, (INT16)MousePos.x, (INT16)MousePos.y,_LeftButtonDown, _RightButtonDown); + break; + } + #endif + if( InputEvent.usEvent == KEY_DOWN ) { // if game is paused because of player, unpause with any key diff --git a/Tactical/Auto Bandage.cpp b/Tactical/Auto Bandage.cpp index 63528479..e749eddb 100644 --- a/Tactical/Auto Bandage.cpp +++ b/Tactical/Auto Bandage.cpp @@ -279,7 +279,11 @@ BOOLEAN HandleAutoBandage( ) // Deque all game events DequeAllGameEvents( TRUE ); +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&InputEvent, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while (DequeueEvent(&InputEvent) == TRUE) +#endif { if ( InputEvent.usEvent == KEY_UP ) { diff --git a/Tactical/ShopKeeper Interface.cpp b/Tactical/ShopKeeper Interface.cpp index 4c7a7190..5b728c1f 100644 --- a/Tactical/ShopKeeper Interface.cpp +++ b/Tactical/ShopKeeper Interface.cpp @@ -1738,7 +1738,11 @@ void GetShopKeeperInterfaceUserInput() GetCursorPos(&MousePos); ScreenToClient(ghWindow, &MousePos); // In window coords! +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&Event, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while( DequeueEvent( &Event ) ) +#endif { // HOOK INTO MOUSE HOOKS /* removed warning condition C4060 (jonathanl) diff --git a/Tactical/Strategic Exit GUI.cpp b/Tactical/Strategic Exit GUI.cpp index f6ff728b..3506f84e 100644 --- a/Tactical/Strategic Exit GUI.cpp +++ b/Tactical/Strategic Exit GUI.cpp @@ -620,7 +620,11 @@ void RenderSectorExitMenu( ) gsGlobalCursorYOffset = 0; SetCurrentCursorFromDatabase( CURSOR_NORMAL ); +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&Event, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while( DequeueEvent( &Event ) ) +#endif { if( Event.usEvent == KEY_DOWN ) { diff --git a/Tactical/Tactical Turns.cpp b/Tactical/Tactical Turns.cpp index 555ece2e..7a83432c 100644 --- a/Tactical/Tactical Turns.cpp +++ b/Tactical/Tactical Turns.cpp @@ -151,7 +151,9 @@ void HandleTacticalEndTurn( ) // OK, Do a number of things here.... // Every few turns...... +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER SetFastForwardMode(FALSE); // Cancel FF at end of battle +#endif // Get time elasped uiTime = GetWorldTotalSeconds( ); diff --git a/Tactical/TeamTurns.cpp b/Tactical/TeamTurns.cpp index c74cdd1d..55895647 100644 --- a/Tactical/TeamTurns.cpp +++ b/Tactical/TeamTurns.cpp @@ -167,7 +167,10 @@ void StartPlayerTeamTurn( BOOLEAN fDoBattleSnd, BOOLEAN fEnteringCombatMode ) DebugMsg (TOPIC_JA2INTERRUPT,DBG_LEVEL_3,"StartPlayerTeamTurn"); // SOLDIERTYPE *pSoldier; // EV_S_BEGINTURN SBeginTurn; + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER SetFastForwardMode(FALSE); +#endif // Start the turn of player charactors @@ -496,6 +499,7 @@ void BeginTeamTurn( UINT8 ubTeam ) if( !LightningEndOfTurn( ubTeam ) )return; //end rain +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER // disable for our turn and enable for other teams if ( gGameSettings.fOptions[TOPTION_AUTO_FAST_FORWARD_MODE] ) { @@ -510,6 +514,7 @@ void BeginTeamTurn( UINT8 ubTeam ) SetFastForwardMode( (ubTeam != OUR_TEAM) ); } } +#endif while( 1 ) { @@ -837,7 +842,9 @@ void StartInterrupt( void ) INT32 iSquad, iCounter; // disable ff mode +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER SetFastForwardMode(FALSE); +#endif // build string for display of who gets interrupt //while( 1 ) @@ -1432,6 +1439,7 @@ void EndInterrupt( BOOLEAN fMarkInterruptOccurred ) } +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER if ( gGameSettings.fOptions[TOPTION_AUTO_FAST_FORWARD_MODE] ) { if (is_networked) @@ -1445,6 +1453,7 @@ void EndInterrupt( BOOLEAN fMarkInterruptOccurred ) SetFastForwardMode( (gTacticalStatus.ubCurrentTeam != OUR_TEAM) ); } } +#endif } diff --git a/TileEngine/overhead map.cpp b/TileEngine/overhead map.cpp index b4413f1e..8dd9e232 100644 --- a/TileEngine/overhead map.cpp +++ b/TileEngine/overhead map.cpp @@ -674,7 +674,11 @@ void HandleOverheadUI(void) ScrollOverheadMap(); +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while(DequeueSpecificEvent(&InputEvent, KEY_DOWN|KEY_UP|KEY_REPEAT) == TRUE) +#else + while(DequeueEvent(&InputEvent) == TRUE) +#endif { if(InputEvent.usEvent == KEY_DOWN || InputEvent.usEvent == KEY_REPEAT) { diff --git a/Utils/MapUtility.cpp b/Utils/MapUtility.cpp index 5a6ced33..08bbd955 100644 --- a/Utils/MapUtility.cpp +++ b/Utils/MapUtility.cpp @@ -101,7 +101,11 @@ UINT32 MapUtilScreenHandle(void) INT32 cnt, iX, iY, iSubX1, iSubY1, iSubX2, iSubY2, iWindowX, iWindowY, iCount; FLOAT dX, dY, dStartX, dStartY; +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while(DequeueSpecificEvent(&InputEvent, KEY_DOWN|KEY_UP) == TRUE) +#else + while(DequeueEvent(&InputEvent) == TRUE) +#endif { if(InputEvent.usParam == ESC) { diff --git a/Utils/Timer Control.cpp b/Utils/Timer Control.cpp index 4405b237..9389b102 100644 --- a/Utils/Timer Control.cpp +++ b/Utils/Timer Control.cpp @@ -14,9 +14,13 @@ #include "worlddef.h" #include "renderworld.h" #include "interface control.h" + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER #include "keymap.h" #endif +#endif + #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif @@ -25,11 +29,13 @@ #include "connect.h" // Base resolution of callback timer -static INT32 BASETIMESLICE = 10; -const INT32 FASTFORWARDTIMESLICE = 1000; -const UINT32 FREQUENCY_CONST = 1000000; -static INT32 MIN_NOTIFY_TIME = 16000; -static INT32 UPDATETIMESLICE = 10000; +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + static INT32 BASETIMESLICE = 10; + const INT32 FASTFORWARDTIMESLICE = 1000; + const UINT32 FREQUENCY_CONST = 1000000; + static INT32 MIN_NOTIFY_TIME = 16000; + static INT32 UPDATETIMESLICE = 10000; +#endif INT32 giClockTimer = -1; INT32 giTimerDiag = 0; @@ -38,19 +44,22 @@ 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; } +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + BOOLEAN gfHispeedClockMode = FALSE; -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}; + 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}; +#endif INT32 giTimerIntervals[ NUMTIMERS ] = { @@ -95,16 +104,19 @@ CUSTOMIZABLE_TIMER_CALLBACK gpCustomizableTimerCallback = NULL; // Clock Callback event ID MMRESULT gTimerID; -TIMECAPS gtc; -HANDLE ghClockThread; -DWORD gdwClockThreadId; -HANDLE ghClockThreadShutdown; +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + TIMECAPS gtc; -HANDLE ghNotifyThread; -DWORD gdwNotifyThreadId; -HANDLE ghNotifyThreadEvent; -HANDLE ghNotifyThreadShutdownComplete; + HANDLE ghClockThread; + DWORD gdwClockThreadId; + HANDLE ghClockThreadShutdown; + + HANDLE ghNotifyThread; + DWORD gdwNotifyThreadId; + HANDLE ghNotifyThreadEvent; + HANDLE ghNotifyThreadShutdownComplete; +#endif // GLOBALS FOR CALLBACK UINT32 gCNT; @@ -129,328 +141,494 @@ 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_LIST; -typedef TIMER_NOTIFY_ITEM_LIST::iterator TIMER_NOTIFY_ITEM_ITERATOR; -static TIMER_NOTIFY_ITEM_LIST glNotifyCallbacks; -static CRITICAL_SECTION gcsNotifyLock; +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + 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_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(); + static bool HasTimerNotifyCallbacks( ); + static void BroadcastTimerNotify(INT32 ); + static BOOLEAN UpdateTimeCounter( INT32 &counter, INT32 &iTimeLeft ); + static BOOLEAN UpdateCounter( INT32 counter, INT32 &iTimeLeft); + static void UpdateTimer(); +#endif 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 ) +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + void CALLBACK TimeProc( UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2 ) { - fInFunction = TRUE; + static BOOLEAN fInFunction = FALSE; + //SOLDIERTYPE *pSoldier; - BOOLEAN timerDone = FALSE; - BOOLEAN tickTime = FALSE; - INT32 iTimeLeft = 0; - - // Use QPC to check if BASETIMESLICE (in ms) has passed - if (IsHiSpeedClockMode()) + if ( !fInFunction ) { - // Only advance time when sufficient time has passed to exceed next time - QueryPerformanceCounter(&gliPerfCount); - if (gliPerfCount.QuadPart > gliPerfCountNext.QuadPart) + fInFunction = TRUE; + + BOOLEAN timerDone = FALSE; + BOOLEAN tickTime = FALSE; + INT32 iTimeLeft = 0; + + // Use QPC to check if BASETIMESLICE (in ms) has passed + if (IsHiSpeedClockMode()) { - INT32 iNext = IsFastForwardMode() ? giFastForwardPeriod : UPDATETIMESLICE; - gliPerfCountNext.QuadPart = gliPerfCount.QuadPart + (iNext * gliPerfFreq.QuadPart) / FREQUENCY_CONST; - iTimeLeft = iNext; - timerDone = IsFastForwardMode(); - tickTime = TRUE; + // Only advance time when sufficient time has passed to exceed next time + QueryPerformanceCounter(&gliPerfCount); + if (gliPerfCount.QuadPart > gliPerfCountNext.QuadPart) + { + INT32 iNext = IsFastForwardMode() ? giFastForwardPeriod : UPDATETIMESLICE; + gliPerfCountNext.QuadPart = gliPerfCount.QuadPart + (iNext * gliPerfFreq.QuadPart) / FREQUENCY_CONST; + 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; } - else - { - // When using millisecond timer, advance time everytime this function is called - tickTime = TRUE; - timerDone = !IsFastForwardMode(); - } - if (tickTime) + } +#else + void CALLBACK TimeProc( UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2 ) + { + static BOOLEAN fInFunction = FALSE; + //SOLDIERTYPE *pSoldier; + + if ( !fInFunction ) { + fInFunction = TRUE; + guiBaseJA2NoPauseClock += BASETIMESLICE; + if ( !gfPauseClock ) { guiBaseJA2Clock += BASETIMESLICE; for ( gCNT = 0; gCNT < NUMTIMERS; gCNT++ ) { - timerDone |= UpdateCounter( gCNT, iTimeLeft ); + UPDATECOUNTER( gCNT ); } // Update some specialized countdown timers... - timerDone |= UpdateTimeCounter( giTimerAirRaidQuote, iTimeLeft ); - timerDone |= UpdateTimeCounter( giTimerAirRaidDiveStarted, iTimeLeft ); - timerDone |= UpdateTimeCounter( giTimerAirRaidUpdate, iTimeLeft ); - timerDone |= UpdateTimeCounter( giTimerTeamTurnUpdate, iTimeLeft ); + UPDATETIMECOUNTER( giTimerAirRaidQuote ); + UPDATETIMECOUNTER( giTimerAirRaidDiveStarted ); + UPDATETIMECOUNTER( giTimerAirRaidUpdate ); + UPDATETIMECOUNTER( giTimerTeamTurnUpdate ); if ( gpCustomizableTimerCallback ) { - timerDone |= UpdateTimeCounter( giTimerCustomizable, iTimeLeft ); + UPDATETIMECOUNTER( giTimerCustomizable ); } -#ifndef BOUNDS_CHECKER + #ifndef BOUNDS_CHECKER - // If mapscreen... - if( guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN ) + // 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++ ) { - // 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 + gPSOLDIER = MercPtrs[ gCNT ]; + UPDATETIMECOUNTER( gPSOLDIER->timeCounters.PortraitFlashCounter ); + UPDATETIMECOUNTER( gPSOLDIER->timeCounters.PanelAnimateCounter ); } + } + else + { + // Set update flags for soldiers + //////////////////////////// + for ( gCNT = 0; gCNT < guiNumMercSlots; gCNT++ ) + { + gPSOLDIER = MercSlots[ gCNT ]; + + if ( gPSOLDIER != NULL ) + { + UPDATETIMECOUNTER( gPSOLDIER->timeCounters.UpdateCounter ); + UPDATETIMECOUNTER( gPSOLDIER->timeCounters.DamageCounter ); + UPDATETIMECOUNTER( gPSOLDIER->timeCounters.ReloadCounter ); + UPDATETIMECOUNTER( gPSOLDIER->timeCounters.FlashSelCounter ); + UPDATETIMECOUNTER( gPSOLDIER->timeCounters.BlinkSelCounter ); + UPDATETIMECOUNTER( gPSOLDIER->timeCounters.PortraitFlashCounter ); + UPDATETIMECOUNTER( gPSOLDIER->timeCounters.AICounter ); + UPDATETIMECOUNTER( gPSOLDIER->timeCounters.FadeCounter ); + UPDATETIMECOUNTER( gPSOLDIER->timeCounters.NextTileCounter ); + UPDATETIMECOUNTER( gPSOLDIER->timeCounters.PanelAnimateCounter ); + #ifdef JA2UB + UPDATETIMECOUNTER( gPSOLDIER->GetupFromJA25StartCounter ); + #endif + } + } + } + #endif + } + + + fInFunction = FALSE; } - - if (timerDone) - SetEvent(ghNotifyThreadEvent); - fInFunction = FALSE; } -} +#endif -static UINT32 MIN_TIMER(UINT32 timer, UINT32 other) -{ - UINT32 value = TIME_MS_TO_US(timer); - return ( value && value < other ? value : other ); -} - -// Returns the smallest time interval for a counter currently in use -UINT32 GetNextCounterDoneTime(void) -{ - QueryPerformanceCounter(&gliPerfCount); - INT32 time = (INT32)(((gliPerfCountNext.QuadPart - gliPerfCount.QuadPart) * FREQUENCY_CONST) / gliPerfFreq.QuadPart); - return (UINT32)((time > 0) ? time : 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 +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + static UINT32 MIN_TIMER(UINT32 timer, UINT32 other) { + UINT32 value = TIME_MS_TO_US(timer); + return ( value && value < other ? value : other ); + } + + // Returns the smallest time interval for a counter currently in use + UINT32 GetNextCounterDoneTime(void) + { + QueryPerformanceCounter(&gliPerfCount); + INT32 time = (INT32)(((gliPerfCountNext.QuadPart - gliPerfCount.QuadPart) * FREQUENCY_CONST) / gliPerfFreq.QuadPart); + return (UINT32)((time > 0) ? time : 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()) + Sleep( TIME_US_TO_MS( GetNextCounterDoneTime() ) ); + } + } + __except( EXCEPTION_EXECUTE_HANDLER ) + { + // Unhandled exception just exit + } + return 0L; + } + + DWORD WINAPI JA2NotifyThread( LPVOID lpParam ) + { + HANDLE waitHandles[] = {ghClockThreadShutdown, ghNotifyThreadEvent}; 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()) - Sleep( TIME_US_TO_MS( GetNextCounterDoneTime() ) ); - } - } - __except( EXCEPTION_EXECUTE_HANDLER ) - { - // Unhandled exception just exit - } - 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()) + 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) { - BroadcastTimerNotify(-1); + if (HasTimerNotifyCallbacks()) + { + BroadcastTimerNotify(-1); + } + } + else + { + // unexpected failure + } + } + SetEvent(ghNotifyThreadShutdownComplete); + return 0L; + } +#endif + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + 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; + } +#else + BOOLEAN InitializeJA2Clock(void) + { + + #ifdef CALLBACKTIMER + + + MMRESULT mmResult; + TIMECAPS tc; + INT32 cnt; + + // Init timer delays + for ( cnt = 0; cnt < NUMTIMERS; cnt++ ) + { + giTimerCounters[ cnt ] = giTimerIntervals[ cnt ]; + } + + + // First get timer resolutions + mmResult = timeGetDevCaps( &tc, sizeof( tc ) ); + + if ( mmResult != TIMERR_NOERROR ) + { + 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 + gTimerID = timeSetEvent( BASETIMESLICE, BASETIMESLICE, TimeProc, (DWORD)0, TIME_PERIODIC ); + + if ( !gTimerID ) + { + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Could not create timer callback"); + } + + #endif + + return TRUE; + } +#endif + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + 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 { - // unexpected failure + // Make sure we kill the timer + #ifdef CALLBACKTIMER + timeKillEvent( gTimerID ); + #endif } - } - 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 ]; + timeEndPeriod(gtc.wPeriodMin); } - - - // 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 +#else + void ShutdownJA2Clock(void) { // Make sure we kill the timer -#ifdef CALLBACKTIMER + #ifdef CALLBACKTIMER + timeKillEvent( gTimerID ); + + #endif + + } #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 ) +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + UINT32 InitializeJA2TimerCallback( UINT32 uiDelay, LPTIMECALLBACK TimerProc, UINT32 uiUser ) { - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Could not get timer properties"); + MMRESULT mmResult; + MMRESULT TimerID; + + + // First get timer resolutions + mmResult = timeGetDevCaps( >c, sizeof( gtc ) ); + + if ( mmResult != TIMERR_NOERROR ) + { + 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 ) + { + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Could not create timer callback"); + } + + return ( (UINT32)TimerID ); } - - // 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 ) +#else + UINT32 InitializeJA2TimerCallback( UINT32 uiDelay, LPTIMECALLBACK TimerProc, UINT32 uiUser ) { - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Could not create timer callback"); + MMRESULT mmResult; + TIMECAPS tc; + MMRESULT TimerID; + + + // First get timer resolutions + mmResult = timeGetDevCaps( &tc, sizeof( tc ) ); + + if ( mmResult != TIMERR_NOERROR ) + { + 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 ) + { + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Could not create timer callback"); + } + + return ( (UINT32)TimerID ); } - return ( (UINT32)TimerID ); -} +#endif void RemoveJA2TimerCallback( UINT32 uiTimer ) @@ -550,237 +728,241 @@ 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() -{ - // WANNE: In a multiplayer game it is not allowed for the "pure" client to do fast forward - // Only the server is allowed to do, because the AI is generated on the server - if (is_networked) +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + void SetFastForwardPeriod(DOUBLE value) { - if (!is_server) // It is not allowed when we are not the server - return false; - else if (gTacticalStatus.ubCurrentTeam != 1) // It is not allowed, when it is not the enemy turn! - return false; + giFastForwardPeriod = (UINT32)(value); + if (giFastForwardPeriod <= 1) + giFastForwardPeriod = 1; } - return giFastForwardKey && IsKeyPressed(giFastForwardKey); -} + void SetFastForwardKey(INT32 key) + { + giFastForwardKey = key; + } -void SetFastForwardMode(BOOLEAN enable) -{ - giFastForwardMode = enable; - UpdateTimer(); -} + BOOLEAN IsFastForwardKeyPressed() + { + // WANNE: In a multiplayer game it is not allowed for the "pure" client to do fast forward + // Only the server is allowed to do, because the AI is generated on the server + if (is_networked) + { + if (!is_server) // It is not allowed when we are not the server + return false; + else if (gTacticalStatus.ubCurrentTeam != 1) // It is not allowed, when it is not the enemy turn! + return false; + } -BOOLEAN IsFastForwardMode() -{ - return giFastForwardMode || IsFastForwardKeyPressed(); -} + return giFastForwardKey && IsKeyPressed(giFastForwardKey); + } -LONGLONG GetJA2Microseconds() -{ - return gliPerfCount.QuadPart * FREQUENCY_CONST / gliPerfFreq.QuadPart; -} + void SetFastForwardMode(BOOLEAN enable) + { + giFastForwardMode = enable; + UpdateTimer(); + } -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; + BOOLEAN IsFastForwardMode() + { + return 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); } } - if (addItem) + + static bool HasTimerNotifyCallbacks( ) { - TIMER_NOTIFY_ITEM item; - item.callback = callback; - item.state = state; - glNotifyCallbacks.push_back(item); + return !glNotifyCallbacks.empty(); } - LeaveCriticalSection(&gcsNotifyLock); -} -void RemoveTimerNotifyCallback( TIMER_NOTIFY_CALLBACK callback, PTR state ) -{ - EnterCriticalSection(&gcsNotifyLock); - for ( TIMER_NOTIFY_ITEM_ITERATOR itr = glNotifyCallbacks.begin(); itr != glNotifyCallbacks.end(); ) + + // 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) { - if ( callback == (*itr).callback && state == (*itr).state ) - itr = glNotifyCallbacks.erase(itr); - else - ++itr; + try + { + for (TIMER_NOTIFY_ITEM_ITERATOR itr = glNotifyCallbacks.begin(); itr != glNotifyCallbacks.end(); ++itr) + { + if ( NULL != (*itr).callback) + (*itr).callback( timer, (*itr).state ); + } + } + catch (...) {} } - 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) ) + static void BroadcastTimerNotify(INT32 timer) { - 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 (...) {} -} -static void BroadcastTimerNotify(INT32 timer) -{ - EnterCriticalSection(&gcsNotifyLock); - __try - { - __try { InnerTimerNotify(timer); } - __except( EXCEPTION_EXECUTE_HANDLER ) - { /* Not sure. exit? */ } - } - __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) + EnterCriticalSection(&gcsNotifyLock); + __try { - guiTimeSlice = uiTimeSlice; - if (gTimerID != 0) timeKillEvent(gTimerID); - gTimerID = timeSetEvent( uiTimeSlice, uiTimeSlice, TimeProc, (DWORD)0, TIME_PERIODIC ); - if ( !gTimerID ) + __try { InnerTimerNotify(timer); } + __except( EXCEPTION_EXECUTE_HANDLER ) + { /* Not sure. exit? */ } + } + __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) { - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Could not create timer callback"); + guiTimeSlice = uiTimeSlice; + if (gTimerID != 0) timeKillEvent(gTimerID); + gTimerID = timeSetEvent( uiTimeSlice, uiTimeSlice, TimeProc, (DWORD)0, TIME_PERIODIC ); + if ( !gTimerID ) + { + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Could not create timer callback"); + } } } } -} +#endif diff --git a/Utils/Timer Control.h b/Utils/Timer Control.h index 2cd89303..64c7b63a 100644 --- a/Utils/Timer Control.h +++ b/Utils/Timer Control.h @@ -54,6 +54,13 @@ enum NUMTIMERS }; +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER +#else + // Base resultion of callback timer + #define BASETIMESLICE 10 +#endif + + // TIMER INTERVALS extern INT32 giTimerIntervals[ NUMTIMERS ]; // TIMER COUNTERS @@ -70,7 +77,10 @@ BOOLEAN InitializeJA2Clock( void ); void ShutdownJA2Clock( void ); #define GetJA2Clock() guiBaseJA2Clock -#define GetJA2NoPauseClock() guiBaseJA2NoPauseClock + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + #define GetJA2NoPauseClock() guiBaseJA2NoPauseClock +#endif UINT32 GetPauseJA2Clock( ); @@ -82,49 +92,89 @@ void PauseTime( BOOLEAN fPaused ); void SetCustomizableTimerCallbackAndDelay( INT32 iDelay, CUSTOMIZABLE_TIMER_CALLBACK pCallback, BOOLEAN fReplace ); void CheckCustomizableTimer( void ); -void SetFastForwardPeriod(DOUBLE value); -void SetFastForwardKey(INT32 key); -BOOLEAN IsFastForwardKeyPressed(); -void SetFastForwardMode(BOOLEAN enable); -BOOLEAN IsFastForwardMode(); -INT32 GetFastForwardLoopCount(); -void SetFastForwardLoopCount(INT32 value); +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + void SetFastForwardPeriod(DOUBLE value); + void SetFastForwardKey(INT32 key); + BOOLEAN IsFastForwardKeyPressed(); + void SetFastForwardMode(BOOLEAN enable); + BOOLEAN IsFastForwardMode(); + INT32 GetFastForwardLoopCount(); + void SetFastForwardLoopCount(INT32 value); -void SetNotifyFrequencyKey(INT32 value); -void SetClockSpeedPercent(FLOAT value); + void SetNotifyFrequencyKey(INT32 value); + void SetClockSpeedPercent(FLOAT value); -BOOLEAN IsTimerActive(); -BOOLEAN IsJA2TimerThread(); + BOOLEAN IsTimerActive(); + BOOLEAN IsJA2TimerThread(); -BOOLEAN IsHiSpeedClockMode(); -void SetHiSpeedClockMode(BOOLEAN enable); + BOOLEAN IsHiSpeedClockMode(); + void SetHiSpeedClockMode(BOOLEAN enable); +#endif //Don't modify this value extern UINT32 guiBaseJA2Clock; extern UINT32 guiBaseJA2NoPauseClock; extern CUSTOMIZABLE_TIMER_CALLBACK gpCustomizableTimerCallback; -typedef void (*TIMER_NOTIFY_CALLBACK) ( INT32 timer, PTR state ); -void AddTimerNotifyCallback( TIMER_NOTIFY_CALLBACK callback, PTR state ); -void RemoveTimerNotifyCallback( TIMER_NOTIFY_CALLBACK callback, PTR state ); -void ClearTimerNotifyCallbacks(); + #ifdef USE_HIGHSPEED_GAMELOOP_TIMER + typedef void (*TIMER_NOTIFY_CALLBACK) ( INT32 timer, PTR state ); + void AddTimerNotifyCallback( TIMER_NOTIFY_CALLBACK callback, PTR state ); + void RemoveTimerNotifyCallback( TIMER_NOTIFY_CALLBACK callback, PTR state ); + void ClearTimerNotifyCallbacks(); -BOOLEAN UpdateCounter(INT32 iTimer); -void ResetCounter(INT32 iTimer); -BOOLEAN CounterDone(INT32 iTimer); -void ResetTimerCounter(INT32 &timer, INT32 value); -BOOLEAN TimeCounterDone(INT32 timer); -void ZeroTimeCounter(INT32& timer); + BOOLEAN UpdateCounter(INT32 iTimer); + void ResetCounter(INT32 iTimer); + BOOLEAN CounterDone(INT32 iTimer); + void ResetTimerCounter(INT32 &timer, INT32 value); + BOOLEAN TimeCounterDone(INT32 timer); + void ZeroTimeCounter(INT32& timer); -#define UPDATECOUNTER( c ) UpdateCounter(c) -#define RESETCOUNTER( c ) ResetCounter(c) -#define COUNTERDONE( c ) CounterDone(c) -#define UPDATETIMECOUNTER( c ) UpdateTimeCounter(c) -#define RESETTIMECOUNTER( c, d ) ResetTimerCounter(c, d) -#define TIMECOUNTERDONE(c, d) TimeCounterDone(c) -#define SYNCTIMECOUNTER( ) -#define ZEROTIMECOUNTER(c) ZeroTimeCounter(c) + #define UPDATECOUNTER( c ) UpdateCounter(c) + #define RESETCOUNTER( c ) ResetCounter(c) + #define COUNTERDONE( c ) CounterDone(c) + #define UPDATETIMECOUNTER( c ) UpdateTimeCounter(c) + #define RESETTIMECOUNTER( c, d ) ResetTimerCounter(c, d) + #define TIMECOUNTERDONE(c, d) TimeCounterDone(c) + #define SYNCTIMECOUNTER( ) + #define ZEROTIMECOUNTER(c) ZeroTimeCounter(c) +#else + + // MACROS + // CHeck if new counter < 0 | set to 0 | Decrement + + #ifdef CALLBACKTIMER + + #define UPDATECOUNTER( c ) ( ( giTimerCounters[ c ] - BASETIMESLICE ) < 0 ) ? ( giTimerCounters[ c ] = 0 ) : ( giTimerCounters[ c ] -= BASETIMESLICE ) + #define RESETCOUNTER( c ) ( giTimerCounters[ c ] = giTimerIntervals[ c ] ) + #define COUNTERDONE( c ) ( giTimerCounters[ c ] == 0 ) ? TRUE : FALSE + + #define UPDATETIMECOUNTER( c ) ( ( c - BASETIMESLICE ) < 0 ) ? ( c = 0 ) : ( c -= BASETIMESLICE ) + #define RESETTIMECOUNTER( c, d ) ( c = d ) + + #ifdef BOUNDS_CHECKER + #define TIMECOUNTERDONE( c, d ) ( TRUE ) + #else + #define TIMECOUNTERDONE( c, d ) ( c == 0 ) ? TRUE : FALSE + #endif + + #define SYNCTIMECOUNTER( ) + #define ZEROTIMECOUNTER( c ) ( c = 0 ) + + #else + + #define UPDATECOUNTER( c ) + #define RESETCOUNTER( c ) ( giTimerCounters[ c ] = giClockTimer ) + #define COUNTERDONE( c ) ( ( ( giClockTimer = GetJA2Clock() ) - giTimerCounters[ c ] ) > giTimerIntervals[ c ] ) ? TRUE : FALSE + + #define UPDATETIMECOUNTER( c ) + #define RESETTIMECOUNTER( c, d ) ( c = giClockTimer ) + #define TIMECOUNTERDONE( c, d ) ( giClockTimer - c > d ) ? TRUE : FALSE + #define SYNCTIMECOUNTER( ) ( giClockTimer = GetJA2Clock() ) + + #endif + +#endif void SetTileAnimCounter( INT32 iTime ); #endif \ No newline at end of file diff --git a/Utils/Utils All.h b/Utils/Utils All.h index a8ed4673..a5dc1640 100644 --- a/Utils/Utils All.h +++ b/Utils/Utils All.h @@ -103,7 +103,11 @@ #include "vobject.h" #include "overhead types.h" #include "tactical save.h" -#include "KeyMap.h" + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + #include "KeyMap.h" +#endif + //#include //#include //#include diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 75139409..3949cc18 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -5110,7 +5110,11 @@ STR16 zOptionsToggleText[] = L"Quiet Training", // Madd: mercs don't say quotes while training // TODO.Translate L"Quiet Repairing", // Madd: mercs don't say quotes while repairing //TODO.Translate L"Quiet Doctoring", // Madd: mercs don't say quotes while doctoring //TODO.Translate + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER L"自动加速敌军回合", // Automatic fast forward through AI turns +#endif + L"Allow Zombies", // TODO.Translate L"--作弊模式选项--", // TOPTION_CHEAT_MODE_OPTIONS_HEADER, L"强制 Bobby Ray 送货", // force all pending Bobby Ray shipments @@ -5219,7 +5223,11 @@ STR16 zOptionsScreenHelpText[] = L"When ON, mercs will not report progress during training.", //TODO.Translate L"When ON, mercs will not report progress during repairing.", // TODO.Translate L"When ON, mercs will not report progress during doctoring.", // TODO.Translate + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER L"打开时,敌军回合将被大幅加速。", +#endif + L"When ON, zombies will span. Be aware!", // allow zombies // TODO.Translate L"(text not rendered)TOPTION_CHEAT_MODE_OPTIONS_HEADER", L"强制 Bobby Ray 出货", diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index c0973e37..62dafd81 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -5109,7 +5109,11 @@ STR16 zOptionsToggleText[] = L"Quiet Training", // Madd: mercs don't say quotes while training // TODO.Translate L"Quiet Repairing", // Madd: mercs don't say quotes while repairing //TODO.Translate L"Quiet Doctoring", // Madd: mercs don't say quotes while doctoring //TODO.Translate + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER L"Auto Fast Forward AI Turns", // Automatic fast forward through AI turns // TODO.Translate +#endif + L"Allow Zombies", // TODO.Translate L"--Cheat Mode Options--", // TOPTION_CHEAT_MODE_OPTIONS_HEADER, L"Force Bobby Ray shipments", // force all pending Bobby Ray shipments @@ -5218,7 +5222,11 @@ STR16 zOptionsScreenHelpText[] = L"When ON, mercs will not report progress during training.", //TODO.Translate L"When ON, mercs will not report progress during repairing.", // TODO.Translate L"When ON, mercs will not report progress during doctoring.", // TODO.Translate + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER L"When ON, AI turns will be much faster.", // TODO.Translate +#endif + L"When ON, zombies will span. Be aware!", // allow zombies // TODO.Translate L"(text not rendered)TOPTION_CHEAT_MODE_OPTIONS_HEADER", L"Force all pending Bobby Ray shipments", diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index c2c79ccc..ac63fe7a 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -5108,7 +5108,11 @@ STR16 zOptionsToggleText[] = L"Quiet Training", // Madd: mercs don't say quotes while training L"Quiet Repairing", // Madd: mercs don't say quotes while repairing L"Quiet Doctoring", // Madd: mercs don't say quotes while doctoring + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER L"Auto Fast Forward AI Turns", // Automatic fast forward through AI turns +#endif + L"Allow Zombies", // Flugente Zombies 1.0 L"--Cheat Mode Options--", // TOPTION_CHEAT_MODE_OPTIONS_HEADER, L"Force Bobby Ray shipments", // force all pending Bobby Ray shipments @@ -5217,7 +5221,11 @@ STR16 zOptionsScreenHelpText[] = L"When ON, mercs will not report progress during training.", L"When ON, mercs will not report progress during repairing.", L"When ON, mercs will not report progress during doctoring.", + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER L"When ON, AI turns will be much faster.", +#endif + L"When ON, zombies will spawn. Be aware!", // allow zombies L"(text not rendered)TOPTION_CHEAT_MODE_OPTIONS_HEADER", L"Force all pending Bobby Ray shipments", diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 6f11ae6d..a96fc380 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -5099,7 +5099,11 @@ STR16 zOptionsToggleText[] = L"Quiet Training", // Madd: mercs don't say quotes while training // TODO.Translate L"Quiet Repairing", // Madd: mercs don't say quotes while repairing //TODO.Translate L"Quiet Doctoring", // Madd: mercs don't say quotes while doctoring //TODO.Translate + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER L"Auto Fast Forward AI Turns", // Automatic fast forward through AI turns // TODO.Translate +#endif + L"Allow Zombies", // Flugente Zombies 1.0 L"--Cheat Mode Options--", // TOPTION_CHEAT_MODE_OPTIONS_HEADER, L"Forcer envois Bobby Ray", // force all pending Bobby Ray shipments @@ -5208,7 +5212,11 @@ STR16 zOptionsScreenHelpText[] = L"When ON, mercs will not report progress during training.", L"When ON, mercs will not report progress during repairing.", // TODO.Translate L"When ON, mercs will not report progress during doctoring.", // TODO.Translate + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER L"When ON, AI turns will be much faster.", // TODO.Translate +#endif + L"When ON, zombies will span. Be aware!", // allow zombies // TODO.Translate L"(text not rendered)TOPTION_CHEAT_MODE_OPTIONS_HEADER", L"Forcer tous les envois en attente de Bobby Ray", diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index 58a10556..69a8a739 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -4957,7 +4957,11 @@ STR16 zOptionsToggleText[] = L"Stummes Trainieren", // Madd: mercs don't say quotes while training L"Stummes Reparieren", // Madd: mercs don't say quotes while repairing L"Stumme Behandlung", // Madd: mercs don't say quotes while doctoring + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER L"Autom. schnelle Gegner-Züge", // Automatic fast forward through AI turns +#endif + L"Allow Zombies", // Flugente Zombies 1.0 L"--Cheat Mode Options--", // TOPTION_CHEAT_MODE_OPTIONS_HEADER, L"Erzwinge BR Lieferung", // force all pending Bobby Ray shipments @@ -5066,7 +5070,11 @@ STR16 zOptionsScreenHelpText[] = L"Wenn diese Funktion aktiviert ist, werden die Söldner über ihren Fortschritt während des Trainings nicht mehr berichten.", L"When ON, mercs will not report progress during repairing.", // TODO.Translate L"When ON, mercs will not report progress during doctoring.", // TODO.Translate + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER L"Wenn diese Funktion aktiviert ist, werden gegnerische Züge schneller durchgeführt.", +#endif + L"When ON, zombies will span. Be aware!", // allow zombies // TODO.Translate L"(text not rendered)TOPTION_CHEAT_MODE_OPTIONS_HEADER", L"Force all pending Bobby Ray shipments", diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index 2976ff28..da02cf1b 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -5094,7 +5094,11 @@ STR16 zOptionsToggleText[] = L"Quiet Training", // Madd: mercs don't say quotes while training // TODO.Translate L"Quiet Repairing", // Madd: mercs don't say quotes while repairing //TODO.Translate L"Quiet Doctoring", // Madd: mercs don't say quotes while doctoring //TODO.Translate + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER L"Auto Fast Forward AI Turns", // Automatic fast forward through AI turns // TODO.Translate +#endif + L"Allow Zombies", // Flugente Zombies 1.0 L"--Cheat Mode Options--", // TOPTION_CHEAT_MODE_OPTIONS_HEADER, L"Force Bobby Ray shipments", // force all pending Bobby Ray shipments @@ -5203,7 +5207,11 @@ STR16 zOptionsScreenHelpText[] = L"When ON, mercs will not report progress during training.", L"When ON, mercs will not report progress during repairing.", // TODO.Translate L"When ON, mercs will not report progress during doctoring.", // TODO.Translate + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER L"When ON, AI turns will be much faster.", // TODO.Translate +#endif + L"When ON, zombies will span. Be aware!", // allow zombies // TODO.Translate L"(text not rendered)TOPTION_CHEAT_MODE_OPTIONS_HEADER", L"Force all pending Bobby Ray shipments", diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index 6cd735d3..336b67d5 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -5106,7 +5106,11 @@ STR16 zOptionsToggleText[] = L"Quiet Training", // Madd: mercs don't say quotes while training // TODO.Translate L"Quiet Repairing", // Madd: mercs don't say quotes while repairing //TODO.Translate L"Quiet Doctoring", // Madd: mercs don't say quotes while doctoring //TODO.Translate + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER L"Auto Fast Forward AI Turns", // Automatic fast forward through AI turns // TODO.Translate +#endif + L"Allow Zombies", // Flugente Zombies 1.0 L"--Cheat Mode Options--", // TOPTION_CHEAT_MODE_OPTIONS_HEADER, L"Force Bobby Ray shipments", // force all pending Bobby Ray shipments @@ -5215,7 +5219,11 @@ STR16 zOptionsScreenHelpText[] = L"When ON, mercs will not report progress during training.", L"When ON, mercs will not report progress during repairing.", // TODO.Translate L"When ON, mercs will not report progress during doctoring.", // TODO.Translate + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER L"When ON, AI turns will be much faster.", // TODO.Translate +#endif + L"When ON, zombies will span. Be aware!", // allow zombies // TODO.Translate L"(text not rendered)TOPTION_CHEAT_MODE_OPTIONS_HEADER", L"WymuŚ wszystkie oczekiwane dostawy od Bobby Ray's.", diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 544673a7..6779f607 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -5089,7 +5089,11 @@ STR16 zOptionsToggleText[] = L"Quiet Training", // Madd: mercs don't say quotes while training // TODO.Translate L"Quiet Repairing", // Madd: mercs don't say quotes while repairing //TODO.Translate L"Quiet Doctoring", // Madd: mercs don't say quotes while doctoring //TODO.Translate + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER L"Auto Fast Forward AI Turns", // Automatic fast forward through AI turns // TODO.Translate +#endif + L"Allow Zombies", // Flugente Zombies 1.0 L"--Читерские настройки--", // TOPTION_CHEAT_MODE_OPTIONS_HEADER, L"Ускорить доставку Бобби Рэя", // force all pending Bobby Ray shipments @@ -5198,7 +5202,11 @@ STR16 zOptionsScreenHelpText[] = L"When ON, mercs will not report progress during training.", L"When ON, mercs will not report progress during repairing.", // TODO.Translate L"When ON, mercs will not report progress during doctoring.", // TODO.Translate + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER L"When ON, AI turns will be much faster.", // TODO.Translate +#endif + L"When ON, zombies will span. Be aware!", // allow zombies // TODO.Translate L"(text not rendered)TOPTION_CHEAT_MODE_OPTIONS_HEADER", L"Выберите этот пункт чтобы груз Бобби Рэя прибыл немедленно.", diff --git a/Utils/_TaiwaneseText.cpp b/Utils/_TaiwaneseText.cpp index 6a33facb..ec73b153 100644 --- a/Utils/_TaiwaneseText.cpp +++ b/Utils/_TaiwaneseText.cpp @@ -5110,7 +5110,11 @@ STR16 zOptionsToggleText[] = L"Quiet Training", // Madd: mercs don't say quotes while training // TODO.Translate L"Quiet Repairing", // Madd: mercs don't say quotes while repairing //TODO.Translate L"Quiet Doctoring", // Madd: mercs don't say quotes while doctoring //TODO.Translate + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER L"Auto Fast Forward AI Turns", // Automatic fast forward through AI turns // TODO.Translate +#endif + L"Allow Zombies", // Flugente Zombies 1.0 L"--Cheat Mode Options--", // TOPTION_CHEAT_MODE_OPTIONS_HEADER, L"Force Bobby Ray shipments", // force all pending Bobby Ray shipments @@ -5219,7 +5223,11 @@ STR16 zOptionsScreenHelpText[] = L"When ON, mercs will not report progress during training.", L"When ON, mercs will not report progress during repairing.", // TODO.Translate L"When ON, mercs will not report progress during doctoring.", // TODO.Translate + +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER L"When ON, AI turns will be much faster.", // TODO.Translate +#endif + L"When ON, zombies will span. Be aware!", // allow zombies // TODO.Translate L"(text not rendered)TOPTION_CHEAT_MODE_OPTIONS_HEADER", L"Force all pending Bobby Ray shipments", diff --git a/aniviewscreen.cpp b/aniviewscreen.cpp index 55b19ef6..983956ce 100644 --- a/aniviewscreen.cpp +++ b/aniviewscreen.cpp @@ -185,7 +185,11 @@ UINT32 AniEditScreenHandle(void) } +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER if (DequeueSpecificEvent(&InputEvent, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + if (DequeueEvent(&InputEvent) == TRUE) +#endif { if ((InputEvent.usEvent == KEY_DOWN)&&(InputEvent.usParam == ESC)) { diff --git a/builddefines.h b/builddefines.h index 6f72b812..a8ccd5c5 100644 --- a/builddefines.h +++ b/builddefines.h @@ -3,6 +3,11 @@ #include "Language Defines.h" +// WANNE: Enable this define, to build the gameloop with the highspeed timer. To use the highspeed timer, you also have to set the HIGHSPEED_TIMER = TRUE in ja2.ini +// CAUTION: A lot of games reported, when the exe is compiled with the highspeed timer on, the game runs very slowly in strategy map screen when doing repair, .. +// This is the reason, why I made a compilation define, where we can turn on/off the highspeed timer. +//#define USE_HIGHSPEED_GAMELOOP_TIMER + // ----------------------------- // ***************************** // WANNE: Enable those 2 defines, if you want to build UB-Version!! diff --git a/gameloop.cpp b/gameloop.cpp index b9bf2ffc..8adfbe4c 100644 --- a/gameloop.cpp +++ b/gameloop.cpp @@ -148,11 +148,12 @@ BOOLEAN InitializeGame(void) InitButtonSystem(); InitCursors( ); +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER SetFastForwardPeriod(gGameExternalOptions.iFastForwardPeriod); SetFastForwardKey(gGameExternalOptions.iFastForwardKey); SetNotifyFrequencyKey(gGameExternalOptions.iNotifyFrequency); SetClockSpeedPercent(gGameExternalOptions.fClockSpeedPercent); - +#endif // Init Fonts if ( !InitializeFonts( ) ) @@ -599,19 +600,21 @@ void NextLoopCheckForEnoughFreeHardDriveSpace() } -// Called by any game loop after all known events were handled -void HandleDefaultEvent(InputAtom *Event) -{ - const int MouseButtonEvents = LEFT_BUTTON_REPEAT|RIGHT_BUTTON_REPEAT| - LEFT_BUTTON_DOWN|LEFT_BUTTON_UP|MIDDLE_BUTTON_UP|X1_BUTTON_UP|X2_BUTTON_UP| - RIGHT_BUTTON_DOWN|RIGHT_BUTTON_UP|MIDDLE_BUTTON_DOWN|X1_BUTTON_DOWN|X2_BUTTON_DOWN| - MOUSE_WHEEL_UP|MOUSE_WHEEL_DOWN; - - if (Event != NULL && Event->usEvent & MouseButtonEvents) +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + // Called by any game loop after all known events were handled + void HandleDefaultEvent(InputAtom *Event) { - POINT MousePos; - GetCursorPos(&MousePos); - ScreenToClient(ghWindow, &MousePos); // In window coords! - MouseSystemHook(Event->usEvent, (UINT16)MousePos.x ,(UINT16)MousePos.y ,_LeftButtonDown, _RightButtonDown); + const int MouseButtonEvents = LEFT_BUTTON_REPEAT|RIGHT_BUTTON_REPEAT| + LEFT_BUTTON_DOWN|LEFT_BUTTON_UP|MIDDLE_BUTTON_UP|X1_BUTTON_UP|X2_BUTTON_UP| + RIGHT_BUTTON_DOWN|RIGHT_BUTTON_UP|MIDDLE_BUTTON_DOWN|X1_BUTTON_DOWN|X2_BUTTON_DOWN| + MOUSE_WHEEL_UP|MOUSE_WHEEL_DOWN; + + if (Event != NULL && Event->usEvent & MouseButtonEvents) + { + POINT MousePos; + GetCursorPos(&MousePos); + ScreenToClient(ghWindow, &MousePos); // In window coords! + MouseSystemHook(Event->usEvent, (UINT16)MousePos.x ,(UINT16)MousePos.y ,_LeftButtonDown, _RightButtonDown); + } } -} +#endif diff --git a/gameloop.h b/gameloop.h index e9ccfbc2..6c5d2357 100644 --- a/gameloop.h +++ b/gameloop.h @@ -18,7 +18,9 @@ void HandleShortCutExitState( void ); void SetPendingNewScreen( UINT32 uiNewScreen ); -struct InputAtom; -void HandleDefaultEvent(InputAtom *Event); +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER + struct InputAtom; + void HandleDefaultEvent(InputAtom *Event); +#endif #endif diff --git a/jascreens.cpp b/jascreens.cpp index 5639d63e..084702ff 100644 --- a/jascreens.cpp +++ b/jascreens.cpp @@ -321,7 +321,11 @@ UINT32 ErrorScreenHandle(void) EndFrameBufferRender( ); // Check for esc +#ifdef USE_HIGHSPEED_GAMELOOP_TIMER while (DequeueSpecificEvent(&InputEvent, KEY_DOWN|KEY_UP|KEY_REPEAT)) +#else + while (DequeueEvent(&InputEvent) == TRUE) +#endif { if( InputEvent.usEvent == KEY_DOWN ) {