Cvar compatibility with older demos

This commit is contained in:
James R 2020-06-19 18:04:20 -07:00
parent 32134a01fe
commit db34d70faa
4 changed files with 132 additions and 4 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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__

View File

@ -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)