Lots of changes

* Show emblem requirement on record attack menu
* Use bigger emblems on the menu.
* Display your best number of collected rings in yellow if reached perfect bonus.
* Adjusted XTRA frames (again)
This commit is contained in:
Steel Titanium 2019-10-15 22:54:21 -04:00
parent 313b534911
commit 9c33f160a6
No known key found for this signature in database
GPG Key ID: 924BA411F18DFDBE
8 changed files with 93 additions and 51 deletions

View File

@ -327,7 +327,7 @@ 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[7]; ///< Intermission screen music.
char muspostbossname[7]; ///< Post-bossdeath music. char muspostbossname[7]; ///< Post-bossdeath music.
UINT16 muspostbosstrack; ///< Post-bossdeath track. UINT16 muspostbosstrack; ///< Post-bossdeath track.
UINT32 muspostbosspos; ///< Post-bossdeath position UINT32 muspostbosspos; ///< Post-bossdeath position
@ -433,6 +433,7 @@ typedef struct
tic_t time; ///< Time in which the level was finished. tic_t time; ///< Time in which the level was finished.
UINT32 score; ///< Score when the level was finished. UINT32 score; ///< Score when the level was finished.
UINT16 rings; ///< Rings when the level was finished. UINT16 rings; ///< Rings when the level was finished.
boolean gotperfect; ///< Got perfect bonus?
} recorddata_t; } recorddata_t;
/** Setup for one NiGHTS map. /** Setup for one NiGHTS map.

View File

@ -3341,6 +3341,7 @@ void G_LoadGameData(void)
UINT32 recscore; UINT32 recscore;
tic_t rectime; tic_t rectime;
UINT16 recrings; UINT16 recrings;
boolean gotperf;
UINT8 recmares; UINT8 recmares;
INT32 curmare; INT32 curmare;
@ -3433,6 +3434,7 @@ void G_LoadGameData(void)
recscore = READUINT32(save_p); recscore = READUINT32(save_p);
rectime = (tic_t)READUINT32(save_p); rectime = (tic_t)READUINT32(save_p);
recrings = READUINT16(save_p); recrings = READUINT16(save_p);
gotperf = (boolean)READUINT8(save_p);
if (recrings > 10000 || recscore > MAXSCORE) if (recrings > 10000 || recscore > MAXSCORE)
goto datacorrupt; goto datacorrupt;
@ -3444,6 +3446,9 @@ void G_LoadGameData(void)
mainrecords[i]->time = rectime; mainrecords[i]->time = rectime;
mainrecords[i]->rings = recrings; mainrecords[i]->rings = recrings;
} }
if (gotperf)
mainrecords[i]->gotperfect = gotperf;
} }
// Nights records // Nights records
@ -3575,12 +3580,14 @@ void G_SaveGameData(void)
WRITEUINT32(save_p, mainrecords[i]->score); WRITEUINT32(save_p, mainrecords[i]->score);
WRITEUINT32(save_p, mainrecords[i]->time); WRITEUINT32(save_p, mainrecords[i]->time);
WRITEUINT16(save_p, mainrecords[i]->rings); WRITEUINT16(save_p, mainrecords[i]->rings);
WRITEUINT8(save_p, mainrecords[i]->gotperfect);
} }
else else
{ {
WRITEUINT32(save_p, 0); WRITEUINT32(save_p, 0);
WRITEUINT32(save_p, 0); WRITEUINT32(save_p, 0);
WRITEUINT16(save_p, 0); WRITEUINT16(save_p, 0);
WRITEUINT8(save_p, 0);
} }
} }

View File

@ -874,9 +874,8 @@ typedef enum playersprite
// SPR2_XTRA // SPR2_XTRA
#define XTRA_LIFEPIC 0 // Life icon patch #define XTRA_LIFEPIC 0 // Life icon patch
#define XTRA_CHARSEL 1 // Character select picture #define XTRA_CHARSEL 1 // Character select picture
#define XTRA_NAMETAG 2 // Character select nametag #define XTRA_CONTINUE 2 // Continue icon
#define XTRA_CONTINUE 3 // Continue icon #define XTRA_ENDING 3 // Ending finale patches
#define XTRA_ENDING 4 // Ending finale patches
typedef enum state typedef enum state
{ {

View File

@ -528,12 +528,22 @@ skincolors_t M_GetEmblemColor(emblem_t *em)
return em->color; return em->color;
} }
const char *M_GetEmblemPatch(emblem_t *em) const char *M_GetEmblemPatch(emblem_t *em, boolean big)
{ {
static char pnamebuf[7] = "GOTITn"; static char pnamebuf[7];
if (!big)
strcpy(pnamebuf, "GOTITn");
else
strcpy(pnamebuf, "EMBMn0");
I_Assert(em->sprite >= 'A' && em->sprite <= 'Z'); I_Assert(em->sprite >= 'A' && em->sprite <= 'Z');
pnamebuf[5] = em->sprite;
if (!big)
pnamebuf[5] = em->sprite;
else
pnamebuf[4] = em->sprite;
return pnamebuf; return pnamebuf;
} }
@ -544,11 +554,21 @@ skincolors_t M_GetExtraEmblemColor(extraemblem_t *em)
return em->color; return em->color;
} }
const char *M_GetExtraEmblemPatch(extraemblem_t *em) const char *M_GetExtraEmblemPatch(extraemblem_t *em, boolean big)
{ {
static char pnamebuf[7] = "GOTITn"; static char pnamebuf[7];
if (!big)
strcpy(pnamebuf, "GOTITn");
else
strcpy(pnamebuf, "EMBMn0");
I_Assert(em->sprite >= 'A' && em->sprite <= 'Z'); I_Assert(em->sprite >= 'A' && em->sprite <= 'Z');
pnamebuf[5] = em->sprite;
if (!big)
pnamebuf[5] = em->sprite;
else
pnamebuf[4] = em->sprite;
return pnamebuf; return pnamebuf;
} }

View File

@ -171,9 +171,9 @@ INT32 M_CountEmblems(void);
// Emblem shit // Emblem shit
emblem_t *M_GetLevelEmblems(INT32 mapnum); emblem_t *M_GetLevelEmblems(INT32 mapnum);
skincolors_t M_GetEmblemColor(emblem_t *em); skincolors_t M_GetEmblemColor(emblem_t *em);
const char *M_GetEmblemPatch(emblem_t *em); const char *M_GetEmblemPatch(emblem_t *em, boolean big);
skincolors_t M_GetExtraEmblemColor(extraemblem_t *em); skincolors_t M_GetExtraEmblemColor(extraemblem_t *em);
const char *M_GetExtraEmblemPatch(extraemblem_t *em); const char *M_GetExtraEmblemPatch(extraemblem_t *em, boolean big);
// If you're looking to compare stats for unlocks or what not, use these // If you're looking to compare stats for unlocks or what not, use these
// They stop checking upon reaching the target number so they // They stop checking upon reaching the target number so they

View File

@ -753,8 +753,8 @@ static menuitem_t SP_TimeAttackLevelSelectMenu[] =
// Single Player Time Attack // Single Player Time Attack
static menuitem_t SP_TimeAttackMenu[] = static menuitem_t SP_TimeAttackMenu[] =
{ {
{IT_STRING|IT_KEYHANDLER, NULL, "Level Select...", M_HandleTimeAttackLevelSelect, 52}, {IT_STRING|IT_KEYHANDLER, NULL, "Level Select...", M_HandleTimeAttackLevelSelect, 62},
{IT_STRING|IT_CVAR, NULL, "Character", &cv_chooseskin, 62}, {IT_STRING|IT_CVAR, NULL, "Character", &cv_chooseskin, 72},
{IT_DISABLED, NULL, "Guest Option...", &SP_GuestReplayDef, 100}, {IT_DISABLED, NULL, "Guest Option...", &SP_GuestReplayDef, 100},
{IT_DISABLED, NULL, "Replay...", &SP_ReplayDef, 110}, {IT_DISABLED, NULL, "Replay...", &SP_ReplayDef, 110},
@ -3906,7 +3906,7 @@ static void M_DrawMapEmblems(INT32 mapnum, INT32 x, INT32 y)
lasttype = curtype; lasttype = curtype;
if (emblem->collected) if (emblem->collected)
V_DrawSmallMappedPatch(x, y, 0, W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE), V_DrawSmallMappedPatch(x, y, 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_CACHE),
R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE)); R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE));
else else
V_DrawSmallScaledPatch(x, y, 0, W_CachePatchName("NEEDIT", PU_CACHE)); V_DrawSmallScaledPatch(x, y, 0, W_CachePatchName("NEEDIT", PU_CACHE));
@ -4345,7 +4345,7 @@ static void M_DrawPauseMenu(void)
continue; continue;
if (emblem->collected) if (emblem->collected)
V_DrawSmallMappedPatch(40, 44 + (i*8), 0, W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE), V_DrawSmallMappedPatch(40, 44 + (i*8), 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_CACHE),
R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE)); R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE));
else else
V_DrawSmallScaledPatch(40, 44 + (i*8), 0, W_CachePatchName("NEEDIT", PU_CACHE)); V_DrawSmallScaledPatch(40, 44 + (i*8), 0, W_CachePatchName("NEEDIT", PU_CACHE));
@ -6866,7 +6866,7 @@ static void M_DrawEmblemHints(void)
if (emblem->collected) if (emblem->collected)
{ {
collected = V_GREENMAP; collected = V_GREENMAP;
V_DrawMappedPatch(12, 12+(28*j), 0, W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE), V_DrawMappedPatch(12, 12+(28*j), 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_CACHE),
R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE)); R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE));
} }
else else
@ -8487,7 +8487,7 @@ static void M_DrawStatsMaps(int location)
exemblem = &extraemblems[i]; exemblem = &extraemblems[i];
if (exemblem->collected) if (exemblem->collected)
V_DrawSmallMappedPatch(292, y, 0, W_CachePatchName(M_GetExtraEmblemPatch(exemblem), PU_CACHE), V_DrawSmallMappedPatch(292, y, 0, W_CachePatchName(M_GetExtraEmblemPatch(exemblem, false), PU_CACHE),
R_GetTranslationColormap(TC_DEFAULT, M_GetExtraEmblemColor(exemblem), GTC_CACHE)); R_GetTranslationColormap(TC_DEFAULT, M_GetExtraEmblemColor(exemblem), GTC_CACHE));
else else
V_DrawSmallScaledPatch(292, y, 0, W_CachePatchName("NEEDIT", PU_CACHE)); V_DrawSmallScaledPatch(292, y, 0, W_CachePatchName("NEEDIT", PU_CACHE));
@ -8632,9 +8632,10 @@ static void M_HandleLevelStats(INT32 choice)
// Drawing function for Time Attack // Drawing function for Time Attack
void M_DrawTimeAttackMenu(void) void M_DrawTimeAttackMenu(void)
{ {
INT32 i, x, y, cursory = 0; INT32 i, x, y, empatx, empaty, cursory = 0;
UINT16 dispstatus; UINT16 dispstatus;
patch_t *PictureOfUrFace; // my WHAT patch_t *PictureOfUrFace; // my WHAT
patch_t *empatch;
M_SetMenuCurBackground("RECATKBG"); M_SetMenuCurBackground("RECATKBG");
@ -8738,16 +8739,22 @@ void M_DrawTimeAttackMenu(void)
PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE);
y = 32+lsheadingheight; y = 32+lsheadingheight;
V_DrawSmallScaledPatch(208, y, 0, PictureOfLevel); V_DrawSmallScaledPatch(216, y, 0, PictureOfLevel);
if (itemOn == talevel)
if (currentMenu == &SP_TimeAttackDef)
{ {
/* Draw arrows !! */ if (itemOn == talevel)
y = y + 25 - 4; {
V_DrawCharacter(208 - 10 - (skullAnimCounter/5), y, /* Draw arrows !! */
'\x1C' | V_YELLOWMAP, false); y = y + 25 - 4;
V_DrawCharacter(208 + 80 + 2 + (skullAnimCounter/5), y, V_DrawCharacter(216 - 10 - (skullAnimCounter/5), y,
'\x1D' | V_YELLOWMAP, false); '\x1C' | V_YELLOWMAP, false);
V_DrawCharacter(216 + 80 + 2 + (skullAnimCounter/5), y,
'\x1D' | V_YELLOWMAP, false);
}
// Draw press ESC to exit string on main record attack menu
V_DrawString(104-72, 180, V_TRANSLUCENT, M_GetText("Press ESC to exit"));
} }
em = M_GetLevelEmblems(cv_nextmap.value); em = M_GetLevelEmblems(cv_nextmap.value);
@ -8757,42 +8764,46 @@ void M_DrawTimeAttackMenu(void)
switch (em->type) switch (em->type)
{ {
case ET_SCORE: case ET_SCORE:
yHeight = 48; yHeight = 33;
sprintf(reqscore, "%u", em->var); sprintf(reqscore, "(%u)", em->var);
break; break;
case ET_TIME: case ET_TIME:
yHeight = 58; yHeight = 53;
sprintf(reqtime, "%i:%02i.%02i", G_TicsToMinutes((tic_t)em->var, true), sprintf(reqtime, "(%i:%02i.%02i)", G_TicsToMinutes((tic_t)em->var, true),
G_TicsToSeconds((tic_t)em->var), G_TicsToSeconds((tic_t)em->var),
G_TicsToCentiseconds((tic_t)em->var)); G_TicsToCentiseconds((tic_t)em->var));
break; break;
case ET_RINGS: case ET_RINGS:
yHeight = 68; yHeight = 73;
sprintf(reqrings, "%u", em->var); sprintf(reqrings, "(%u)", em->var);
break; break;
default: default:
goto skipThisOne; goto skipThisOne;
} }
empatch = W_CachePatchName(M_GetEmblemPatch(em, true), PU_CACHE);
empatx = SHORT(empatch->leftoffset)/2;
empaty = SHORT(empatch->topoffset)/2;
if (em->collected) if (em->collected)
V_DrawSmallMappedPatch(104+76, yHeight+lsheadingheight/2, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), V_DrawSmallMappedPatch(104+76+empatx, yHeight+lsheadingheight/2+empaty, 0, empatch,
R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE)); R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE));
else else
V_DrawSmallScaledPatch(104+76, yHeight+lsheadingheight/2, 0, W_CachePatchName("NEEDIT", PU_CACHE)); V_DrawSmallScaledPatch(104+76, yHeight+lsheadingheight/2, 0, W_CachePatchName("NEEDITL", PU_CACHE));
skipThisOne: skipThisOne:
em = M_GetLevelEmblems(-1); em = M_GetLevelEmblems(-1);
} }
V_DrawString(104 - 72, 32+lsheadingheight/2, 0, "* LEVEL RECORDS *");
if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->score) if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->score)
sprintf(beststr, "(none)"); sprintf(beststr, "(none)");
else else
sprintf(beststr, "%u", mainrecords[cv_nextmap.value-1]->score); sprintf(beststr, "%u", mainrecords[cv_nextmap.value-1]->score);
V_DrawString(104-72, 48+lsheadingheight/2, V_YELLOWMAP, "SCORE:"); V_DrawString(104-72, 33+lsheadingheight/2, V_YELLOWMAP, "SCORE:");
V_DrawRightAlignedString(104+72, 48+lsheadingheight/2, V_ALLOWLOWERCASE, va("%s%s", beststr,reqscore)); V_DrawRightAlignedString(104+64, 33+lsheadingheight/2, V_ALLOWLOWERCASE, beststr);
V_DrawRightAlignedString(104+72, 43+lsheadingheight/2, V_ALLOWLOWERCASE, reqscore);
if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->time) if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->time)
sprintf(beststr, "(none)"); sprintf(beststr, "(none)");
@ -8801,16 +8812,23 @@ void M_DrawTimeAttackMenu(void)
G_TicsToSeconds(mainrecords[cv_nextmap.value-1]->time), G_TicsToSeconds(mainrecords[cv_nextmap.value-1]->time),
G_TicsToCentiseconds(mainrecords[cv_nextmap.value-1]->time)); G_TicsToCentiseconds(mainrecords[cv_nextmap.value-1]->time));
V_DrawString(104-72, 58+lsheadingheight/2, V_YELLOWMAP, "TIME:"); V_DrawString(104-72, 53+lsheadingheight/2, V_YELLOWMAP, "TIME:");
V_DrawRightAlignedString(104+72, 58+lsheadingheight/2, V_ALLOWLOWERCASE, va("%s%s", beststr,reqtime)); V_DrawRightAlignedString(104+64, 53+lsheadingheight/2, V_ALLOWLOWERCASE, beststr);
V_DrawRightAlignedString(104+72, 63+lsheadingheight/2, V_ALLOWLOWERCASE, reqtime);
if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->rings) if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->rings)
sprintf(beststr, "(none)"); sprintf(beststr, "(none)");
else else
sprintf(beststr, "%hu", mainrecords[cv_nextmap.value-1]->rings); sprintf(beststr, "%hu", mainrecords[cv_nextmap.value-1]->rings);
V_DrawString(104-72, 68+lsheadingheight/2, V_YELLOWMAP, "RINGS:"); V_DrawString(104-72, 73+lsheadingheight/2, V_YELLOWMAP, "RINGS:");
V_DrawRightAlignedString(104+72, 68+lsheadingheight/2, V_ALLOWLOWERCASE, va("%s%s", beststr,reqrings));
if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->gotperfect)
V_DrawRightAlignedString(104+64, 73+lsheadingheight/2, V_ALLOWLOWERCASE, beststr);
else
V_DrawRightAlignedString(104+64, 73+lsheadingheight/2, V_ALLOWLOWERCASE|V_YELLOWMAP, beststr);
V_DrawRightAlignedString(104+72, 83+lsheadingheight/2, V_ALLOWLOWERCASE, reqrings);
} }
// ALWAYS DRAW level and skin even when not on this menu! // ALWAYS DRAW level and skin even when not on this menu!
@ -8827,10 +8845,6 @@ void M_DrawTimeAttackMenu(void)
V_DrawString(x, y + SP_TimeAttackMenu[taplayer].alphaKey, V_TRANSLUCENT, SP_TimeAttackMenu[taplayer].text); V_DrawString(x, y + SP_TimeAttackMenu[taplayer].alphaKey, V_TRANSLUCENT, SP_TimeAttackMenu[taplayer].text);
V_DrawString(BASEVIDWIDTH - x - V_StringWidth(ncv->string, 0), y + SP_TimeAttackMenu[taplayer].alphaKey, V_YELLOWMAP|V_TRANSLUCENT, ncv->string); V_DrawString(BASEVIDWIDTH - x - V_StringWidth(ncv->string, 0), y + SP_TimeAttackMenu[taplayer].alphaKey, V_YELLOWMAP|V_TRANSLUCENT, ncv->string);
} }
// Draw press ESC to exit string on main record attack menu
if (currentMenu == &SP_TimeAttackDef)
V_DrawString(104-72, 180, V_TRANSLUCENT, M_GetText("Press ESC to exit"));
} }
static void M_HandleTimeAttackLevelSelect(INT32 choice) static void M_HandleTimeAttackLevelSelect(INT32 choice)
@ -8985,8 +8999,6 @@ void M_DrawNightsAttackMenu(void)
V_DrawSmallScaledPatch(208, 32+lsheadingheight, 0, PictureOfLevel); V_DrawSmallScaledPatch(208, 32+lsheadingheight, 0, PictureOfLevel);
V_DrawString(104 - 72, 32+lsheadingheight/2, 0, "* LEVEL RECORDS *");
// Super Sonic // Super Sonic
M_DrawNightsAttackSuperSonic(); M_DrawNightsAttackSuperSonic();
//if (P_HasGrades(cv_nextmap.value, 0)) //if (P_HasGrades(cv_nextmap.value, 0))
@ -9032,7 +9044,7 @@ void M_DrawNightsAttackMenu(void)
} }
if (em->collected) if (em->collected)
V_DrawSmallMappedPatch(104+38, yHeight+lsheadingheight/2, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), V_DrawSmallMappedPatch(104+38, yHeight+lsheadingheight/2, 0, W_CachePatchName(M_GetEmblemPatch(em, false), PU_CACHE),
R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE)); R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE));
else else
V_DrawSmallScaledPatch(104+38, yHeight+lsheadingheight/2, 0, W_CachePatchName("NEEDIT", PU_CACHE)); V_DrawSmallScaledPatch(104+38, yHeight+lsheadingheight/2, 0, W_CachePatchName("NEEDIT", PU_CACHE));

View File

@ -1074,7 +1074,7 @@ void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT8 skin
if (skinnum >= 0 && skinnum < numskins && skins[skinnum].sprites[SPR2_XTRA].numframes >= 4) if (skinnum >= 0 && skinnum < numskins && skins[skinnum].sprites[SPR2_XTRA].numframes >= 4)
{ {
spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA];
spriteframe_t *sprframe = &sprdef->spriteframes[3]; spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CONTINUE];
patch_t *patch = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); patch_t *patch = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL);
const UINT8 *colormap = R_GetTranslationColormap(skinnum, skincolor, GTC_CACHE); const UINT8 *colormap = R_GetTranslationColormap(skinnum, skincolor, GTC_CACHE);

View File

@ -1047,6 +1047,9 @@ static void Y_UpdateRecordReplays(void)
if ((UINT16)(players[consoleplayer].rings) > mainrecords[gamemap-1]->rings) if ((UINT16)(players[consoleplayer].rings) > mainrecords[gamemap-1]->rings)
mainrecords[gamemap-1]->rings = (UINT16)(players[consoleplayer].rings); mainrecords[gamemap-1]->rings = (UINT16)(players[consoleplayer].rings);
if (data.coop.gotperfbonus)
mainrecords[gamemap-1]->gotperfect = true;
// Save demo! // Save demo!
bestdemo[255] = '\0'; bestdemo[255] = '\0';
lastdemo[255] = '\0'; lastdemo[255] = '\0';