diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6c266eb865..fc6545ea32 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -879,6 +879,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 76c552db23..b1a5575149 100644 --- a/src/c_bind.cpp +++ b/src/c_bind.cpp @@ -47,6 +47,7 @@ #include "templates.h" #include "dobject.h" #include "vm.h" +#include "i_time.h" #include #include @@ -743,8 +744,8 @@ bool C_DoKey (event_t *ev, FKeyBindings *binds, FKeyBindings *doublebinds) dclick = false; // This used level.time which didn't work outside a level. - nowtime = I_MSTime(); - if (doublebinds != NULL && DClickTime[ev->data1] > nowtime && ev->type == EV_KeyDown) + nowtime = I_msTime(); + if (doublebinds != NULL && int(DClickTime[ev->data1] - nowtime) > 0 && ev->type == EV_KeyDown) { // Key pressed for a double click binding = doublebinds->GetBinding(ev->data1); diff --git a/src/c_console.cpp b/src/c_console.cpp index 12be598180..c3ab769037 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -69,6 +69,7 @@ #include "c_consolebuffer.h" #include "g_levellocals.h" #include "vm.h" +#include "i_time.h" FString FStringFormat(VM_ARGS); // extern from thingdef_data.cpp @@ -528,7 +529,7 @@ static void maybedrawnow (bool tick, bool force) || gamestate == GS_STARTUP)) { static size_t lastprinttime = 0; - size_t nowtime = I_GetTime(false); + size_t nowtime = I_GetTime(); if (nowtime - lastprinttime > 1 || force) { diff --git a/src/cmdlib.h b/src/cmdlib.h index 605a56995a..f8fdfc4962 100644 --- a/src/cmdlib.h +++ b/src/cmdlib.h @@ -65,23 +65,9 @@ struct FFileList void ScanDirectory(TArray &list, const char *dirpath); -//========================================================================== -// -// Functions to compensate for a tic being a bit short. -// Since ZDoom uses a milliseconds timer for game timing -// 35 tics are actually only 0.98 seconds. -// For real time display this needs to be adjusted -// -//========================================================================== - -inline int AdjustTics(int tics) -{ - return Scale(tics, 98, 100); -} - inline int Tics2Seconds(int tics) { - return Scale(tics, 98, (100 * TICRATE)); + return tics * TICRATE; } diff --git a/src/d_main.cpp b/src/d_main.cpp index 29cc82a168..be097ac98f 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" @@ -280,7 +281,7 @@ void D_ProcessEvents (void) { M_SetDefaultMode (); } - else if (testingmode <= I_GetTime(false)) + else if (testingmode <= I_GetTime()) { M_RestoreMode (); } @@ -778,9 +779,9 @@ void D_Display () { - unsigned int nowtime = I_FPSTime(); - TexMan.UpdateAnimations(nowtime); - R_UpdateSky(nowtime); + screen->FrameTime = I_msTime(); + TexMan.UpdateAnimations(screen->FrameTime); + R_UpdateSky(screen->FrameTime); switch (gamestate) { case GS_FULLCONSOLE: @@ -937,14 +938,14 @@ void D_Display () else { // wipe update - unsigned int wipestart, nowtime, diff; + uint64_t wipestart, nowtime, diff; bool done; GSnd->SetSfxPaused(true, 1); I_FreezeTime(true); screen->WipeEndScreen (); - wipestart = I_MSTime(); + wipestart = I_msTime(); NetUpdate(); // send out any new accumulation do @@ -952,7 +953,7 @@ void D_Display () do { I_WaitVBL(2); - nowtime = I_MSTime(); + nowtime = I_msTime(); diff = (nowtime - wipestart) * 40 / 1000; // Using 35 here feels too slow. } while (diff < 1); wipestart = nowtime; diff --git a/src/d_main.h b/src/d_main.h index 1fa0368d6e..5addc5eb46 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -162,5 +162,4 @@ public: }; - #endif diff --git a/src/d_net.cpp b/src/d_net.cpp index 8a21205bd3..e8711bda50 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -68,6 +68,7 @@ #include "intermission/intermission.h" #include "g_levellocals.h" #include "events.h" +#include "i_time.h" EXTERN_CVAR (Int, disableautosave) EXTERN_CVAR (Int, autosavecount) @@ -112,9 +113,9 @@ bool remoteresend[MAXNETNODES]; // set when local needs tics int resendto[MAXNETNODES]; // set when remote needs tics int resendcount[MAXNETNODES]; -unsigned int lastrecvtime[MAXPLAYERS]; // [RH] Used for pings -unsigned int currrecvtime[MAXPLAYERS]; -unsigned int lastglobalrecvtime; // Identify the last time a packet was received. +uint64_t lastrecvtime[MAXPLAYERS]; // [RH] Used for pings +uint64_t currrecvtime[MAXPLAYERS]; +uint64_t lastglobalrecvtime; // Identify the last time a packet was received. bool hadlate; int netdelay[MAXNETNODES][BACKUPTICS]; // Used for storing network delay times. int lastaverage; @@ -531,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 @@ -539,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(); @@ -580,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; } @@ -590,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); @@ -782,7 +783,7 @@ void GetPackets (void) // [RH] Get "ping" times - totally useless, since it's bound to the frequency // packets go out at. lastrecvtime[netconsole] = currrecvtime[netconsole]; - currrecvtime[netconsole] = I_MSTime (); + currrecvtime[netconsole] = I_msTime (); // check for exiting the game if (netbuffer[0] & NCMD_EXIT) @@ -956,7 +957,7 @@ void NetUpdate (void) } // check time - nowtime = I_GetTime (false); + nowtime = I_GetTime (); newtics = nowtime - gametime; gametime = nowtime; @@ -1830,7 +1831,7 @@ void TryRunTics (void) } else { - entertic = I_GetTime (false); + entertic = I_GetTime (); } realtics = entertic - oldentertics; oldentertics = entertic; @@ -1913,7 +1914,7 @@ void TryRunTics (void) Net_CheckLastReceived (counts); // don't stay in here forever -- give the menu a chance to work - if (I_GetTime (false) - entertic >= 1) + if (I_GetTime () - entertic >= 1) { C_Ticker (); M_Ticker (); @@ -1928,7 +1929,7 @@ void TryRunTics (void) hadlate = false; for (i = 0; i < MAXPLAYERS; i++) players[i].waiting = false; - lastglobalrecvtime = I_GetTime (false); //Update the last time the game tic'd over + lastglobalrecvtime = I_GetTime (); //Update the last time the game tic'd over // run the count tics if (counts > 0) @@ -1947,8 +1948,6 @@ void TryRunTics (void) if (debugfile) fprintf (debugfile, "run tic %d\n", gametic); C_Ticker (); M_Ticker (); - I_GetTime (true); - I_SetFrameTime(); G_Ticker(); gametic++; @@ -1963,9 +1962,9 @@ void Net_CheckLastReceived (int counts) { // [Ed850] Check to see the last time a packet was received. // If it's longer then 3 seconds, a node has likely stalled. - if (I_GetTime(false) - lastglobalrecvtime >= TICRATE * 3) + if (I_GetTime() - lastglobalrecvtime >= TICRATE * 3) { - lastglobalrecvtime = I_GetTime(false); //Bump the count + lastglobalrecvtime = I_GetTime(); //Bump the count if (NetMode == NET_PeerToPeer || consoleplayer == Net_Arbitrator) { diff --git a/src/dobject.cpp b/src/dobject.cpp index 39c55f2b57..df8bb1acbf 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -51,6 +51,7 @@ #include "vm.h" #include "g_levellocals.h" #include "types.h" +#include "i_time.h" //========================================================================== // @@ -614,7 +615,7 @@ void DObject::CheckIfSerialized () const DEFINE_ACTION_FUNCTION(DObject, MSTime) { - ACTION_RETURN_INT(I_MSTime()); + ACTION_RETURN_INT((uint32_t)I_msTime()); } void *DObject::ScriptVar(FName field, PType *type) diff --git a/src/doomdef.h b/src/doomdef.h index e64e5e2153..b324fa90f9 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 db5c1cb2e6..ec1a7be506 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" @@ -92,6 +93,7 @@ #include "g_hub.h" #include "g_levellocals.h" #include "events.h" +#include "d_main.h" static FRandom pr_dmspawn ("DMSpawn"); @@ -2887,7 +2889,7 @@ bool G_CheckDemoStatus (void) int endtime = 0; if (timingdemo) - endtime = I_GetTime (false) - starttime; + endtime = I_GetTime () - starttime; C_RestoreCVars (); // [RH] Restore cvars demo might have changed M_Free (demobuffer); diff --git a/src/g_level.cpp b/src/g_level.cpp index 701d35b531..0ee56d6c3d 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -94,6 +94,7 @@ #include "g_levellocals.h" #include "actorinlines.h" #include "vm.h" +#include "i_time.h" #include @@ -1021,7 +1022,7 @@ void G_DoLoadLevel (int position, bool autosave) if (firstTime) { - starttime = I_GetTime (false); + starttime = I_GetTime (); firstTime = false; } } diff --git a/src/g_level.h b/src/g_level.h index 8b27dc68d2..7fb38a046c 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -367,7 +367,7 @@ struct level_info_t int outsidefogdensity; int skyfog; float pixelstretch; - + // Redirection: If any player is carrying the specified item, then // you go to the RedirectMap instead of this one. FName RedirectType; diff --git a/src/g_levellocals.h b/src/g_levellocals.h index b7f4f9aa33..505d797b6e 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -67,6 +67,8 @@ struct FLevelLocals FString F1Pic; EMapType maptype; + uint64_t ShaderStartTime = 0; // tell the shader system when we started the level (forces a timer restart) + TArray vertexes; TArray sectors; TArray linebuffer; // contains the line lists for the sectors. diff --git a/src/gl/data/gl_data.cpp b/src/gl/data/gl_data.cpp index 9a7c2e0379..42fc6e96d6 100644 --- a/src/gl/data/gl_data.cpp +++ b/src/gl/data/gl_data.cpp @@ -55,7 +55,6 @@ #include "gl/gl_functions.h" GLRenderSettings glset; -long gl_frameMS; EXTERN_CVAR(Int, gl_lightmode) EXTERN_CVAR(Bool, gl_brightfog) diff --git a/src/gl/data/gl_data.h b/src/gl/data/gl_data.h index a46680ab77..518f330c90 100644 --- a/src/gl/data/gl_data.h +++ b/src/gl/data/gl_data.h @@ -65,6 +65,4 @@ void gl_InitPortals(); void gl_BuildPortalCoverage(FPortalCoverage *coverage, subsector_t *subsector, const DVector2 &displacement); void gl_InitData(); -extern long gl_frameMS; - #endif diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index c782bd5788..c64f058549 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -39,6 +39,7 @@ #include "d_player.h" #include "g_levellocals.h" #include "r_utility.h" +#include "i_time.h" //#include "resources/voxels.h" //#include "gl/gl_intern.h" @@ -75,7 +76,7 @@ void FModelRenderer::RenderModel(float x, float y, float z, FSpriteModelFrame *s float scaleFactorZ = actor->Scale.Y * smf->zscale; float pitch = 0; float roll = 0; - float rotateOffset = 0; + double rotateOffset = 0; float angle = actor->Angles.Yaw.Degrees; // [BB] Workaround for the missing pitch information. @@ -101,8 +102,8 @@ void FModelRenderer::RenderModel(float x, float y, float z, FSpriteModelFrame *s if (smf->flags & MDL_ROTATING) { - const float time = smf->rotationSpeed*GetTimeFloat() / 200.f; - rotateOffset = float((time - xs_FloorToInt(time)) *360.f); + const double time = smf->rotationSpeed*GetTimeFloat() / 200.; + rotateOffset = double((time - xs_FloorToInt(time)) *360.); } // Added MDL_USEACTORPITCH and MDL_USEACTORROLL flags processing. @@ -224,7 +225,7 @@ void FModelRenderer::RenderFrameModels(const FSpriteModelFrame *smf, // [BB] In case the tic counter is frozen we have to leave ticFraction at zero. if (ConsoleState == c_up && menuactive != MENU_On && !(level.flags2 & LEVEL2_FROZEN)) { - float time = GetTimeFloat(); + double time = GetTimeFloat(); ticFraction = (time - static_cast(time)); } inter = static_cast(curState->Tics - curTics - ticFraction) / static_cast(curState->Tics); @@ -381,9 +382,9 @@ void FGLModelRenderer::DrawElements(int primitiveType, int numIndices, int eleme glDrawElements(primitiveType, numIndices, elementType, (void*)(intptr_t)offset); } -float FGLModelRenderer::GetTimeFloat() +double FGLModelRenderer::GetTimeFloat() { - return (float)I_MSTime() * (float)TICRATE / 1000.0f; + return (float)I_msTime() * (float)TICRATE / 1000.0f; } ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gl/models/gl_models.h b/src/gl/models/gl_models.h index 84e331e311..cc41466db8 100644 --- a/src/gl/models/gl_models.h +++ b/src/gl/models/gl_models.h @@ -71,7 +71,7 @@ public: virtual void DrawArrays(int primitiveType, int start, int count) = 0; virtual void DrawElements(int primitiveType, int numIndices, int elementType, size_t offset) = 0; - virtual float GetTimeFloat() = 0; + virtual double GetTimeFloat() = 0; private: void RenderFrameModels(const FSpriteModelFrame *smf, const FState *curState, const int curTics, const PClass *ti, Matrix3x4 *normaltransform, int translation); @@ -92,7 +92,7 @@ public: void SetMaterial(FTexture *skin, int clampmode, int translation) override; void DrawArrays(int primitiveType, int start, int count) override; void DrawElements(int primitiveType, int numIndices, int elementType, size_t offset) override; - float GetTimeFloat() override; + double GetTimeFloat() override; }; class FModel diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 67c9c21faf..c37ccbb992 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -37,6 +37,7 @@ #include "gl/renderer/gl_colormap.h" #include "gl/dynlights//gl_lightbuffer.h" #include "gl/renderer/gl_renderbuffers.h" +#include "g_levellocals.h" void gl_SetTextureMode(int type); @@ -118,6 +119,12 @@ void FRenderState::Reset() bool FRenderState::ApplyShader() { + static uint64_t firstFrame = 0; + // if firstFrame is not yet initialized, initialize it to current time + // if we're going to overflow a float (after ~4.6 hours, or 24 bits), re-init to regain precision + if ((firstFrame == 0) || (screen->FrameTime - firstFrame >= 1<<24) || level.ShaderStartTime >= firstFrame) + firstFrame = screen->FrameTime; + static const float nulvec[] = { 0.f, 0.f, 0.f, 0.f }; if (mSpecialEffect > EFF_NONE) { @@ -161,7 +168,7 @@ bool FRenderState::ApplyShader() activeShader->muInterpolationFactor.Set(mInterpolationFactor); activeShader->muClipHeight.Set(mClipHeight); activeShader->muClipHeightDirection.Set(mClipHeightDirection); - activeShader->muTimer.Set(gl_frameMS * mShaderTimer / 1000.f); + activeShader->muTimer.Set((double)(screen->FrameTime - firstFrame) * mShaderTimer / 1000.f); activeShader->muAlphaThreshold.Set(mAlphaThreshold); activeShader->muLightIndex.Set(mLightIndex); // will always be -1 for now activeShader->muClipSplit.Set(mClipSplit); diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 9bfca82ffe..329ac64840 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" @@ -799,8 +800,8 @@ sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, f GLRenderer->mAngles.Roll.Degrees = r_viewpoint.Angles.Roll.Degrees; // Scroll the sky - GLRenderer->mSky1Pos = (float)fmod(gl_frameMS * level.skyspeed1, 1024.f) * 90.f/256.f; - GLRenderer->mSky2Pos = (float)fmod(gl_frameMS * level.skyspeed2, 1024.f) * 90.f/256.f; + GLRenderer->mSky1Pos = (double)fmod(screen->FrameTime * level.skyspeed1, 1024.f) * 90./256.; + GLRenderer->mSky2Pos = (double)fmod(screen->FrameTime * level.skyspeed2, 1024.f) * 90./256.; @@ -889,8 +890,7 @@ void FGLRenderer::RenderView (player_t* player) // Get this before everything else if (cl_capfps || r_NoInterpolate) r_viewpoint.TicFrac = 1.; - else r_viewpoint.TicFrac = I_GetTimeFrac (&r_viewpoint.FrameTime); - gl_frameMS = I_MSTime(); + else r_viewpoint.TicFrac = I_GetTimeFrac (); P_FindParticleSubsectors (); diff --git a/src/gl/system/gl_framebuffer.h b/src/gl/system/gl_framebuffer.h index 7d11db921a..1d85562b35 100644 --- a/src/gl/system/gl_framebuffer.h +++ b/src/gl/system/gl_framebuffer.h @@ -12,7 +12,6 @@ class FHardwareTexture; class FSimpleVertexBuffer; class FGLDebug; -extern long gl_frameMS; #ifdef _WIN32 class OpenGLFrameBuffer : public Win32GLFrameBuffer { diff --git a/src/gl/textures/gl_material.cpp b/src/gl/textures/gl_material.cpp index f45a702b90..53d22f8573 100644 --- a/src/gl/textures/gl_material.cpp +++ b/src/gl/textures/gl_material.cpp @@ -320,10 +320,10 @@ const FHardwareTexture *FGLTexture::Bind(int texunit, int clampmode, int transla // need to do software warping FWarpTexture *wt = static_cast(tex); unsigned char *warpbuffer = new unsigned char[w*h*4]; - WarpBuffer((uint32_t*)warpbuffer, (const uint32_t*)buffer, w, h, wt->WidthOffsetMultiplier, wt->HeightOffsetMultiplier, r_viewpoint.FrameTime, wt->Speed, tex->bWarped); + WarpBuffer((uint32_t*)warpbuffer, (const uint32_t*)buffer, w, h, wt->WidthOffsetMultiplier, wt->HeightOffsetMultiplier, screen->FrameTime, wt->Speed, tex->bWarped); delete[] buffer; buffer = warpbuffer; - wt->GenTime = r_viewpoint.FrameTime; + wt->GenTime = screen->FrameTime; } tex->ProcessData(buffer, w, h, false); } diff --git a/src/gl/utility/gl_clock.cpp b/src/gl/utility/gl_clock.cpp index 81cb52b011..df96fb6b8f 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 "i_time.h" glcycle_t RenderWall,SetupWall,ClipWall; glcycle_t RenderFlat,SetupFlat; @@ -187,8 +187,8 @@ static void AppendLightStats(FString &out) ADD_STAT(rendertimes) { static FString buff; - static int lasttime=0; - int t=I_FPSTime(); + static int64_t lasttime=0; + int64_t t=I_msTime(); if (t-lasttime>1000) { buff.Truncate(0); @@ -217,7 +217,7 @@ void AppendMissingTextureStats(FString &out); static int printstats; static bool switchfps; -static unsigned int waitstart; +static uint64_t waitstart; EXTERN_CVAR(Bool, vid_fps) void CheckBench() @@ -226,7 +226,7 @@ void CheckBench() { // if we started the FPS counter ourselves or ran from the console // we need to wait for it to stabilize before using it. - if (waitstart > 0 && I_MSTime() < waitstart + 5000) return; + if (waitstart > 0 && I_msTime() - waitstart < 5000) return; FString compose; @@ -257,12 +257,12 @@ CCMD(bench) if (vid_fps == 0) { vid_fps = 1; - waitstart = I_MSTime(); + waitstart = I_msTime(); switchfps = true; } else { - if (ConsoleState == c_up) waitstart = I_MSTime(); + if (ConsoleState == c_up) waitstart = I_msTime(); switchfps = false; } C_HideConsole (); diff --git a/src/i_time.cpp b/src/i_time.cpp new file mode 100644 index 0000000000..516ecfad1e --- /dev/null +++ b/src/i_time.cpp @@ -0,0 +1,182 @@ +/* +** i_time.cpp +** Implements the timer +** +**--------------------------------------------------------------------------- +** Copyright 1998-2016 Randy Heit +** Copyright 2017 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" +#include "c_cvars.h" +#include "doomstat.h" + +//========================================================================== +// +// Tick time functions +// +//========================================================================== + +static uint64_t FirstFrameStartTime; +static uint64_t CurrentFrameStartTime; +static uint64_t FreezeTime; + +static double TimeScale = 1.0; + +CUSTOM_CVAR(Float, i_timescale, 1.0f, CVAR_NOINITCALL) +{ + if (netgame && self != 1.0f) + { + Printf("Time scale cannot be changed in net games.\n"); + self = 1.0f; + } + else + { + I_FreezeTime(true); + float clampValue = (self < 0.05) ? 0.05f : self; + if (self != clampValue) + self = clampValue; + TimeScale = self; + I_FreezeTime(false); + } +} + +static uint64_t GetClockTimeNS() +{ + using namespace std::chrono; + return (uint64_t)((duration_cast(steady_clock::now().time_since_epoch()).count()) * TimeScale); +} + +static uint64_t MSToNS(unsigned int ms) +{ + return static_cast(ms) * 1'000'000; +} + +static uint64_t NSToMS(uint64_t ns) +{ + return static_cast(ns / 1'000'000); +} + +static int NSToTic(uint64_t ns) +{ + return static_cast(ns * TICRATE / 1'000'000'000); +} + +static uint64_t TicToNS(int tic) +{ + return static_cast(tic) * 1'000'000'000 / TICRATE; +} + +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_GetTime or I_GetTimeFrac will return + // the same time. + + if (FreezeTime == 0) + { + CurrentFrameStartTime = GetClockTimeNS(); + 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. + uint64_t sleepTime = NSToMS(FirstFrameStartTime + TicToNS(prevtic + 1) - I_nsTime()); + if (sleepTime > 2) + std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime - 2)); + + I_SetFrameTime(); + } + + return time; +} + +uint64_t I_nsTime() +{ + return GetClockTimeNS(); +} + +uint64_t I_msTime() +{ + return NSToMS(I_nsTime()); +} + +int I_GetTime() +{ + return NSToTic(CurrentFrameStartTime - FirstFrameStartTime); +} + +double I_GetTimeFrac() +{ + int currentTic = NSToTic(CurrentFrameStartTime - FirstFrameStartTime); + uint64_t ticStartTime = FirstFrameStartTime + TicToNS(currentTic); + uint64_t ticNextTime = FirstFrameStartTime + TicToNS(currentTic + 1); + + return (CurrentFrameStartTime - ticStartTime) / (double)(ticNextTime - ticStartTime); +} + +void I_FreezeTime(bool frozen) +{ + if (frozen) + { + FreezeTime = GetClockTimeNS(); + } + else + { + FirstFrameStartTime += GetClockTimeNS() - FreezeTime; + FreezeTime = 0; + I_SetFrameTime(); + } +} + diff --git a/src/i_time.h b/src/i_time.h new file mode 100644 index 0000000000..33907ded2a --- /dev/null +++ b/src/i_time.h @@ -0,0 +1,26 @@ +#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(); + +// 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. +// 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 +uint64_t I_msTime(); + +// Nanosecond-accurate time +uint64_t I_nsTime(); diff --git a/src/menu/videomenu.cpp b/src/menu/videomenu.cpp index cea99cd422..d3ba14e925 100644 --- a/src/menu/videomenu.cpp +++ b/src/menu/videomenu.cpp @@ -55,6 +55,7 @@ #include "hardware.h" #include "vm.h" #include "r_videoscale.h" +#include "i_time.h" /*======================================= * @@ -312,7 +313,7 @@ DEFINE_ACTION_FUNCTION(DVideoModeMenu, SetSelectedSize) OldBits = DisplayBits; NewBits = BitTranslate[DummyDepthCvar]; setmodeneeded = true; - testingmode = I_GetTime(false) + 5 * TICRATE; + testingmode = I_GetTime() + 5 * TICRATE; SetModesMenu (NewWidth, NewHeight, NewBits); ACTION_RETURN_BOOL(true); } diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index 36873f4ba5..e1510145e3 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -68,6 +68,7 @@ #include "r_utility.h" #include "cmdlib.h" #include "g_levellocals.h" +#include "i_time.h" void P_GetPolySpots (MapData * lump, TArray &spots, TArray &anchors); @@ -954,9 +955,9 @@ bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime) if (!loaded) { // none found - we have to build new ones! - unsigned int startTime, endTime; + uint64_t startTime, endTime; - startTime = I_FPSTime (); + startTime = I_msTime (); TArray polyspots, anchors; P_GetPolySpots (map, polyspots, anchors); FNodeBuilder::FLevel leveldata = @@ -970,9 +971,9 @@ bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime) FNodeBuilder builder (leveldata, polyspots, anchors, true); builder.Extract (level); - endTime = I_FPSTime (); + endTime = I_msTime (); DPrintf (DMSG_NOTIFY, "BSP generation took %.3f sec (%u segs)\n", (endTime - startTime) * 0.001, level.segs.Size()); - buildtime = endTime - startTime; + buildtime = (int32_t)(endTime - startTime); } } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 1bb0e9d8b0..dfa7ecb267 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -115,6 +115,7 @@ #endif #include "events.h" #include "types.h" +#include "i_time.h" #include "fragglescript/t_fs.h" @@ -3626,6 +3627,8 @@ void P_SetupLevel (const char *lumpname, int position) bool buildmap; const int *oldvertextable = NULL; + level.ShaderStartTime = I_msTime(); // indicate to the shader system that the level just started + // This is motivated as follows: bool RequireGLNodes = Renderer->RequireGLNodes() || am_textured; @@ -3930,14 +3933,14 @@ void P_SetupLevel (const char *lumpname, int position) } else reloop = true; - unsigned int startTime=0, endTime=0; + uint64_t startTime=0, endTime=0; bool BuildGLNodes; if (ForceNodeBuild) { BuildGLNodes = RequireGLNodes || multiplayer || demoplayback || demorecording || genglnodes; - startTime = I_FPSTime (); + startTime = I_msTime (); TArray polyspots, anchors; P_GetPolySpots (map, polyspots, anchors); FNodeBuilder::FLevel leveldata = @@ -3953,7 +3956,7 @@ void P_SetupLevel (const char *lumpname, int position) // if the different machines' am_textured setting differs. FNodeBuilder builder (leveldata, polyspots, anchors, BuildGLNodes); builder.Extract (level); - endTime = I_FPSTime (); + endTime = I_msTime (); DPrintf (DMSG_NOTIFY, "BSP generation took %.3f sec (%d segs)\n", (endTime - startTime) * 0.001, level.segs.Size()); oldvertextable = builder.GetOldVertexTable(); reloop = true; @@ -3987,7 +3990,7 @@ void P_SetupLevel (const char *lumpname, int position) // If the original nodes being loaded are not GL nodes they will be kept around for // use in P_PointInSubsector to avoid problems with maps that depend on the specific // nodes they were built with (P:AR E1M3 is a good example for a map where this is the case.) - reloop |= P_CheckNodes(map, BuildGLNodes, endTime - startTime); + reloop |= P_CheckNodes(map, BuildGLNodes, (uint32_t)(endTime - startTime)); hasglnodes = true; } else diff --git a/src/polyrenderer/scene/poly_model.cpp b/src/polyrenderer/scene/poly_model.cpp index 88064ce97c..f9d7b48871 100644 --- a/src/polyrenderer/scene/poly_model.cpp +++ b/src/polyrenderer/scene/poly_model.cpp @@ -175,7 +175,7 @@ void PolyModelRenderer::DrawElements(int primitiveType, int numIndices, int elem args.DrawElements(Thread, VertexBuffer, IndexBuffer + offset / sizeof(unsigned int), numIndices); } -float PolyModelRenderer::GetTimeFloat() +double PolyModelRenderer::GetTimeFloat() { return 0.0f; // (float)gl_frameMS * (float)TICRATE / 1000.0f; } diff --git a/src/polyrenderer/scene/poly_model.h b/src/polyrenderer/scene/poly_model.h index 8585be44c8..d80bed45f9 100644 --- a/src/polyrenderer/scene/poly_model.h +++ b/src/polyrenderer/scene/poly_model.h @@ -46,7 +46,7 @@ public: void SetMaterial(FTexture *skin, int clampmode, int translation) override; void DrawArrays(int primitiveType, int start, int count) override; void DrawElements(int primitiveType, int numIndices, int elementType, size_t offset) override; - float GetTimeFloat() override; + double GetTimeFloat() override; PolyRenderThread *Thread = nullptr; const TriMatrix &WorldToClip; diff --git a/src/posix/cocoa/i_system.mm b/src/posix/cocoa/i_system.mm index 7b7c6dcc2c..cc9dc613a1 100644 --- a/src/posix/cocoa/i_system.mm +++ b/src/posix/cocoa/i_system.mm @@ -56,11 +56,6 @@ EXTERN_CVAR(String, language) 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*/) { } @@ -73,18 +68,6 @@ ticcmd_t* I_BaseTiccmd() } -void I_WaitVBL(const int count) -{ - // I_WaitVBL is never used to actually synchronize to the - // vertical blank. Instead, it's used for delay purposes. - struct timespec delay, rem; - delay.tv_sec = count / 70; - /* Avoid overflow. Microsec res should be good enough. */ - delay.tv_nsec = (count%70)*1000000/70 * 1000; - while(nanosleep(&delay, &rem) == -1 && errno == EINTR) - delay = rem; -} - // // SetLanguageIDs diff --git a/src/posix/cocoa/i_timer.cpp b/src/posix/cocoa/i_timer.cpp index dbeca12705..503fa64ec5 100644 --- a/src/posix/cocoa/i_timer.cpp +++ b/src/posix/cocoa/i_timer.cpp @@ -40,202 +40,12 @@ #include "i_system.h" #include "templates.h" - -namespace -{ - -timeval s_gameStartTicks; -timeval s_systemBootTicks; - -unsigned int GetMillisecondsSince(const timeval& time) -{ - timeval now; - gettimeofday(&now, NULL); - - return static_cast( - (now.tv_sec - time.tv_sec ) * 1000 - + (now.tv_usec - time.tv_usec) / 1000); -} - - -bool s_isTicFrozen; - -timespec GetNextTickTime() -{ - static const long MILLISECONDS_IN_SECOND = 1000; - static const long MICROSECONDS_IN_SECOND = 1000 * MILLISECONDS_IN_SECOND; - static const long NANOSECONDS_IN_SECOND = 1000 * MICROSECONDS_IN_SECOND; - - static timespec ts = {}; - - if (__builtin_expect((0 == ts.tv_sec), 0)) - { - timeval tv; - gettimeofday(&tv, NULL); - - ts.tv_sec = tv.tv_sec; - ts.tv_nsec = (tv.tv_usec + MICROSECONDS_IN_SECOND / TICRATE) * MILLISECONDS_IN_SECOND; - } - else - { - ts.tv_nsec += (MICROSECONDS_IN_SECOND / TICRATE) * MILLISECONDS_IN_SECOND; - } - - if (ts.tv_nsec >= NANOSECONDS_IN_SECOND) - { - ts.tv_sec++; - ts.tv_nsec -= NANOSECONDS_IN_SECOND; - } - - return ts; -} - - -pthread_cond_t s_timerEvent; -pthread_mutex_t s_timerMutex; -pthread_t s_timerThread; - -bool s_timerInitialized; -bool s_timerExitRequested; - -uint32_t s_ticStart; -uint32_t s_timerStart; - -int s_tics; - - -void* TimerThreadFunc(void*) -{ - assert(s_timerInitialized); - assert(!s_timerExitRequested); - - while (true) - { - if (s_timerExitRequested) - { - break; - } - - const timespec timeToNextTick = GetNextTickTime(); - - pthread_mutex_lock(&s_timerMutex); - pthread_cond_timedwait(&s_timerEvent, &s_timerMutex, &timeToNextTick); - - if (!s_isTicFrozen) - { - __sync_add_and_fetch(&s_tics, 1); - } - - s_timerStart = I_MSTime(); - - pthread_cond_broadcast(&s_timerEvent); - pthread_mutex_unlock(&s_timerMutex); - } - - return NULL; -} - -int GetTimeThreaded(bool saveMS) -{ - if (saveMS) - { - s_ticStart = s_timerStart; - } - - return s_tics; -} - -int WaitForTicThreaded(int prevTic) -{ - assert(!s_isTicFrozen); - - while (s_tics <= prevTic) - { - pthread_mutex_lock(&s_timerMutex); - pthread_cond_wait(&s_timerEvent, &s_timerMutex); - pthread_mutex_unlock(&s_timerMutex); - } - - return s_tics; -} - -void FreezeTimeThreaded(bool frozen) -{ - s_isTicFrozen = frozen; -} - -} // unnamed namespace - - -unsigned int I_MSTime() -{ - return GetMillisecondsSince(s_gameStartTicks); -} - -unsigned int I_FPSTime() -{ - return GetMillisecondsSince(s_systemBootTicks); -} - - -static uint32_t FrameTime; - -void I_SetFrameTime() -{ - FrameTime = I_MSTime(); -} - - -double I_GetTimeFrac(uint32_t* ms) -{ - const uint32_t now = FrameTime; - - if (NULL != ms) - { - *ms = s_ticStart + 1000 / TICRATE; - } - - return 0 == s_ticStart - ? 1. - : clamp( (now - s_ticStart) * TICRATE / 1000., 0, 1); -} - +// To do: this file is obviously not needed anymore. It needs to be removed. void I_InitTimer() { - assert(!s_timerInitialized); - s_timerInitialized = true; - - gettimeofday(&s_gameStartTicks, NULL); - - int mib[2] = { CTL_KERN, KERN_BOOTTIME }; - size_t len = sizeof s_systemBootTicks; - - sysctl(mib, 2, &s_systemBootTicks, &len, NULL, 0); - - pthread_cond_init (&s_timerEvent, NULL); - pthread_mutex_init(&s_timerMutex, NULL); - - pthread_create(&s_timerThread, NULL, TimerThreadFunc, NULL); - - I_GetTime = GetTimeThreaded; - I_WaitForTic = WaitForTicThreaded; - I_FreezeTime = FreezeTimeThreaded; } void I_ShutdownTimer() { - if (!s_timerInitialized) - { - // This might happen if Cancel button was pressed - // in the IWAD selector window - return; - } - - s_timerExitRequested = true; - - pthread_join(s_timerThread, NULL); - - pthread_mutex_destroy(&s_timerMutex); - pthread_cond_destroy (&s_timerEvent); } diff --git a/src/posix/cocoa/st_console.mm b/src/posix/cocoa/st_console.mm index 87d93038f9..dd876c378c 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) @@ -199,7 +200,7 @@ struct TimedUpdater { explicit TimedUpdater(const Function& function) { - const unsigned int currentTime = I_MSTime(); + const unsigned int currentTime = I_msTime(); if (currentTime - m_previousTime > interval) { diff --git a/src/posix/i_system.h b/src/posix/i_system.h index 0649b7f3c8..7f468f1432 100644 --- a/src/posix/i_system.h +++ b/src/posix/i_system.h @@ -57,22 +57,6 @@ extern void SetLanguageIDs (); // Called by DoomMain. void I_Init (void); -// Called by D_DoomLoop, -// returns current time in tics. -extern int (*I_GetTime) (bool saveMS); - -// like I_GetTime, except it waits for a new tic before returning -extern 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). -extern void (*I_FreezeTime) (bool frozen); - -double I_GetTimeFrac (uint32_t *ms); -void I_SetFrameTime(); - // Return a seed value for the RNG. unsigned int I_MakeRNGSeed(); @@ -140,10 +124,6 @@ TArray I_GetGogPaths(); // The ini could not be saved at exit bool I_WriteIniFailed (); -// [RH] Returns millisecond-accurate time -unsigned int I_MSTime (void); -unsigned int I_FPSTime(); - class FTexture; bool I_SetCursor(FTexture *); diff --git a/src/posix/sdl/i_system.cpp b/src/posix/sdl/i_system.cpp index 02dc270e46..903563da05 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*/) { } @@ -109,18 +105,6 @@ void I_EndRead(void) } -void I_WaitVBL (int count) -{ - // I_WaitVBL is never used to actually synchronize to the - // vertical blank. Instead, it's used for delay purposes. - struct timespec delay, rem; - delay.tv_sec = count / 70; - /* Avoid overflow. Microsec res should be good enough. */ - delay.tv_nsec = (count%70)*1000000/70 * 1000; - while(nanosleep(&delay, &rem) == -1 && errno == EINTR) - delay = rem; -} - // // SetLanguageIDs // diff --git a/src/posix/sdl/i_timer.cpp b/src/posix/sdl/i_timer.cpp index a779852c73..dab7c30acf 100644 --- a/src/posix/sdl/i_timer.cpp +++ b/src/posix/sdl/i_timer.cpp @@ -44,201 +44,13 @@ #include "i_system.h" #include "templates.h" - -static uint32_t TicStart; -static uint32_t BaseTime; -static int TicFrozen; - -// Signal based timer. -static Semaphore timerWait; -static int tics; -static uint32_t sig_start; - -void I_SelectTimer(); - -// [RH] Returns time in milliseconds -unsigned int I_MSTime (void) -{ - unsigned int time = SDL_GetTicks (); - return time - BaseTime; -} - -// Exactly the same thing, but based does no modification to the time. -unsigned int I_FPSTime() -{ - return SDL_GetTicks(); -} - -// -// I_GetTime -// returns time in 1/35th second tics -// -int I_GetTimeSelect (bool saveMS) -{ - I_SelectTimer(); - return I_GetTime (saveMS); -} - -int I_GetTimePolled (bool saveMS) -{ - if (TicFrozen != 0) - { - return TicFrozen; - } - - uint32_t tm = SDL_GetTicks(); - - if (saveMS) - { - TicStart = tm; - } - return Scale(tm - BaseTime, TICRATE, 1000); -} - -int I_GetTimeSignaled (bool saveMS) -{ - if (saveMS) - { - TicStart = sig_start; - } - return tics; -} - -int I_WaitForTicPolled (int prevtic) -{ - int time; - - assert (TicFrozen == 0); - while ((time = I_GetTimePolled(false)) <= prevtic) - ; - - return time; -} - -int I_WaitForTicSignaled (int prevtic) -{ - assert (TicFrozen == 0); - - while(tics <= prevtic) - { - SEMAPHORE_WAIT(timerWait) - } - - return tics; -} - -void I_FreezeTimeSelect (bool frozen) -{ - I_SelectTimer(); - return I_FreezeTime (frozen); -} - -void I_FreezeTimePolled (bool frozen) -{ - if (frozen) - { - assert(TicFrozen == 0); - TicFrozen = I_GetTimePolled(false); - } - else - { - assert(TicFrozen != 0); - int froze = TicFrozen; - TicFrozen = 0; - int now = I_GetTimePolled(false); - BaseTime += (now - froze) * 1000 / TICRATE; - } -} - -void I_FreezeTimeSignaled (bool frozen) -{ - TicFrozen = frozen; -} - -int I_WaitForTicSelect (int prevtic) -{ - I_SelectTimer(); - return I_WaitForTic (prevtic); -} - -// -// I_HandleAlarm -// Should be called every time there is an alarm. -// -void I_HandleAlarm (int sig) -{ - if(!TicFrozen) - tics++; - sig_start = SDL_GetTicks(); - SEMAPHORE_SIGNAL(timerWait) -} - -// -// I_SelectTimer -// Sets up the timer function based on if we can use signals for efficent CPU -// usage. -// -void I_SelectTimer() -{ - SEMAPHORE_INIT(timerWait, 0, 0) -#ifndef __sun - signal(SIGALRM, I_HandleAlarm); -#else - struct sigaction alrmaction; - sigaction(SIGALRM, NULL, &alrmaction); - alrmaction.sa_handler = I_HandleAlarm; - sigaction(SIGALRM, &alrmaction, NULL); -#endif - - struct itimerval itv; - itv.it_interval.tv_sec = itv.it_value.tv_sec = 0; - itv.it_interval.tv_usec = itv.it_value.tv_usec = 1000000/TICRATE; - - if (setitimer(ITIMER_REAL, &itv, NULL) != 0) - { - I_GetTime = I_GetTimePolled; - I_FreezeTime = I_FreezeTimePolled; - I_WaitForTic = I_WaitForTicPolled; - } - else - { - I_GetTime = I_GetTimeSignaled; - I_FreezeTime = I_FreezeTimeSignaled; - I_WaitForTic = I_WaitForTicSignaled; - } -} - - -static uint32_t FrameTime; - -void I_SetFrameTime() -{ - FrameTime = SDL_GetTicks(); -} - -// Returns the fractional amount of a tic passed since the most recent tic -double I_GetTimeFrac (uint32_t *ms) -{ - uint32_t now = FrameTime; - if (ms) *ms = TicStart + (1000 / TICRATE); - if (TicStart == 0) - { - return 1; - } - else - { - return clamp((now - TicStart) * TICRATE / 1000., 0, 1); - } -} - void I_InitTimer () { if(SDL_InitSubSystem(SDL_INIT_TIMER) < 0) I_FatalError("Could not initialize SDL timers:\n%s\n", SDL_GetError()); - I_GetTime = I_GetTimeSelect; - I_WaitForTic = I_WaitForTicSelect; - I_FreezeTime = I_FreezeTimeSelect; + // Maybe this file isn't needed at all anymore. + // Someone with Linux should test if the timer subsystem is used elsewhere.. } void I_ShutdownTimer () diff --git a/src/r_sky.cpp b/src/r_sky.cpp index eb31e20648..cc84f9fbb2 100644 --- a/src/r_sky.cpp +++ b/src/r_sky.cpp @@ -165,7 +165,7 @@ void R_InitSkyMap () // //========================================================================== -void R_UpdateSky (uint32_t mstime) +void R_UpdateSky (uint64_t mstime) { // Scroll the sky double ms = (double)mstime * FRACUNIT; diff --git a/src/r_sky.h b/src/r_sky.h index 39ac77f27f..e186ad3ae5 100644 --- a/src/r_sky.h +++ b/src/r_sky.h @@ -44,6 +44,6 @@ extern int freelookviewheight; // Called whenever the sky changes. void R_InitSkyMap (); -void R_UpdateSky (uint32_t mstime); +void R_UpdateSky (uint64_t mstime); #endif //__R_SKY_H__ diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 22fba0f688..fc3e963c7b 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -66,6 +66,7 @@ #include "sbar.h" #include "math/cmath.h" #include "vm.h" +#include "i_time.h" // EXTERNAL DATA DECLARATIONS ---------------------------------------------- @@ -136,8 +137,6 @@ FRenderViewpoint::FRenderViewpoint() FRenderViewpoint r_viewpoint; FViewWindow r_viewwindow; -int otic; - bool r_NoInterpolate; angle_t LocalViewAngle; @@ -784,7 +783,7 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor iview = FindPastViewer (viewpoint.camera); - int nowtic = I_GetTime (false); + int nowtic = I_GetTime (); if (iview->otic != -1 && nowtic > iview->otic) { iview->otic = nowtic; @@ -832,7 +831,7 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor iview->otic = nowtic; } - viewpoint.TicFrac = I_GetTimeFrac (&viewpoint.FrameTime); + viewpoint.TicFrac = I_GetTimeFrac (); if (cl_capfps || r_NoInterpolate) { viewpoint.TicFrac = 1.; @@ -983,7 +982,7 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor if (hom == 3) { - hom = ((I_FPSTime() / 128) & 1) + 1; + hom = ((screen->FrameTime / 128) & 1) + 1; } if (hom == 1) { @@ -995,7 +994,7 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor } else if (hom == 4) { - color = (I_FPSTime() / 32) & 255; + color = (screen->FrameTime / 32) & 255; } else { diff --git a/src/statistics.cpp b/src/statistics.cpp index e96f103272..2abd0bf12c 100644 --- a/src/statistics.cpp +++ b/src/statistics.cpp @@ -420,7 +420,7 @@ static void StoreLevelStats() LevelData[i].killcount = level.killed_monsters; LevelData[i].totalsecrets = level.total_secrets; LevelData[i].secretcount = level.found_secrets; - LevelData[i].leveltime = AdjustTics(level.maptime); + LevelData[i].leveltime = level.maptime; // Check for living monsters. On some maps it can happen // that the counter misses some. @@ -490,7 +490,7 @@ void STAT_ChangeLevel(const char *newl) } infostring.Format("%4d/%4d, %3d/%3d, %2d", statvals[0], statvals[1], statvals[2], statvals[3], validlevels); - FSessionStatistics *es = StatisticsEntry(sl, infostring, AdjustTics(level.totaltime)); + FSessionStatistics *es = StatisticsEntry(sl, infostring, level.totaltime); for(unsigned i = 0; i < LevelData.Size(); i++) { diff --git a/src/swrenderer/things/r_voxel.cpp b/src/swrenderer/things/r_voxel.cpp index f324523992..75b0a2c077 100644 --- a/src/swrenderer/things/r_voxel.cpp +++ b/src/swrenderer/things/r_voxel.cpp @@ -42,6 +42,7 @@ #include "d_net.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" @@ -134,7 +135,7 @@ namespace swrenderer int voxelspin = (thing->flags & MF_DROPPED) ? voxel->DroppedSpin : voxel->PlacedSpin; if (voxelspin != 0) { - DAngle ang = double(I_FPSTime()) * voxelspin / 1000; + DAngle ang = double(screen->FrameTime) * voxelspin / 1000; vis->Angle -= ang; } diff --git a/src/textures/animations.cpp b/src/textures/animations.cpp index 7b2aab98bb..a9fa4c1bf5 100644 --- a/src/textures/animations.cpp +++ b/src/textures/animations.cpp @@ -876,7 +876,7 @@ FDoorAnimation *FTextureManager::FindAnimatedDoor (FTextureID picnum) // //========================================================================== -void FAnimDef::SetSwitchTime (uint32_t mstime) +void FAnimDef::SetSwitchTime (uint64_t mstime) { int speedframe = bDiscrete ? CurFrame : 0; @@ -917,7 +917,7 @@ void FTextureManager::SetTranslation (FTextureID fromtexnum, FTextureID totexnum // //========================================================================== -void FTextureManager::UpdateAnimations (uint32_t mstime) +void FTextureManager::UpdateAnimations (uint64_t mstime) { for (unsigned int j = 0; j < mAnimations.Size(); ++j) { diff --git a/src/textures/textures.h b/src/textures/textures.h index 96bd8d3ca8..539d38c43c 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -90,7 +90,7 @@ struct FAnimDef uint16_t CurFrame; uint8_t AnimType; bool bDiscrete; // taken out of AnimType to have better control - uint32_t SwitchTime; // Time to advance to next frame + uint64_t SwitchTime; // Time to advance to next frame struct FAnimFrame { uint32_t SpeedMin; // Speeds are in ms, not tics @@ -106,7 +106,7 @@ struct FAnimDef ANIM_Random }; - void SetSwitchTime (uint32_t mstime); + void SetSwitchTime (uint64_t mstime); }; struct FSwitchDef @@ -505,7 +505,7 @@ public: int NumTextures () const { return (int)Textures.Size(); } - void UpdateAnimations (uint32_t mstime); + void UpdateAnimations (uint64_t mstime); int GuesstimateNumTextures (); FSwitchDef *FindSwitch (FTextureID texture); @@ -604,8 +604,8 @@ public: void SetSpeed(float fac) { Speed = fac; } FTexture *GetRedirect(bool wantwarped); - uint32_t GenTime; - uint32_t GenTimeBgra; + uint64_t GenTime; + uint64_t GenTimeBgra; float Speed; int WidthOffsetMultiplier, HeightOffsetMultiplier; // [mxd] protected: @@ -613,7 +613,7 @@ protected: uint8_t *Pixels; Span **Spans; - virtual void MakeTexture (uint32_t time); + virtual void MakeTexture (uint64_t time); int NextPo2 (int v); // [mxd] void SetupMultipliers (int width, int height); // [mxd] }; diff --git a/src/textures/warpbuffer.h b/src/textures/warpbuffer.h index 668c40aeb8..62b0db13db 100644 --- a/src/textures/warpbuffer.h +++ b/src/textures/warpbuffer.h @@ -35,7 +35,7 @@ #include "textures/textures.h" template -void WarpBuffer(TYPE *Pixels, const TYPE *source, int width, int height, int xmul, int ymul, unsigned time, float Speed, int warptype) +void WarpBuffer(TYPE *Pixels, const TYPE *source, int width, int height, int xmul, int ymul, uint64_t time, float Speed, int warptype) { int ymask = height - 1; int x, y; diff --git a/src/textures/warptexture.cpp b/src/textures/warptexture.cpp index 1de8624fea..2e073c1869 100644 --- a/src/textures/warptexture.cpp +++ b/src/textures/warptexture.cpp @@ -40,6 +40,7 @@ #include "textures/textures.h" #include "warpbuffer.h" #include "v_palette.h" +#include "v_video.h" FWarpTexture::FWarpTexture (FTexture *source, int warptype) @@ -80,12 +81,12 @@ void FWarpTexture::Unload () bool FWarpTexture::CheckModified () { - return r_viewpoint.FrameTime != GenTime; + return screen->FrameTime != GenTime; } const uint8_t *FWarpTexture::GetPixels () { - uint32_t time = r_viewpoint.FrameTime; + uint64_t time = screen->FrameTime; if (Pixels == NULL || time != GenTime) { @@ -96,7 +97,7 @@ const uint8_t *FWarpTexture::GetPixels () const uint32_t *FWarpTexture::GetPixelsBgra() { - uint32_t time = r_viewpoint.FrameTime; + uint64_t time = screen->FrameTime; if (Pixels == NULL || time != GenTime) MakeTexture(time); @@ -118,7 +119,7 @@ const uint32_t *FWarpTexture::GetPixelsBgra() const uint8_t *FWarpTexture::GetColumn (unsigned int column, const Span **spans_out) { - uint32_t time = r_viewpoint.FrameTime; + uint64_t time =screen->FrameTime; if (Pixels == NULL || time != GenTime) { @@ -147,7 +148,7 @@ const uint8_t *FWarpTexture::GetColumn (unsigned int column, const Span **spans_ } -void FWarpTexture::MakeTexture(uint32_t time) +void FWarpTexture::MakeTexture(uint64_t time) { const uint8_t *otherpix = SourcePic->GetPixels(); diff --git a/src/v_video.cpp b/src/v_video.cpp index 9268125341..01ae8b428e 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -84,6 +84,7 @@ #include "r_data/voxels.h" #include "vm.h" #include "r_videoscale.h" +#include "i_time.h" EXTERN_CVAR(Bool, r_blendmethod) @@ -869,8 +870,8 @@ void DFrameBuffer::DrawRateStuff () // Draws frame time and cumulative fps if (vid_fps) { - uint32_t ms = I_FPSTime(); - uint32_t howlong = ms - LastMS; + uint64_t ms = screen->FrameTime; + uint64_t howlong = ms - LastMS; if ((signed)howlong >= 0) { char fpsbuff[40]; @@ -887,7 +888,7 @@ void DFrameBuffer::DrawRateStuff () DTA_VirtualHeight, screen->GetHeight() / textScale, DTA_KeepRatio, true, TAG_DONE); - uint32_t thisSec = ms/1000; + uint32_t thisSec = (uint32_t)(ms/1000); if (LastSec < thisSec) { LastCount = FrameCount / (thisSec - LastSec); @@ -902,8 +903,8 @@ void DFrameBuffer::DrawRateStuff () // draws little dots on the bottom of the screen if (ticker) { - int i = I_GetTime(false); - int tics = i - LastTic; + int64_t i = I_GetTime(); + int64_t tics = i - LastTic; uint8_t *buffer = GetBuffer(); LastTic = i; @@ -930,6 +931,7 @@ void DFrameBuffer::DrawRateStuff () } else { + int i; for (i = 0; i < tics*2; i += 2) Clear(i, Height-1, i+1, Height, 255, 0); for ( ; i < 20*2; i += 2) Clear(i, Height-1, i+1, Height, 0, 0); } diff --git a/src/v_video.h b/src/v_video.h index fc4d3924dd..1cbf565af5 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -442,7 +442,7 @@ public: virtual void ScaleCoordsFromWindow(int16_t &x, int16_t &y) {} - uint32_t GetLastFPS() const { return LastCount; } + uint64_t GetLastFPS() const { return LastCount; } #ifdef _WIN32 virtual void PaletteChanged () = 0; @@ -453,6 +453,7 @@ public: // The original size of the framebuffer as selected in the video menu. int VideoWidth = 0; int VideoHeight = 0; + uint64_t FrameTime = 0; protected: void DrawRateStuff (); @@ -462,7 +463,7 @@ protected: DFrameBuffer () {} private: - uint32_t LastMS, LastSec, FrameCount, LastCount, LastTic; + uint64_t LastMS, LastSec, FrameCount, LastCount, LastTic; bool isIn2D = false; }; diff --git a/src/win32/i_input.h b/src/win32/i_input.h index 500e27bb79..529ea83f54 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 diff --git a/src/win32/i_system.cpp b/src/win32/i_system.cpp index 2f1270697f..a537329e40 100644 --- a/src/win32/i_system.cpp +++ b/src/win32/i_system.cpp @@ -118,15 +118,6 @@ extern void LayoutMainWindow(HWND hWnd, HWND pane); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void CalculateCPUSpeed(); -static void I_SelectTimer(); - -static int I_GetTimePolled(bool saveMS); -static int I_WaitForTicPolled(int prevtic); -static void I_FreezeTimePolled(bool frozen); -static int I_GetTimeEventDriven(bool saveMS); -static int I_WaitForTicEvent(int prevtic); -static void I_FreezeTimeEventDriven(bool frozen); -static void CALLBACK TimerTicked(UINT id, UINT msg, DWORD_PTR user, DWORD_PTR dw1, DWORD_PTR dw2); static HCURSOR CreateCompatibleCursor(FTexture *cursorpic); static HCURSOR CreateAlphaCursor(FTexture *cursorpic); @@ -158,15 +149,9 @@ CVAR (String, queryiwad_key, "shift", CVAR_GLOBALCONFIG|CVAR_ARCHIVE); CVAR (Bool, con_debugoutput, false, 0); double PerfToSec, PerfToMillisec; -UINT TimerPeriod; -UINT TimerEventID; -UINT MillisecondsPerTic; -HANDLE NewTicArrived; uint32_t LanguageIDs[4]; -int (*I_GetTime) (bool saveMS); -int (*I_WaitForTic) (int); -void (*I_FreezeTime) (bool frozen); +UINT TimerPeriod; bool gameisdead; @@ -175,24 +160,12 @@ bool gameisdead; static ticcmd_t emptycmd; static bool HasExited; -static DWORD basetime = 0; -// These are for the polled timer. -static DWORD TicStart; -static DWORD TicNext; -static int TicFrozen; - -// These are for the event-driven timer. -static int tics; -static DWORD ted_start, ted_next; - static WadStuff *WadList; static int NumWads; static int DefaultWad; static HCURSOR CustomCursor; -// CODE -------------------------------------------------------------------- - //========================================================================== // // I_Tactile @@ -222,314 +195,6 @@ ticcmd_t *I_BaseTiccmd() return &emptycmd; } -// Stubs that select the timer to use and then call into it ---------------- - -//========================================================================== -// -// I_GetTimeSelect -// -//========================================================================== - -static int I_GetTimeSelect(bool saveMS) -{ - I_SelectTimer(); - return I_GetTime(saveMS); -} - -//========================================================================== -// -// I_WaitForTicSelect -// -//========================================================================== - -static int I_WaitForTicSelect(int prevtic) -{ - I_SelectTimer(); - return I_WaitForTic(prevtic); -} - -//========================================================================== -// -// I_SelectTimer -// -// Tries to create a timer event for efficent CPU use when the FPS is -// capped. Failing that, it sets things up for a polling timer instead. -// -//========================================================================== - -static void I_SelectTimer() -{ - assert(basetime == 0); - - // Use a timer event if possible. - NewTicArrived = CreateEvent(NULL, FALSE, FALSE, NULL); - if (NewTicArrived) - { - UINT delay; - const char *cmdDelay; - - cmdDelay = Args->CheckValue("-timerdelay"); - delay = 0; - if (cmdDelay != 0) - { - delay = atoi(cmdDelay); - } - if (delay == 0) - { - delay = 1000/TICRATE; - } - MillisecondsPerTic = delay; - TimerEventID = timeSetEvent(delay, 0, TimerTicked, 0, TIME_PERIODIC); - } - // Get the current time as the basetime. - basetime = timeGetTime(); - // Set timer functions. - if (TimerEventID != 0) - { - I_GetTime = I_GetTimeEventDriven; - I_WaitForTic = I_WaitForTicEvent; - I_FreezeTime = I_FreezeTimeEventDriven; - } - else - { - I_GetTime = I_GetTimePolled; - I_WaitForTic = I_WaitForTicPolled; - I_FreezeTime = I_FreezeTimePolled; - } -} - -//========================================================================== -// -// I_MSTime -// -// Returns the current time in milliseconds, where 0 is the first call -// to I_GetTime or I_WaitForTic. -// -//========================================================================== - -unsigned int I_MSTime() -{ - assert(basetime != 0); - return timeGetTime() - basetime; -} - -//========================================================================== -// -// I_FPSTime -// -// Returns the current system time in milliseconds. This is used by the FPS -// meter of DFrameBuffer::DrawRateStuff(). Since the screen can display -// before the play simulation is ready to begin, this needs to be -// separate from I_MSTime(). -// -//========================================================================== - -unsigned int I_FPSTime() -{ - return timeGetTime(); -} - -//========================================================================== -// -// I_GetTimePolled -// -// Returns the current time in tics. If saveMS is true, then calls to -// I_GetTimeFrac() will use this tic as 0 and the next tic as 1. -// -//========================================================================== - -static int I_GetTimePolled(bool saveMS) -{ - DWORD tm; - - if (TicFrozen != 0) - { - return TicFrozen; - } - - tm = timeGetTime(); - if (basetime == 0) - { - basetime = tm; - } - if (saveMS) - { - TicStart = tm; - TicNext = (tm * TICRATE / 1000 + 1) * 1000 / TICRATE; - } - - return ((tm-basetime)*TICRATE)/1000; -} - -//========================================================================== -// -// I_WaitForTicPolled -// -// Busy waits until the current tic is greater than prevtic. Time must not -// be frozen. -// -//========================================================================== - -static int I_WaitForTicPolled(int prevtic) -{ - int time; - - assert(TicFrozen == 0); - while ((time = I_GetTimePolled(false)) <= prevtic) - { } - - return time; -} - -//========================================================================== -// -// I_FreezeTimePolled -// -// Freeze/unfreeze the timer. -// -//========================================================================== - -static void I_FreezeTimePolled(bool frozen) -{ - if (frozen) - { - assert(TicFrozen == 0); - TicFrozen = I_GetTimePolled(false); - } - else - { - assert(TicFrozen != 0); - int froze = TicFrozen; - TicFrozen = 0; - int now = I_GetTimePolled(false); - basetime += (now - froze) * 1000 / TICRATE; - } -} - -//========================================================================== -// -// I_GetTimeEventDriven -// -// Returns the current tick counter. This is incremented asynchronously as -// the timer event fires. -// -//========================================================================== - -static int I_GetTimeEventDriven(bool saveMS) -{ - if (saveMS) - { - TicStart = ted_start; - TicNext = ted_next; - } - return tics; -} - -//========================================================================== -// -// I_WaitForTicEvent -// -// Waits on the timer event as long as the current tic is not later than -// prevtic. -// -//========================================================================== - -static int I_WaitForTicEvent(int prevtic) -{ - assert(!TicFrozen); - while (prevtic >= tics) - { - WaitForSingleObject(NewTicArrived, 1000/TICRATE); - } - return tics; -} - -//========================================================================== -// -// I_FreezeTimeEventDriven -// -// Freeze/unfreeze the ticker. -// -//========================================================================== - -static void I_FreezeTimeEventDriven(bool frozen) -{ - TicFrozen = frozen; -} - -//========================================================================== -// -// TimerTicked -// -// Advance the tick count and signal the NewTicArrived event. -// -//========================================================================== - -static void CALLBACK TimerTicked(UINT id, UINT msg, DWORD_PTR user, DWORD_PTR dw1, DWORD_PTR dw2) -{ - if (!TicFrozen) - { - tics++; - } - ted_start = timeGetTime (); - ted_next = ted_start + MillisecondsPerTic; - SetEvent(NewTicArrived); -} - -//========================================================================== -// -// I_GetTimeFrac -// -// Returns the fractional amount of a tic passed since the most recently -// saved tic. -// -//========================================================================== -static uint32_t FrameTime; - -void I_SetFrameTime() -{ - FrameTime = timeGetTime(); -} - -double I_GetTimeFrac(uint32_t *ms) -{ - //DWORD now = MAX(FrameTime, TicStart); - DWORD now = FrameTime; - if (FrameTime < TicStart) - { - // Preliminary kept in to see if this can happen. Should be removed once confirmed ok. - Printf("Timer underflow!\n"); - } - if (ms != NULL) - { - *ms = TicNext; - } - DWORD step = TicNext - TicStart; - if (step == 0) - { - return 1.; - } - else - { - return clamp(double(now - TicStart) / step, 0, 1); - } -} - -//========================================================================== -// -// I_WaitVBL -// -// 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. -// -//========================================================================== - -void I_WaitVBL(int count) -{ - Sleep(1000 * count / 70); -} - //========================================================================== // // I_DetectOS @@ -736,9 +401,6 @@ void I_Init() CalculateCPUSpeed(); DumpCPUInfo(&CPU); - I_GetTime = I_GetTimeSelect; - I_WaitForTic = I_WaitForTicSelect; - atterm (I_ShutdownSound); I_InitSound (); } @@ -753,15 +415,8 @@ void I_Quit() { HasExited = true; /* Prevent infinitely recursive exits -- killough */ - if (TimerEventID != 0) - { - timeKillEvent(TimerEventID); - } - if (NewTicArrived != NULL) - { - CloseHandle(NewTicArrived); - } timeEndPeriod(TimerPeriod); + if (demorecording) { G_CheckDemoStatus(); diff --git a/src/win32/i_system.h b/src/win32/i_system.h index 8c4699c281..a5f7b5d0ba 100644 --- a/src/win32/i_system.h +++ b/src/win32/i_system.h @@ -50,21 +50,6 @@ void I_DetectOS (void); // Called by DoomMain. void I_Init (void); -// Called by D_DoomLoop, returns current time in tics. -extern int (*I_GetTime) (bool saveMS); - -// like I_GetTime, except it waits for a new tic before returning -extern 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). -extern void (*I_FreezeTime) (bool frozen); - -double I_GetTimeFrac (uint32_t *ms); -void I_SetFrameTime(); - // Return a seed value for the RNG. unsigned int I_MakeRNGSeed(); @@ -132,10 +117,6 @@ int I_PickIWad (WadStuff *wads, int numwads, bool queryiwad, int defaultiwad); // The ini could not be saved at exit bool I_WriteIniFailed (); -// [RH] Returns millisecond-accurate time -unsigned int I_MSTime (void); -unsigned int I_FPSTime(); - // [RH] Used by the display code to set the normal window procedure void I_SetWndProc();