From db34d70faa7cd60c3f75dc9e985fb0b91bb20211 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 19 Jun 2020 18:04:20 -0700 Subject: [PATCH] Cvar compatibility with older demos --- src/command.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/command.h | 17 +++++++++ src/doomdef.h | 3 ++ src/g_demo.c | 14 ++++++- 4 files changed, 132 insertions(+), 4 deletions(-) diff --git a/src/command.c b/src/command.c index 5d75d9cc4..8c2200b24 100644 --- a/src/command.c +++ b/src/command.c @@ -60,6 +60,10 @@ static const char *CV_StringValue(const char *var_name); static consvar_t *consvar_vars; // list of registered console variables static UINT16 consvar_number_of_netids = 0; +#ifdef OLD22DEMOCOMPAT +static old_demo_var_t *consvar_old_demo_vars; +#endif + static char com_token[1024]; static char *COM_Parse(char *data); @@ -1123,13 +1127,16 @@ consvar_t *CV_FindVar(const char *name) return NULL; } -/** Builds a unique Net Variable identifier number, which is used - * in network packets instead of the full name. +#ifdef OLD22DEMOCOMPAT +/** Builds a unique Net Variable identifier number, which was used + * in network packets and demos instead of the full name. + * + * This function only still exists to keep compatibility with old demos. * * \param s Name of the variable. * \return A new unique identifier. */ -static inline UINT16 CV_ComputeNetid(const char *s) +static inline UINT16 CV_ComputeOldDemoID(const char *s) { UINT16 ret = 0, i = 0; static UINT16 premiers[16] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53}; @@ -1143,6 +1150,26 @@ static inline UINT16 CV_ComputeNetid(const char *s) return ret; } +/** Finds a net variable based on its old style hash. If a hash collides, a + * warning is printed and this function returns NULL. + * + * \param chk The variable's old style hash. + * \return A pointer to the variable itself if found, or NULL. + */ +static old_demo_var_t *CV_FindOldDemoVar(UINT16 chk) +{ + old_demo_var_t *demovar; + + for (demovar = consvar_old_demo_vars; demovar; demovar = demovar->next) + { + if (demovar->checksum == chk) + return demovar; + } + + return NULL; +} +#endif/*OLD22DEMOCOMPAT*/ + /** Finds a net variable based on its identifier number. * * \param netid The variable's identifier number. @@ -1164,6 +1191,32 @@ static consvar_t *CV_FindNetVar(UINT16 netid) static void Setvalue(consvar_t *var, const char *valstr, boolean stealth); +#ifdef OLD22DEMOCOMPAT +/* Sets up a netvar for compatibility with old demos. */ +static void CV_RegisterOldDemoVar(consvar_t *variable) +{ + old_demo_var_t *demovar; + UINT16 old_demo_id; + + old_demo_id = CV_ComputeOldDemoID(variable->name); + + demovar = CV_FindOldDemoVar(old_demo_id); + + if (demovar) + demovar->collides = true; + else + { + demovar = ZZ_Calloc(sizeof *demovar); + + demovar->checksum = old_demo_id; + demovar->cvar = variable; + + demovar->next = consvar_old_demo_vars; + consvar_old_demo_vars = demovar; + } +} +#endif + /** Registers a variable for later use from the console. * * \param variable The variable to register. @@ -1192,6 +1245,10 @@ void CV_RegisterVar(consvar_t *variable) /* in case of overflow... */ if (variable->netid > consvar_number_of_netids) I_Error("Way too many netvars"); + +#ifdef OLD22DEMOCOMPAT + CV_RegisterOldDemoVar(variable); +#endif } // link the variable in @@ -1480,6 +1537,38 @@ ReadNetVar (UINT8 **p, char **return_value, boolean *return_stealth) return cvar; } +#ifdef OLD22DEMOCOMPAT +static consvar_t * +ReadOldDemoVar (UINT8 **p, char **return_value, boolean *return_stealth) +{ + UINT16 id; + char *val; + boolean stealth; + + old_demo_var_t *demovar; + + id = READUINT16 (*p); + val = (char *)*p; + SKIPSTRING (*p); + stealth = READUINT8 (*p); + + demovar = CV_FindOldDemoVar(id); + + if (demovar) + { + (*return_value) = val; + (*return_stealth) = stealth; + + return demovar->cvar; + } + else + { + CONS_Alert(CONS_WARNING, "Netvar not found with old demo id %hu\n", id); + return NULL; + } +} +#endif/*OLD22DEMOCOMPAT*/ + static consvar_t * ReadDemoVar (UINT8 **p, char **return_value, boolean *return_stealth) { @@ -1582,6 +1671,13 @@ void CV_LoadNetVars(UINT8 **p) CV_LoadVars(p, ReadNetVar); } +#ifdef OLD22DEMOCOMPAT +void CV_LoadOldDemoVars(UINT8 **p) +{ + CV_LoadVars(p, ReadOldDemoVar); +} +#endif + void CV_LoadDemoVars(UINT8 **p) { CV_LoadVars(p, ReadDemoVar); diff --git a/src/command.h b/src/command.h index 341be5fc2..fe5c0eb7b 100644 --- a/src/command.h +++ b/src/command.h @@ -144,6 +144,19 @@ typedef struct consvar_s //NULL, NULL, 0, NULL, NULL |, 0, NULL, NULL, 0, 0, NUL struct consvar_s *next; } consvar_t; +#ifdef OLD22DEMOCOMPAT +typedef struct old_demo_var old_demo_var_t; + +struct old_demo_var +{ + UINT16 checksum; + boolean collides;/* this var is a collision of multiple hashes */ + + consvar_t *cvar; + old_demo_var_t *next; +}; +#endif/*OLD22DEMOCOMPAT*/ + extern CV_PossibleValue_t CV_OnOff[]; extern CV_PossibleValue_t CV_YesNo[]; extern CV_PossibleValue_t CV_Unsigned[]; @@ -189,6 +202,10 @@ void CV_LoadNetVars(UINT8 **p); void CV_LoadDemoVars(UINT8 **p); +#ifdef OLD22DEMOCOMPAT +void CV_LoadOldDemoVars(UINT8 **p); +#endif + // reset cheat netvars after cheats is deactivated void CV_ResetCheatNetVars(void); diff --git a/src/doomdef.h b/src/doomdef.h index 0b76cebc7..54e4ed914 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -662,4 +662,7 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// Render flats on walls #define WALLFLATS +/// Maintain compatibility with older 2.2 demos +#define OLD22DEMOCOMPAT + #endif // __DOOMDEF__ diff --git a/src/g_demo.c b/src/g_demo.c index 3ef5b5073..306c4f1ae 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -1756,6 +1756,9 @@ void G_DoPlayDemo(char *defdemoname) UINT32 randseed, followitem; fixed_t camerascale,shieldscale,actionspd,mindash,maxdash,normalspeed,runspeed,jumpfactor,height,spinheight; char msg[1024]; +#ifdef OLD22DEMOCOMPAT + boolean use_old_demo_vars = false; +#endif skin[16] = '\0'; color[MAXCOLORNAME] = '\0'; @@ -1818,10 +1821,13 @@ void G_DoPlayDemo(char *defdemoname) case DEMOVERSION: // latest always supported cnamelen = MAXCOLORNAME; break; +#ifdef OLD22DEMOCOMPAT // all that changed between then and now was longer color name case 0x000c: cnamelen = 16; + use_old_demo_vars = true; break; +#endif // too old, cannot support. default: snprintf(msg, 1024, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemoname); @@ -1923,7 +1929,13 @@ void G_DoPlayDemo(char *defdemoname) } // net var data - CV_LoadDemoVars(&demo_p); +#ifdef OLD22DEMOCOMPAT + if (use_old_demo_vars) + CV_LoadOldDemoVars(&demo_p); + else +#else + CV_LoadDemoVars(&demo_p); +#endif // Sigh ... it's an empty demo. if (*demo_p == DEMOMARKER)