diff --git a/src/d_netcmd.c b/src/d_netcmd.c index d73d6829a..2e7ef982b 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -864,6 +864,7 @@ void D_RegisterClientCommands(void) // GIF variables CV_RegisterVar(&cv_gif_optimize); CV_RegisterVar(&cv_gif_downscale); + CV_RegisterVar(&cv_gif_dynamicdelay); #ifdef WALLSPLATS CV_RegisterVar(&cv_splats); diff --git a/src/m_anigif.c b/src/m_anigif.c index 05b1f8287..28fdafc9f 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -18,6 +18,7 @@ #include "z_zone.h" #include "v_video.h" #include "i_video.h" +#include "i_system.h" // I_GetPreciseTime #ifdef HWRENDER #include "hardware/hw_main.h" @@ -26,16 +27,26 @@ // GIFs are always little-endian #include "byteptr.h" +CV_PossibleValue_t gif_dynamicdelay_cons_t[] = { + {0, "Off"}, + {1, "On"}, + {2, "Accurate, experimental"}, +{0, NULL}}; + consvar_t cv_gif_optimize = {"gif_optimize", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_gif_downscale = {"gif_downscale", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_gif_dynamicdelay = {"gif_dynamicdelay", "On", CV_SAVE, gif_dynamicdelay_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; #ifdef HAVE_ANIGIF static boolean gif_optimize = false; // So nobody can do something dumb static boolean gif_downscale = false; // like changing cvars mid output +static UINT8 gif_dynamicdelay = (UINT8)0; // and messing something up static RGBA_t *gif_palette = NULL; static FILE *gif_out = NULL; static INT32 gif_frames = 0; +static precise_t gif_prevframetime = 0; +static UINT32 gif_delayus = 0; // "us" is microseconds static UINT8 gif_writeover = 0; @@ -550,11 +561,39 @@ static void GIF_framewrite(void) // screen regions are handled in GIF_lzw { - int d1 = (int)((100.0f/NEWTICRATE)*(gif_frames+1)); - int d2 = (int)((100.0f/NEWTICRATE)*(gif_frames)); - UINT16 delay = d1-d2; + UINT16 delay = 0; INT32 startline; + if (gif_dynamicdelay ==(UINT8) 2) + { + // golden's attempt at creating a "dynamic delay" + UINT16 mingifdelay = 10; // minimum gif delay in milliseconds (keep at 10 because gifs can't get more precise). + gif_delayus += (I_GetPreciseTime() - gif_prevframetime) / (I_GetPrecisePrecision() / 1000000); // increase delay by how much time was spent between last measurement + + if (gif_delayus/1000 >= mingifdelay) // delay is big enough to be able to effect gif frame delay? + { + int frames = (gif_delayus/1000) / mingifdelay; // get amount of frames to delay. + delay = frames; // set the delay to delay that amount of frames. + gif_delayus -= frames*(mingifdelay*1000); // remove frames by the amount of milliseconds they take. don't reset to 0, the microseconds help consistency. + } + } + else if (gif_dynamicdelay ==(UINT8) 1) + { + float delayf = ceil(100.0f/NEWTICRATE); + + delay = (UINT16)((I_GetPreciseTime() - gif_prevframetime)) / (I_GetPrecisePrecision() / 1000000) /10/1000; + + if (delay < (UINT16)(delayf)) + delay = (UINT16)(delayf); + } + else + { + // the original code + int d1 = (int)((100.0f/NEWTICRATE)*(gif_frames+1)); + int d2 = (int)((100.0f/NEWTICRATE)*(gif_frames)); + delay = d1-d2; + } + WRITEMEM(p, gifframe_gchead, 4); WRITEUINT16(p, delay); @@ -619,6 +658,7 @@ static void GIF_framewrite(void) } fwrite(gifframe_data, 1, (p - gifframe_data), gif_out); ++gif_frames; + gif_prevframetime = I_GetPreciseTime(); } @@ -639,12 +679,15 @@ INT32 GIF_open(const char *filename) gif_optimize = (!!cv_gif_optimize.value); gif_downscale = (!!cv_gif_downscale.value); + gif_dynamicdelay = (UINT8)cv_gif_dynamicdelay.value; // no master palettes in SRB2Kart land gif_palette = pLocalPalette; GIF_headwrite(); gif_frames = 0; + gif_prevframetime = I_GetPreciseTime(); + gif_delayus = 0; return 1; } diff --git a/src/m_anigif.h b/src/m_anigif.h index 6d94ecf8c..b283dce02 100644 --- a/src/m_anigif.h +++ b/src/m_anigif.h @@ -27,6 +27,6 @@ void GIF_frame(void); INT32 GIF_close(void); #endif -extern consvar_t cv_gif_optimize, cv_gif_downscale; +extern consvar_t cv_gif_optimize, cv_gif_dynamicdelay, cv_gif_downscale; #endif