* Fix an issue where valid savefiles would be hidden because there were at least three unused slots between that and the last visible save. In the process, made sure there were at least three slots visible at all times, but never show extras not needed to show all the saves.

* Optimisations in a bunch of places, including to static
* Fix some visual errors with text and patches near the edges of the screen in non-standard resolutions.
This commit is contained in:
toasterbabe 2017-08-22 21:02:33 +01:00
parent 6e7605e4f3
commit 8d78d32d64
2 changed files with 121 additions and 91 deletions

View File

@ -174,6 +174,7 @@ static UINT32 serverlistpage;
static UINT8 numsaves = 0;
static saveinfo_t* savegameinfo = NULL; // Extra info about the save games.
static patch_t *savselp[7];
INT16 startmap; // Mario, NiGHTS, or just a plain old normal game?
@ -223,7 +224,7 @@ static INT32 lsoffs[2];
#define lshli levelselectselect[2]
#define lshseperation 101
#define lsbasevseperation 62
#define lsbasevseperation (62*vid.height)/(BASEVIDHEIGHT*vid.dupy) //62
#define lsheadingheight 16
#define getheadingoffset(row) (levelselect.rows[row].header[0] ? lsheadingheight : 0)
#define lsvseperation(row) lsbasevseperation + getheadingoffset(row)
@ -4280,14 +4281,10 @@ void M_DrawLevelPlatterHeader(INT32 y, const char *header, boolean headerhighlig
y += lsheadingheight - 12;
V_DrawString(19, y, (headerhighlight ? V_YELLOWMAP : 0)|(allowlowercase ? V_ALLOWLOWERCASE : 0), header);
y += 9;
if ((y >= 0) && (y < 200))
{
V_DrawFill(19, y, 281, 1, (headerhighlight ? yellowmap[3] : 3));
V_DrawFill(300, y, 1, 1, 26);
}
V_DrawFill(19, y, 281, 1, (headerhighlight ? yellowmap[3] : 3));
V_DrawFill(300, y, 1, 1, 26);
y++;
if ((y >= 0) && (y < 200))
V_DrawFill(19, y, 282, 1, 26);
V_DrawFill(19, y, 282, 1, 26);
}
static void M_DrawLevelPlatterWideMap(UINT8 row, UINT8 col, INT32 x, INT32 y, boolean highlight)
@ -4311,22 +4308,9 @@ static void M_DrawLevelPlatterWideMap(UINT8 row, UINT8 col, INT32 x, INT32 y, bo
V_DrawSmallScaledPatch(x, y, 0, patch);
}
if ((y+50) < 200)
{
INT32 topy = (y+50), h = 8;
if (topy < 0)
{
h += topy;
topy = 0;
}
else if (topy + h >= 200)
h = 200 - y;
if (h > 0)
V_DrawFill(x, topy, 282, h,
((mapheaderinfo[map-1]->unlockrequired < 0)
? 159 : 63));
}
V_DrawFill(x, y+50, 282, 8,
((mapheaderinfo[map-1]->unlockrequired < 0)
? 159 : 63));
V_DrawString(x, y+50, (highlight ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]);
}
@ -4352,22 +4336,9 @@ static void M_DrawLevelPlatterMap(UINT8 row, UINT8 col, INT32 x, INT32 y, boolea
V_DrawSmallScaledPatch(x, y, 0, patch);
}
if ((y+50) < 200)
{
INT32 topy = (y+50), h = 8;
if (topy < 0)
{
h += topy;
topy = 0;
}
else if (topy + h >= 200)
h = 200 - y;
if (h > 0)
V_DrawFill(x, topy, 80, h,
((mapheaderinfo[map-1]->unlockrequired < 0)
? 159 : 63));
}
V_DrawFill(x, y+50, 80, 8,
((mapheaderinfo[map-1]->unlockrequired < 0)
? 159 : 63));
if (strlen(levelselect.rows[row].mapnames[col]) > 6) // "AERIAL GARDEN" vs "ACT 18" - "THE ACT" intentionally compressed
V_DrawThinString(x, y+50, (highlight ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]);
@ -6053,13 +6024,16 @@ static UINT8 loadgameoffset = 0;
static void M_DrawLoadGameData(void)
{
INT32 i, savetodraw, x, y;
INT32 i, savetodraw, x, y, hsep = 90;
skin_t *charskin = NULL;
if (vid.width != BASEVIDWIDTH*vid.dupx)
hsep = (hsep*vid.width)/(BASEVIDWIDTH*vid.dupx);
for (i = -2; i <= 2; i++)
{
savetodraw = (saveSlotSelected + i + numsaves)%numsaves;
x = (BASEVIDWIDTH/2 - 42 + loadgamescroll) + (i*90);
x = (BASEVIDWIDTH/2 - 42 + loadgamescroll) + (i*hsep);
y = 33 + 9;
{
@ -6075,7 +6049,7 @@ static void M_DrawLoadGameData(void)
if (savetodraw == 0)
{
V_DrawSmallScaledPatch(x, y, 0,
W_CachePatchName(((ultimate_selectable) ? "ULTIMATE" : "SAVENONE"), PU_CACHE));
savselp[((ultimate_selectable) ? 2 : 1)]);
x += 2;
y += 1;
V_DrawString(x, y,
@ -6084,8 +6058,7 @@ static void M_DrawLoadGameData(void)
if (savetodraw == saveSlotSelected)
V_DrawFill(x, y+9, 80, 1, yellowmap[3]);
y += 11;
V_DrawSmallScaledPatch(x, y, V_STATIC,
W_CachePatchName("BLACXLVL", PU_CACHE));
V_DrawSmallScaledPatch(x, y, V_STATIC, savselp[4]);
y += 41;
if (ultimate_selectable)
V_DrawRightAlignedThinString(x + 79, y, V_REDMAP, "ULTIMATE.");
@ -6104,8 +6077,7 @@ static void M_DrawLoadGameData(void)
UINT8 col;
if (savegameinfo[savetodraw].lives == -666)
{
V_DrawSmallScaledPatch(x+2, y+64, 0,
W_CachePatchName("BLANKLVL", PU_CACHE));
V_DrawSmallScaledPatch(x+2, y+64, 0, savselp[5]);
}
else
{
@ -6125,8 +6097,7 @@ static void M_DrawLoadGameData(void)
}
}
V_DrawSmallScaledPatch(x, y, 0,
W_CachePatchName("SAVEBACK", PU_CACHE));
V_DrawSmallScaledPatch(x, y, 0, savselp[0]);
x += 2;
y += 1;
V_DrawString(x, y,
@ -6144,18 +6115,18 @@ static void M_DrawLoadGameData(void)
if ((savegameinfo[savetodraw].lives == -42)
|| (savegameinfo[savetodraw].lives == -666))
{
patch = W_CachePatchName("BLACKLVL", PU_CACHE);
patch = savselp[3];
flags = V_STATIC;
}
else if (savegameinfo[savetodraw].gamemap & 8192)
patch = W_CachePatchName("GAMEDONE", PU_CACHE);
patch = savselp[6];
else
{
lumpnum_t lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName((savegameinfo[savetodraw].gamemap) & 8191)));
if (lumpnum != LUMPERROR)
patch = W_CachePatchNum(lumpnum, PU_CACHE);
else
patch = W_CachePatchName("BLANKLVL", PU_CACHE);
patch = savselp[5];
}
V_DrawSmallScaledPatch(x, y, flags, patch);
@ -6451,30 +6422,42 @@ static void M_ReadSaveStrings(void)
SINT8 i;
char name[256];
boolean nofile[MAXSAVEGAMES-1];
UINT8 tolerance = 0;
SINT8 tolerance = 3; // empty slots at any time
UINT8 lastseen = 0;
loadgamescroll = 0;
loadgameoffset = 14;
for (i = 1; ((i < MAXSAVEGAMES) && ((i <= saveSlotSelected) || (tolerance < 3))); i++) // slot 0 is no save
for (i = 1; (i < MAXSAVEGAMES); i++) // slot 0 is no save
{
snprintf(name, sizeof name, savegamename, i);
name[sizeof name - 1] = '\0';
handle = fopen(name, "rb");
if ((nofile[i-1] = (handle == NULL)))
{
tolerance++;
continue;
}
fclose(handle);
tolerance = 0;
lastseen = i;
}
if (savegameinfo)
Z_Free(savegameinfo);
savegameinfo = NULL;
if (lastseen < saveSlotSelected)
lastseen = saveSlotSelected;
i = lastseen;
for (; (lastseen > 0 && tolerance); lastseen--)
{
if (nofile[lastseen-1])
tolerance--;
}
if ((i += tolerance+1) > MAXSAVEGAMES) // show 3 empty slots at minimum
i = MAXSAVEGAMES;
numsaves = i;
savegameinfo = Z_Realloc(savegameinfo, numsaves*sizeof(saveinfo_t), PU_STATIC, NULL);
if (!savegameinfo)
@ -6489,6 +6472,27 @@ static void M_ReadSaveStrings(void)
}
M_ReadSavegameInfo(i);
}
if (savselp[0]) // never going to have some provided but not all, saves individually checking
{
W_UnlockCachedPatch(savselp[0]);
W_UnlockCachedPatch(savselp[1]);
W_UnlockCachedPatch(savselp[2]);
W_UnlockCachedPatch(savselp[3]);
W_UnlockCachedPatch(savselp[4]);
W_UnlockCachedPatch(savselp[5]);
W_UnlockCachedPatch(savselp[6]);
}
savselp[0] = W_CachePatchName("SAVEBACK", PU_STATIC);
savselp[1] = W_CachePatchName("SAVENONE", PU_STATIC);
savselp[2] = W_CachePatchName("ULTIMATE", PU_STATIC);
savselp[3] = W_CachePatchName("BLACKLVL", PU_STATIC);
savselp[4] = W_CachePatchName("BLACXLVL", PU_STATIC);
savselp[5] = W_CachePatchName("BLANKLVW", PU_STATIC);
savselp[6] = W_CachePatchName("GAMEDONE", PU_STATIC);
}
//

View File

@ -524,12 +524,20 @@ static inline UINT8 transmappedpdraw(const UINT8 *dest, const UINT8 *source, fix
{
return *(v_translevel + (((*(v_colormap + source[ofs>>FRACBITS]))<<8)&0xff00) + (*dest&0xff));
}
static UINT8 staticstep[2] = {0, 0};
static inline UINT8 staticpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs)
{
UINT8 val = source[ofs>>FRACBITS];
(void)dest;
if ((++staticstep[1]) >= 4)
{
staticstep[1] = 0;
staticstep[0] = M_RandomFixed();
}
if (val < 7) return val;
return M_RandomKey(7+1)+(val-7);//M_RandomByte();
return ((staticstep[0]>>staticstep[1])&7)+(val-7);
}
// Draws a patch scaled to arbitrary size.
@ -660,30 +668,10 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t
y = FixedMul(y,dupy<<FRACBITS);
x >>= FRACBITS;
y >>= FRACBITS;
desttop += (y*vid.width) + x;
// Center it if necessary
if (!(scrn & V_SCALEPATCHMASK))
{
if (vid.width != BASEVIDWIDTH * dupx)
{
// dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx,
// so center this imaginary screen
if (scrn & V_SNAPTORIGHT)
desttop += (vid.width - (BASEVIDWIDTH * dupx));
else if (!(scrn & V_SNAPTOLEFT))
desttop += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
}
if (vid.height != BASEVIDHEIGHT * dupy)
{
// same thing here
if ((scrn & (V_SPLITSCREEN|V_SNAPTOBOTTOM)) == (V_SPLITSCREEN|V_SNAPTOBOTTOM))
desttop += (vid.height/2 - (BASEVIDHEIGHT/2 * dupy)) * vid.width;
else if (scrn & V_SNAPTOBOTTOM)
desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width;
else if (!(scrn & V_SNAPTOTOP))
desttop += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2;
}
// if it's meant to cover the whole screen, black out the rest
if (x == 0 && SHORT(patch->width) == BASEVIDWIDTH && y == 0 && SHORT(patch->height) == BASEVIDHEIGHT)
{
@ -691,7 +679,29 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t
source = (const UINT8 *)(column) + 3;
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0]));
}
if (vid.width != BASEVIDWIDTH * dupx)
{
// dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx,
// so center this imaginary screen
if (scrn & V_SNAPTORIGHT)
x += (vid.width - (BASEVIDWIDTH * dupx));
else if (!(scrn & V_SNAPTOLEFT))
x += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
}
if (vid.height != BASEVIDHEIGHT * dupy)
{
// same thing here
if ((scrn & (V_SPLITSCREEN|V_SNAPTOBOTTOM)) == (V_SPLITSCREEN|V_SNAPTOBOTTOM))
y += (vid.height/2 - (BASEVIDHEIGHT/2 * dupy));
else if (scrn & V_SNAPTOBOTTOM)
y += (vid.height - (BASEVIDHEIGHT * dupy));
else if (!(scrn & V_SNAPTOTOP))
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2;
}
}
desttop += (y*vid.width) + x;
}
if (pscale != FRACUNIT) // scale width properly
@ -1346,7 +1356,7 @@ char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string)
//
void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string)
{
INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth = BASEVIDWIDTH, center = 0;
INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, center = 0, left = 0;
const char *ch = string;
INT32 charflags = 0;
const UINT8 *colormap = NULL;
@ -1362,7 +1372,11 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string)
scrwidth = vid.width;
}
else
{
dupx = dupy = 1;
scrwidth = vid.width/vid.dupx;
left = (scrwidth - BASEVIDWIDTH)/2;
}
charflags = (option & V_CHARCOLORMASK);
@ -1422,9 +1436,9 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string)
else
w = SHORT(hu_font[c]->width) * dupx;
if (cx > scrwidth)
if (cx+left > scrwidth)
break;
if (cx + w < 0) //left boundary check
if (cx+left + w < 0) //left boundary check
{
cx += w;
continue;
@ -1455,7 +1469,7 @@ void V_DrawRightAlignedString(INT32 x, INT32 y, INT32 option, const char *string
//
void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string)
{
INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth = BASEVIDWIDTH, center = 0;
INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, center = 0, left = 0;
const char *ch = string;
INT32 charflags = 0;
const UINT8 *colormap = NULL;
@ -1471,7 +1485,11 @@ void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string)
scrwidth = vid.width;
}
else
{
dupx = dupy = 1;
scrwidth = vid.width/vid.dupx;
left = (scrwidth - BASEVIDWIDTH)/2;
}
charflags = (option & V_CHARCOLORMASK);
@ -1529,9 +1547,9 @@ void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string)
}
else
w = SHORT(hu_font[c]->width) * dupx / 2;
if (cx + w > scrwidth)
if (cx+left > scrwidth)
break;
if (cx < 0) //left boundary check
if (cx+left + w < 0) //left boundary check
{
cx += w;
continue;
@ -1556,7 +1574,7 @@ void V_DrawRightAlignedSmallString(INT32 x, INT32 y, INT32 option, const char *s
//
void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string)
{
INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth = BASEVIDWIDTH;
INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, left = 0;
const char *ch = string;
INT32 charflags = 0;
const UINT8 *colormap = NULL;
@ -1572,7 +1590,11 @@ void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string)
scrwidth = vid.width;
}
else
{
dupx = dupy = 1;
scrwidth = vid.width/vid.dupx;
left = (scrwidth - BASEVIDWIDTH)/2;
}
charflags = (option & V_CHARCOLORMASK);
@ -1628,9 +1650,9 @@ void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string)
else
w = (SHORT(tny_font[c]->width) * dupx);
if (cx > scrwidth)
if (cx+left > scrwidth)
break;
if (cx + w < 0) //left boundary check
if (cx+left + w < 0) //left boundary check
{
cx += w;
continue;
@ -1653,7 +1675,7 @@ void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *st
void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
{
fixed_t cx = x, cy = y;
INT32 w, c, dupx, dupy, scrwidth = BASEVIDWIDTH, center = 0;
INT32 w, c, dupx, dupy, scrwidth, center = 0, left = 0;
const char *ch = string;
INT32 spacewidth = 4, charwidth = 0;
@ -1667,7 +1689,11 @@ void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
scrwidth = vid.width;
}
else
{
dupx = dupy = 1;
scrwidth = vid.width/vid.dupx;
left = (scrwidth - BASEVIDWIDTH)/2;
}
switch (option & V_SPACINGMASK)
{
@ -1720,9 +1746,9 @@ void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
else
w = SHORT(hu_font[c]->width) * dupx;
if ((cx>>FRACBITS) + w > scrwidth)
if ((cx>>FRACBITS)+left > scrwidth)
break;
if (cx < 0) //left boundary check
if (cx+left + w < 0) //left boundary check
{
cx += w<<FRACBITS;
continue;