* Fix a serious logic mistake with checksectorpointer. Previously, a white wall could 'connect' to a red one, leaving the reverse link intact and creating a situation like this: w_new <-> w <-- w_old.

* Have the corruption checker catch this case among a few other new ones. Rename OSD command 'autocorruptcheck' to simply 'corruptcheck' with options 'corruptcheck <seconds>', 'corruptcheck now' and 'corruptcheck tryfix'.
* When pasting sector selection into valid player space (releasing AltGr), ask whether a surrounding outer loop should be created since this is probably not always desired.

git-svn-id: https://svn.eduke32.com/eduke32@1790 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2011-02-10 23:15:02 +00:00
parent f4b4234ce1
commit cf9e3fd3f6
5 changed files with 361 additions and 226 deletions

View file

@ -528,6 +528,7 @@ void getzsofslope(int16_t sectnum, int32_t dax, int32_t day, int32_t *ceilz, i
void alignceilslope(int16_t dasect, int32_t x, int32_t y, int32_t z); void alignceilslope(int16_t dasect, int32_t x, int32_t y, int32_t z);
void alignflorslope(int16_t dasect, int32_t x, int32_t y, int32_t z); void alignflorslope(int16_t dasect, int32_t x, int32_t y, int32_t z);
int32_t sectorofwall(int16_t theline); int32_t sectorofwall(int16_t theline);
int32_t sectorofwall_noquick(int16_t theline);
int32_t loopnumofsector(int16_t sectnum, int16_t wallnum); int32_t loopnumofsector(int16_t sectnum, int16_t wallnum);
// int32_t insertsprite(int16_t sectnum, int16_t statnum); // int32_t insertsprite(int16_t sectnum, int16_t statnum);

View file

@ -116,7 +116,7 @@ extern const char *SaveBoard(const char *fn, uint32_t flags);
#define MAXCORRUPTTHINGS 64 #define MAXCORRUPTTHINGS 64
extern int32_t numcorruptthings, corruptthings[MAXCORRUPTTHINGS]; extern int32_t numcorruptthings, corruptthings[MAXCORRUPTTHINGS];
extern int32_t autocorruptcheck; extern int32_t autocorruptcheck;
extern int32_t CheckMapCorruption(int32_t printfromlev); extern int32_t CheckMapCorruption(int32_t printfromlev, int32_t tryfixing);
extern void showsectordata(int16_t sectnum, int16_t small); extern void showsectordata(int16_t sectnum, int16_t small);
extern void showwalldata(int16_t wallnum, int16_t small); extern void showwalldata(int16_t wallnum, int16_t small);
@ -215,4 +215,11 @@ extern int32_t scripthistend;
// showdebug is now used as a general informational on-screen display // showdebug is now used as a general informational on-screen display
#define M32_SHOWDEBUG #define M32_SHOWDEBUG
// this should be only used if there's no dependency on endwall after the loop.
// of course, users of this macro should know that it modifies startwall and endwall.
#define WALLS_OF_SECTOR(Sect, Itervar) \
startwall=sector[(Sect)].wallptr, endwall=startwall+sector[(Sect)].wallnum, Itervar=startwall; \
Itervar < endwall; \
Itervar++
#endif #endif

View file

@ -617,7 +617,7 @@ CANCEL:
if (asksave) if (asksave)
{ {
i = CheckMapCorruption(4); i = CheckMapCorruption(4, 0);
printext256(0,8,whitecol,0,i<4?"Save changes?":"Map is heavily corrupt. Save changes?",0); printext256(0,8,whitecol,0,i<4?"Save changes?":"Map is heavily corrupt. Save changes?",0);
showframe(1); showframe(1);
@ -1259,6 +1259,18 @@ static inline void drawline16base(int32_t bx, int32_t by, int32_t x1, int32_t y1
drawline16(bx+x1, by+y1, bx+x2, by+y2, col); drawline16(bx+x1, by+y1, bx+x2, by+y2, col);
} }
static void drawsmalllabel(const char *text, char col, char backcol,
int32_t x1, int32_t y1, int32_t x2, int32_t y2)
{
printext16(x1,y1, col,backcol, text,1);
drawline16(x1-1,y1-1, x2-3,y1-1, backcol);
drawline16(x1-1,y2+1, x2-3,y2+1, backcol);
drawline16(x1-2,y1, x1-2,y2, backcol);
drawline16(x2-2,y1, x2-2,y2, backcol);
drawline16(x2-3,y1, x2-3,y2, backcol);
}
// backup highlighted sectors with sprites as mapinfo for later restoration // backup highlighted sectors with sprites as mapinfo for later restoration
// return values: // return values:
// -1: highlightsectorcnt<=0 // -1: highlightsectorcnt<=0
@ -1483,9 +1495,7 @@ static void duplicate_selected_sectors()
{ {
// first, make red lines of old selected sectors, effectively // first, make red lines of old selected sectors, effectively
// restoring the original state // restoring the original state
startwall = sector[highlightsector[i]].wallptr; for (WALLS_OF_SECTOR(highlightsector[i], j))
endwall = startwall+sector[highlightsector[i]].wallnum-1;
for (j=startwall; j<=endwall; j++)
{ {
if (wall[j].nextwall >= 0) if (wall[j].nextwall >= 0)
checksectorpointer(wall[j].nextwall,wall[j].nextsector); checksectorpointer(wall[j].nextwall,wall[j].nextsector);
@ -1917,17 +1927,15 @@ void overheadeditor(void)
dax = 0; //Get average point of sector dax = 0; //Get average point of sector
day = 0; day = 0;
startwall = sector[i].wallptr; for (WALLS_OF_SECTOR(i, j))
endwall = startwall + sector[i].wallnum - 1;
for (j=startwall; j<=endwall; j++)
{ {
dax += wall[j].x; dax += wall[j].x;
day += wall[j].y; day += wall[j].y;
} }
if (endwall > startwall) if (sector[i].wallnum > 0)
{ {
dax /= (endwall-startwall+1); dax /= sector[i].wallnum;
day /= (endwall-startwall+1); day /= sector[i].wallnum;
} }
if (m32_sideview) if (m32_sideview)
@ -1941,15 +1949,8 @@ void overheadeditor(void)
x2 = x1 + (Bstrlen(dabuffer)<<2)+2; x2 = x1 + (Bstrlen(dabuffer)<<2)+2;
y2 = y1 + 7; y2 = y1 + 7;
if ((x1 > 3) && (x2 < xdim) && (y1 > 1) && (y2 < ydim16)) if ((x1 > 3) && (x2 < xdim) && (y1 > 1) && (y2 < ydim16))
{ drawsmalllabel(dabuffer, editorcolors[0], editorcolors[7],
printext16(x1,y1,editorcolors[0],editorcolors[7],dabuffer,1); x1,y1, x2,y2);
drawline16(x1-1,y1-1, x2-3,y1-1, editorcolors[7]);
drawline16(x1-1,y2+1, x2-3,y2+1, editorcolors[7]);
drawline16(x1-2,y1, x1-2,y2, editorcolors[7]);
drawline16(x2-2,y1, x2-2,y2, editorcolors[7]);
drawline16(x2-3,y1, x2-3,y2, editorcolors[7]);
}
} }
} }
} }
@ -1971,6 +1972,7 @@ void overheadeditor(void)
for (wal=&wall[i]; i>=0; i--,wal--) for (wal=&wall[i]; i>=0; i--,wal--)
{ {
if (zoom < 768 && !(wal->cstat & (1<<14))) continue; if (zoom < 768 && !(wal->cstat & (1<<14))) continue;
//Get average point of wall //Get average point of wall
dax = (wal->x+wall[wal->point2].x)>>1; dax = (wal->x+wall[wal->point2].x)>>1;
day = (wal->y+wall[wal->point2].y)>>1; day = (wal->y+wall[wal->point2].y)>>1;
@ -1989,15 +1991,8 @@ void overheadeditor(void)
y2 = y1 + 7; y2 = y1 + 7;
if ((x1 > 3) && (x2 < xdim) && (y1 > 1) && (y2 < ydim16)) if ((x1 > 3) && (x2 < xdim) && (y1 > 1) && (y2 < ydim16))
{ drawsmalllabel(dabuffer, editorcolors[0], editorcolors[31],
printext16(x1,y1,editorcolors[0],editorcolors[31],dabuffer,1); x1,y1, x2,y2);
drawline16(x1-1,y1-1, x2-3,y1-1, editorcolors[31]);
drawline16(x1-1,y2+1, x2-3,y2+1, editorcolors[31]);
drawline16(x1-2,y1, x1-2,y2, editorcolors[31]);
drawline16(x2-2,y1, x2-2,y2, editorcolors[31]);
drawline16(x2-3,y1, x2-3,y2, editorcolors[31]);
}
} }
} }
} }
@ -2043,14 +2038,8 @@ void overheadeditor(void)
if ((i == pointhighlight-16384) && (totalclock & 32)) if ((i == pointhighlight-16384) && (totalclock & 32))
col += (2<<2); col += (2<<2);
printext16(x1,y1,editorcolors[0],editorcolors[col],dabuffer,1); drawsmalllabel(dabuffer, editorcolors[0], editorcolors[col],
x1,y1, x2,y2);
drawline16(x1-1,y1-1, x2-3,y1-1, editorcolors[col]);
drawline16(x1-1,y2+1, x2-3,y2+1, editorcolors[col]);
drawline16(x1-2,y1, x1-2,y2, editorcolors[col]);
drawline16(x2-2,y1, x2-2,y2, editorcolors[col]);
drawline16(x2-3,y1, x2-3,y2, editorcolors[col]);
} }
} }
j--; j--;
@ -2164,9 +2153,7 @@ void overheadeditor(void)
for (i=0; i<highlightsectorcnt; i++) for (i=0; i<highlightsectorcnt; i++)
{ {
startwall = sector[highlightsector[i]].wallptr; for (WALLS_OF_SECTOR(highlightsector[i], j))
endwall = startwall+sector[highlightsector[i]].wallnum-1;
for (j=startwall; j<=endwall; j++)
{ {
dax += wall[j].x; dax += wall[j].x;
day += wall[j].y; day += wall[j].y;
@ -2385,9 +2372,7 @@ void overheadeditor(void)
day = 0; day = 0;
for (i=0; i<highlightsectorcnt; i++) for (i=0; i<highlightsectorcnt; i++)
{ {
startwall = sector[highlightsector[i]].wallptr; for (WALLS_OF_SECTOR(highlightsector[i], j))
endwall = startwall+sector[highlightsector[i]].wallnum-1;
for (j=startwall; j<=endwall; j++)
{ {
dax += wall[j].x; dax += wall[j].x;
day += wall[j].y; day += wall[j].y;
@ -2410,9 +2395,7 @@ void overheadeditor(void)
for (i=0; i<highlightsectorcnt; i++) for (i=0; i<highlightsectorcnt; i++)
{ {
startwall = sector[highlightsector[i]].wallptr; for (WALLS_OF_SECTOR(highlightsector[i], j))
endwall = startwall+sector[highlightsector[i]].wallnum-1;
for (j=startwall; j<=endwall; j++)
{ {
if (k == 0) if (k == 0)
{ {
@ -2755,9 +2738,7 @@ void overheadeditor(void)
for (i=0; i<highlightsectorcnt; i++) for (i=0; i<highlightsectorcnt; i++)
{ {
startwall = sector[highlightsector[i]].wallptr; for (WALLS_OF_SECTOR(highlightsector[i], j))
endwall = startwall+sector[highlightsector[i]].wallnum-1;
for (j=startwall; j<=endwall; j++)
{ {
if (wall[j].nextwall >= 0) if (wall[j].nextwall >= 0)
checksectorpointer(wall[j].nextwall,wall[j].nextsector); checksectorpointer(wall[j].nextwall,wall[j].nextsector);
@ -2765,10 +2746,28 @@ void overheadeditor(void)
} }
} }
if (!didmakered && newnumwalls<0)
{
char blackcol=editorcolors[0], greycol=whitecol-25, *cp;
// fade the screen to have the user's attention
begindrawing();
cp = (char *)frameplace;
for (i=0; i<bytesperline*(ydim-STATUS2DSIZ2); i++, cp++)
if (*cp==greycol)
*cp = blackcol;
else if (*cp != blackcol)
*cp = greycol;
enddrawing();
showframe(1);
didmakered |= !ask_if_sure("Insert outer loop and make red walls?", 0);
clearkeys();
}
while (!didmakered && newnumwalls<0) // if while (!didmakered && newnumwalls<0) // if
{ {
int32_t tmpnumwalls=0, refwall, n; int32_t tmpnumwalls=0, refwall;
int16_t refsect, ignore;
uint8_t *visitedwall = Bcalloc((numwalls+7)>>3,1); uint8_t *visitedwall = Bcalloc((numwalls+7)>>3,1);
if (!visitedwall) if (!visitedwall)
@ -2782,12 +2781,15 @@ void overheadeditor(void)
for (i=0; i<highlightsectorcnt; i++) for (i=0; i<highlightsectorcnt; i++)
{ {
startwall = sector[highlightsector[i]].wallptr; for (WALLS_OF_SECTOR(highlightsector[i], j))
endwall = startwall+sector[highlightsector[i]].wallnum-1;
for (j=startwall; j<=endwall; j++)
if (wall[j].nextwall<0 && !(visitedwall[j>>3]&(1<<(j&7))))
{ {
n=tmpnumwalls; int16_t refsect, ignore;
int32_t n;
if (wall[j].nextwall>=0 || (visitedwall[j>>3]&(1<<(j&7))))
continue;
n=2*tmpnumwalls; // simple inf loop check
refwall = j; refwall = j;
k = numwalls; k = numwalls;
@ -2810,7 +2812,7 @@ void overheadeditor(void)
{ {
if (k>=MAXWALLS) if (k>=MAXWALLS)
{ {
message("Wall limits exceeded while trying to trace outer loop."); message("Wall limits exceeded while tracing outer loop.");
goto outtathis; goto outtathis;
} }
@ -2833,9 +2835,10 @@ void overheadeditor(void)
} }
} }
while (j!=refwall && n>0); while (j!=refwall && n>0);
if (j!=refwall) if (j!=refwall)
{ {
message("internal error while trying to trace outer loop: j!=refwall"); message("internal error while tracing outer loop: didn't reach refwall");
goto outtathis; goto outtathis;
} }
@ -2859,7 +2862,9 @@ void overheadeditor(void)
if (!tmpwall) if (!tmpwall)
{ {
message("out of memory!"); message("out of memory!");
goto outtathis; ExtUnInit();
uninitsystem();
exit(1);
} }
for (m=0; m<numwalls; m++) for (m=0; m<numwalls; m++)
@ -2883,10 +2888,10 @@ void overheadeditor(void)
numwalls = newnumwalls; numwalls = newnumwalls;
newnumwalls = -1; newnumwalls = -1;
message("Attached new inner loop to sector %d", refsect);
for (m=begwalltomove; m<begwalltomove+n; m++) for (m=begwalltomove; m<begwalltomove+n; m++)
checksectorpointer(m, refsect); checksectorpointer(m, refsect);
message("Attached new inner loop to sector %d", refsect);
} }
} }
} }
@ -2894,6 +2899,7 @@ void overheadeditor(void)
outtathis: outtathis:
newnumwalls = -1; newnumwalls = -1;
Bfree(visitedwall); Bfree(visitedwall);
break; // --| break; // --|
} // <---------/ } // <---------/
@ -2923,10 +2929,8 @@ outtathis:
for (i=0; i<numsectors; i++) for (i=0; i<numsectors; i++)
{ {
startwall = sector[i].wallptr;
endwall = startwall + sector[i].wallnum;
bad = 0; bad = 0;
for (j=startwall; j<endwall; j++) for (WALLS_OF_SECTOR(i, j))
{ {
if (wall[j].x < highlightx1) bad = 1; if (wall[j].x < highlightx1) bad = 1;
if (wall[j].x > highlightx2) bad = 1; if (wall[j].x > highlightx2) bad = 1;
@ -3118,9 +3122,7 @@ SKIP:
for (i=0; i<highlightsectorcnt; i++) for (i=0; i<highlightsectorcnt; i++)
{ {
startwall = sector[highlightsector[i]].wallptr; for (WALLS_OF_SECTOR(highlightsector[i], j))
endwall = startwall+sector[highlightsector[i]].wallnum-1;
for (j=startwall; j<=endwall; j++)
{ wall[j].x += dax; wall[j].y += day; } { wall[j].x += dax; wall[j].y += day; }
for (j=headspritesect[highlightsector[i]]; j>=0; j=nextspritesect[j]) for (j=headspritesect[highlightsector[i]]; j>=0; j=nextspritesect[j])
@ -3218,7 +3220,7 @@ SKIP:
vec.z = sprite[daspr].z; vec.z = sprite[daspr].z;
if (setsprite(daspr, &vec) == -1 && osec>=0) if (setsprite(daspr, &vec) == -1 && osec>=0)
Bmemcpy(&sprite[daspr], &ovec, sizeof(vec3_t)); Bmemcpy(&sprite[daspr], &ovec, sizeof(vec3_t));
/* #if 0
daz = ((tilesizy[sprite[daspr].picnum]*sprite[daspr].yrepeat)<<2); daz = ((tilesizy[sprite[daspr].picnum]*sprite[daspr].yrepeat)<<2);
for (i=0; i<numsectors; i++) for (i=0; i<numsectors; i++)
@ -3232,7 +3234,7 @@ SKIP:
changespritesect(daspr,(int16_t)i); changespritesect(daspr,(int16_t)i);
break; break;
} }
*/ #endif
} }
} }
asksave = 1; asksave = 1;
@ -3497,9 +3499,7 @@ SKIP:
for (k=0; k<2; k++) for (k=0; k<2; k++)
{ {
startwall = sector[joinsector[k]].wallptr; for (WALLS_OF_SECTOR(joinsector[k], j))
endwall = startwall + sector[joinsector[k]].wallnum - 1;
for (j=startwall; j<=endwall; j++)
{ {
if (wall[j].cstat == 255) if (wall[j].cstat == 255)
continue; continue;
@ -3565,9 +3565,7 @@ SKIP:
for (k=0; k<2; k++) for (k=0; k<2; k++)
{ {
startwall = sector[joinsector[k]].wallptr; for (WALLS_OF_SECTOR(joinsector[k], j))
endwall = startwall + sector[joinsector[k]].wallnum - 1;
for (j=startwall; j<=endwall; j++)
{ {
wall[j].nextwall = -1; wall[j].nextwall = -1;
wall[j].nextsector = -1; wall[j].nextsector = -1;
@ -3935,9 +3933,7 @@ SKIP:
{ {
//check if first point at point of sector //check if first point at point of sector
m = -1; m = -1;
startwall = sector[i].wallptr; for (WALLS_OF_SECTOR(i, k))
endwall = startwall + sector[i].wallnum - 1;
for (k=startwall; k<=endwall; k++)
if (wall[k].x==wall[numwalls].x && wall[k].y==wall[numwalls].y) if (wall[k].x==wall[numwalls].x && wall[k].y==wall[numwalls].y)
{ {
m = k; m = k;
@ -4490,10 +4486,8 @@ SKIP:
} }
for (i=0; i<numsectors; i++) for (i=0; i<numsectors; i++)
{ {
startwall = sector[i].wallptr; for (WALLS_OF_SECTOR(i, j))
endwall = startwall + sector[i].wallnum; checksectorpointer(j, i);
for (j=startwall; j<endwall; j++)
checksectorpointer((int16_t)j,(int16_t)i);
} }
printmessage16("ALL POINTERS CHECKED!"); printmessage16("ALL POINTERS CHECKED!");
asksave = 1; asksave = 1;
@ -4858,7 +4852,7 @@ CANCEL:
} }
else if (ch == 'a' || ch == 'A') //A else if (ch == 'a' || ch == 'A') //A
{ {
int32_t corrupt = CheckMapCorruption(4); int32_t corrupt = CheckMapCorruption(4, 0);
bad = 0; bad = 0;
@ -4947,7 +4941,7 @@ CANCEL:
bad = 0; bad = 0;
if (CheckMapCorruption(4)>=4) if (CheckMapCorruption(4, 0)>=4)
if (!ask_if_sure("Map is corrupt. Are you sure you want to save?", 0)) if (!ask_if_sure("Map is corrupt. Are you sure you want to save?", 0))
break; break;
@ -4987,7 +4981,7 @@ CANCEL:
{ {
//QUIT! //QUIT!
int32_t corrupt = CheckMapCorruption(4); int32_t corrupt = CheckMapCorruption(4, 0);
if (ask_if_sure(corrupt<4?"Save changes?":"Map corrupt. Save changes?", corrupt<4?0:1)) if (ask_if_sure(corrupt<4?"Save changes?":"Map corrupt. Save changes?", corrupt<4?0:1))
SaveBoard(NULL, 0); SaveBoard(NULL, 0);
@ -5002,10 +4996,10 @@ CANCEL:
goto CANCEL; goto CANCEL;
} }
ExtUnInit();
clearfilenames(); clearfilenames();
uninittimer(); uninittimer();
uninitinput(); uninitinput();
ExtUnInit();
uninitengine(); uninitengine();
exit(0); exit(0);
} }
@ -5026,9 +5020,7 @@ CANCEL:
for (i=0; i<highlightsectorcnt; i++) for (i=0; i<highlightsectorcnt; i++)
{ {
startwall = sector[highlightsector[i]].wallptr; for (WALLS_OF_SECTOR(highlightsector[i], j))
endwall = startwall+sector[highlightsector[i]].wallnum-1;
for (j=startwall; j<=endwall; j++)
{ {
if (wall[j].nextwall >= 0) if (wall[j].nextwall >= 0)
checksectorpointer(wall[j].nextwall,wall[j].nextsector); checksectorpointer(wall[j].nextwall,wall[j].nextsector);
@ -5040,10 +5032,10 @@ CANCEL:
if (setgamemode(fullscreen,xdimgame,ydimgame,bppgame) < 0) if (setgamemode(fullscreen,xdimgame,ydimgame,bppgame) < 0)
{ {
initprintf("%d * %d not supported in this graphics mode\n",xdim,ydim);
ExtUnInit(); ExtUnInit();
uninitinput(); uninitinput();
uninittimer(); uninittimer();
initprintf("%d * %d not supported in this graphics mode\n",xdim,ydim);
uninitsystem(); uninitsystem();
clearfilenames(); clearfilenames();
exit(0); exit(0);
@ -5071,6 +5063,7 @@ static int32_t ask_if_sure(const char *query, int32_t quit_is_yes)
_printmessage16("%s", query); _printmessage16("%s", query);
showframe(1); showframe(1);
bflushchars(); bflushchars();
while ((keystatus[1]|keystatus[0x2e]) == 0) while ((keystatus[1]|keystatus[0x2e]) == 0)
{ {
if (handleevents()) if (handleevents())
@ -5178,7 +5171,7 @@ int32_t LoadBoard(const char *filename, uint32_t flags)
if (mapversion < 7) message("Map %s loaded successfully and autoconverted to V7!",boardfilename); if (mapversion < 7) message("Map %s loaded successfully and autoconverted to V7!",boardfilename);
else else
{ {
i = CheckMapCorruption(4); i = CheckMapCorruption(4, 0);
message("Loaded map %s %s",boardfilename, i==0?"successfully": message("Loaded map %s %s",boardfilename, i==0?"successfully":
(i<4 ? "(moderate corruption)" : "(HEAVY corruption)")); (i<4 ? "(moderate corruption)" : "(HEAVY corruption)"));
} }
@ -5535,7 +5528,6 @@ static int32_t deletesector(int16_t sucksect)
} }
numsectors--; numsectors--;
j = endwall-startwall+1;
for (i=startwall; i<=endwall; i++) for (i=startwall; i<=endwall; i++)
if (wall[i].nextwall != -1) if (wall[i].nextwall != -1)
{ {
@ -5543,6 +5535,7 @@ static int32_t deletesector(int16_t sucksect)
NEXTWALL(i).nextsector = -1; NEXTWALL(i).nextsector = -1;
} }
j = endwall-startwall+1;
movewalls(startwall,-j); movewalls(startwall,-j);
for (i=0; i<numwalls; i++) for (i=0; i<numwalls; i++)
if (wall[i].nextwall >= startwall) if (wall[i].nextwall >= startwall)

View file

@ -758,6 +758,11 @@ int32_t checksectorpointer(int16_t i, int16_t sectnum)
if ((wall[wall[k].point2]).x == x1 && (wall[wall[k].point2]).y == y1) if ((wall[wall[k].point2]).x == x1 && (wall[wall[k].point2]).y == y1)
if (j != sectnum) if (j != sectnum)
{ {
// Don't create link if the other side is connected to another wall.
// The nextwall relation should be definitely one-to-one at all times!
if (wall[k].nextwall>=0 && wall[k].nextwall != i)
continue;
if (sectnum != -2) // -2 means dry run if (sectnum != -2) // -2 means dry run
{ {
wall[i].nextsector = j; wall[i].nextsector = j;
@ -11548,13 +11553,10 @@ void completemirror(void)
// //
// sectorofwall // sectorofwall
// //
int32_t sectorofwall(int16_t theline) static int32_t sectorofwall_internal(int16_t theline)
{ {
int32_t i, gap; int32_t i, gap;
if ((theline < 0) || (theline >= numwalls)) return(-1);
i = wall[theline].nextwall; if (i >= 0 && i < MAXWALLS) return(wall[i].nextsector);
gap = (numsectors>>1); i = gap; gap = (numsectors>>1); i = gap;
while (gap > 1) while (gap > 1)
{ {
@ -11566,6 +11568,23 @@ int32_t sectorofwall(int16_t theline)
return(i); return(i);
} }
int32_t sectorofwall(int16_t theline)
{
int32_t i;
if ((theline < 0) || (theline >= numwalls)) return(-1);
i = wall[theline].nextwall; if (i >= 0 && i < MAXWALLS) return(wall[i].nextsector);
return sectorofwall_internal(theline);
}
int32_t sectorofwall_noquick(int16_t theline)
{
if ((theline < 0) || (theline >= numwalls)) return(-1);
return sectorofwall_internal(theline);
}
// //
// getceilzofslope // getceilzofslope

View file

@ -7878,12 +7878,23 @@ static int32_t osdcmd_vars_pk(const osdfuncparm_t *parm)
else else
return OSDCMD_SHOWHELP; return OSDCMD_SHOWHELP;
} }
else if (!Bstrcasecmp(parm->name, "autocorruptcheck")) else if (!Bstrcasecmp(parm->name, "corruptcheck"))
{ {
if (parm->numparms == 1) if (parm->numparms == 1)
{
if (!Bstrcasecmp(parm->parms[0], "now"))
{
CheckMapCorruption(1, 0);
}
else if (!Bstrcasecmp(parm->parms[0], "tryfix"))
{
CheckMapCorruption(3, 1);
}
else if (isdigit(parm->parms[0][0]))
{ {
autocorruptcheck = clamp(atoi(parm->parms[0]), 0, 3600); autocorruptcheck = clamp(atoi(parm->parms[0]), 0, 3600);
corruptchecktimer = 0; // force checking now corruptchecktimer = totalclock + 120*autocorruptcheck;
}
} }
if (parm->numparms <= 1) if (parm->numparms <= 1)
@ -8172,9 +8183,9 @@ static int32_t registerosdcommands(void)
OSD_RegisterFunction("pk_uedaccel", "pk_uedaccel <value>: sets UnrealEd movement speed factor (0-5, exponentially)", osdcmd_vars_pk); OSD_RegisterFunction("pk_uedaccel", "pk_uedaccel <value>: sets UnrealEd movement speed factor (0-5, exponentially)", osdcmd_vars_pk);
OSD_RegisterFunction("pk_quickmapcycling", "pk_quickmapcycling: toggles quick cycling of maps with (Shift-)Ctrl-X", osdcmd_vars_pk); OSD_RegisterFunction("pk_quickmapcycling", "pk_quickmapcycling: toggles quick cycling of maps with (Shift-)Ctrl-X", osdcmd_vars_pk);
OSD_RegisterFunction("testplay_addparam", "testplay_addparam \"string\": sets additional parameters for test playing", osdcmd_testplay_addparam); OSD_RegisterFunction("testplay_addparam", "testplay_addparam \"string\": sets additional parameters for test playing", osdcmd_testplay_addparam);
OSD_RegisterFunction("show_heightindicators", "show_heightindicators <0, 1 or 2>: sets display of height indicators in 2D mode", osdcmd_vars_pk); OSD_RegisterFunction("show_heightindicators", "show_heightindicators {0, 1 or 2}: sets display of height indicators in 2D mode", osdcmd_vars_pk);
OSD_RegisterFunction("show_ambiencesounds", "show_ambiencesounds <0, 1 or 2>: sets display of MUSICANDSFX circles in 2D mode", osdcmd_vars_pk); OSD_RegisterFunction("show_ambiencesounds", "show_ambiencesounds {0, 1 or 2}>: sets display of MUSICANDSFX circles in 2D mode", osdcmd_vars_pk);
OSD_RegisterFunction("autocorruptcheck", "autocorruptcheck <seconds>: sets auto corruption check interval", osdcmd_vars_pk); OSD_RegisterFunction("corruptcheck", "corruptcheck {<seconds>|now|tryfix}: sets auto corruption check interval if <seconds> given, otherwise as indicated", osdcmd_vars_pk);
#ifdef POLYMOST #ifdef POLYMOST
OSD_RegisterFunction("tint", "tint <pal> <r> <g> <b> <flags>: queries or sets hightile tinting", osdcmd_tint); OSD_RegisterFunction("tint", "tint <pal> <r> <g> <b> <flags>: queries or sets hightile tinting", osdcmd_tint);
#endif #endif
@ -8184,8 +8195,8 @@ static int32_t registerosdcommands(void)
OSD_RegisterFunction("do", "do (m32 script ...): executes M32 script statements", osdcmd_do); OSD_RegisterFunction("do", "do (m32 script ...): executes M32 script statements", osdcmd_do);
OSD_RegisterFunction("script_info", "script_info: shows information about compiled M32 script", osdcmd_scriptinfo); OSD_RegisterFunction("script_info", "script_info: shows information about compiled M32 script", osdcmd_scriptinfo);
OSD_RegisterFunction("script_expertmode", "script_expertmode: toggles M32 script expert mode", osdcmd_vars_pk); OSD_RegisterFunction("script_expertmode", "script_expertmode: toggles M32 script expert mode", osdcmd_vars_pk);
OSD_RegisterFunction("enableevent", "enableevent <all|EVENT_...|(event number)>", osdcmd_endisableevent); OSD_RegisterFunction("enableevent", "enableevent {all|EVENT_...|(event number)}", osdcmd_endisableevent);
OSD_RegisterFunction("disableevent", "disableevent <all|EVENT_...|(event number)>", osdcmd_endisableevent); OSD_RegisterFunction("disableevent", "disableevent {all|EVENT_...|(event number)}", osdcmd_endisableevent);
OSD_RegisterFunction("osd_tryscript", "osd_tryscript: toggles execution of M32 script on invalid OSD command", osdcmd_vars_pk); OSD_RegisterFunction("osd_tryscript", "osd_tryscript: toggles execution of M32 script on invalid OSD command", osdcmd_vars_pk);
OSD_RegisterFunction("sideview_reversehorizrot", "sideview_reversehorizrot: toggles reversion of Q and W keys in side view mode", osdcmd_vars_pk); OSD_RegisterFunction("sideview_reversehorizrot", "sideview_reversehorizrot: toggles reversion of Q and W keys in side view mode", osdcmd_vars_pk);
#ifdef DEBUGGINGAIDS #ifdef DEBUGGINGAIDS
@ -8306,11 +8317,13 @@ void GAME_clearbackground(int32_t numcols, int32_t numrows)
static void m32_osdsetfunctions() static void m32_osdsetfunctions()
{ {
OSD_SetFunctions( OSD_SetFunctions(
/* GAME_drawosdchar, /*
GAME_drawosdchar,
GAME_drawosdstr, GAME_drawosdstr,
GAME_drawosdcursor, GAME_drawosdcursor,
GAME_getcolumnwidth, GAME_getcolumnwidth,
GAME_getrowheight,*/ GAME_getrowheight,
*/
0,0,0,0,0, 0,0,0,0,0,
GAME_clearbackground, GAME_clearbackground,
(int32_t( *)(void))GetTime, (int32_t( *)(void))GetTime,
@ -9235,9 +9248,10 @@ void ExtUnInit(void)
{ {
int32_t i; int32_t i;
// setvmode(0x03); // setvmode(0x03);
writesetup(setupfilename);
S_SoundShutdown(); S_SoundShutdown();
uninitgroupfile(); uninitgroupfile();
writesetup(setupfilename);
for (i = MAX_TILE_GROUPS-1; i >= 0; i--) for (i = MAX_TILE_GROUPS-1; i >= 0; i--)
{ {
@ -9821,7 +9835,7 @@ static void Keys2d3d(void)
{ {
keystatus[KEYSC_S] = 0; keystatus[KEYSC_S] = 0;
i = CheckMapCorruption(4); i = CheckMapCorruption(4, 0);
if (i<4) if (i<4)
{ {
SaveBoard(levelname, 0); SaveBoard(levelname, 0);
@ -9973,7 +9987,7 @@ void ExtCheckKeys(void)
if (autocorruptcheck>0 && totalclock > corruptchecktimer) if (autocorruptcheck>0 && totalclock > corruptchecktimer)
{ {
if (CheckMapCorruption(3)>=4) if (CheckMapCorruption(3, 0)>=4)
message("Corruption detected. See OSD for details."); message("Corruption detected. See OSD for details.");
corruptchecktimer = totalclock + 120*autocorruptcheck; corruptchecktimer = totalclock + 120*autocorruptcheck;
} }
@ -9991,7 +10005,7 @@ void ExtCheckKeys(void)
{ {
if (asksave == 3) if (asksave == 3)
{ {
if (CheckMapCorruption(6)>=4) if (CheckMapCorruption(6, 0)>=4)
{ {
SaveBoard("autosave_corrupt.map", 1); SaveBoard("autosave_corrupt.map", 1);
message("Board autosaved to AUTOSAVE_CORRUPT.MAP"); message("Board autosaved to AUTOSAVE_CORRUPT.MAP");
@ -10017,33 +10031,66 @@ void ExtCheckKeys(void)
//// port of a.m32's corruptchk //// //// port of a.m32's corruptchk ////
// returns value from 0 (all OK) to 5 (panic!) // returns value from 0 (all OK) to 5 (panic!)
#define CCHK_PANIC OSDTEXT_DARKRED "PANIC!!!^O "
#define CCHKPREF OSDTEXT_RED "* ^O"
#define CCHK_CORRECTED OSDTEXT_GREEN " -> "
#define CORRUPTCHK_PRINT(errlev, what, fmt, ...) do \ #define CORRUPTCHK_PRINT(errlev, what, fmt, ...) do \
{ \ { \
bad = max(bad, errlev); \ bad = max(bad, errlev); \
if (numcorruptthings<MAXCORRUPTTHINGS) \ if (numcorruptthings<MAXCORRUPTTHINGS) \
corruptthings[numcorruptthings++] = what; \ corruptthings[numcorruptthings++] = what; \
if (errlev >= printfromlev) \ if (errlev >= printfromlev) \
OSD_Printf(fmt "\n", ## __VA_ARGS__); \ OSD_Printf(CCHKPREF fmt "\n", ## __VA_ARGS__); \
} while (0) } while (0)
int32_t CheckMapCorruption(int32_t printfromlev) static void suggest_nextsector_correction(int32_t nw, int32_t j)
{
if (nw>=0 && nw<numwalls)
{
// maybe nextwall is right?
if (wall[nw].nextwall==j && wall[j].x==POINT2(nw).x && wall[j].y==POINT2(nw).y)
OSD_Printf(" suggest setting wall[%d].nextsector to %d\n", j, sectorofwall_noquick(nw));
}
}
static void do_nextsector_correction(int32_t nw, int32_t j)
{
if (nw>=0 && nw<numwalls)
if (wall[nw].nextwall==j && wall[j].x==POINT2(nw).x && wall[j].y==POINT2(nw).y)
{
int32_t newns = sectorofwall_noquick(nw);
wall[j].nextsector = newns;
OSD_Printf(CCHK_CORRECTED "auto-correction: set wall[%d].nextsector=%d\n", j, newns);
}
}
int32_t CheckMapCorruption(int32_t printfromlev, int32_t tryfixing)
{ {
int32_t i, j, w0, numw, endwall, ns, nw; int32_t i, j, w0, numw, endwall, ns, nw;
int32_t ewall=0; // expected wall index int32_t ewall=0; // expected wall index
int32_t errlevel=0, bad=0; int32_t errlevel=0, bad=0;
uint8_t *seen_nextwalls;
int16_t *lastnextwallsource;
numcorruptthings = 0; numcorruptthings = 0;
if (numsectors>MAXSECTORS) if (numsectors>MAXSECTORS)
CORRUPTCHK_PRINT(5, 0, "PANIC!!! SECTOR LIMIT EXCEEDED (MAXSECTORS=%d)!!!", MAXSECTORS); CORRUPTCHK_PRINT(5, 0, CCHK_PANIC "SECTOR LIMIT EXCEEDED (MAXSECTORS=%d)!!!", MAXSECTORS);
if (numwalls>MAXWALLS) if (numwalls>MAXWALLS)
CORRUPTCHK_PRINT(5, 0, "PANIC!!! WALL LIMIT EXCEEDED (MAXWALLS=%d)!!!", MAXWALLS); CORRUPTCHK_PRINT(5, 0, CCHK_PANIC "WALL LIMIT EXCEEDED (MAXWALLS=%d)!!!", MAXWALLS);
if (numsectors>MAXSECTORS || numwalls>MAXWALLS) if (numsectors>MAXSECTORS || numwalls>MAXWALLS)
return bad; return bad;
seen_nextwalls = Bcalloc((numwalls+7)>>3,1);
if (!seen_nextwalls) return 5;
lastnextwallsource = Bmalloc(numwalls*sizeof(lastnextwallsource[0]));
if (!lastnextwallsource) { Bfree(seen_nextwalls); return 5; }
for (i=0; i<numsectors; i++) for (i=0; i<numsectors; i++)
{ {
bad = 0; bad = 0;
@ -10058,7 +10105,7 @@ int32_t CheckMapCorruption(int32_t printfromlev)
CORRUPTCHK_PRINT(4, CORRUPT_SECTOR|i, "SECTOR[%d].WALLPTR=%d inconsistent, expected %d", i, w0, ewall); CORRUPTCHK_PRINT(4, CORRUPT_SECTOR|i, "SECTOR[%d].WALLPTR=%d inconsistent, expected %d", i, w0, ewall);
if (numw <= 1) if (numw <= 1)
CORRUPTCHK_PRINT(5, CORRUPT_SECTOR|i, "PANIC!!! SECTOR[%d].WALLNUM=%d INVALID!!!", i, numw); CORRUPTCHK_PRINT(5, CORRUPT_SECTOR|i, CCHK_PANIC "SECTOR[%d].WALLNUM=%d INVALID!!!", i, numw);
else if (numw==2) else if (numw==2)
CORRUPTCHK_PRINT(3, CORRUPT_SECTOR|i, "SECTOR[%d].WALLNUM=2, expected at least 3", i); CORRUPTCHK_PRINT(3, CORRUPT_SECTOR|i, "SECTOR[%d].WALLNUM=2, expected at least 3", i);
@ -10079,8 +10126,14 @@ int32_t CheckMapCorruption(int32_t printfromlev)
bad = 0; bad = 0;
if (wall[j].point2 < w0 || wall[j].point2 > endwall) if (wall[j].point2 < w0 || wall[j].point2 > endwall)
{
if (wall[j].point2 < 0 || wall[j].point2 >= MAXWALLS)
CORRUPTCHK_PRINT(5, CORRUPT_WALL|j, CCHK_PANIC "WALL[%d].POINT2=%d INVALID!!!",
j, wall[j].point2);
else
CORRUPTCHK_PRINT(4, CORRUPT_WALL|j, "WALL[%d].POINT2=%d out of range [%d, %d]", CORRUPTCHK_PRINT(4, CORRUPT_WALL|j, "WALL[%d].POINT2=%d out of range [%d, %d]",
j, wall[j].point2, w0, endwall); j, wall[j].point2, w0, endwall);
}
nw = wall[j].nextwall; nw = wall[j].nextwall;
ns = wall[j].nextsector; ns = wall[j].nextsector;
@ -10093,19 +10146,78 @@ int32_t CheckMapCorruption(int32_t printfromlev)
CORRUPTCHK_PRINT(4, CORRUPT_WALL|j, "WALL[%d].NEXTSECTOR=%d out of range: numsectors=%d", CORRUPTCHK_PRINT(4, CORRUPT_WALL|j, "WALL[%d].NEXTSECTOR=%d out of range: numsectors=%d",
j, ns, numsectors); j, ns, numsectors);
if (ns == i)
CORRUPTCHK_PRINT(4, CORRUPT_WALL|j, "WALL[%d].NEXTSECTOR is its own sector", j);
if (nw>=w0 && nw<=endwall) if (nw>=w0 && nw<=endwall)
CORRUPTCHK_PRINT(4, CORRUPT_WALL|j, "WALL[%d].NEXTWALL is its own sector's wall", j); CORRUPTCHK_PRINT(4, CORRUPT_WALL|j, "WALL[%d].NEXTWALL is its own sector's wall", j);
if (ns == i)
{
CORRUPTCHK_PRINT(4, CORRUPT_WALL|j, "WALL[%d].NEXTSECTOR is its own sector", j);
if (!bad) if (!bad)
{ {
if (ns>=0 || (ns^nw)<0) if (tryfixing)
do_nextsector_correction(nw, j);
else if (4>=printfromlev)
suggest_nextsector_correction(nw, j);
}
}
if (nw>=0 && nw<numwalls)
{ {
if ((ns^nw)<0 || nw<sector[ns].wallptr || nw>=sector[ns].wallptr+sector[ns].wallnum) if (seen_nextwalls[nw>>3]&(1<<(nw&7)))
CORRUPTCHK_PRINT(4, CORRUPT_WALL|j, "WALL[%d].NEXTSECTOR=%d and .NEXTWALL=%d inconsistent", {
j, ns, nw); int16_t nwnw, lnws;
lnws = lastnextwallsource[nw];
CORRUPTCHK_PRINT(3, CORRUPT_WALL|j, "WALL[%d].NEXTWALL=%d already referenced from wall %d",
j, nw, lnws);
nwnw = wall[nw].nextwall;
if (nwnw==j || nwnw==lnws)
{
int32_t walltoclear = nwnw==j ? lnws : j;
if (tryfixing)
{
wall[walltoclear].nextsector = wall[walltoclear].nextwall = -1;
OSD_Printf(CCHK_CORRECTED "auto-correction: cleared wall %d's nextwall and nextsector tags to -1\n",
walltoclear);
}
else if (3 >= printfromlev)
OSD_Printf(" wall[%d].nextwall=%d, suggest clearing wall %d's nextwall and nextsector tags to -1\n",
nw, nwnw, walltoclear);
}
}
else
{
seen_nextwalls[nw>>3] |= 1<<(nw&7);
lastnextwallsource[nw] = j;
}
}
if (bad<4)
{
if ((ns^nw)<0)
{
CORRUPTCHK_PRINT(4, CORRUPT_WALL|j, "WALL[%d].NEXTSECTOR=%d and .NEXTWALL=%d inconsistent:"
" missing one next pointer", j, ns, nw);
if (tryfixing)
do_nextsector_correction(nw, j);
else if (4>=printfromlev)
suggest_nextsector_correction(nw, j);
}
else if (ns>=0)
{
if (nw<sector[ns].wallptr || nw>=sector[ns].wallptr+sector[ns].wallnum)
{
CORRUPTCHK_PRINT(4, CORRUPT_WALL|j, "WALL[%d].NEXTWALL=%d out of .NEXTSECTOR=%d's bounds",
j, nw, ns);
if (tryfixing)
do_nextsector_correction(nw, j);
else if (4 >= printfromlev)
{
OSD_Printf(" sector %d's walls: [%d .. %d]\n", ns, sector[ns].wallptr,
sector[ns].wallptr+sector[ns].wallnum-1);
suggest_nextsector_correction(nw, j);
}
}
} }
} }
@ -10138,6 +10250,9 @@ int32_t CheckMapCorruption(int32_t printfromlev)
OSD_Printf("-- corruption level: %d\n", errlevel); OSD_Printf("-- corruption level: %d\n", errlevel);
} }
Bfree(seen_nextwalls);
Bfree(lastnextwallsource);
return errlevel; return errlevel;
} }
//// ////