Replays: larger buffers for player name, skin name, color name; bump demo version 0x0009 -> 0x000A

- Name buffers are the same size as everywhere else
  - Billiards Cactus no longer gets cut short
  - Long player names no longer get cut short
- System in place to allow easily changing the buffer
  sizes across all the demo code
This commit is contained in:
James R 2024-03-19 01:23:51 -07:00
parent 2cb62c8663
commit 5445d59d57
3 changed files with 86 additions and 100 deletions

View file

@ -448,7 +448,7 @@ struct staffbrief_t
{ {
UINT16 wad; UINT16 wad;
UINT16 lump; UINT16 lump;
char name[16]; char name[MAXPLAYERNAME+1];
tic_t time; tic_t time;
tic_t lap; tic_t lap;
}; };

View file

@ -93,6 +93,25 @@ boolean nodrawers; // for comparative timing purposes
boolean noblit; // for comparative timing purposes boolean noblit; // for comparative timing purposes
tic_t demostarttime; // for comparative timing purposes tic_t demostarttime; // for comparative timing purposes
static constexpr DemoBufferSizes get_buffer_sizes(UINT16 version)
{
(void)version;
// These sizes are compatible as of version 0x000A
static_assert(MAXPLAYERNAME == 21);
static_assert(SKINNAMESIZE == 16);
static_assert(MAXCOLORNAME == 32);
return {21, 16, 32};
}
static DemoBufferSizes g_buffer_sizes;
size_t copy_fixed_buf(void* p, const void* s, size_t n)
{
strncpy((char*)p, (const char*)s, n);
((char*)p)[n] = '\0';
return n;
}
static char demoname[MAX_WADPATH]; static char demoname[MAX_WADPATH];
static savebuffer_t demobuf = {0}; static savebuffer_t demobuf = {0};
static UINT8 *demotime_p, *demoinfo_p; static UINT8 *demotime_p, *demoinfo_p;
@ -135,7 +154,7 @@ demoghost *ghosts = NULL;
// DEMO RECORDING // DEMO RECORDING
// //
#define DEMOVERSION 0x0009 #define DEMOVERSION 0x000A
#define DEMOHEADER "\xF0" "KartReplay" "\x0F" #define DEMOHEADER "\xF0" "KartReplay" "\x0F"
#define DF_ATTACKMASK (ATTACKING_TIME|ATTACKING_LAP|ATTACKING_SPB) // This demo contains time/lap data #define DF_ATTACKMASK (ATTACKING_TIME|ATTACKING_LAP|ATTACKING_SPB) // This demo contains time/lap data
@ -221,7 +240,8 @@ static mobj_t oldghost[MAXPLAYERS];
void G_ReadDemoExtraData(void) void G_ReadDemoExtraData(void)
{ {
INT32 p, extradata, i; INT32 p, extradata, i;
char name[17]; char name[64];
static_assert(sizeof name >= std::max({MAXPLAYERNAME+1u, SKINNAMESIZE+1u, MAXCOLORNAME+1u}));
if (leveltime > starttime) if (leveltime > starttime)
{ {
@ -233,7 +253,7 @@ void G_ReadDemoExtraData(void)
} }
} }
memset(name, '\0', 17); memset(name, '\0', sizeof name);
p = READUINT8(demobuf.p); p = READUINT8(demobuf.p);
@ -327,8 +347,7 @@ void G_ReadDemoExtraData(void)
if (extradata & DXD_COLOR) if (extradata & DXD_COLOR)
{ {
// Color // Color
M_Memcpy(name, demobuf.p, 16); demobuf.p += copy_fixed_buf(name, demobuf.p, g_buffer_sizes.color_name);
demobuf.p += 16;
for (i = 0; i < numskincolors; i++) for (i = 0; i < numskincolors; i++)
if (!stricmp(skincolors[i].name, name)) // SRB2kart if (!stricmp(skincolors[i].name, name)) // SRB2kart
{ {
@ -341,19 +360,16 @@ void G_ReadDemoExtraData(void)
if (extradata & DXD_NAME) if (extradata & DXD_NAME)
{ {
// Name // Name
M_Memcpy(player_names[p],demobuf.p,16); demobuf.p += copy_fixed_buf(player_names[p], demobuf.p, g_buffer_sizes.player_name);
demobuf.p += 16;
} }
if (extradata & DXD_FOLLOWER) if (extradata & DXD_FOLLOWER)
{ {
// Set our follower // Set our follower
M_Memcpy(name, demobuf.p, 16); demobuf.p += copy_fixed_buf(name, demobuf.p, g_buffer_sizes.skin_name);
demobuf.p += 16;
K_SetFollowerByName(p, name); K_SetFollowerByName(p, name);
// Follower's color // Follower's color
M_Memcpy(name, demobuf.p, 16); demobuf.p += copy_fixed_buf(name, demobuf.p, g_buffer_sizes.color_name);
demobuf.p += 16;
for (i = 0; i < numskincolors +2; i++) // +2 because of Match and Opposite for (i = 0; i < numskincolors +2; i++) // +2 because of Match and Opposite
{ {
if (!stricmp(Followercolor_cons_t[i].strvalue, name)) if (!stricmp(Followercolor_cons_t[i].strvalue, name))
@ -411,7 +427,8 @@ void G_ReadDemoExtraData(void)
void G_WriteDemoExtraData(void) void G_WriteDemoExtraData(void)
{ {
INT32 i, j; INT32 i, j;
char name[16]; char name[64];
static_assert(sizeof name >= std::max({MAXPLAYERNAME+1u, SKINNAMESIZE+1u, MAXCOLORNAME+1u}));
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
@ -464,41 +481,28 @@ void G_WriteDemoExtraData(void)
if (demo_extradata[i] & DXD_COLOR) if (demo_extradata[i] & DXD_COLOR)
{ {
// Color // Color
memset(name, 0, 16); demobuf.p += copy_fixed_buf(demobuf.p, skincolors[players[i].skincolor].name, g_buffer_sizes.color_name);
strlcpy(name, skincolors[players[i].skincolor].name, 16);
M_Memcpy(demobuf.p,name,16);
demobuf.p += 16;
} }
if (demo_extradata[i] & DXD_NAME) if (demo_extradata[i] & DXD_NAME)
{ {
// Name // Name
memset(name, 0, 16); demobuf.p += copy_fixed_buf(demobuf.p, player_names[i], g_buffer_sizes.player_name);
strlcpy(name, player_names[i], 16);
M_Memcpy(demobuf.p,name,16);
demobuf.p += 16;
} }
if (demo_extradata[i] & DXD_FOLLOWER) if (demo_extradata[i] & DXD_FOLLOWER)
{ {
// write follower // write follower
memset(name, 0, 16);
if (players[i].followerskin == -1) if (players[i].followerskin == -1)
strncpy(name, "None", 16); demobuf.p += copy_fixed_buf(demobuf.p, "None", g_buffer_sizes.skin_name);
else else
strlcpy(name, followers[players[i].followerskin].name, 16); demobuf.p += copy_fixed_buf(demobuf.p, followers[players[i].followerskin].name, g_buffer_sizes.skin_name);
M_Memcpy(demobuf.p, name, 16);
demobuf.p += 16;
// write follower color // write follower color
memset(name, 0, 16);
for (j = (numskincolors+2)-1; j > 0; j--) for (j = (numskincolors+2)-1; j > 0; j--)
{ {
if (Followercolor_cons_t[j].value == players[i].followercolor) if (Followercolor_cons_t[j].value == players[i].followercolor)
break; break;
} }
strlcpy(name, Followercolor_cons_t[j].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match" demobuf.p += copy_fixed_buf(demobuf.p, Followercolor_cons_t[j].strvalue, g_buffer_sizes.color_name); // Not KartColor_Names because followercolor has extra values such as "Match"
M_Memcpy(demobuf.p,name,16);
demobuf.p += 16;
} }
if (demo_extradata[i] & DXD_WEAPONPREF) if (demo_extradata[i] & DXD_WEAPONPREF)
{ {
@ -1293,11 +1297,11 @@ readghosttic:
if (ziptic & DXD_SKIN) if (ziptic & DXD_SKIN)
g->p++; // We _could_ read this info, but it shouldn't change anything in record attack... g->p++; // We _could_ read this info, but it shouldn't change anything in record attack...
if (ziptic & DXD_COLOR) if (ziptic & DXD_COLOR)
g->p += 16; // Same tbh g->p += g->sizes.color_name; // Same tbh
if (ziptic & DXD_NAME) if (ziptic & DXD_NAME)
g->p += 16; // yea g->p += g->sizes.player_name; // yea
if (ziptic & DXD_FOLLOWER) if (ziptic & DXD_FOLLOWER)
g->p += 32; // ok (32 because there's both the skin and the colour) g->p += g->sizes.skin_name + g->sizes.color_name;
if (ziptic & DXD_WEAPONPREF) if (ziptic & DXD_WEAPONPREF)
g->p++; // ditto g->p++; // ditto
if (ziptic & DXD_START) if (ziptic & DXD_START)
@ -2019,9 +2023,8 @@ static UINT8 G_CheckDemoExtraFiles(savebuffer_t *info, boolean quick)
return error; return error;
} }
static void G_SaveDemoSkins(UINT8 **pp) static void G_SaveDemoSkins(UINT8 **pp, const DemoBufferSizes &psizes)
{ {
char skin[16];
UINT8 i; UINT8 i;
UINT8 *availabilitiesbuffer = R_GetSkinAvailabilities(true, -1); UINT8 *availabilitiesbuffer = R_GetSkinAvailabilities(true, -1);
@ -2029,9 +2032,7 @@ static void G_SaveDemoSkins(UINT8 **pp)
for (i = 0; i < numskins; i++) for (i = 0; i < numskins; i++)
{ {
// Skinname, for first attempt at identification. // Skinname, for first attempt at identification.
memset(skin, 0, 16); (*pp) += copy_fixed_buf((*pp), skins[i].name, psizes.skin_name);
strlcpy(skin, skins[i].name, 16);
WRITEMEM((*pp), skin, 16);
// Backup information for second pass. // Backup information for second pass.
WRITEUINT8((*pp), skins[i].kartspeed); WRITEUINT8((*pp), skins[i].kartspeed);
@ -2045,7 +2046,7 @@ static void G_SaveDemoSkins(UINT8 **pp)
} }
} }
static democharlist_t *G_LoadDemoSkins(savebuffer_t *info, UINT8 *worknumskins, boolean getclosest) static democharlist_t *G_LoadDemoSkins(const DemoBufferSizes &psizes, savebuffer_t *info, UINT8 *worknumskins, boolean getclosest)
{ {
UINT8 i, byte, shif; UINT8 i, byte, shif;
democharlist_t *skinlist = NULL; democharlist_t *skinlist = NULL;
@ -2069,14 +2070,13 @@ static democharlist_t *G_LoadDemoSkins(savebuffer_t *info, UINT8 *worknumskins,
{ {
INT32 result = -1; INT32 result = -1;
if (P_SaveBufferRemaining(info) < 16+1+1+4) if (P_SaveBufferRemaining(info) < psizes.skin_name+1+1+4)
{ {
Z_Free(skinlist); Z_Free(skinlist);
return NULL; return NULL;
} }
READMEM(info->p, skinlist[i].name, 16); info->p += copy_fixed_buf(skinlist[i].name, info->p, psizes.skin_name);
skinlist[i].name[16] = '\0';
skinlist[i].namehash = quickncasehash(skinlist[i].name, SKINNAMESIZE); skinlist[i].namehash = quickncasehash(skinlist[i].name, SKINNAMESIZE);
skinlist[i].kartspeed = READUINT8(info->p); skinlist[i].kartspeed = READUINT8(info->p);
skinlist[i].kartweight = READUINT8(info->p); skinlist[i].kartweight = READUINT8(info->p);
@ -2128,7 +2128,7 @@ static democharlist_t *G_LoadDemoSkins(savebuffer_t *info, UINT8 *worknumskins,
return skinlist; return skinlist;
} }
static void G_SkipDemoSkins(UINT8 **pp) static void G_SkipDemoSkins(UINT8 **pp, const DemoBufferSizes& psizes)
{ {
UINT8 demonumskins; UINT8 demonumskins;
UINT8 i; UINT8 i;
@ -2136,7 +2136,7 @@ static void G_SkipDemoSkins(UINT8 **pp)
demonumskins = READUINT8((*pp)); demonumskins = READUINT8((*pp));
for (i = 0; i < demonumskins; ++i) for (i = 0; i < demonumskins; ++i)
{ {
(*pp) += 16; // name (*pp) += psizes.skin_name; // name
(*pp)++; // kartspeed (*pp)++; // kartspeed
(*pp)++; // kartweight (*pp)++; // kartweight
(*pp) += 4; // flags (*pp) += 4; // flags
@ -2148,12 +2148,10 @@ static void G_SkipDemoSkins(UINT8 **pp)
void G_BeginRecording(void) void G_BeginRecording(void)
{ {
UINT8 i, j, p; UINT8 i, j, p;
char name[MAXCOLORNAME+1];
player_t *player = &players[consoleplayer]; player_t *player = &players[consoleplayer];
if (demobuf.p) if (demobuf.p)
return; return;
memset(name,0,sizeof(name));
demobuf.p = demobuf.buffer; demobuf.p = demobuf.buffer;
@ -2186,6 +2184,7 @@ void G_BeginRecording(void)
WRITEUINT16(demobuf.p,DEMOVERSION); WRITEUINT16(demobuf.p,DEMOVERSION);
demo.version = DEMOVERSION; demo.version = DEMOVERSION;
g_buffer_sizes = get_buffer_sizes(DEMOVERSION);
// Full replay title // Full replay title
demobuf.p += 64; demobuf.p += 64;
@ -2213,7 +2212,7 @@ void G_BeginRecording(void)
G_SaveDemoExtraFiles(&demobuf.p); G_SaveDemoExtraFiles(&demobuf.p);
// character list // character list
G_SaveDemoSkins(&demobuf.p); G_SaveDemoSkins(&demobuf.p, g_buffer_sizes);
if ((demoflags & DF_ATTACKMASK)) if ((demoflags & DF_ATTACKMASK))
{ {
@ -2293,10 +2292,7 @@ void G_BeginRecording(void)
} }
// Name // Name
memset(name, 0, 16); demobuf.p += copy_fixed_buf(demobuf.p, player_names[p], g_buffer_sizes.player_name);
strlcpy(name, player_names[p], 16);
M_Memcpy(demobuf.p,name,16);
demobuf.p += 16;
for (j = 0; j < MAXAVAILABILITY; j++) for (j = 0; j < MAXAVAILABILITY; j++)
{ {
@ -2308,34 +2304,24 @@ void G_BeginRecording(void)
WRITEUINT8(demobuf.p, player->lastfakeskin); WRITEUINT8(demobuf.p, player->lastfakeskin);
// Color // Color
memset(name, 0, 16); demobuf.p += copy_fixed_buf(demobuf.p, skincolors[player->skincolor].name, g_buffer_sizes.color_name);
strncpy(name, skincolors[player->skincolor].name, 16);
M_Memcpy(demobuf.p,name,16);
demobuf.p += 16;
// Save follower's skin name // Save follower's skin name
// PS: We must check for 'follower' to determine if the followerskin is valid. It's going to be 0 if we don't have a follower, but 0 is also absolutely a valid follower! // PS: We must check for 'follower' to determine if the followerskin is valid. It's going to be 0 if we don't have a follower, but 0 is also absolutely a valid follower!
// Doesn't really matter if the follower mobj is valid so long as it exists in a way or another. // Doesn't really matter if the follower mobj is valid so long as it exists in a way or another.
memset(name, 0, 16);
if (player->follower) if (player->follower)
strncpy(name, followers[player->followerskin].name, 16); demobuf.p += copy_fixed_buf(demobuf.p, followers[player->followerskin].name, g_buffer_sizes.skin_name);
else else
strncpy(name, "None", 16); // Say we don't have one, then. demobuf.p += copy_fixed_buf(demobuf.p, "None", g_buffer_sizes.skin_name); // Say we don't have one, then.
M_Memcpy(demobuf.p,name,16);
demobuf.p += 16;
// Save follower's colour // Save follower's colour
memset(name, 0, 16);
for (j = (numskincolors+2)-1; j > 0; j--) for (j = (numskincolors+2)-1; j > 0; j--)
{ {
if (Followercolor_cons_t[j].value == players[i].followercolor) if (Followercolor_cons_t[j].value == players[i].followercolor)
break; break;
} }
strncpy(name, Followercolor_cons_t[j].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match" demobuf.p += copy_fixed_buf(demobuf.p, Followercolor_cons_t[j].strvalue, g_buffer_sizes.color_name); // Not KartColor_Names because followercolor has extra values such as "Match"
M_Memcpy(demobuf.p, name, 16);
demobuf.p += 16;
// Score, since Kart uses this to determine where you start on the map // Score, since Kart uses this to determine where you start on the map
WRITEUINT32(demobuf.p, player->score); WRITEUINT32(demobuf.p, player->score);
@ -2466,7 +2452,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
p++; // numlaps p++; // numlaps
G_SkipDemoExtraFiles(&p); G_SkipDemoExtraFiles(&p);
G_SkipDemoSkins(&p); G_SkipDemoSkins(&p, get_buffer_sizes(DEMOVERSION));
aflags = flags & DF_ATTACKMASK; aflags = flags & DF_ATTACKMASK;
I_Assert(aflags); I_Assert(aflags);
@ -2531,7 +2517,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
return UINT8_MAX; return UINT8_MAX;
} }
G_SkipDemoSkins(&p); G_SkipDemoSkins(&p, get_buffer_sizes(oldversion));
if (flags & ATTACKING_TIME) if (flags & ATTACKING_TIME)
oldtime = READUINT32(p); oldtime = READUINT32(p);
@ -2581,7 +2567,7 @@ static bool load_ubjson_standing(menudemo_t* pdemo, tcb::span<std::byte> slice,
StandingJson& jsstanding = js.standings[i]; StandingJson& jsstanding = js.standings[i];
auto& memstanding = pdemo->standings[i]; auto& memstanding = pdemo->standings[i];
memstanding.ranking = jsstanding.ranking; memstanding.ranking = jsstanding.ranking;
strlcpy(memstanding.name, jsstanding.name.c_str(), 17); strlcpy(memstanding.name, jsstanding.name.c_str(), sizeof memstanding.name);
if (jsstanding.demoskin >= demoskins.size()) if (jsstanding.demoskin >= demoskins.size())
{ {
memstanding.skin = demoskins[0].mapping; memstanding.skin = demoskins[0].mapping;
@ -2713,7 +2699,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo, boolean allownonmultiplayer)
pdemo->addonstatus = G_CheckDemoExtraFiles(&info, true); pdemo->addonstatus = G_CheckDemoExtraFiles(&info, true);
skinlist = G_LoadDemoSkins(&info, &worknumskins, false); skinlist = G_LoadDemoSkins(get_buffer_sizes(pdemoversion), &info, &worknumskins, false);
if (!skinlist) if (!skinlist)
{ {
@ -2807,8 +2793,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo, boolean allownonmultiplayer)
pdemo->standings[legacystandingplayercount].ranking = READUINT8(info.p); pdemo->standings[legacystandingplayercount].ranking = READUINT8(info.p);
// Name // Name
M_Memcpy(pdemo->standings[legacystandingplayercount].name, info.p, 16); info.p += copy_fixed_buf(pdemo->standings[legacystandingplayercount].name, info.p, 16);
info.p += 16;
// Skin // Skin
skinid = READUINT8(info.p); skinid = READUINT8(info.p);
@ -2817,8 +2802,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo, boolean allownonmultiplayer)
pdemo->standings[legacystandingplayercount].skin = skinlist[skinid].mapping; pdemo->standings[legacystandingplayercount].skin = skinlist[skinid].mapping;
// Color // Color
M_Memcpy(temp,info.p,16); info.p += copy_fixed_buf(temp, info.p, 16);
info.p += 16;
for (i = 0; i < numskincolors; i++) for (i = 0; i < numskincolors; i++)
if (!stricmp(skincolors[i].name,temp)) // SRB2kart if (!stricmp(skincolors[i].name,temp)) // SRB2kart
{ {
@ -2911,7 +2895,7 @@ void G_DoPlayDemoEx(const char *defdemoname, lumpnum_t deflumpnum)
INT32 i; INT32 i;
UINT8 p, numslots = 0; UINT8 p, numslots = 0;
lumpnum_t l; lumpnum_t l;
char color[MAXCOLORNAME+1],follower[17],mapname[MAXMAPLUMPNAME],gtname[MAXGAMETYPELENGTH]; char color[MAXCOLORNAME+1],follower[SKINNAMESIZE+1],mapname[MAXMAPLUMPNAME],gtname[MAXGAMETYPELENGTH];
char *pdemoname; char *pdemoname;
UINT8 availabilities[MAXPLAYERS][MAXAVAILABILITY]; UINT8 availabilities[MAXPLAYERS][MAXAVAILABILITY];
UINT8 version,subversion; UINT8 version,subversion;
@ -2931,8 +2915,6 @@ void G_DoPlayDemoEx(const char *defdemoname, lumpnum_t deflumpnum)
G_InitDemoRewind(); G_InitDemoRewind();
follower[16] = '\0';
color[MAXCOLORNAME] = '\0';
gtname[MAXGAMETYPELENGTH-1] = '\0'; gtname[MAXGAMETYPELENGTH-1] = '\0';
if (deflumpnum != LUMPERROR) if (deflumpnum != LUMPERROR)
@ -3093,6 +3075,8 @@ void G_DoPlayDemoEx(const char *defdemoname, lumpnum_t deflumpnum)
return; return;
} }
g_buffer_sizes = get_buffer_sizes(demo.version);
// demo title // demo title
M_Memcpy(demo.titlename, demobuf.p, 64); M_Memcpy(demo.titlename, demobuf.p, 64);
demobuf.p += 64; demobuf.p += 64;
@ -3190,7 +3174,7 @@ void G_DoPlayDemoEx(const char *defdemoname, lumpnum_t deflumpnum)
G_SetGametype(i); G_SetGametype(i);
// character list // character list
demo.skinlist = G_LoadDemoSkins(&demobuf, &demo.numskins, true); demo.skinlist = G_LoadDemoSkins(g_buffer_sizes, &demobuf, &demo.numskins, true);
if (!demo.skinlist) if (!demo.skinlist)
{ {
snprintf(msg, 1024, M_GetText("%s has an invalid skin list and cannot be played.\n"), pdemoname); snprintf(msg, 1024, M_GetText("%s has an invalid skin list and cannot be played.\n"), pdemoname);
@ -3379,8 +3363,7 @@ void G_DoPlayDemoEx(const char *defdemoname, lumpnum_t deflumpnum)
K_UpdateShrinkCheat(&players[p]); K_UpdateShrinkCheat(&players[p]);
// Name // Name
M_Memcpy(player_names[p],demobuf.p,16); demobuf.p += copy_fixed_buf(player_names[p], demobuf.p, g_buffer_sizes.player_name);
demobuf.p += 16;
for (i = 0; i < MAXAVAILABILITY; i++) for (i = 0; i < MAXAVAILABILITY; i++)
{ {
@ -3395,8 +3378,7 @@ void G_DoPlayDemoEx(const char *defdemoname, lumpnum_t deflumpnum)
lastfakeskin[p] = READUINT8(demobuf.p); lastfakeskin[p] = READUINT8(demobuf.p);
// Color // Color
M_Memcpy(color,demobuf.p,16); demobuf.p += copy_fixed_buf(color, demobuf.p, g_buffer_sizes.color_name);
demobuf.p += 16;
for (i = 0; i < numskincolors; i++) for (i = 0; i < numskincolors; i++)
if (!stricmp(skincolors[i].name,color)) // SRB2kart if (!stricmp(skincolors[i].name,color)) // SRB2kart
{ {
@ -3405,13 +3387,11 @@ void G_DoPlayDemoEx(const char *defdemoname, lumpnum_t deflumpnum)
} }
// Follower // Follower
M_Memcpy(follower, demobuf.p, 16); demobuf.p += copy_fixed_buf(follower, demobuf.p, g_buffer_sizes.skin_name);
demobuf.p += 16;
K_SetFollowerByName(p, follower); K_SetFollowerByName(p, follower);
// Follower colour // Follower colour
M_Memcpy(color, demobuf.p, 16); demobuf.p += copy_fixed_buf(color, demobuf.p, g_buffer_sizes.color_name);
demobuf.p += 16;
for (i = 0; i < numskincolors +2; i++) // +2 because of Match and Opposite for (i = 0; i < numskincolors +2; i++) // +2 because of Match and Opposite
{ {
if (!stricmp(Followercolor_cons_t[i].strvalue, color)) if (!stricmp(Followercolor_cons_t[i].strvalue, color))
@ -3508,7 +3488,7 @@ void G_DoPlayDemoEx(const char *defdemoname, lumpnum_t deflumpnum)
void G_AddGhost(savebuffer_t *buffer, const char *defdemoname) void G_AddGhost(savebuffer_t *buffer, const char *defdemoname)
{ {
INT32 i; INT32 i;
char name[17], color[MAXCOLORNAME+1], md5[16]; char name[MAXPLAYERNAME+1], color[MAXCOLORNAME+1], md5[16];
demoghost *gh; demoghost *gh;
UINT16 flags; UINT16 flags;
UINT8 *p; UINT8 *p;
@ -3518,9 +3498,6 @@ void G_AddGhost(savebuffer_t *buffer, const char *defdemoname)
UINT8 worknumskins; UINT8 worknumskins;
democharlist_t *skinlist = NULL; democharlist_t *skinlist = NULL;
name[16] = '\0';
color[16] = '\0';
p = buffer->buffer; p = buffer->buffer;
// read demo header // read demo header
@ -3546,6 +3523,8 @@ void G_AddGhost(savebuffer_t *buffer, const char *defdemoname)
return; return;
} }
const DemoBufferSizes ghostsizes = get_buffer_sizes(ghostversion);
p += 64; // title p += 64; // title
M_Memcpy(md5, p, 16); p += 16; // demo checksum M_Memcpy(md5, p, 16); p += 16; // demo checksum
@ -3590,7 +3569,7 @@ void G_AddGhost(savebuffer_t *buffer, const char *defdemoname)
{ {
// FIXME: the rest of this function is not modifying buffer->p directly so fuck it // FIXME: the rest of this function is not modifying buffer->p directly so fuck it
buffer->p = p; buffer->p = p;
skinlist = G_LoadDemoSkins(buffer, &worknumskins, true); skinlist = G_LoadDemoSkins(ghostsizes, buffer, &worknumskins, true);
p = buffer->p; p = buffer->p;
} }
if (!skinlist) if (!skinlist)
@ -3653,8 +3632,7 @@ void G_AddGhost(savebuffer_t *buffer, const char *defdemoname)
} }
// Player name (TODO: Display this somehow if it doesn't match cv_playername!) // Player name (TODO: Display this somehow if it doesn't match cv_playername!)
M_Memcpy(name, p, 16); p += copy_fixed_buf(name, p, ghostsizes.player_name);
p += 16;
p += MAXAVAILABILITY; p += MAXAVAILABILITY;
@ -3665,11 +3643,10 @@ void G_AddGhost(savebuffer_t *buffer, const char *defdemoname)
p++; // lastfakeskin p++; // lastfakeskin
// Color // Color
M_Memcpy(color, p, 16); p += copy_fixed_buf(color, p, ghostsizes.color_name);
p += 16;
// Follower data was here, skip it, we don't care about it for ghosts. // Follower data was here, skip it, we don't care about it for ghosts.
p += 32; // followerskin (16) + followercolor (16) p += ghostsizes.skin_name + ghostsizes.color_name;
p += 4; // score p += 4; // score
p += 2; // powerlevel p += 2; // powerlevel
@ -3689,6 +3666,7 @@ void G_AddGhost(savebuffer_t *buffer, const char *defdemoname)
gh = static_cast<demoghost*>(Z_Calloc(sizeof(demoghost), PU_LEVEL, NULL)); gh = static_cast<demoghost*>(Z_Calloc(sizeof(demoghost), PU_LEVEL, NULL));
gh->sizes = ghostsizes;
gh->next = ghosts; gh->next = ghosts;
gh->buffer = buffer->buffer; gh->buffer = buffer->buffer;
M_Memcpy(gh->checksum, md5, 16); M_Memcpy(gh->checksum, md5, 16);
@ -3821,7 +3799,7 @@ staffbrief_t *G_GetStaffGhostBrief(UINT8 *buffer)
p++; // numlaps p++; // numlaps
G_SkipDemoExtraFiles(&p); G_SkipDemoExtraFiles(&p);
G_SkipDemoSkins(&p); G_SkipDemoSkins(&p, get_buffer_sizes(ghostversion));
if (flags & ATTACKING_TIME) if (flags & ATTACKING_TIME)
temp.time = READUINT32(p); temp.time = READUINT32(p);
@ -3861,7 +3839,7 @@ staffbrief_t *G_GetStaffGhostBrief(UINT8 *buffer)
if (READUINT8(p) & (DEMO_SPECTATOR|DEMO_BOT)) if (READUINT8(p) & (DEMO_SPECTATOR|DEMO_BOT))
goto fail; goto fail;
M_Memcpy(temp.name, p, 16); copy_fixed_buf(temp.name, p, get_buffer_sizes(ghostversion).player_name);
ret = static_cast<staffbrief_t*>(Z_Malloc(sizeof(staffbrief_t), PU_STATIC, NULL)); ret = static_cast<staffbrief_t*>(Z_Malloc(sizeof(staffbrief_t), PU_STATIC, NULL));
if (ret) if (ret)

View file

@ -69,7 +69,7 @@ extern consvar_t cv_recordmultiplayerdemos, cv_netdemosyncquality;
extern tic_t demostarttime; extern tic_t demostarttime;
struct democharlist_t { struct democharlist_t {
char name[17]; char name[SKINNAMESIZE+1];
UINT32 namehash; UINT32 namehash;
UINT8 mapping; // No, this isn't about levels. It maps to loaded character ID. UINT8 mapping; // No, this isn't about levels. It maps to loaded character ID.
UINT8 kartspeed; UINT8 kartspeed;
@ -128,7 +128,7 @@ struct menudemo_t {
struct { struct {
UINT8 ranking; UINT8 ranking;
char name[17]; char name[MAXPLAYERNAME+1];
UINT8 skin, color; UINT8 skin, color;
UINT32 timeorscore; UINT32 timeorscore;
} standings[MAXPLAYERS]; } standings[MAXPLAYERS];
@ -189,6 +189,13 @@ void G_StoreRewindInfo(void);
void G_PreviewRewind(tic_t previewtime); void G_PreviewRewind(tic_t previewtime);
void G_ConfirmRewind(tic_t rewindtime); void G_ConfirmRewind(tic_t rewindtime);
struct DemoBufferSizes
{
size_t player_name;
size_t skin_name;
size_t color_name;
};
// Your naming conventions are stupid and useless. // Your naming conventions are stupid and useless.
// There is no conflict here. // There is no conflict here.
struct demoghost { struct demoghost {
@ -201,6 +208,7 @@ struct demoghost {
boolean done; boolean done;
democharlist_t *skinlist; democharlist_t *skinlist;
mobj_t oldmo, *mo; mobj_t oldmo, *mo;
struct DemoBufferSizes sizes;
struct demoghost *next; struct demoghost *next;
}; };
extern demoghost *ghosts; extern demoghost *ghosts;