mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-22 04:21:23 +00:00
Completely refactor timing system
Time is now tracked internally in the game using I_GetPreciseTime and I_UpdateTime. I_Time now pulls from this internal timer. The system code no longer needs to keep track of time itself. This significantly improves frame and tic timing in interp mode, resulting in a much smoother image with essentially no judder at any framerate.
This commit is contained in:
parent
dcbe929baa
commit
e79654a33a
22 changed files with 193 additions and 124 deletions
|
@ -18,6 +18,7 @@ am_map.c
|
|||
command.c
|
||||
console.c
|
||||
hu_stuff.c
|
||||
i_time.c
|
||||
y_inter.c
|
||||
st_stuff.c
|
||||
m_aatree.c
|
||||
|
|
|
@ -82,18 +82,6 @@ INT64 current_time_in_ps() {
|
|||
return (t.tv_sec * (INT64)1000000) + t.tv_usec;
|
||||
}
|
||||
|
||||
tic_t I_GetTime(void)
|
||||
{
|
||||
INT64 since_start = current_time_in_ps() - start_time;
|
||||
return (since_start*TICRATE)/1000000;
|
||||
}
|
||||
|
||||
fixed_t I_GetTimeFrac(void)
|
||||
{
|
||||
//stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
void I_Sleep(void){}
|
||||
|
||||
void I_GetEvent(void){}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <unistd.h> //for unlink
|
||||
#endif
|
||||
|
||||
#include "i_time.h"
|
||||
#include "i_net.h"
|
||||
#include "i_system.h"
|
||||
#include "i_video.h"
|
||||
|
|
68
src/d_main.c
68
src/d_main.c
|
@ -40,6 +40,7 @@
|
|||
#include "hu_stuff.h"
|
||||
#include "i_sound.h"
|
||||
#include "i_system.h"
|
||||
#include "i_time.h"
|
||||
#include "i_threads.h"
|
||||
#include "i_video.h"
|
||||
#include "m_argv.h"
|
||||
|
@ -695,10 +696,9 @@ tic_t rendergametic;
|
|||
|
||||
void D_SRB2Loop(void)
|
||||
{
|
||||
tic_t oldentertics = 0, entertic = 0, realtics = 0, rendertimeout = INFTICS;
|
||||
tic_t realtics = 0, rendertimeout = INFTICS;
|
||||
static lumpnum_t gstartuplumpnum;
|
||||
|
||||
boolean ticked = false;
|
||||
boolean interp = false;
|
||||
boolean doDisplay = false;
|
||||
boolean screenUpdate = false;
|
||||
|
@ -715,7 +715,7 @@ void D_SRB2Loop(void)
|
|||
I_DoStartupMouse();
|
||||
#endif
|
||||
|
||||
oldentertics = I_GetTime();
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
|
||||
// end of loading screen: CONS_Printf() will no more call FinishUpdate()
|
||||
con_refresh = false;
|
||||
|
@ -757,17 +757,18 @@ void D_SRB2Loop(void)
|
|||
{
|
||||
frameEnd = I_GetFrameTime();
|
||||
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
|
||||
// Can't guarantee that I_UpdateTime won't be called inside TryRunTics
|
||||
// so capture the realtics for later use
|
||||
realtics = g_time.realtics;
|
||||
|
||||
if (lastwipetic)
|
||||
{
|
||||
oldentertics = lastwipetic;
|
||||
// oldentertics = lastwipetic;
|
||||
lastwipetic = 0;
|
||||
}
|
||||
|
||||
// get real tics
|
||||
entertic = I_GetTime();
|
||||
realtics = entertic - oldentertics;
|
||||
oldentertics = entertic;
|
||||
|
||||
if (demoplayback && gamestate == GS_LEVEL)
|
||||
{
|
||||
// Nicer place to put this.
|
||||
|
@ -782,7 +783,6 @@ void D_SRB2Loop(void)
|
|||
|
||||
interp = R_UsingFrameInterpolation() && !dedicated;
|
||||
doDisplay = screenUpdate = false;
|
||||
ticked = false;
|
||||
|
||||
#ifdef HW3SOUND
|
||||
HW3S_BeginFrameUpdate();
|
||||
|
@ -798,16 +798,16 @@ void D_SRB2Loop(void)
|
|||
realtics = 1;
|
||||
|
||||
// process tics (but maybe not if realtic == 0)
|
||||
ticked = TryRunTics(realtics);
|
||||
TryRunTics(realtics);
|
||||
|
||||
if (lastdraw || singletics || gametic > rendergametic)
|
||||
{
|
||||
rendergametic = gametic;
|
||||
rendertimeout = entertic+TICRATE/17;
|
||||
rendertimeout = g_time.time + TICRATE/17;
|
||||
|
||||
doDisplay = true;
|
||||
}
|
||||
else if (rendertimeout < entertic) // in case the server hang or netsplit
|
||||
else if (rendertimeout < g_time.time) // in case the server hang or netsplit
|
||||
{
|
||||
// Lagless camera! Yay!
|
||||
if (gamestate == GS_LEVEL && netgame)
|
||||
|
@ -836,41 +836,21 @@ void D_SRB2Loop(void)
|
|||
|
||||
if (interp)
|
||||
{
|
||||
static float tictime = 0.0f;
|
||||
static float prevtime = 0.0f;
|
||||
float entertime = I_GetTimeFrac();
|
||||
|
||||
fixed_t entertimefrac = FRACUNIT;
|
||||
|
||||
if (ticked)
|
||||
{
|
||||
tictime = entertime;
|
||||
}
|
||||
|
||||
// I looked at the possibility of putting in a float drawer for
|
||||
// perfstats and it's very complicated, so we'll just do this instead...
|
||||
ps_interp_frac.value.p = (precise_t)((entertime - tictime) * 1000.0f);
|
||||
ps_interp_lag.value.p = (precise_t)((entertime - prevtime) * 1000.0f);
|
||||
ps_interp_frac.value.p = (precise_t)((FIXED_TO_FLOAT(g_time.timefrac)) * 1000.0f);
|
||||
ps_interp_lag.value.p = (precise_t)((FIXED_TO_FLOAT(g_time.deltaseconds)) * 1000.0f);
|
||||
|
||||
renderdeltatics = g_time.deltatics;
|
||||
|
||||
if (!(paused || P_AutoPause()))
|
||||
{
|
||||
if (entertime - prevtime >= 1.0f)
|
||||
{
|
||||
// Lagged for more frames than a gametic...
|
||||
// No need for interpolation.
|
||||
entertimefrac = FRACUNIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
entertimefrac = min(FRACUNIT, FLOAT_TO_FIXED(entertime - tictime));
|
||||
}
|
||||
|
||||
// renderdeltatics is a bit awkard to evaluate, since the system time interface is whole tic-based
|
||||
renderdeltatics = FloatToFixed(entertime - prevtime);
|
||||
rendertimefrac = entertimefrac;
|
||||
rendertimefrac = g_time.timefrac;
|
||||
}
|
||||
else
|
||||
{
|
||||
rendertimefrac = FRACUNIT;
|
||||
}
|
||||
|
||||
prevtime = entertime;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1398,8 +1378,8 @@ void D_SRB2Main(void)
|
|||
//---------------------------------------------------- READY TIME
|
||||
// we need to check for dedicated before initialization of some subsystems
|
||||
|
||||
CONS_Printf("I_StartupTimer()...\n");
|
||||
I_StartupTimer();
|
||||
CONS_Printf("I_InitializeTime()...\n");
|
||||
I_InitializeTime();
|
||||
|
||||
// Make backups of some SOCcable tables.
|
||||
P_BackupTables();
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "doomdef.h"
|
||||
#include "g_game.h"
|
||||
#include "i_time.h"
|
||||
#include "i_net.h"
|
||||
#include "i_system.h"
|
||||
#include "m_argv.h"
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "console.h"
|
||||
#include "command.h"
|
||||
#include "i_time.h"
|
||||
#include "i_system.h"
|
||||
#include "g_game.h"
|
||||
#include "hu_stuff.h"
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "doomstat.h"
|
||||
#include "d_main.h"
|
||||
#include "g_game.h"
|
||||
#include "i_time.h"
|
||||
#include "i_net.h"
|
||||
#include "i_system.h"
|
||||
#include "m_argv.h"
|
||||
|
|
|
@ -11,16 +11,6 @@ UINT32 I_GetFreeMem(UINT32 *total)
|
|||
return 0;
|
||||
}
|
||||
|
||||
tic_t I_GetTime(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
fixed_t I_GetTimeFrac(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void I_Sleep(void){}
|
||||
|
||||
void I_GetEvent(void){}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "hu_stuff.h"
|
||||
#include "r_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "i_time.h"
|
||||
#include "i_video.h"
|
||||
#include "v_video.h"
|
||||
#include "w_wad.h"
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "w_wad.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
#include "i_time.h"
|
||||
#include "i_system.h"
|
||||
#include "i_threads.h"
|
||||
#include "m_menu.h"
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "d_player.h"
|
||||
#include "d_clisrv.h"
|
||||
#include "p_setup.h"
|
||||
#include "i_time.h"
|
||||
#include "i_system.h"
|
||||
#include "m_random.h"
|
||||
#include "p_local.h"
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "f_finale.h"
|
||||
#include "p_setup.h"
|
||||
#include "p_saveg.h"
|
||||
#include "i_time.h"
|
||||
#include "i_system.h"
|
||||
#include "am_map.h"
|
||||
#include "m_random.h"
|
||||
|
|
|
@ -42,14 +42,6 @@ extern UINT8 keyboard_started;
|
|||
*/
|
||||
UINT32 I_GetFreeMem(UINT32 *total);
|
||||
|
||||
/** \brief Called by D_SRB2Loop, returns current time in game tics.
|
||||
*/
|
||||
tic_t I_GetTime(void);
|
||||
|
||||
/** \brief Get the current time in game tics, including fractions.
|
||||
*/
|
||||
float I_GetTimeFrac(void);
|
||||
|
||||
/** \brief Returns precise time value for performance measurement.
|
||||
*/
|
||||
precise_t I_GetPreciseTime(void);
|
||||
|
@ -58,6 +50,10 @@ precise_t I_GetPreciseTime(void);
|
|||
*/
|
||||
int I_PreciseToMicros(precise_t d);
|
||||
|
||||
/** \brief Calculates the elapsed microseconds between two precise_t.
|
||||
*/
|
||||
double I_PreciseElapsedSeconds(precise_t before, precise_t after);
|
||||
|
||||
/** \brief Get the current time in rendering tics, including fractions.
|
||||
*/
|
||||
double I_GetFrameTime(void);
|
||||
|
|
86
src/i_time.c
Normal file
86
src/i_time.c
Normal file
|
@ -0,0 +1,86 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2022 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file i_time.c
|
||||
/// \brief Timing for the system layer.
|
||||
|
||||
#include "i_time.h"
|
||||
|
||||
#include "command.h"
|
||||
#include "doomtype.h"
|
||||
#include "m_fixed.h"
|
||||
#include "i_system.h"
|
||||
|
||||
timestate_t g_time;
|
||||
|
||||
static CV_PossibleValue_t timescale_cons_t[] = {{FRACUNIT/20, "MIN"}, {20*FRACUNIT, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_timescale = CVAR_INIT ("timescale", "1.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, timescale_cons_t, NULL);
|
||||
|
||||
static precise_t enterprecise, oldenterprecise;
|
||||
static fixed_t entertic, oldentertics;
|
||||
static double tictimer;
|
||||
|
||||
tic_t I_GetTime(void)
|
||||
{
|
||||
return g_time.time;
|
||||
}
|
||||
|
||||
void I_InitializeTime(void)
|
||||
{
|
||||
g_time.time = 0;
|
||||
g_time.timefrac = 0;
|
||||
g_time.realtics = 0;
|
||||
g_time.deltaseconds = 0;
|
||||
g_time.ticrate = FLOAT_TO_FIXED(TICRATE);
|
||||
|
||||
enterprecise = 0;
|
||||
oldenterprecise = 0;
|
||||
tictimer = 0.0;
|
||||
|
||||
CV_RegisterVar(&cv_timescale);
|
||||
|
||||
// I_StartupTimer is preserved for potential subsystems that need to setup
|
||||
// timing information for I_GetPreciseTime and sleeping
|
||||
I_StartupTimer();
|
||||
}
|
||||
|
||||
void I_UpdateTime(fixed_t timescale)
|
||||
{
|
||||
double ticratescaled;
|
||||
double elapsedseconds;
|
||||
tic_t realtics;
|
||||
|
||||
// get real tics
|
||||
ticratescaled = (double)TICRATE * FIXED_TO_FLOAT(timescale);
|
||||
|
||||
enterprecise = I_GetPreciseTime();
|
||||
elapsedseconds = I_PreciseElapsedSeconds(oldenterprecise, enterprecise);
|
||||
tictimer += elapsedseconds;
|
||||
while (tictimer > 1.0/ticratescaled)
|
||||
{
|
||||
entertic += 1;
|
||||
tictimer -= 1.0/ticratescaled;
|
||||
}
|
||||
realtics = entertic - oldentertics;
|
||||
oldentertics = entertic;
|
||||
oldenterprecise = enterprecise;
|
||||
|
||||
// Update global time state
|
||||
g_time.time += realtics;
|
||||
{
|
||||
double fractional, integral;
|
||||
fractional = modf(tictimer * ticratescaled, &integral);
|
||||
g_time.timefrac = FLOAT_TO_FIXED(fractional);
|
||||
}
|
||||
g_time.realtics = realtics;
|
||||
g_time.deltatics = FLOAT_TO_FIXED(elapsedseconds * ticratescaled);
|
||||
g_time.deltaseconds = FLOAT_TO_FIXED(elapsedseconds);
|
||||
g_time.ticrate = FLOAT_TO_FIXED(ticratescaled);
|
||||
}
|
51
src/i_time.h
Normal file
51
src/i_time.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2022 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file i_time.h
|
||||
/// \brief Timing for the system layer.
|
||||
|
||||
#ifndef __I_TIME_H__
|
||||
#define __I_TIME_H__
|
||||
|
||||
#include "command.h"
|
||||
#include "doomtype.h"
|
||||
#include "m_fixed.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct timestate_s {
|
||||
tic_t time;
|
||||
fixed_t timefrac;
|
||||
fixed_t realtics;
|
||||
fixed_t deltatics;
|
||||
fixed_t deltaseconds;
|
||||
fixed_t ticrate;
|
||||
} timestate_t;
|
||||
|
||||
extern timestate_t g_time;
|
||||
extern consvar_t cv_timescale;
|
||||
|
||||
/** \brief Called by D_SRB2Loop, returns current time in game tics.
|
||||
*/
|
||||
tic_t I_GetTime(void);
|
||||
|
||||
/** \brief Initializes timing system.
|
||||
*/
|
||||
void I_InitializeTime(void);
|
||||
|
||||
void I_UpdateTime(fixed_t timescale);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __I_TIME_H__
|
|
@ -32,6 +32,7 @@
|
|||
// Data.
|
||||
#include "sounds.h"
|
||||
#include "s_sound.h"
|
||||
#include "i_time.h"
|
||||
#include "i_system.h"
|
||||
#include "i_threads.h"
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "v_video.h"
|
||||
#include "z_zone.h"
|
||||
#include "g_input.h"
|
||||
#include "i_time.h"
|
||||
#include "i_video.h"
|
||||
#include "d_main.h"
|
||||
#include "m_argv.h"
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "p_spec.h"
|
||||
#include "p_saveg.h"
|
||||
|
||||
#include "i_time.h"
|
||||
#include "i_sound.h" // for I_PlayCD()..
|
||||
#include "i_video.h" // for I_FinishUpdate()..
|
||||
#include "r_sky.h"
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "screen.h"
|
||||
#include "console.h"
|
||||
#include "am_map.h"
|
||||
#include "i_time.h"
|
||||
#include "i_system.h"
|
||||
#include "i_video.h"
|
||||
#include "r_local.h"
|
||||
|
|
|
@ -170,6 +170,7 @@ static char returnWadPath[256];
|
|||
|
||||
#include "../doomdef.h"
|
||||
#include "../m_misc.h"
|
||||
#include "../i_time.h"
|
||||
#include "../i_video.h"
|
||||
#include "../i_sound.h"
|
||||
#include "../i_system.h"
|
||||
|
@ -2143,44 +2144,6 @@ ticcmd_t *I_BaseTiccmd2(void)
|
|||
|
||||
static Uint64 timer_frequency;
|
||||
|
||||
static double tic_frequency;
|
||||
static Uint64 tic_epoch;
|
||||
static double elapsed_tics;
|
||||
|
||||
static void UpdateTicFreq(void)
|
||||
{
|
||||
tic_frequency = (timer_frequency / (double)NEWTICRATE) / FixedToFloat(cv_timescale.value);
|
||||
}
|
||||
|
||||
static CV_PossibleValue_t timescale_cons_t[] = {{FRACUNIT/20, "MIN"}, {20*FRACUNIT, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_timescale = CVAR_INIT ("timescale", "1.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_CALL, timescale_cons_t, UpdateTicFreq);
|
||||
|
||||
static void UpdateElapsedTics(void)
|
||||
{
|
||||
const Uint64 now = SDL_GetPerformanceCounter();
|
||||
|
||||
elapsed_tics += (now - tic_epoch) / tic_frequency;
|
||||
tic_epoch = now; // moving epoch
|
||||
}
|
||||
|
||||
tic_t I_GetTime(void)
|
||||
{
|
||||
float f = 0.0f;
|
||||
|
||||
UpdateElapsedTics();
|
||||
|
||||
// This needs kept in a separate variable before converting
|
||||
// to tic_t, due to stupid -Wbad-function-cast error.
|
||||
f = floor(elapsed_tics);
|
||||
return (tic_t)f;
|
||||
}
|
||||
|
||||
float I_GetTimeFrac(void)
|
||||
{
|
||||
UpdateElapsedTics();
|
||||
return elapsed_tics;
|
||||
}
|
||||
|
||||
//
|
||||
// I_GetPreciseTime
|
||||
// returns time in precise_t
|
||||
|
@ -2201,6 +2164,11 @@ int I_PreciseToMicros(precise_t d)
|
|||
return (int)(UINT64)(d / (timer_frequency / 1000000.0));
|
||||
}
|
||||
|
||||
double I_PreciseElapsedSeconds(precise_t before, precise_t after)
|
||||
{
|
||||
return (after - before) / (double)timer_frequency;
|
||||
}
|
||||
|
||||
//
|
||||
// I_GetFrameTime
|
||||
// returns time in 1/fpscap second tics
|
||||
|
@ -2259,15 +2227,9 @@ double I_GetFrameTime(void)
|
|||
//
|
||||
void I_StartupTimer(void)
|
||||
{
|
||||
CV_RegisterVar(&cv_timescale);
|
||||
|
||||
timer_frequency = SDL_GetPerformanceFrequency();
|
||||
tic_epoch = SDL_GetPerformanceCounter();
|
||||
|
||||
tic_frequency = timer_frequency / (double)NEWTICRATE;
|
||||
elapsed_tics = 0.0;
|
||||
|
||||
I_InitFrameTime(tic_epoch, R_GetFramerateCap());
|
||||
I_InitFrameTime(0, R_GetFramerateCap());
|
||||
elapsed_frames = 0.0;
|
||||
}
|
||||
|
||||
|
@ -2279,6 +2241,10 @@ void I_Sleep(void)
|
|||
{
|
||||
if (cv_sleep.value > 0)
|
||||
SDL_Delay(cv_sleep.value);
|
||||
|
||||
// I_Sleep is still called in a number of places
|
||||
// we need to update the internal time state to make this work
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "r_textures.h"
|
||||
#include "r_patch.h"
|
||||
#include "r_picformats.h"
|
||||
#include "i_time.h"
|
||||
#include "i_system.h"
|
||||
#include "i_video.h" // rendermode
|
||||
#include "md5.h"
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <mmsystem.h>
|
||||
|
||||
#include "../m_misc.h"
|
||||
#include "../i_time.h"
|
||||
#include "../i_video.h"
|
||||
#include "../i_sound.h"
|
||||
#include "../i_system.h"
|
||||
|
@ -262,15 +263,12 @@ tic_t I_GetTime(void)
|
|||
return newtics;
|
||||
}
|
||||
|
||||
fixed_t I_GetTimeFrac(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void I_Sleep(void)
|
||||
{
|
||||
if (cv_sleep.value != -1)
|
||||
Sleep(cv_sleep.value);
|
||||
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
}
|
||||
|
||||
// should move to i_video
|
||||
|
|
Loading…
Reference in a new issue