diff --git a/src/m_menu.c b/src/m_menu.c index 480ec7ca2..214755651 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -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); } // diff --git a/src/v_video.c b/src/v_video.c index b07237d74..d965a0939 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -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; 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<