From 32773b71e0fafd620d08c9847b79d25941af449d Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 19 Jun 2020 16:36:36 -0700 Subject: [PATCH 1/7] Use ordered ids instead of hashes for cvar netid Originally 6acd99c0a465ab1594edc12502f71a5e0a3af938 --- src/command.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/command.c b/src/command.c index f5c02d877..78230404e 100644 --- a/src/command.c +++ b/src/command.c @@ -56,7 +56,9 @@ static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr); static boolean CV_Command(void); consvar_t *CV_FindVar(const char *name); 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; static char com_token[1024]; static char *COM_Parse(char *data); @@ -1126,7 +1128,6 @@ consvar_t *CV_FindVar(const char *name) * * \param s Name of the variable. * \return A new unique identifier. - * \sa CV_FindNetVar */ static inline UINT16 CV_ComputeNetid(const char *s) { @@ -1146,12 +1147,14 @@ static inline UINT16 CV_ComputeNetid(const char *s) * * \param netid The variable's identifier number. * \return A pointer to the variable itself if found, or NULL. - * \sa CV_ComputeNetid */ static consvar_t *CV_FindNetVar(UINT16 netid) { consvar_t *cvar; + if (netid > consvar_number_of_netids) + return NULL; + for (cvar = consvar_vars; cvar; cvar = cvar->next) if (cvar->netid == netid) return cvar; @@ -1184,11 +1187,11 @@ void CV_RegisterVar(consvar_t *variable) // check net variables if (variable->flags & CV_NETVAR) { - const consvar_t *netvar; - variable->netid = CV_ComputeNetid(variable->name); - netvar = CV_FindNetVar(variable->netid); - if (netvar) - I_Error("Variables %s and %s have same netid\n", variable->name, netvar->name); + variable->netid = consvar_number_of_netids++; + + /* in case of overflow... */ + if (variable->netid > consvar_number_of_netids) + I_Error("Way too many netvars"); } // link the variable in From 32134a01fe996cf6cce6b11f1ea41950af98691b Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 19 Jun 2020 17:58:42 -0700 Subject: [PATCH 2/7] Save cvar names in demos; refactor cvar loading --- src/command.c | 98 ++++++++++++++++++++++++++++++++++++++++++--------- src/command.h | 2 ++ src/g_demo.c | 2 +- 3 files changed, 85 insertions(+), 17 deletions(-) diff --git a/src/command.c b/src/command.c index 78230404e..5d75d9cc4 100644 --- a/src/command.c +++ b/src/command.c @@ -1451,12 +1451,68 @@ badinput: static boolean serverloading = false; +static consvar_t * +ReadNetVar (UINT8 **p, char **return_value, boolean *return_stealth) +{ + UINT16 netid; + char *val; + boolean stealth; + + consvar_t *cvar; + + netid = READUINT16 (*p); + val = (char *)*p; + SKIPSTRING (*p); + stealth = READUINT8 (*p); + + cvar = CV_FindNetVar(netid); + + if (cvar) + { + (*return_value) = val; + (*return_stealth) = stealth; + + DEBFILE(va("Netvar received: %s [netid=%d] value %s\n", cvar->name, netid, val)); + } + else + CONS_Alert(CONS_WARNING, "Netvar not found with netid %hu\n", netid); + + return cvar; +} + +static consvar_t * +ReadDemoVar (UINT8 **p, char **return_value, boolean *return_stealth) +{ + char *name; + char *val; + boolean stealth; + + consvar_t *cvar; + + name = (char *)*p; + SKIPSTRING (*p); + val = (char *)*p; + SKIPSTRING (*p); + stealth = READUINT8 (*p); + + cvar = CV_FindVar(name); + + if (cvar) + { + (*return_value) = val; + (*return_stealth) = stealth; + } + else + CONS_Alert(CONS_WARNING, "Netvar not found with name %s\n", name); + + return cvar; +} + static void Got_NetVar(UINT8 **p, INT32 playernum) { consvar_t *cvar; - UINT16 netid; char *svalue; - UINT8 stealth = false; + boolean stealth; if (playernum != serverplayer && !IsPlayerAdmin(playernum) && !serverloading) { @@ -1466,20 +1522,11 @@ static void Got_NetVar(UINT8 **p, INT32 playernum) SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); return; } - netid = READUINT16(*p); - cvar = CV_FindNetVar(netid); - svalue = (char *)*p; - SKIPSTRING(*p); - stealth = READUINT8(*p); - if (!cvar) - { - CONS_Alert(CONS_WARNING, "Netvar not found with netid %hu\n", netid); - return; - } - DEBFILE(va("Netvar received: %s [netid=%d] value %s\n", cvar->name, netid, svalue)); + cvar = ReadNetVar(p, &svalue, &stealth); - Setvalue(cvar, svalue, stealth); + if (cvar) + Setvalue(cvar, svalue, stealth); } void CV_SaveNetVars(UINT8 **p) @@ -1502,11 +1549,15 @@ void CV_SaveNetVars(UINT8 **p) WRITEUINT16(count_p, count); } -void CV_LoadNetVars(UINT8 **p) +static void CV_LoadVars(UINT8 **p, + consvar_t *(*got)(UINT8 **p, char **ret_value, boolean *ret_stealth)) { consvar_t *cvar; UINT16 count; + char *val; + boolean stealth; + // prevent "invalid command received" serverloading = true; @@ -1516,11 +1567,26 @@ void CV_LoadNetVars(UINT8 **p) count = READUINT16(*p); while (count--) - Got_NetVar(p, 0); + { + cvar = (*got)(p, &val, &stealth); + + if (cvar) + Setvalue(cvar, val, stealth); + } serverloading = false; } +void CV_LoadNetVars(UINT8 **p) +{ + CV_LoadVars(p, ReadNetVar); +} + +void CV_LoadDemoVars(UINT8 **p) +{ + CV_LoadVars(p, ReadDemoVar); +} + static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth); void CV_ResetCheatNetVars(void) diff --git a/src/command.h b/src/command.h index 404052ce4..341be5fc2 100644 --- a/src/command.h +++ b/src/command.h @@ -187,6 +187,8 @@ void CV_SaveVariables(FILE *f); void CV_SaveNetVars(UINT8 **p); void CV_LoadNetVars(UINT8 **p); +void CV_LoadDemoVars(UINT8 **p); + // reset cheat netvars after cheats is deactivated void CV_ResetCheatNetVars(void); diff --git a/src/g_demo.c b/src/g_demo.c index 4dad85a3c..3ef5b5073 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -1923,7 +1923,7 @@ void G_DoPlayDemo(char *defdemoname) } // net var data - CV_LoadNetVars(&demo_p); + CV_LoadDemoVars(&demo_p); // Sigh ... it's an empty demo. if (*demo_p == DEMOMARKER) From db34d70faa7cd60c3f75dc9e985fb0b91bb20211 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 19 Jun 2020 18:04:20 -0700 Subject: [PATCH 3/7] 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) From 3e52764935cd189a9821c03a2cf63ef6ef2bd5b2 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 19 Jun 2020 18:08:04 -0700 Subject: [PATCH 4/7] Actually print a warning if the old demo id collides --- src/command.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/command.c b/src/command.c index 8c2200b24..4af27e5f6 100644 --- a/src/command.c +++ b/src/command.c @@ -1163,7 +1163,16 @@ static old_demo_var_t *CV_FindOldDemoVar(UINT16 chk) for (demovar = consvar_old_demo_vars; demovar; demovar = demovar->next) { if (demovar->checksum == chk) + { + if (demovar->collides) + { + CONS_Alert(CONS_WARNING, + "Old demo netvar id %hu is a collision\n", chk); + return NULL; + } + return demovar; + } } return NULL; From 7ec0b6c792246d0aee917977a027a563ee9623cf Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 20 Jun 2020 00:53:51 -0700 Subject: [PATCH 5/7] I meant consvar_number_of_netids to be exclusive :V --- src/command.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/command.c b/src/command.c index 4af27e5f6..45f553a10 100644 --- a/src/command.c +++ b/src/command.c @@ -1188,7 +1188,7 @@ static consvar_t *CV_FindNetVar(UINT16 netid) { consvar_t *cvar; - if (netid > consvar_number_of_netids) + if (netid >= consvar_number_of_netids) return NULL; for (cvar = consvar_vars; cvar; cvar = cvar->next) From e741a7b3c7c892126b4c115f6fad98aae968e38e Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 4 Jul 2020 12:51:07 -0700 Subject: [PATCH 6/7] Actually save the cvar name in demos --- src/command.c | 7 +++++-- src/command.h | 5 ++++- src/g_demo.c | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/command.c b/src/command.c index 45f553a10..c57111410 100644 --- a/src/command.c +++ b/src/command.c @@ -1627,7 +1627,7 @@ static void Got_NetVar(UINT8 **p, INT32 playernum) Setvalue(cvar, svalue, stealth); } -void CV_SaveNetVars(UINT8 **p) +void CV_SaveVars(UINT8 **p, boolean in_demo) { consvar_t *cvar; UINT8 *count_p = *p; @@ -1639,7 +1639,10 @@ void CV_SaveNetVars(UINT8 **p) for (cvar = consvar_vars; cvar; cvar = cvar->next) if ((cvar->flags & CV_NETVAR) && !CV_IsSetToDefault(cvar)) { - WRITEUINT16(*p, cvar->netid); + if (in_demo) + WRITESTRING(*p, cvar->name); + else + WRITEUINT16(*p, cvar->netid); WRITESTRING(*p, cvar->string); WRITEUINT8(*p, false); ++count; diff --git a/src/command.h b/src/command.h index fe5c0eb7b..b39153a65 100644 --- a/src/command.h +++ b/src/command.h @@ -197,9 +197,12 @@ void CV_AddValue(consvar_t *var, INT32 increment); void CV_SaveVariables(FILE *f); // load/save gamesate (load and save option and for network join in game) -void CV_SaveNetVars(UINT8 **p); +void CV_SaveVars(UINT8 **p, boolean in_demo); + +#define CV_SaveNetVars(p) CV_SaveVars(p, false) void CV_LoadNetVars(UINT8 **p); +#define CV_SaveDemoVars(p) CV_SaveVars(p, true) void CV_LoadDemoVars(UINT8 **p); #ifdef OLD22DEMOCOMPAT diff --git a/src/g_demo.c b/src/g_demo.c index 306c4f1ae..6c58f12fb 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -1525,7 +1525,7 @@ void G_BeginRecording(void) } // Save netvar data - CV_SaveNetVars(&demo_p); + CV_SaveDemoVars(&demo_p); memset(&oldcmd,0,sizeof(oldcmd)); memset(&oldghost,0,sizeof(oldghost)); From d9005203c72d2456fb7071b1e21a230009fcc5b3 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 4 Jul 2020 12:52:01 -0700 Subject: [PATCH 7/7] Fuck you macro --- src/byteptr.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/byteptr.h b/src/byteptr.h index 933c2af34..01a6293b4 100644 --- a/src/byteptr.h +++ b/src/byteptr.h @@ -150,15 +150,15 @@ FUNCINLINE static ATTRINLINE UINT32 readulong(void *ptr) #undef DEALIGNED -#define WRITESTRINGN(p,s,n) { size_t tmp_i = 0; for (; tmp_i < n && s[tmp_i] != '\0'; tmp_i++) WRITECHAR(p, s[tmp_i]); if (tmp_i < n) WRITECHAR(p, '\0');} -#define WRITESTRING(p,s) { size_t tmp_i = 0; for (; s[tmp_i] != '\0'; tmp_i++) WRITECHAR(p, s[tmp_i]); WRITECHAR(p, '\0');} -#define WRITEMEM(p,s,n) { memcpy(p, s, n); p += n; } +#define WRITESTRINGN(p,s,n) do { size_t tmp_i = 0; for (; tmp_i < n && s[tmp_i] != '\0'; tmp_i++) WRITECHAR(p, s[tmp_i]); if (tmp_i < n) WRITECHAR(p, '\0');} while (0) +#define WRITESTRING(p,s) do { size_t tmp_i = 0; for (; s[tmp_i] != '\0'; tmp_i++) WRITECHAR(p, s[tmp_i]); WRITECHAR(p, '\0');} while (0) +#define WRITEMEM(p,s,n) do { memcpy(p, s, n); p += n; } while (0) #define SKIPSTRING(p) while (READCHAR(p) != '\0') -#define READSTRINGN(p,s,n) { size_t tmp_i = 0; for (; tmp_i < n && (s[tmp_i] = READCHAR(p)) != '\0'; tmp_i++); s[tmp_i] = '\0';} -#define READSTRING(p,s) { size_t tmp_i = 0; for (; (s[tmp_i] = READCHAR(p)) != '\0'; tmp_i++); s[tmp_i] = '\0';} -#define READMEM(p,s,n) { memcpy(s, p, n); p += n; } +#define READSTRINGN(p,s,n) ({ size_t tmp_i = 0; for (; tmp_i < n && (s[tmp_i] = READCHAR(p)) != '\0'; tmp_i++); s[tmp_i] = '\0';}) +#define READSTRING(p,s) ({ size_t tmp_i = 0; for (; (s[tmp_i] = READCHAR(p)) != '\0'; tmp_i++); s[tmp_i] = '\0';}) +#define READMEM(p,s,n) ({ memcpy(s, p, n); p += n; }) #if 0 // old names #define WRITEBYTE(p,b) WRITEUINT8(p,b)