Merge branch 'soc-strlcpy-fix' into 'next'

Use deh_strlcpy instead of strncpy or strlcpy in SOC parser

See merge request STJr/SRB2!2614
This commit is contained in:
Lactozilla 2025-01-23 18:43:07 +00:00
commit 13df48b116
3 changed files with 106 additions and 71 deletions

View file

@ -1,7 +1,7 @@
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2024 by Sonic Team Junior. // Copyright (C) 1999-2025 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
@ -286,6 +286,7 @@ void readPlayer(MYFILE *f, INT32 num)
} }
if (playertext) if (playertext)
{ {
// PLAYERTEXT is really weird, so this doesn't use deh_strlcpy.
strlcpy(description[num].notes, playertext, NOTE_SIZE); strlcpy(description[num].notes, playertext, NOTE_SIZE);
strlcat(description[num].notes, strlcat(description[num].notes,
myhashfgets(playertext, NOTE_SIZE, f), NOTE_SIZE); myhashfgets(playertext, NOTE_SIZE, f), NOTE_SIZE);
@ -324,7 +325,8 @@ void readPlayer(MYFILE *f, INT32 num)
if (fastcmp(word, "PICNAME")) if (fastcmp(word, "PICNAME"))
{ {
SLOTFOUND SLOTFOUND
strncpy(description[num].picname, word2, sizeof(description[num].picname)-1); deh_strlcpy(description[num].picname, word2, sizeof description[num].picname,
va("Character %d: picname", num));
} }
else if (fastcmp(word, "DISPLAYNAME")) else if (fastcmp(word, "DISPLAYNAME"))
{ {
@ -345,7 +347,8 @@ void readPlayer(MYFILE *f, INT32 num)
cur = strchr(cur, '#'); cur = strchr(cur, '#');
} }
strlcpy(description[num].displayname, stringvalue, sizeof description[num].displayname); deh_strlcpy(description[num].displayname, stringvalue, sizeof description[num].displayname,
va("Character %d: displayname", num));
} }
else if (fastcmp(word, "OPPOSITECOLOR") || fastcmp(word, "OPPOSITECOLOUR")) else if (fastcmp(word, "OPPOSITECOLOR") || fastcmp(word, "OPPOSITECOLOUR"))
{ {
@ -355,7 +358,8 @@ void readPlayer(MYFILE *f, INT32 num)
else if (fastcmp(word, "NAMETAG") || fastcmp(word, "TAGNAME")) else if (fastcmp(word, "NAMETAG") || fastcmp(word, "TAGNAME"))
{ {
SLOTFOUND SLOTFOUND
strncpy(description[num].nametag, word2, sizeof(description[num].nametag)-1); deh_strlcpy(description[num].nametag, word2, sizeof description[num].nametag,
va("Character %d: nametag", num));
} }
else if (fastcmp(word, "TAGTEXTCOLOR") || fastcmp(word, "TAGTEXTCOLOUR")) else if (fastcmp(word, "TAGTEXTCOLOR") || fastcmp(word, "TAGTEXTCOLOUR"))
{ {
@ -387,7 +391,8 @@ void readPlayer(MYFILE *f, INT32 num)
{ {
// Send to free slot. // Send to free slot.
SLOTFOUND SLOTFOUND
strlcpy(description[num].skinname, word2, sizeof description[num].skinname); deh_strlcpy(description[num].skinname, word2, sizeof description[num].skinname,
va("Character %d: skinname", num));
strlwr(description[num].skinname); strlwr(description[num].skinname);
} }
else if (!failure) else if (!failure)
@ -1196,6 +1201,7 @@ void readgametype(MYFILE *f, char *gtname)
} }
if (descr) if (descr)
{ {
// DESCRIPTION is really weird, so this doesn't use deh_strlcpy.
strlcpy(gtdescription, descr, sizeof (gtdescription)); strlcpy(gtdescription, descr, sizeof (gtdescription));
strlcat(gtdescription, strlcat(gtdescription,
myhashfgets(descr, sizeof (gtdescription), f), myhashfgets(descr, sizeof (gtdescription), f),
@ -1402,7 +1408,7 @@ void readlevelheader(MYFILE *f, INT32 num)
{ {
deh_strlcpy(mapheaderinfo[num-1]->lvlttl, word2, deh_strlcpy(mapheaderinfo[num-1]->lvlttl, word2,
sizeof(mapheaderinfo[num-1]->lvlttl), va("Level header %d: levelname", num)); sizeof(mapheaderinfo[num-1]->lvlttl), va("Level header %d: levelname", num));
strlcpy(mapheaderinfo[num-1]->selectheading, word2, sizeof(mapheaderinfo[num-1]->selectheading)); // not deh_ so only complains once strlcpy(mapheaderinfo[num-1]->selectheading, word2, sizeof(mapheaderinfo[num-1]->selectheading)); // not deh_strlcpy so only complains once
continue; continue;
} }
// CHEAP HACK: move this over here for lowercase subtitles // CHEAP HACK: move this over here for lowercase subtitles
@ -1445,10 +1451,10 @@ void readlevelheader(MYFILE *f, INT32 num)
// Newly allocated // Newly allocated
modoption = &mapheaderinfo[num-1]->customopts[j]; modoption = &mapheaderinfo[num-1]->customopts[j];
strncpy(modoption->option, word, 31); deh_strlcpy(modoption->option, word, sizeof(modoption->option),
modoption->option[31] = '\0'; va("Level header %d: custom option %d key", num, j));
strncpy(modoption->value, word2, 255); deh_strlcpy(modoption->value, word2, sizeof(modoption->value),
modoption->value[255] = '\0'; va("Level header %d: custom option %d value", num, j));
continue; continue;
} }
@ -1675,7 +1681,8 @@ void readlevelheader(MYFILE *f, INT32 num)
} }
else if (fastcmp(word, "FORCECHARACTER")) else if (fastcmp(word, "FORCECHARACTER"))
{ {
strlcpy(mapheaderinfo[num-1]->forcecharacter, word2, SKINNAMESIZE+1); deh_strlcpy(mapheaderinfo[num-1]->forcecharacter, word2, sizeof mapheaderinfo[num-1]->forcecharacter,
va("Level header %d: forcecharacter", num));
strlwr(mapheaderinfo[num-1]->forcecharacter); // skin names are lowercase strlwr(mapheaderinfo[num-1]->forcecharacter); // skin names are lowercase
} }
else if (fastcmp(word, "WEATHER")) else if (fastcmp(word, "WEATHER"))
@ -1683,7 +1690,10 @@ void readlevelheader(MYFILE *f, INT32 num)
else if (fastcmp(word, "SKYNUM")) else if (fastcmp(word, "SKYNUM"))
mapheaderinfo[num-1]->skynum = (INT16)i; mapheaderinfo[num-1]->skynum = (INT16)i;
else if (fastcmp(word, "INTERSCREEN")) else if (fastcmp(word, "INTERSCREEN"))
strncpy(mapheaderinfo[num-1]->interscreen, word2, sizeof(mapheaderinfo[num-1]->interscreen)-1); {
deh_strlcpy(mapheaderinfo[num-1]->interscreen, word2, sizeof mapheaderinfo[num-1]->interscreen,
va("Level header %d: interscreen", num));
}
else if (fastcmp(word, "PRECUTSCENENUM")) else if (fastcmp(word, "PRECUTSCENENUM"))
mapheaderinfo[num-1]->precutscenenum = (UINT8)i; mapheaderinfo[num-1]->precutscenenum = (UINT8)i;
else if (fastcmp(word, "CUTSCENENUM")) else if (fastcmp(word, "CUTSCENENUM"))
@ -1985,14 +1995,17 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
picid = (UINT8)atoi(word + 3); picid = (UINT8)atoi(word + 3);
if (picid > 8 || picid == 0) if (picid > 8 || picid == 0)
{ {
deh_warning("CutSceneScene %d: unknown word '%s'", num, word); deh_warning("Cutscene %d, scene %d: pic number %d out of range (1 - %d)",
num + 1, scenenum + 1, picid, 8);
continue; continue;
} }
--picid; --picid;
if (fastcmp(word+4, "NAME")) if (fastcmp(word+4, "NAME"))
{ {
strncpy(cutscenes[num]->scene[scenenum].picname[picid], word2, 8); deh_strlcpy(cutscenes[num]->scene[scenenum].picname[picid], word2,
sizeof cutscenes[num]->scene[scenenum].picname[picid],
va("Cutscene %d, scene %d, pic %d: name", num + 1, scenenum + 1, picid + 1));
} }
else if (fastcmp(word+4, "HIRES")) else if (fastcmp(word+4, "HIRES"))
{ {
@ -2011,12 +2024,13 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
cutscenes[num]->scene[scenenum].ycoord[picid] = usi; cutscenes[num]->scene[scenenum].ycoord[picid] = usi;
} }
else else
deh_warning("CutSceneScene %d: unknown word '%s'", num, word); deh_warning("Cutscene %d, scene %d: unknown word '%s'", num + 1, scenenum + 1, word);
} }
else if (fastcmp(word, "MUSIC")) else if (fastcmp(word, "MUSIC"))
{ {
strncpy(cutscenes[num]->scene[scenenum].musswitch, word2, 7); deh_strlcpy(cutscenes[num]->scene[scenenum].musswitch, word2,
cutscenes[num]->scene[scenenum].musswitch[6] = 0; sizeof cutscenes[num]->scene[scenenum].musswitch,
va("Cutscene %d, scene %d: music", num + 1, scenenum + 1));
} }
else if (fastcmp(word, "MUSICTRACK")) else if (fastcmp(word, "MUSICTRACK"))
{ {
@ -2051,7 +2065,7 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
cutscenes[num]->scene[scenenum].fadecolor = (UINT8)i; cutscenes[num]->scene[scenenum].fadecolor = (UINT8)i;
} }
else else
deh_warning("CutSceneScene %d: unknown word '%s'", num, word); deh_warning("Cutscene %d, scene %d: unknown word '%s'", num + 1, scenenum + 1, word);
} }
} while (!myfeof(f)); // finish when the line is empty } while (!myfeof(f)); // finish when the line is empty
@ -2109,11 +2123,10 @@ void readcutscene(MYFILE *f, INT32 num)
readcutscenescene(f, num, value - 1); readcutscenescene(f, num, value - 1);
} }
else else
deh_warning("Scene number %d out of range (1 - 128)", value); deh_warning("Cutscene %d: scene number %d out of range (1 - 128)", num + 1, value);
} }
else else
deh_warning("Cutscene %d: unknown word '%s', Scene <num> expected.", num, word); deh_warning("Cutscene %d: unknown word '%s', Scene <num> expected.", num + 1, word);
} }
} while (!myfeof(f)); // finish when the line is empty } while (!myfeof(f)); // finish when the line is empty
@ -2234,7 +2247,8 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum)
for (picid = 0; picid < MAX_PROMPT_PICS; picid++) for (picid = 0; picid < MAX_PROMPT_PICS; picid++)
{ {
strncpy(textprompts[num]->page[pagenum].picname[picid], textprompts[num]->page[metapagenum].picname[picid], 8); // Doesn't use deh_strlcpy because it's not copying input.
strlcpy(textprompts[num]->page[pagenum].picname[picid], textprompts[num]->page[metapagenum].picname[picid], sizeof textprompts[num]->page[pagenum].picname[picid]);
textprompts[num]->page[pagenum].pichires[picid] = textprompts[num]->page[metapagenum].pichires[picid]; textprompts[num]->page[pagenum].pichires[picid] = textprompts[num]->page[metapagenum].pichires[picid];
textprompts[num]->page[pagenum].picduration[picid] = textprompts[num]->page[metapagenum].picduration[picid]; textprompts[num]->page[pagenum].picduration[picid] = textprompts[num]->page[metapagenum].picduration[picid];
textprompts[num]->page[pagenum].xcoord[picid] = textprompts[num]->page[metapagenum].xcoord[picid]; textprompts[num]->page[pagenum].xcoord[picid] = textprompts[num]->page[metapagenum].xcoord[picid];
@ -2247,14 +2261,17 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum)
picid = (UINT8)atoi(word + 3); picid = (UINT8)atoi(word + 3);
if (picid > MAX_PROMPT_PICS || picid == 0) if (picid > MAX_PROMPT_PICS || picid == 0)
{ {
deh_warning("textpromptscene %d: unknown word '%s'", num, word); deh_warning("Text prompt %d, page %d: pic number %d out of range (1 - %d)",
num + 1, pagenum + 1, picid, MAX_PROMPT_PICS);
continue; continue;
} }
--picid; --picid;
if (fastcmp(word+4, "NAME")) if (fastcmp(word+4, "NAME"))
{ {
strncpy(textprompts[num]->page[pagenum].picname[picid], word2, 8); deh_strlcpy(textprompts[num]->page[pagenum].picname[picid], word2,
sizeof textprompts[num]->page[pagenum].picname[picid],
va("Text prompt %d, page %d, pic %d: name", num + 1, pagenum + 1, picid + 1));
} }
else if (fastcmp(word+4, "HIRES")) else if (fastcmp(word+4, "HIRES"))
{ {
@ -2273,12 +2290,16 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum)
textprompts[num]->page[pagenum].ycoord[picid] = usi; textprompts[num]->page[pagenum].ycoord[picid] = usi;
} }
else else
deh_warning("textpromptscene %d: unknown word '%s'", num, word); {
deh_warning("Text prompt %d, page %d: unknown word '%s'",
num + 1, pagenum + 1, word);
}
} }
else if (fastcmp(word, "MUSIC")) else if (fastcmp(word, "MUSIC"))
{ {
strncpy(textprompts[num]->page[pagenum].musswitch, word2, 7); deh_strlcpy(textprompts[num]->page[pagenum].musswitch, word2,
textprompts[num]->page[pagenum].musswitch[6] = 0; sizeof textprompts[num]->page[pagenum].musswitch,
va("Text prompt %d, page %d: music", num + 1, pagenum + 1));
} }
else if (fastcmp(word, "MUSICTRACK")) else if (fastcmp(word, "MUSICTRACK"))
{ {
@ -2293,30 +2314,35 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum)
{ {
if (*word2 != '\0') if (*word2 != '\0')
{ {
INT32 j; size_t j;
// HACK: Add yellow control char now // HACK: Add yellow control char now
// so the drawing function doesn't call it repeatedly // so the drawing function doesn't call it repeatedly
char name[34]; char name[32 + 2];
name[0] = '\x82'; // color yellow name[0] = '\x82'; // color yellow
name[1] = 0;
strncat(name, word2, 32); // So that we still get a warning.
name[33] = 0; deh_strlcpy(name + 1, word2, (sizeof(name)) - 1,
va("Text prompt %d, page %d: name", num + 1, pagenum + 1));
// Replace _ with ' ' // Replace _ with ' '
for (j = 0; j < 32 && name[j]; j++) for (j = 1; j < sizeof(name) && name[j]; j++)
{ {
if (name[j] == '_') if (name[j] == '_')
name[j] = ' '; name[j] = ' ';
} }
strncpy(textprompts[num]->page[pagenum].name, name, sizeof(textprompts[num]->page[pagenum].name)); strlcpy(textprompts[num]->page[pagenum].name, name, sizeof(textprompts[num]->page[pagenum].name));
} }
else else
*textprompts[num]->page[pagenum].name = '\0'; *textprompts[num]->page[pagenum].name = '\0';
} }
else if (fastcmp(word, "ICON")) else if (fastcmp(word, "ICON"))
strncpy(textprompts[num]->page[pagenum].iconname, word2, 8); {
deh_strlcpy(textprompts[num]->page[pagenum].iconname, word2,
sizeof textprompts[num]->page[pagenum].iconname,
va("Text prompt %d, page %d: icon", num + 1, pagenum + 1));
}
else if (fastcmp(word, "ICONALIGN")) else if (fastcmp(word, "ICONALIGN"))
textprompts[num]->page[pagenum].rightside = (i || word2[0] == 'R'); textprompts[num]->page[pagenum].rightside = (i || word2[0] == 'R');
else if (fastcmp(word, "ICONFLIP")) else if (fastcmp(word, "ICONFLIP"))
@ -2383,8 +2409,9 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum)
{ {
UINT8 metapagenum = usi - 1; UINT8 metapagenum = usi - 1;
strncpy(textprompts[num]->page[pagenum].name, textprompts[num]->page[metapagenum].name, 32); // Doesn't use deh_strlcpy because it's not copying input.
strncpy(textprompts[num]->page[pagenum].iconname, textprompts[num]->page[metapagenum].iconname, 8); strlcpy(textprompts[num]->page[pagenum].name, textprompts[num]->page[metapagenum].name, sizeof textprompts[num]->page[pagenum].name);
strlcpy(textprompts[num]->page[pagenum].iconname, textprompts[num]->page[metapagenum].iconname, sizeof textprompts[num]->page[pagenum].iconname);
textprompts[num]->page[pagenum].rightside = textprompts[num]->page[metapagenum].rightside; textprompts[num]->page[pagenum].rightside = textprompts[num]->page[metapagenum].rightside;
textprompts[num]->page[pagenum].iconflip = textprompts[num]->page[metapagenum].iconflip; textprompts[num]->page[pagenum].iconflip = textprompts[num]->page[metapagenum].iconflip;
textprompts[num]->page[pagenum].lines = textprompts[num]->page[metapagenum].lines; textprompts[num]->page[pagenum].lines = textprompts[num]->page[metapagenum].lines;
@ -2399,17 +2426,25 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum)
} }
} }
else if (fastcmp(word, "TAG")) else if (fastcmp(word, "TAG"))
strncpy(textprompts[num]->page[pagenum].tag, word2, 33); {
deh_strlcpy(textprompts[num]->page[pagenum].tag, word2,
sizeof textprompts[num]->page[pagenum].tag,
va("Text prompt %d, page %d: tag", num + 1, pagenum + 1));
}
else if (fastcmp(word, "NEXTPROMPT")) else if (fastcmp(word, "NEXTPROMPT"))
textprompts[num]->page[pagenum].nextprompt = usi; textprompts[num]->page[pagenum].nextprompt = usi;
else if (fastcmp(word, "NEXTPAGE")) else if (fastcmp(word, "NEXTPAGE"))
textprompts[num]->page[pagenum].nextpage = usi; textprompts[num]->page[pagenum].nextpage = usi;
else if (fastcmp(word, "NEXTTAG")) else if (fastcmp(word, "NEXTTAG"))
strncpy(textprompts[num]->page[pagenum].nexttag, word2, 33); {
deh_strlcpy(textprompts[num]->page[pagenum].nexttag, word2,
sizeof textprompts[num]->page[pagenum].nexttag,
va("Text prompt %d, page %d: nexttag", num + 1, pagenum + 1));
}
else if (fastcmp(word, "TIMETONEXT")) else if (fastcmp(word, "TIMETONEXT"))
textprompts[num]->page[pagenum].timetonext = get_number(word2); textprompts[num]->page[pagenum].timetonext = get_number(word2);
else else
deh_warning("PromptPage %d: unknown word '%s'", num, word); deh_warning("Text prompt %d, page %d: unknown word '%s'", num + 1, pagenum + 1, word);
} }
} while (!myfeof(f)); // finish when the line is empty } while (!myfeof(f)); // finish when the line is empty
@ -2469,11 +2504,11 @@ void readtextprompt(MYFILE *f, INT32 num)
readtextpromptpage(f, num, value - 1); readtextpromptpage(f, num, value - 1);
} }
else else
deh_warning("Page number %d out of range (1 - %d)", value, MAX_PAGES); deh_warning("Prompt %d: page number %d out of range (1 - %d)", num + 1, value, MAX_PAGES);
} }
else else
deh_warning("Prompt %d: unknown word '%s', Page <num> expected.", num, word); deh_warning("Prompt %d: unknown word '%s', Page <num> expected.", num + 1, word);
} }
} while (!myfeof(f)); // finish when the line is empty } while (!myfeof(f)); // finish when the line is empty
@ -2522,7 +2557,8 @@ void readmenu(MYFILE *f, INT32 num)
if (fastcmp(word, "BACKGROUNDNAME")) if (fastcmp(word, "BACKGROUNDNAME"))
{ {
strncpy(menupres[num].bgname, word2, 8); deh_strlcpy(menupres[num].bgname, word2,
sizeof menupres[num].bgname, va("Menu %d: backgroundname", num));
titlechanged = true; titlechanged = true;
} }
else if (fastcmp(word, "HIDEBACKGROUND")) else if (fastcmp(word, "HIDEBACKGROUND"))
@ -2565,7 +2601,8 @@ void readmenu(MYFILE *f, INT32 num)
} }
else if (fastcmp(word, "TITLEPICSNAME")) else if (fastcmp(word, "TITLEPICSNAME"))
{ {
strncpy(menupres[num].ttname, word2, 9); deh_strlcpy(menupres[num].ttname, word2,
sizeof menupres[num].ttname, va("Menu %d: titlepicsname", num));
titlechanged = true; titlechanged = true;
} }
else if (fastcmp(word, "TITLEPICSX")) else if (fastcmp(word, "TITLEPICSX"))
@ -2601,8 +2638,8 @@ void readmenu(MYFILE *f, INT32 num)
} }
else if (fastcmp(word, "MUSIC")) else if (fastcmp(word, "MUSIC"))
{ {
strncpy(menupres[num].musname, word2, 7); deh_strlcpy(menupres[num].musname, word2,
menupres[num].musname[6] = 0; sizeof menupres[num].musname, va("Menu %d: music", num));
titlechanged = true; titlechanged = true;
} }
else if (fastcmp(word, "MUSICTRACK")) else if (fastcmp(word, "MUSICTRACK"))
@ -3590,9 +3627,7 @@ void readmaincfg(MYFILE *f)
lumpnum_t lumpnum; lumpnum_t lumpnum;
char newname[9]; char newname[9];
strncpy(newname, word2, 8); deh_strlcpy(newname, word2, sizeof newname, va("Maincfg: execcfg"));
newname[8] = '\0';
lumpnum = W_CheckNumForName(newname); lumpnum = W_CheckNumForName(newname);
@ -3800,7 +3835,7 @@ void readmaincfg(MYFILE *f)
} }
else if (fastcmp(word, "TITLEPICSNAME")) else if (fastcmp(word, "TITLEPICSNAME"))
{ {
strncpy(ttname, word2, sizeof(ttname)-1); deh_strlcpy(ttname, word2, sizeof ttname, va("Maincfg: titlepicsname"));
titlechanged = true; titlechanged = true;
} }
else if (fastcmp(word, "TITLEPICSX")) else if (fastcmp(word, "TITLEPICSX"))
@ -3910,7 +3945,7 @@ void readmaincfg(MYFILE *f)
} }
else if (fastcmp(word, "CUSTOMVERSION")) else if (fastcmp(word, "CUSTOMVERSION"))
{ {
strlcpy(customversionstring, word2, sizeof (customversionstring)); deh_strlcpy(customversionstring, word2, sizeof customversionstring, va("Maincfg: customversion"));
//titlechanged = true; //titlechanged = true;
} }
else if (fastcmp(word, "BOOTMAP")) else if (fastcmp(word, "BOOTMAP"))

View file

@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2024 by Sonic Team Junior. // Copyright (C) 1999-2025 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
@ -209,19 +209,19 @@ typedef struct
UINT8 picmode; // sequence mode after displaying last pic, 0 = persist, 1 = loop, 2 = destroy UINT8 picmode; // sequence mode after displaying last pic, 0 = persist, 1 = loop, 2 = destroy
UINT8 pictoloop; // if picmode == loop, which pic to loop to? UINT8 pictoloop; // if picmode == loop, which pic to loop to?
UINT8 pictostart; // initial pic number to show UINT8 pictostart; // initial pic number to show
char picname[MAX_PROMPT_PICS][8]; char picname[MAX_PROMPT_PICS][8+1];
UINT8 pichires[MAX_PROMPT_PICS]; UINT8 pichires[MAX_PROMPT_PICS];
UINT16 xcoord[MAX_PROMPT_PICS]; // gfx UINT16 xcoord[MAX_PROMPT_PICS]; // gfx
UINT16 ycoord[MAX_PROMPT_PICS]; // gfx UINT16 ycoord[MAX_PROMPT_PICS]; // gfx
UINT16 picduration[MAX_PROMPT_PICS]; UINT16 picduration[MAX_PROMPT_PICS];
char musswitch[7]; char musswitch[6+1];
UINT16 musswitchflags; UINT16 musswitchflags;
UINT8 musicloop; UINT8 musicloop;
char tag[33]; // page tag char tag[32+1]; // page tag
char name[34]; // narrator name, extra char for color char name[32+2]; // narrator name, extra char for color
char iconname[8]; // narrator icon lump char iconname[8+1]; // narrator icon lump
boolean rightside; // narrator side, false = left, true = right boolean rightside; // narrator side, false = left, true = right
boolean iconflip; // narrator flip icon horizontally boolean iconflip; // narrator flip icon horizontally
UINT8 hidehud; // hide hud, 0 = show all, 1 = hide depending on prompt position (top/bottom), 2 = hide all UINT8 hidehud; // hide hud, 0 = show all, 1 = hide depending on prompt position (top/bottom), 2 = hide all
@ -233,7 +233,7 @@ typedef struct
sfxenum_t textsfx; // sfx_ id for printing text sfxenum_t textsfx; // sfx_ id for printing text
UINT8 nextprompt; // next prompt to jump to, one-based. 0 = current prompt UINT8 nextprompt; // next prompt to jump to, one-based. 0 = current prompt
UINT8 nextpage; // next page to jump to, one-based. 0 = next page within prompt->numpages UINT8 nextpage; // next page to jump to, one-based. 0 = next page within prompt->numpages
char nexttag[33]; // next tag to jump to. If set, this overrides nextprompt and nextpage. char nexttag[32+1]; // next tag to jump to. If set, this overrides nextprompt and nextpage.
INT32 timetonext; // time in tics to jump to next page automatically. 0 = don't jump automatically INT32 timetonext; // time in tics to jump to next page automatically. 0 = don't jump automatically
char *text; char *text;
} textpage_t; } textpage_t;
@ -287,8 +287,8 @@ typedef struct
// (This is not ifdeffed so the map header structure can stay identical, just in case.) // (This is not ifdeffed so the map header structure can stay identical, just in case.)
typedef struct typedef struct
{ {
char option[32]; // 31 usable characters char option[31+1]; // 31 usable characters
char value[256]; // 255 usable characters. If this seriously isn't enough then wtf. char value[255+1]; // 255 usable characters. If this seriously isn't enough then wtf.
} customoption_t; } customoption_t;
/** Map header information. /** Map header information.
@ -303,7 +303,7 @@ typedef struct
INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end. INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end.
INT16 marathonnext; ///< See nextlevel, but for Marathon mode. Necessary to support hub worlds ala SUGOI. INT16 marathonnext; ///< See nextlevel, but for Marathon mode. Necessary to support hub worlds ala SUGOI.
char keywords[32+1]; ///< Keywords separated by space to search for. 32 characters. char keywords[32+1]; ///< Keywords separated by space to search for. 32 characters.
char musname[7]; ///< Music track to play. "" for no music. char musname[6+1]; ///< Music track to play. "" for no music.
UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore. UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore.
UINT32 muspos; ///< Music position to jump to. UINT32 muspos; ///< Music position to jump to.
char forcecharacter[16+1]; ///< (SKINNAMESIZE+1) Skin to switch to or "" to disable. char forcecharacter[16+1]; ///< (SKINNAMESIZE+1) Skin to switch to or "" to disable.
@ -330,7 +330,7 @@ typedef struct
UINT16 levelflags; ///< LF_flags: merged booleans into one UINT16 for space, see below UINT16 levelflags; ///< LF_flags: merged booleans into one UINT16 for space, see below
UINT8 menuflags; ///< LF2_flags: options that affect record attack / nights mode menus UINT8 menuflags; ///< LF2_flags: options that affect record attack / nights mode menus
char selectheading[22]; ///< Level select heading. Allows for controllable grouping. char selectheading[21+1]; ///< Level select heading. Allows for controllable grouping.
UINT16 startrings; ///< Number of rings players start with. UINT16 startrings; ///< Number of rings players start with.
INT32 sstimer; ///< Timer for special stages. INT32 sstimer; ///< Timer for special stages.
UINT32 ssspheres; ///< Sphere requirement in special stages. UINT32 ssspheres; ///< Sphere requirement in special stages.
@ -352,9 +352,9 @@ typedef struct
// Music stuff. // Music stuff.
UINT32 musinterfadeout; ///< Fade out level music on intermission screen in milliseconds UINT32 musinterfadeout; ///< Fade out level music on intermission screen in milliseconds
char musintername[7]; ///< Intermission screen music. char musintername[6+1]; ///< Intermission screen music.
char muspostbossname[7]; ///< Post-bossdeath music. char muspostbossname[6+1]; ///< Post-bossdeath music.
UINT16 muspostbosstrack; ///< Post-bossdeath track. UINT16 muspostbosstrack; ///< Post-bossdeath track.
UINT32 muspostbosspos; ///< Post-bossdeath position UINT32 muspostbosspos; ///< Post-bossdeath position
UINT32 muspostbossfadein; ///< Post-bossdeath fade-in milliseconds. UINT32 muspostbossfadein; ///< Post-bossdeath fade-in milliseconds.

View file

@ -3,7 +3,7 @@
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 2011-2016 by Matthew "Kaito Sinclaire" Walsh. // Copyright (C) 2011-2016 by Matthew "Kaito Sinclaire" Walsh.
// Copyright (C) 1999-2024 by Sonic Team Junior. // Copyright (C) 1999-2025 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
@ -143,7 +143,7 @@ typedef enum
typedef struct typedef struct
{ {
char bgname[8]; // name for background gfx lump; lays over titlemap if this is set char bgname[8+1]; // name for background gfx lump; lays over titlemap if this is set
SINT8 fadestrength; // darken background when displaying this menu, strength 0-31 or -1 for undefined SINT8 fadestrength; // darken background when displaying this menu, strength 0-31 or -1 for undefined
INT32 bgcolor; // fill color, overrides bg name. -1 means follow bg name rules. INT32 bgcolor; // fill color, overrides bg name. -1 means follow bg name rules.
INT32 titlescrollxspeed; // background gfx scroll per menu; inherits global setting INT32 titlescrollxspeed; // background gfx scroll per menu; inherits global setting
@ -153,13 +153,13 @@ typedef struct
SINT8 hidetitlepics; // hide title gfx per menu; -1 means undefined, inherits global setting SINT8 hidetitlepics; // hide title gfx per menu; -1 means undefined, inherits global setting
ttmode_enum ttmode; // title wing animation mode; default TTMODE_OLD ttmode_enum ttmode; // title wing animation mode; default TTMODE_OLD
UINT8 ttscale; // scale of title wing gfx (FRACUNIT / ttscale); -1 means undefined, inherits global setting UINT8 ttscale; // scale of title wing gfx (FRACUNIT / ttscale); -1 means undefined, inherits global setting
char ttname[9]; // lump name of title wing gfx. If name length is <= 6, engine will attempt to load numbered frames (TTNAMExx) char ttname[8+1]; // lump name of title wing gfx. If name length is <= 6, engine will attempt to load numbered frames (TTNAMExx)
INT16 ttx; // X position of title wing INT16 ttx; // X position of title wing
INT16 tty; // Y position of title wing INT16 tty; // Y position of title wing
INT16 ttloop; // # frame to loop; -1 means dont loop INT16 ttloop; // # frame to loop; -1 means dont loop
UINT16 tttics; // # of tics per frame UINT16 tttics; // # of tics per frame
char musname[7]; ///< Music track to play. "" for no music. char musname[6+1]; ///< Music track to play. "" for no music.
UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore. UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore.
boolean muslooping; ///< Loop the music boolean muslooping; ///< Loop the music
boolean musstop; ///< Don't play any music boolean musstop; ///< Don't play any music
@ -370,8 +370,8 @@ extern menu_t OP_JoystickSetDef;
typedef struct typedef struct
{ {
boolean used; boolean used;
char notes[441]; char notes[440+1];
char picname[8]; char picname[8+1];
char skinname[SKINNAMESIZE*2+2]; // skin&skin\0 char skinname[SKINNAMESIZE*2+2]; // skin&skin\0
patch_t *charpic; patch_t *charpic;
UINT8 prev; UINT8 prev;