diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7ede5128b..189ca980c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -877,6 +877,7 @@ set (PCH_SOURCES hu_scores.cpp i_module.cpp i_net.cpp + i_time.cpp info.cpp keysections.cpp lumpconfigfile.cpp diff --git a/src/c_bind.cpp b/src/c_bind.cpp index 8fb29de87..83e5e1820 100644 --- a/src/c_bind.cpp +++ b/src/c_bind.cpp @@ -47,7 +47,7 @@ #include "templates.h" #include "dobject.h" #include "vm.h" -#include "d_main.h" +#include "i_time.h" #include #include diff --git a/src/c_console.cpp b/src/c_console.cpp index 4d8d64dd8..c3ab76903 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -69,7 +69,7 @@ #include "c_consolebuffer.h" #include "g_levellocals.h" #include "vm.h" -#include "d_main.h" +#include "i_time.h" FString FStringFormat(VM_ARGS); // extern from thingdef_data.cpp diff --git a/src/d_main.cpp b/src/d_main.cpp index 21383118d..7c426375a 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -51,6 +51,7 @@ #include "doomerrors.h" +#include "i_time.h" #include "d_gui.h" #include "m_random.h" #include "doomdef.h" @@ -117,8 +118,6 @@ #include "vm.h" #include "types.h" #include "r_data/r_vanillatrans.h" -#include -#include EXTERN_CVAR(Bool, hud_althud) void DrawHUD(); @@ -1082,127 +1081,6 @@ void D_DoomLoop () } } -//========================================================================== -// -// Tick time functions -// -//========================================================================== - -static unsigned int FirstFrameStartTime; -static unsigned int CurrentFrameStartTime; -static unsigned int FreezeTime; - -static uint32_t performanceGetTime() -{ - using namespace std::chrono; - return (uint32_t)duration_cast(steady_clock::now().time_since_epoch()).count(); -} - -void I_SetFrameTime() -{ - // Must only be called once per frame/swapbuffers. - // - // Caches all timing information for the current rendered frame so that any - // calls to I_FPSTime, I_MSTime, I_GetTime or I_GetTimeFrac will return - // the same time. - - if (FreezeTime == 0) - { - CurrentFrameStartTime = performanceGetTime(); - if (FirstFrameStartTime == 0) - FirstFrameStartTime = CurrentFrameStartTime; - } -} - -void I_WaitVBL(int count) -{ - // I_WaitVBL is never used to actually synchronize to the vertical blank. - // Instead, it's used for delay purposes. Doom used a 70 Hz display mode, - // so that's what we use to determine how long to wait for. - - std::this_thread::sleep_for(std::chrono::milliseconds(1000 * count / 70)); - I_SetFrameTime(); -} - -int I_WaitForTic(int prevtic) -{ - // Waits until the current tic is greater than prevtic. Time must not be frozen. - - int time; - assert(TicFrozen == 0); - while ((time = I_GetTime()) <= prevtic) - { - // The minimum amount of time a thread can sleep is controlled by timeBeginPeriod. - // We set this to 1 ms in DoMain. - int sleepTime = prevtic - time; - if (sleepTime > 2) - std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime - 2)); - - I_SetFrameTime(); - } - - return time; -} - -unsigned int I_FPSTime() -{ - if (FreezeTime == 0) - return CurrentFrameStartTime; - else - return performanceGetTime(); -} - -unsigned int I_MSTime() -{ - if (FreezeTime == 0) - { - return CurrentFrameStartTime - FirstFrameStartTime; - } - else - { - if (FirstFrameStartTime == 0) - { - FirstFrameStartTime = performanceGetTime(); - return 0; - } - else - { - return performanceGetTime() - FirstFrameStartTime; - } - } -} - -int I_GetTime() -{ - return (CurrentFrameStartTime - FirstFrameStartTime) * TICRATE / 1000 + 1; -} - -double I_GetTimeFrac(uint32_t *ms) -{ - unsigned int currentTic = (CurrentFrameStartTime - FirstFrameStartTime) * TICRATE / 1000; - unsigned int ticStartTime = FirstFrameStartTime + currentTic * 1000 / TICRATE; - unsigned int ticNextTime = FirstFrameStartTime + (currentTic + 1) * 1000 / TICRATE; - - if (ms) - *ms = currentTic + 1; - - return (CurrentFrameStartTime - ticStartTime) / (double)(ticNextTime - ticStartTime); -} - -void I_FreezeTime(bool frozen) -{ - if (frozen) - { - FreezeTime = performanceGetTime(); - } - else - { - FirstFrameStartTime += performanceGetTime() - FreezeTime; - FreezeTime = 0; - I_SetFrameTime(); - } -} - //========================================================================== // // D_PageTicker diff --git a/src/d_main.h b/src/d_main.h index 73690cc05..5addc5eb4 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -162,25 +162,4 @@ public: }; -// Called by D_DoomLoop, sets the time for the current frame -void I_SetFrameTime(); - -// Called by D_DoomLoop, returns current time in tics. -int I_GetTime(); - -double I_GetTimeFrac(uint32_t *ms); - -// like I_GetTime, except it waits for a new tic before returning -int I_WaitForTic(int); - -// Freezes tic counting temporarily. While frozen, calls to I_GetTime() -// will always return the same value. This does not affect I_MSTime(). -// You must also not call I_WaitForTic() while freezing time, since the -// tic will never arrive (unless it's the current one). -void I_FreezeTime(bool frozen); - -// [RH] Returns millisecond-accurate time -unsigned int I_MSTime(); -unsigned int I_FPSTime(); - #endif diff --git a/src/d_net.cpp b/src/d_net.cpp index 42f4d425a..12de17c9e 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -68,7 +68,7 @@ #include "intermission/intermission.h" #include "g_levellocals.h" #include "events.h" -#include "d_main.h" +#include "i_time.h" EXTERN_CVAR (Int, disableautosave) EXTERN_CVAR (Int, autosavecount) @@ -532,7 +532,7 @@ void HSendPacket (int node, int len) { PacketStore store; store.message = doomcom; - store.timer = I_GetTime(false) + ((net_fakelatency / 2) / (1000 / TICRATE)); + store.timer = I_GetTime() + ((net_fakelatency / 2) / (1000 / TICRATE)); OutBuffer.Push(store); } else @@ -540,7 +540,7 @@ void HSendPacket (int node, int len) for (unsigned int i = 0; i < OutBuffer.Size(); i++) { - if (OutBuffer[i].timer <= I_GetTime(false)) + if (OutBuffer[i].timer <= I_GetTime()) { doomcom = OutBuffer[i].message; I_NetCmd(); @@ -581,7 +581,7 @@ bool HGetPacket (void) { PacketStore store; store.message = doomcom; - store.timer = I_GetTime(false) + ((net_fakelatency / 2) / (1000 / TICRATE)); + store.timer = I_GetTime() + ((net_fakelatency / 2) / (1000 / TICRATE)); InBuffer.Push(store); doomcom.remotenode = -1; } @@ -591,7 +591,7 @@ bool HGetPacket (void) bool gotmessage = false; for (unsigned int i = 0; i < InBuffer.Size(); i++) { - if (InBuffer[i].timer <= I_GetTime(false)) + if (InBuffer[i].timer <= I_GetTime()) { doomcom = InBuffer[i].message; InBuffer.Delete(i); diff --git a/src/dobject.cpp b/src/dobject.cpp index 1e399908e..17b9743f3 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -51,7 +51,7 @@ #include "vm.h" #include "g_levellocals.h" #include "types.h" -#include "d_main.h" +#include "i_time.h" //========================================================================== // diff --git a/src/doomdef.h b/src/doomdef.h index e64e5e215..b324fa90f 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -57,14 +57,19 @@ typedef enum #endif #endif -// The maximum number of players, multiplayer/networking. -#define MAXPLAYERS 8 +// Global constants that were defines. +enum +{ + // The maximum number of players, multiplayer/networking. + MAXPLAYERS = 8, -// State updates, number of tics / second. -#define TICRATE 35 + // State updates, number of tics / second. + TICRATE = 35, + + // Amount of damage done by a telefrag. + TELEFRAG_DAMAGE = 1000000 +}; -// Amount of damage done by a telefrag. -#define TELEFRAG_DAMAGE 1000000 // The current state of the game: whether we are // playing, gazing at the intermission screen, @@ -114,6 +119,7 @@ enum ESkillLevels // DOOM keyboard definition. Everything below 0x100 matches // a mode 1 keyboard scan code. // + #define KEY_PAUSE 0xc5 // DIK_PAUSE #define KEY_RIGHTARROW 0xcd // DIK_RIGHT #define KEY_LEFTARROW 0xcb // DIK_LEFT diff --git a/src/g_game.cpp b/src/g_game.cpp index 77db68a8d..ec1a7be50 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -32,6 +32,7 @@ #include #endif +#include "i_time.h" #include "templates.h" #include "version.h" #include "doomdef.h" diff --git a/src/g_level.cpp b/src/g_level.cpp index 5309e72cc..a2b15b02d 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -94,7 +94,7 @@ #include "g_levellocals.h" #include "actorinlines.h" #include "vm.h" -#include "d_main.h" +#include "i_time.h" #include diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index 2e6df1ed5..4b7054c2a 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -39,7 +39,7 @@ #include "d_player.h" #include "g_levellocals.h" #include "r_utility.h" -#include "d_main.h" +#include "i_time.h" //#include "resources/voxels.h" //#include "gl/gl_intern.h" diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index ce5fb524f..ae9e08989 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -26,6 +26,7 @@ */ #include "gl/system/gl_system.h" +#include "i_time.h" #include "gi.h" #include "m_png.h" #include "m_random.h" @@ -45,7 +46,6 @@ #include "serializer.h" #include "g_levellocals.h" #include "events.h" -#include "d_main.h" #include "gl/dynlights/gl_lightbuffer.h" #include "gl/system/gl_interface.h" diff --git a/src/gl/utility/gl_clock.cpp b/src/gl/utility/gl_clock.cpp index 27e740318..5cd1daa21 100644 --- a/src/gl/utility/gl_clock.cpp +++ b/src/gl/utility/gl_clock.cpp @@ -52,7 +52,7 @@ #include "g_levellocals.h" #include "gl/utility/gl_clock.h" #include "gl/utility/gl_convert.h" -#include "d_main.h" +#include "i_time.h" glcycle_t RenderWall,SetupWall,ClipWall; glcycle_t RenderFlat,SetupFlat; diff --git a/src/i_time.cpp b/src/i_time.cpp new file mode 100644 index 000000000..47b1b8bdd --- /dev/null +++ b/src/i_time.cpp @@ -0,0 +1,161 @@ +/* +** i_time.cpp +** Implements the timer +** +**--------------------------------------------------------------------------- +** Copyright 1998-2916 Randy Heit +** Copyright 2917 Magnus Norddahl +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include +#include +#include +#include "i_time.h" +#include "doomdef.h" + +//========================================================================== +// +// Tick time functions +// +//========================================================================== + +static unsigned int FirstFrameStartTime; +static unsigned int CurrentFrameStartTime; +static unsigned int FreezeTime; + +static uint32_t performanceGetTime() +{ + using namespace std::chrono; + return (uint32_t)duration_cast(steady_clock::now().time_since_epoch()).count(); +} + +void I_SetFrameTime() +{ + // Must only be called once per frame/swapbuffers. + // + // Caches all timing information for the current rendered frame so that any + // calls to I_FPSTime, I_MSTime, I_GetTime or I_GetTimeFrac will return + // the same time. + + if (FreezeTime == 0) + { + CurrentFrameStartTime = performanceGetTime(); + if (FirstFrameStartTime == 0) + FirstFrameStartTime = CurrentFrameStartTime; + } +} + +void I_WaitVBL(int count) +{ + // I_WaitVBL is never used to actually synchronize to the vertical blank. + // Instead, it's used for delay purposes. Doom used a 70 Hz display mode, + // so that's what we use to determine how long to wait for. + + std::this_thread::sleep_for(std::chrono::milliseconds(1000 * count / 70)); + I_SetFrameTime(); +} + +int I_WaitForTic(int prevtic) +{ + // Waits until the current tic is greater than prevtic. Time must not be frozen. + + int time; + while ((time = I_GetTime()) <= prevtic) + { + // The minimum amount of time a thread can sleep is controlled by timeBeginPeriod. + // We set this to 1 ms in DoMain. + int sleepTime = prevtic - time; + if (sleepTime > 2) + std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime - 2)); + + I_SetFrameTime(); + } + + return time; +} + +unsigned int I_FPSTime() +{ + if (FreezeTime == 0) + return CurrentFrameStartTime; + else + return performanceGetTime(); +} + +unsigned int I_MSTime() +{ + if (FreezeTime == 0) + { + return CurrentFrameStartTime - FirstFrameStartTime; + } + else + { + if (FirstFrameStartTime == 0) + { + FirstFrameStartTime = performanceGetTime(); + return 0; + } + else + { + return performanceGetTime() - FirstFrameStartTime; + } + } +} + +int I_GetTime() +{ + return (CurrentFrameStartTime - FirstFrameStartTime) * TICRATE / 1000 + 1; +} + +double I_GetTimeFrac(uint32_t *ms) +{ + unsigned int currentTic = (CurrentFrameStartTime - FirstFrameStartTime) * TICRATE / 1000; + unsigned int ticStartTime = FirstFrameStartTime + currentTic * 1000 / TICRATE; + unsigned int ticNextTime = FirstFrameStartTime + (currentTic + 1) * 1000 / TICRATE; + + if (ms) + *ms = currentTic + 1; + + return (CurrentFrameStartTime - ticStartTime) / (double)(ticNextTime - ticStartTime); +} + +void I_FreezeTime(bool frozen) +{ + if (frozen) + { + FreezeTime = performanceGetTime(); + } + else + { + FirstFrameStartTime += performanceGetTime() - FreezeTime; + FreezeTime = 0; + I_SetFrameTime(); + } +} + diff --git a/src/i_time.h b/src/i_time.h new file mode 100644 index 000000000..19d047cc2 --- /dev/null +++ b/src/i_time.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +// Called by D_DoomLoop, sets the time for the current frame +void I_SetFrameTime(); + +// Called by D_DoomLoop, returns current time in tics. +int I_GetTime(); + +double I_GetTimeFrac(uint32_t *ms); + +// like I_GetTime, except it waits for a new tic before returning +int I_WaitForTic(int); + +// Freezes tic counting temporarily. While frozen, calls to I_GetTime() +// will always return the same value. This does not affect I_MSTime(). +// You must also not call I_WaitForTic() while freezing time, since the +// tic will never arrive (unless it's the current one). +void I_FreezeTime(bool frozen); + +// [RH] Returns millisecond-accurate time +unsigned int I_MSTime(); +unsigned int I_FPSTime(); diff --git a/src/menu/videomenu.cpp b/src/menu/videomenu.cpp index 74fe71b67..d3ba14e92 100644 --- a/src/menu/videomenu.cpp +++ b/src/menu/videomenu.cpp @@ -55,7 +55,7 @@ #include "hardware.h" #include "vm.h" #include "r_videoscale.h" -#include "d_main.h" +#include "i_time.h" /*======================================= * diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index 8ec8ed8c3..3559887fa 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -68,7 +68,7 @@ #include "r_utility.h" #include "cmdlib.h" #include "g_levellocals.h" -#include "d_main.h" +#include "i_time.h" void P_GetPolySpots (MapData * lump, TArray &spots, TArray &anchors); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index cb8b6e5b6..fb2f1cdb7 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -115,7 +115,7 @@ #endif #include "events.h" #include "types.h" -#include "d_main.h" +#include "i_time.h" #include "fragglescript/t_fs.h" diff --git a/src/posix/cocoa/st_console.mm b/src/posix/cocoa/st_console.mm index 87d93038f..216e795bd 100644 --- a/src/posix/cocoa/st_console.mm +++ b/src/posix/cocoa/st_console.mm @@ -38,6 +38,7 @@ #include "st_console.h" #include "v_text.h" #include "version.h" +#include "i_time.h" static NSColor* RGB(const uint8_t red, const uint8_t green, const uint8_t blue) diff --git a/src/posix/sdl/i_system.cpp b/src/posix/sdl/i_system.cpp index 02dc270e4..43b830490 100644 --- a/src/posix/sdl/i_system.cpp +++ b/src/posix/sdl/i_system.cpp @@ -86,10 +86,6 @@ int I_PickIWad_Cocoa (WadStuff *wads, int numwads, bool showwin, int defaultiwad double PerfToSec, PerfToMillisec; uint32_t LanguageIDs[4]; -int (*I_GetTime) (bool saveMS); -int (*I_WaitForTic) (int); -void (*I_FreezeTime) (bool frozen); - void I_Tactile (int /*on*/, int /*off*/, int /*total*/) { } diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 6e0f9a92b..8a18c433d 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -66,7 +66,7 @@ #include "sbar.h" #include "math/cmath.h" #include "vm.h" -#include "d_main.h" +#include "i_time.h" // EXTERNAL DATA DECLARATIONS ---------------------------------------------- diff --git a/src/swrenderer/things/r_voxel.cpp b/src/swrenderer/things/r_voxel.cpp index 4d2d98ab9..8f2b80f0b 100644 --- a/src/swrenderer/things/r_voxel.cpp +++ b/src/swrenderer/things/r_voxel.cpp @@ -40,9 +40,9 @@ #include "r_data/voxels.h" #include "r_data/sprites.h" #include "d_net.h" -#include "d_main.h" #include "po_man.h" #include "r_utility.h" +#include "i_time.h" #include "swrenderer/drawers/r_draw.h" #include "swrenderer/drawers/r_thread.h" #include "swrenderer/things/r_visiblesprite.h" diff --git a/src/v_video.cpp b/src/v_video.cpp index e7b4e5177..d47ece201 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -84,7 +84,7 @@ #include "r_data/voxels.h" #include "vm.h" #include "r_videoscale.h" -#include "d_main.h" +#include "i_time.h" EXTERN_CVAR(Bool, r_blendmethod) diff --git a/src/win32/i_input.h b/src/win32/i_input.h index 500e27bb7..529ea83f5 100644 --- a/src/win32/i_input.h +++ b/src/win32/i_input.h @@ -56,6 +56,7 @@ enum // Don't make these definitions available to the main body of the source code. + struct tagRAWINPUT; class FInputDevice