diff --git a/GNUmakefile b/GNUmakefile
index c3c4b8f9d..eb6a93951 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -234,6 +234,7 @@ engine_objs := \
softsurface.cpp \
mmulti_null.cpp \
mutex.cpp \
+ timer.cpp \
xxhash.c \
md4.cpp \
colmatch.cpp \
diff --git a/platform/Windows/build.vcxproj b/platform/Windows/build.vcxproj
index 67cafed1e..0699f7305 100644
--- a/platform/Windows/build.vcxproj
+++ b/platform/Windows/build.vcxproj
@@ -293,6 +293,7 @@
+
true
@@ -372,6 +373,7 @@
+
diff --git a/platform/Windows/build.vcxproj.filters b/platform/Windows/build.vcxproj.filters
index 82947b6ec..d92070762 100644
--- a/platform/Windows/build.vcxproj.filters
+++ b/platform/Windows/build.vcxproj.filters
@@ -191,6 +191,8 @@
GL Interface
+
+ Source Files
GL Interface
@@ -394,7 +396,9 @@
Header Files
-
+
+ Header Files
+
GL Interface
diff --git a/source/build/include/baselayer.h b/source/build/include/baselayer.h
index 9a94fd7e9..ac56fb730 100644
--- a/source/build/include/baselayer.h
+++ b/source/build/include/baselayer.h
@@ -9,6 +9,7 @@
#include "compat.h"
#include "osd.h"
+#include "timer.h"
#ifdef __cplusplus
extern "C" {
@@ -262,21 +263,6 @@ void joySetDeadZone(int32_t axis, uint16_t dead, uint16_t satur);
void joyGetDeadZone(int32_t axis, uint16_t *dead, uint16_t *satur);
extern int32_t inputchecked;
-int32_t timerInit(int32_t);
-void timerUninit(void);
-void timerUpdate(void);
-int32_t timerGetFreq(void);
-uint64_t timerGetTicksU64(void);
-uint64_t timerGetFreqU64(void);
-double timerGetHiTicks(void);
-void (*timerSetCallback(void (*callback)(void)))(void);
-
-#if defined RENDERTYPESDL && !defined LUNATIC
-static FORCE_INLINE uint32_t timerGetTicks(void) { return (uint32_t)SDL_GetTicks(); }
-#else
-uint32_t timerGetTicks(void);
-#endif
-
int32_t wm_msgbox(const char *name, const char *fmt, ...) ATTRIBUTE((format(printf,2,3)));
int32_t wm_ynbox(const char *name, const char *fmt, ...) ATTRIBUTE((format(printf,2,3)));
void wm_setapptitle(const char *name);
diff --git a/source/build/include/timer.h b/source/build/include/timer.h
new file mode 100644
index 000000000..d72c21f66
--- /dev/null
+++ b/source/build/include/timer.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#ifndef timer_h__
+#define timer_h__
+
+#include "compat.h"
+
+int32_t timerInit(int32_t);
+void timerUninit(void);
+void timerUpdate(void);
+int32_t timerGetRate(void);
+uint64_t timerGetTicksU64(void);
+uint64_t timerGetFreqU64(void);
+double timerGetHiTicks(void);
+uint32_t timerGetTicks(void);
+void (*timerSetCallback(void (*callback)(void)))(void);
+
+#endif // timer_h__
diff --git a/source/build/src/mdsprite.cpp b/source/build/src/mdsprite.cpp
index 8ca4aaa73..6391c2995 100644
--- a/source/build/src/mdsprite.cpp
+++ b/source/build/src/mdsprite.cpp
@@ -92,8 +92,6 @@ static mdmodel_t *mdload(const char *);
static void mdfree(mdmodel_t *);
int32_t globalnoeffect=0;
-extern int32_t timerticspersec;
-
void freeallmodels()
{
int32_t i;
@@ -1010,7 +1008,7 @@ void updateanimation(md2model_t *m, tspriteptr_t tspr, uint8_t lpal)
fps = smooth->mdsmooth ? Blrintf((1.0f / ((float)tile2model[tile].smoothduration * (1.f / (float)UINT16_MAX))) * 66.f)
: anim ? anim->fpssc : 1;
- i = (mdtims - sprext->mdanimtims) * ((fps * timerticspersec) / 120);
+ i = (mdtims - sprext->mdanimtims) * ((fps * timerGetRate()) / 120);
j = (smooth->mdsmooth || !anim) ? 65536 : ((anim->endframe + 1 - anim->startframe) << 16);
@@ -1018,7 +1016,7 @@ void updateanimation(md2model_t *m, tspriteptr_t tspr, uint8_t lpal)
if (i < 0) { i = 0; sprext->mdanimtims = mdtims; }
//compare with j*2 instead of j to ensure i stays > j-65536 for MDANIM_ONESHOT
if (anim && (i >= j+j) && (fps) && !mdpause) //Keep mdanimtims close to mdtims to avoid the use of MOD
- sprext->mdanimtims += j/((fps*timerticspersec)/120);
+ sprext->mdanimtims += j/((fps*timerGetRate())/120);
k = i;
diff --git a/source/build/src/osd.cpp b/source/build/src/osd.cpp
index c153a531a..fc8a7393b 100644
--- a/source/build/src/osd.cpp
+++ b/source/build/src/osd.cpp
@@ -320,8 +320,8 @@ static int osdfunc_fileinfo(osdcmdptr_t parm)
" CRC-32: %08X (%g sec)\n"
" xxHash: %08X (%g sec)\n",
parm->parms[0], kfilelength(h),
- crcval, (double)crctime/timerGetFreq(),
- xxhash, (double)xxhtime/timerGetFreq());
+ crcval, (double)crctime/timerGetRate(),
+ xxhash, (double)xxhtime/timerGetRate());
kclose(h);
diff --git a/source/build/src/sdlayer.cpp b/source/build/src/sdlayer.cpp
index ead13e21e..ace92afef 100644
--- a/source/build/src/sdlayer.cpp
+++ b/source/build/src/sdlayer.cpp
@@ -1169,123 +1169,6 @@ void joyGetDeadZone(int32_t axis, uint16_t *dead, uint16_t *satur)
//
//
-static uint32_t timerfreq;
-static uint32_t timerlastsample;
-int32_t timerticspersec=0;
-static double msperu64tick = 0;
-static void(*usertimercallback)(void) = NULL;
-
-
-//
-// inittimer() -- initialize timer
-//
-int32_t timerInit(int32_t tickspersecond)
-{
- if (timerfreq) return 0; // already installed
-
-// initprintf("Initializing timer\n");
-
-#if defined(_WIN32) && SDL_MAJOR_VERSION == 1
- int32_t t = win_inittimer();
- if (t < 0)
- return t;
-#endif
-
- timerfreq = 1000;
- timerticspersec = tickspersecond;
- timerlastsample = SDL_GetTicks() * timerticspersec / timerfreq;
-
- usertimercallback = NULL;
-
- msperu64tick = 1000.0 / (double)timerGetFreqU64();
-
- return 0;
-}
-
-//
-// uninittimer() -- shut down timer
-//
-void timerUninit(void)
-{
- timerfreq=0;
-#if defined(_WIN32) && SDL_MAJOR_VERSION==1
- win_timerfreq=0;
-#endif
- msperu64tick = 0;
-}
-
-//
-// sampletimer() -- update totalclock
-//
-void timerUpdate(void)
-{
- if (!timerfreq) return;
-
- int64_t i = SDL_GetTicks();
- int32_t n = tabledivide64(i * timerticspersec, timerfreq) - timerlastsample;
-
- if (n <= 0) return;
-
- totalclock += n;
- timerlastsample += n;
-
- if (usertimercallback)
- for (; n > 0; n--) usertimercallback();
-}
-
-#if defined LUNATIC
-//
-// getticks() -- returns the sdl ticks count
-//
-uint32_t timerGetTicks(void)
-{
- return (uint32_t)SDL_GetTicks();
-}
-#endif
-
-// high-resolution timers for profiling
-
-#if SDL_MAJOR_VERSION != 1
-uint64_t timerGetTicksU64(void)
-{
- return SDL_GetPerformanceCounter();
-}
-
-uint64_t timerGetFreqU64(void)
-{
- return SDL_GetPerformanceFrequency();
-}
-#endif
-
-// Returns the time since an unspecified starting time in milliseconds.
-// (May be not monotonic for certain configurations.)
-ATTRIBUTE((flatten))
-double timerGetHiTicks(void)
-{
- return (double)timerGetTicksU64() * msperu64tick;
-}
-
-//
-// gettimerfreq() -- returns the number of ticks per second the timer is configured to generate
-//
-int32_t timerGetFreq(void)
-{
- return timerticspersec;
-}
-
-
-//
-// installusertimercallback() -- set up a callback function to be called when the timer is fired
-//
-void(*timerSetCallback(void(*callback)(void)))(void)
-{
- void(*oldtimercallback)(void);
-
- oldtimercallback = usertimercallback;
- usertimercallback = callback;
-
- return oldtimercallback;
-}
diff --git a/source/build/src/sdlayer12.cpp b/source/build/src/sdlayer12.cpp
index e2db358da..bedc4d0ab 100644
--- a/source/build/src/sdlayer12.cpp
+++ b/source/build/src/sdlayer12.cpp
@@ -173,52 +173,6 @@ static inline char grabmouse_low(char a)
#endif
}
-// high-resolution timers for profiling
-uint64_t timerGetTicksU64(void)
-{
-# if defined _WIN32
- return win_getu64ticks();
-# elif defined __APPLE__
- return mach_absolute_time();
-# elif _POSIX_TIMERS>0 && defined _POSIX_MONOTONIC_CLOCK
- // This is SDL HG's SDL_GetPerformanceCounter() when clock_gettime() is
- // available.
- uint64_t ticks;
- struct timespec now;
-
- clock_gettime(CLOCK_MONOTONIC, &now);
- ticks = now.tv_sec;
- ticks *= 1000000000;
- ticks += now.tv_nsec;
- return ticks;
-# elif defined GEKKO
- return ticks_to_nanosecs(gettime());
-# else
- // Blar. This pragma is unsupported on earlier GCC versions.
- // At least we'll get a warning and a reference to this line...
-# pragma message "Using low-resolution (1ms) timer for getu64ticks. Profiling will work badly."
- return SDL_GetTicks();
-# endif
-}
-
-uint64_t timerGetFreqU64(void)
-{
-# if defined _WIN32
- return win_timerfreq;
-# elif defined __APPLE__
- static mach_timebase_info_data_t ti;
- if (ti.denom == 0)
- (void) mach_timebase_info(&ti); // ti.numer/ti.denom: nsec/(m_a_t() tick)
- return (1000000000LL*ti.denom)/ti.numer;
-# elif _POSIX_TIMERS>0 && defined _POSIX_MONOTONIC_CLOCK
- return 1000000000;
-# elif defined GEKKO
- return TB_NSPERSEC;
-# else
- return 1000;
-# endif
-}
-
void videoGetModes(void)
{
int32_t i, maxx = 0, maxy = 0;
diff --git a/source/build/src/timer.cpp b/source/build/src/timer.cpp
new file mode 100644
index 000000000..67a31f664
--- /dev/null
+++ b/source/build/src/timer.cpp
@@ -0,0 +1,60 @@
+
+#include "timer.h"
+
+#include "build.h"
+#include "compat.h"
+
+#include
+
+using namespace std;
+using namespace chrono;
+
+static int32_t timerlastsample;
+static int32_t timerticspersec=0;
+static void(*usertimercallback)(void) = NULL;
+
+int32_t timerGetRate(void) { return timerticspersec; }
+void timerUninit(void) { timerticspersec = 0; }
+
+uint32_t timerGetTicks(void) { return duration_cast(system_clock::now().time_since_epoch()).count(); }
+uint64_t timerGetTicksU64(void) { return high_resolution_clock::now().time_since_epoch().count(); }
+uint64_t timerGetFreqU64(void) { return high_resolution_clock::period::den; }
+
+// Returns the time since an unspecified starting time in milliseconds.
+// (May be not monotonic for certain configurations.)
+ATTRIBUTE((flatten))
+double timerGetHiTicks(void) { return duration(high_resolution_clock::now().time_since_epoch()).count(); }
+
+int32_t timerInit(int32_t const tickspersecond)
+{
+ timerticspersec = tickspersecond;
+ timerlastsample = timerGetTicksU64() * timerticspersec / timerGetFreqU64();
+
+ usertimercallback = NULL;
+
+ return 0;
+}
+
+void timerUpdate(void)
+{
+ if (!timerticspersec) return;
+
+ uint64_t n = (timerGetTicksU64() * timerticspersec / timerGetFreqU64()) - timerlastsample;
+ if (n <= 0) return;
+
+ totalclock += n;
+ timerlastsample += n;
+
+ if (usertimercallback)
+ for (; n > 0; n--) usertimercallback();
+}
+
+void(*timerSetCallback(void(*callback)(void)))(void)
+{
+ void(*oldtimercallback)(void);
+
+ oldtimercallback = usertimercallback;
+ usertimercallback = callback;
+
+ return oldtimercallback;
+}
diff --git a/source/build/src/winbits.cpp b/source/build/src/winbits.cpp
index cdc1e24cd..284abafcf 100644
--- a/source/build/src/winbits.cpp
+++ b/source/build/src/winbits.cpp
@@ -18,8 +18,6 @@
int32_t backgroundidle = 1;
-int64_t win_timerfreq = 0;
-
char silentvideomodeswitch = 0;
static char taskswitching = 1;
@@ -147,38 +145,6 @@ int32_t win_checkinstance(void)
return (WaitForSingleObject(instanceflag,0) == WAIT_TIMEOUT);
}
-//
-// high-resolution timers for profiling
-//
-#if defined(RENDERTYPEWIN) || SDL_MAJOR_VERSION==1
-int32_t win_inittimer(void)
-{
- int64_t t;
-
- if (win_timerfreq) return 0; // already installed
-
- // OpenWatcom seems to want us to query the value into a local variable
- // instead of the global 'win_timerfreq' or else it gets pissed with an
- // access violation
- if (!QueryPerformanceFrequency((LARGE_INTEGER *)&t))
- {
- ShowErrorBox("Failed fetching timer frequency");
- return -1;
- }
- win_timerfreq = t;
-
- return 0;
-}
-
-uint64_t win_getu64ticks(void)
-{
- uint64_t i;
- if (win_timerfreq == 0) return 0;
- QueryPerformanceCounter((LARGE_INTEGER *)&i);
- return i;
-}
-#endif
-
static void ToggleDesktopComposition(BOOL compEnable)
{
diff --git a/source/build/src/winlayer.cpp b/source/build/src/winlayer.cpp
index a8b262510..d2763ab5a 100644
--- a/source/build/src/winlayer.cpp
+++ b/source/build/src/winlayer.cpp
@@ -1369,132 +1369,6 @@ static const char *GetDInputError(HRESULT code)
-//-------------------------------------------------------------------------------------------------
-// TIMER
-//=================================================================================================
-
-static int32_t timerlastsample=0;
-int32_t timerticspersec=0;
-static double msperu64tick = 0;
-static void (*usertimercallback)(void) = NULL;
-
-// This timer stuff is all Ken's idea.
-
-//
-// installusertimercallback() -- set up a callback function to be called when the timer is fired
-//
-void (*timerSetCallback(void (*callback)(void)))(void)
-{
- void (*oldtimercallback)(void);
-
- oldtimercallback = usertimercallback;
- usertimercallback = callback;
-
- return oldtimercallback;
-}
-
-
-//
-// inittimer() -- initialize timer
-//
-int32_t timerInit(int32_t tickspersecond)
-{
- int64_t t;
-
- if (win_timerfreq) return 0; // already installed
-
- // initprintf("Initializing timer\n");
-
- t = win_inittimer();
- if (t < 0)
- return t;
-
- timerticspersec = tickspersecond;
- QueryPerformanceCounter((LARGE_INTEGER *)&t);
- timerlastsample = (int32_t)(t*timerticspersec / win_timerfreq);
-
- usertimercallback = NULL;
-
- msperu64tick = 1000.0 / (double)timerGetFreqU64();
-
- return 0;
-}
-
-//
-// uninittimer() -- shut down timer
-//
-void timerUninit(void)
-{
- if (!win_timerfreq) return;
-
- win_timerfreq=0;
- timerticspersec = 0;
-
- msperu64tick = 0;
-}
-
-//
-// sampletimer() -- update totalclock
-//
-void timerUpdate(void)
-{
- int64_t i;
- int32_t n;
-
- if (!win_timerfreq) return;
-
- QueryPerformanceCounter((LARGE_INTEGER *)&i);
- n = (int32_t)((i*timerticspersec / win_timerfreq) - timerlastsample);
-
- if (n <= 0) return;
-
- totalclock += n;
- timerlastsample += n;
-
- if (usertimercallback) for (; n>0; n--) usertimercallback();
-}
-
-
-//
-// getticks() -- returns the windows ticks count
-//
-uint32_t timerGetTicks(void)
-{
- int64_t i;
- if (win_timerfreq == 0) return 0;
- QueryPerformanceCounter((LARGE_INTEGER *)&i);
- return (uint32_t)(i*longlong(1000)/win_timerfreq);
-}
-
-// high-resolution timers for profiling
-uint64_t timerGetTicksU64(void)
-{
- return win_getu64ticks();
-}
-
-uint64_t timerGetFreqU64(void)
-{
- return win_timerfreq;
-}
-
-// Returns the time since an unspecified starting time in milliseconds.
-ATTRIBUTE((flatten))
-double timerGetHiTicks(void)
-{
- return (double)timerGetTicksU64() * msperu64tick;
-}
-
-//
-// gettimerfreq() -- returns the number of ticks per second the timer is configured to generate
-//
-int32_t timerGetFreq(void)
-{
- return timerticspersec;
-}
-
-
-
-
//-------------------------------------------------------------------------------------------------
// VIDEO
//=================================================================================================