From 2820dc85a84d46d17d38faeef738fa83f81820e5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 24 Dec 2019 18:53:29 +0100 Subject: [PATCH] - plugged more memory leaks. I can now start the first Duke Nukem level, exit with Alt-F4 and no leaked memory blocks get reported. --- source/build/include/baselayer.h | 1 + source/build/include/build.h | 4 +- source/build/src/baselayer.cpp | 4 +- source/build/src/engine.cpp | 150 ++++++++++++--------------- source/build/src/engine_priv.h | 2 +- source/build/src/sdlayer.cpp | 4 +- source/common/console/c_console.cpp | 1 + source/common/console/c_dispatch.cpp | 10 ++ source/common/console/c_dispatch.h | 1 + source/common/gamecontrol.cpp | 12 +++ source/common/gamecontrol.h | 3 + source/common/utility/zstring.h | 7 ++ source/duke3d/src/anim.cpp | 2 +- source/duke3d/src/duke3d.h | 4 +- source/duke3d/src/game.cpp | 32 +++--- source/duke3d/src/gamevars.cpp | 4 +- source/platform/win32/i_main.cpp | 3 +- source/rr/src/duke3d.h | 1 + source/rr/src/game.cpp | 28 ++--- source/sw/src/border.cpp | 2 +- source/sw/src/game.h | 2 +- 21 files changed, 139 insertions(+), 138 deletions(-) diff --git a/source/build/include/baselayer.h b/source/build/include/baselayer.h index 62e9abed6..b2ed46637 100644 --- a/source/build/include/baselayer.h +++ b/source/build/include/baselayer.h @@ -108,6 +108,7 @@ struct GameInterface virtual ~GameInterface() {} virtual void faketimerhandler() {} // This is a remnant of older versions, but Blood backend has not updated yet. virtual int app_main() = 0; + virtual void FreeGameData() {} virtual bool validate_hud(int) = 0; virtual void set_hud_layout(int size) = 0; virtual void set_hud_scale(int size) = 0; diff --git a/source/build/include/build.h b/source/build/include/build.h index aba09249d..4af8fc8cb 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -459,7 +459,7 @@ EXTERN tspriteptr_t tspriteptr[MAXSPRITESONSCREEN + 1]; EXTERN int32_t wx1, wy1, wx2, wy2; EXTERN int32_t xdim, ydim, numpages, upscalefactor; EXTERN int32_t yxaspect, viewingrange; -EXTERN intptr_t *ylookup; +EXTERN TArray ylookup; EXTERN int32_t rotatesprite_y_offset; EXTERN int32_t rotatesprite_yxaspect; @@ -527,7 +527,7 @@ EXTERN int32_t g_visibility, parallaxvisibility; EXTERN uint8_t numalphatabs; EXTERN vec2_t windowxy1, windowxy2; -EXTERN int16_t *startumost, *startdmost; +EXTERN TArray startumost, startdmost; // The maximum tile offset ever used in any tiled parallaxed multi-sky. #define PSKYOFF_MAX 8 diff --git a/source/build/src/baselayer.cpp b/source/build/src/baselayer.cpp index 11f4d3680..8bc09337b 100644 --- a/source/build/src/baselayer.cpp +++ b/source/build/src/baselayer.cpp @@ -27,9 +27,7 @@ void calc_ylookup(int32_t bpl, int32_t lastyidx) if (lastyidx > ylookupsiz) { - Xaligned_free(ylookup); - - ylookup = (intptr_t *)Xaligned_alloc(16, lastyidx * sizeof(intptr_t)); + ylookup.Resize(lastyidx); ylookupsiz = lastyidx; } diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index 5222e09b5..03b0d147b 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -130,7 +130,7 @@ static struct { } distrecipcache[DISTRECIPCACHESIZE]; static int32_t distrecipagecnt = 0; -static int32_t *lookups = NULL; +static TArray lookups; static int32_t beforedrawrooms = 1; static int32_t oxdimen = -1, oviewingrange = -1, oxyaspect = -1; @@ -145,7 +145,7 @@ int32_t globalflags; //Textured Map variables static char globalpolytype; -static int16_t **dotp1, **dotp2; +static TArraydotp1, dotp2; static int8_t tempbuf[MAXWALLS]; @@ -165,7 +165,8 @@ static intptr_t slopalookup[SLOPALOOKUPSIZ]; // was 2048 static int32_t no_radarang2 = 0; static int16_t radarang[1280]; -static int32_t qradarang[10240], *radarang2; +static int32_t qradarang[10240]; +static TArray radarang2; const char ATTRIBUTE((used)) pow2char_[8] = {1,2,4,8,16,32,64,128}; uint16_t ATTRIBUTE((used)) sqrtable[4096], ATTRIBUTE((used)) shlookup[4096+256], ATTRIBUTE((used)) sqrtable_old[2048]; @@ -1331,14 +1332,14 @@ int16_t bunchp2[MAXWALLSB], thesector[MAXWALLSB]; int16_t bunchfirst[MAXWALLSB], bunchlast[MAXWALLSB]; static int32_t nodesperline, ysavecnt; -static int16_t *smost, *umost, *dmost, *bakumost, *bakdmost; -static int16_t *uplc, *dplc, *uwall, *dwall; -static int32_t *swplc, *lplc, *swall, *lwall; +static TArray smost, umost, dmost, bakumost, bakdmost; +static TArray uplc, dplc, uwall, dwall; +static TArray swplc, lplc, swall, lwall; #ifdef HIGH_PRECISION_SPRITE -static float *swallf; +static TArray swallf; #endif -uint8_t* mirrorBuffer; +TArray mirrorBuffer; static int32_t smostcnt; static int32_t smoststart[MAXWALLSB]; @@ -1396,7 +1397,7 @@ static int32_t globaly1, globalx2; int16_t sectorborder[256]; int32_t ydim16, qsetmode = 0; int16_t pointhighlight=-1, linehighlight=-1, highlightcnt=0; -static int32_t *lastx; +static TArray lastx; int32_t halfxdim16, midydim16; @@ -1926,7 +1927,7 @@ static void maskwallscan(int32_t x1, int32_t x2, int32_t saturatevplc) palookupoffse[0] = fpalookup + getpalookupsh(mulscale16(swall[x],globvis)); calc_bufplc(&bufplce[0], lwall[x], tsiz); - calc_vplcinc(&vplce[0], &vince[0], swall, x, y1ve[0]); + calc_vplcinc(&vplce[0], &vince[0], swall.Data(), x, y1ve[0]); mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0],p+ylookup[y1ve[0]]); } @@ -1941,7 +1942,7 @@ static void maskwallscan(int32_t x1, int32_t x2, int32_t saturatevplc) if (y2ve[z] < y1ve[z]) { bad += pow2char[z]; continue; } calc_bufplc(&bufplce[z], lwall[dax], tsiz); - calc_vplcinc(&vplce[z], &vince[z], swall, dax, y1ve[z]); + calc_vplcinc(&vplce[z], &vince[z], swall.Data(), dax, y1ve[z]); } if (bad == 15) continue; @@ -1999,7 +2000,7 @@ do_mvlineasm1: palookupoffse[0] = fpalookup + getpalookupsh(mulscale16(swall[x],globvis)); calc_bufplc(&bufplce[0], lwall[x], tsiz); - calc_vplcinc(&vplce[0], &vince[0], swall, x, y1ve[0]); + calc_vplcinc(&vplce[0], &vince[0], swall.Data(), x, y1ve[0]); #ifdef NONPOW2_YSIZE_ASM if (globalshiftval==0) @@ -3042,7 +3043,7 @@ static void transmaskvline(int32_t x) calc_bufplc(&bufplc, lwall[x], ntsiz); uint32_t vplc; int32_t vinc; - calc_vplcinc(&vplc, &vinc, swall, x, y1v); + calc_vplcinc(&vplc, &vinc, swall.Data(), x, y1v); intptr_t p = ylookup[y1v]+x+frameoffset; @@ -3083,8 +3084,8 @@ static void transmaskvline2(int32_t x) calc_bufplc(&bufplce[0], lwall[x], ntsiz); calc_bufplc(&bufplce[1], lwall[x2], ntsiz); - calc_vplcinc(&vplce[0], &vince[0], swall, x, y1ve[0]); - calc_vplcinc(&vplce[1], &vince[1], swall, x2, y1ve[1]); + calc_vplcinc(&vplce[0], &vince[0], swall.Data(), x, y1ve[0]); + calc_vplcinc(&vplce[1], &vince[1], swall.Data(), x2, y1ve[1]); int32_t const y1 = max(y1ve[0],y1ve[1]); int32_t const y2 = min(y2ve[0],y2ve[1]); @@ -3931,8 +3932,8 @@ static void parascan(char dastat, int32_t bunch) globalshade = (int32_t)sec->ceilingshade; globalxpanning = (int32_t)sec->ceilingxpanning; globalypanning = (int32_t)sec->ceilingypanning; - topptr = umost; - botptr = uplc; + topptr = umost.Data(); + botptr = uplc.Data(); } else { @@ -3941,8 +3942,8 @@ static void parascan(char dastat, int32_t bunch) globalshade = (int32_t)sec->floorshade; globalxpanning = (int32_t)sec->floorxpanning; globalypanning = (int32_t)sec->floorypanning; - topptr = dplc; - botptr = dmost; + topptr = dplc.Data(); + botptr = dmost.Data(); } if ((unsigned)globalpicnum >= MAXTILES) globalpicnum = 0; @@ -4040,7 +4041,7 @@ static void parascan(char dastat, int32_t bunch) globalpicnum = l + dapskyoff[lplc[x]>>m]; if (((lplc[x]^lplc[xb1[z]-1])>>m) == 0) - wallscan(x,xb1[z]-1,topptr,botptr,swplc,lplc); + wallscan(x,xb1[z]-1,topptr,botptr,swplc.Data(),lplc.Data()); else { j = x; @@ -4049,14 +4050,14 @@ static void parascan(char dastat, int32_t bunch) n = l + dapskyoff[lplc[x]>>m]; if (n != globalpicnum) { - wallscan(j,x-1,topptr,botptr,swplc,lplc); + wallscan(j,x-1,topptr,botptr,swplc.Data(),lplc.Data()); j = x; globalpicnum = n; } x++; } if (j < x) - wallscan(j,x-1,topptr,botptr,swplc,lplc); + wallscan(j,x-1,topptr,botptr,swplc.Data(),lplc.Data()); } globalpicnum = l; @@ -4070,7 +4071,7 @@ static void parascan(char dastat, int32_t bunch) globalpicnum = l + dapskyoff[lplc[x]>>m]; if (((lplc[x]^lplc[xb2[bunchlast[bunch]]])>>m) == 0) - wallscan(x,xb2[bunchlast[bunch]],topptr,botptr,swplc,lplc); + wallscan(x,xb2[bunchlast[bunch]],topptr,botptr,swplc.Data(),lplc.Data()); else { j = x; @@ -4079,14 +4080,14 @@ static void parascan(char dastat, int32_t bunch) n = l + dapskyoff[lplc[x]>>m]; if (n != globalpicnum) { - wallscan(j,x-1,topptr,botptr,swplc,lplc); + wallscan(j,x-1,topptr,botptr,swplc.Data(),lplc.Data()); j = x; globalpicnum = n; } x++; } if (j <= x) - wallscan(j,x-1,topptr,botptr,swplc,lplc); + wallscan(j,x-1,topptr,botptr,swplc.Data(),lplc.Data()); } globalpicnum = l; } @@ -4221,8 +4222,8 @@ static void classicDrawBunches(int32_t bunch) for (; z>=0; z=bunchp2[z]) //uplc/dplc calculation { - andwstat1 &= wallmost(uplc,z,sectnum,(uint8_t)0); - andwstat2 &= wallmost(dplc,z,sectnum,(uint8_t)1); + andwstat1 &= wallmost(uplc.Data(),z,sectnum,(uint8_t)0); + andwstat2 &= wallmost(dplc.Data(),z,sectnum,(uint8_t)1); } #ifdef YAX_ENABLE @@ -4414,7 +4415,7 @@ static void classicDrawBunches(int32_t bunch) } else { - wallmost(dwall,z,nextsectnum,(uint8_t)0); + wallmost(dwall.Data(),z,nextsectnum,(uint8_t)0); if ((cz[2] > fz[0]) || (cz[3] > fz[1])) for (i=x1; i<=x2; i++) if (dwall[i] > dplc[i]) dwall[i] = dplc[i]; @@ -4435,7 +4436,7 @@ static void classicDrawBunches(int32_t bunch) gotswall = 1; prepwall(z,wal); - wallscan(x1,x2,uplc,dwall,swall,lwall); + wallscan(x1,x2,uplc.Data(),dwall.Data(),swall.Data(),lwall.Data()); if ((cz[2] >= cz[0]) && (cz[3] >= cz[1])) { @@ -4499,7 +4500,7 @@ static void classicDrawBunches(int32_t bunch) } else { - wallmost(uwall,z,nextsectnum,(uint8_t)1); + wallmost(uwall.Data(),z,nextsectnum,(uint8_t)1); if ((fz[2] < cz[0]) || (fz[3] < cz[1])) for (i=x1; i<=x2; i++) if (uwall[i] < uplc[i]) uwall[i] = uplc[i]; @@ -4522,7 +4523,7 @@ static void classicDrawBunches(int32_t bunch) setup_globals_wall2(wal, sec->visibility, nextsec->floorz, sec->ceilingz); if (gotswall == 0) { gotswall = 1; prepwall(z,wal); } - wallscan(x1,x2,uwall,dplc,swall,lwall); + wallscan(x1,x2,uwall.Data(),dplc.Data(),swall.Data(),lwall.Data()); if ((fz[2] <= fz[0]) && (fz[3] <= fz[1])) { @@ -4604,7 +4605,7 @@ static void classicDrawBunches(int32_t bunch) (nextsectnum >= 0) ? sec->ceilingz : sec->floorz); if (gotswall == 0) { gotswall = 1; prepwall(z,wal); } - wallscan(x1,x2,uplc,dplc,swall,lwall); + wallscan(x1,x2,uplc.Data(),dplc.Data(),swall.Data(),lwall.Data()); #ifdef YAX_ENABLE // TODO: slopes? @@ -5447,8 +5448,8 @@ draw_as_face_sprite: xb2[MAXWALLSB-1] = sx2; yb1[MAXWALLSB-1] = sy1; yb2[MAXWALLSB-1] = sy2; - owallmost(uwall, MAXWALLSB-1, z1-globalposz); - owallmost(dwall, MAXWALLSB-1, z2-globalposz); + owallmost(uwall.Data(), MAXWALLSB-1, z1-globalposz); + owallmost(dwall.Data(), MAXWALLSB-1, z2-globalposz); int32_t hplc = divscale19(xdimenscale,sy1); const int32_t hplc2 = divscale19(xdimenscale,sy2); @@ -6156,7 +6157,7 @@ draw_as_face_sprite: const int32_t floorz = (sec->floorstat&3) == 0 ? sec->floorz : INT32_MAX; classicDrawVoxel(tspr->x,tspr->y,tspr->z,i,daxrepeat,(int32_t)tspr->yrepeat,vtilenum, - tspr->shade,tspr->pal,lwall,swall,tspr->cstat,(tspr->cstat&48)!=48,floorz,ceilingz); + tspr->shade,tspr->pal,lwall.Data(),swall.Data(),tspr->cstat,(tspr->cstat&48)!=48,floorz,ceilingz); } if (automapping == 1 && (unsigned)spritenum < MAXSPRITES) @@ -6198,13 +6199,13 @@ static void renderDrawMaskedWall(int16_t damaskwallcnt) int32_t z1 = max(nsec->ceilingz,sec->ceilingz); int32_t z2 = min(nsec->floorz,sec->floorz); - wallmost(uwall,z,sectnum,(uint8_t)0); - wallmost(uplc,z,(int32_t)wal->nextsector,(uint8_t)0); + wallmost(uwall.Data(),z,sectnum,(uint8_t)0); + wallmost(uplc.Data(),z,(int32_t)wal->nextsector,(uint8_t)0); for (bssize_t x=xb1[z]; x<=xb2[z]; x++) if (uplc[x] > uwall[x]) uwall[x] = uplc[x]; - wallmost(dwall,z,sectnum,(uint8_t)1); - wallmost(dplc,z,(int32_t)wal->nextsector,(uint8_t)1); + wallmost(dwall.Data(),z,sectnum,(uint8_t)1); + wallmost(dplc.Data(),z,(int32_t)wal->nextsector,(uint8_t)1); for (bssize_t x=xb1[z]; x<=xb2[z]; x++) if (dplc[x] < dwall[x]) dwall[x] = dplc[x]; @@ -8025,7 +8026,6 @@ void engineUnInit(void) TileFiles.CloseAll(); - DO_FREE_AND_NULL(lookups); for (bssize_t i=0; i dmost[i]) @@ -9835,43 +9835,29 @@ static int32_t get_mapversion(void) static void videoAllocateBuffers(void) { - int32_t i; // Needed for the game's TILT_SETVIEWTOTILE_320. const int32_t clamped_ydim = max(ydim, 320); - struct - { - void **ptr; - size_t size; - } dynarray[] = { - { (void **)&smost, YSAVES * sizeof(int16_t) }, - { (void **)&umost, xdim * sizeof(int16_t) }, - { (void **)&dmost, xdim * sizeof(int16_t) }, - { (void **)&startumost, xdim * sizeof(int16_t) }, - { (void **)&startdmost, xdim * sizeof(int16_t) }, - { (void **)&bakumost, xdim * sizeof(int16_t) }, - { (void **)&bakdmost, xdim * sizeof(int16_t) }, - { (void **)&uplc, xdim * sizeof(int16_t) }, - { (void **)&dplc, xdim * sizeof(int16_t) }, - { (void **)&uwall, xdim * sizeof(int16_t) }, - { (void **)&dwall, xdim * sizeof(int16_t) }, - { (void **)&swplc, xdim * sizeof(int32_t) }, - { (void **)&lplc, xdim * sizeof(int32_t) }, - { (void **)&swall, xdim * sizeof(int32_t) }, - { (void **)&lwall, (xdim + 4) * sizeof(int32_t) }, - { (void **)&radarang2, xdim * sizeof(int32_t) }, - { (void **)&dotp1, clamped_ydim * sizeof(intptr_t) }, - { (void **)&dotp2, clamped_ydim * sizeof(intptr_t) }, - { (void **)&lastx, clamped_ydim * sizeof(int32_t) }, - { (void **)&mirrorBuffer, (size_t) (xdim * ydim)}, - }; - - for (i = 0; i < (signed)ARRAY_SIZE(dynarray); i++) - { - Xaligned_free(*dynarray[i].ptr); - - *dynarray[i].ptr = Xaligned_alloc(16, dynarray[i].size); - } + smost.Resize(YSAVES); + umost.Resize(xdim); + dmost.Resize(xdim); + startumost.Resize(xdim); + startdmost.Resize(xdim); + bakumost.Resize(xdim); + bakdmost.Resize(xdim); + uplc.Resize(xdim); + dplc.Resize(xdim); + uwall.Resize(xdim); + dwall.Resize(xdim); + swplc.Resize(xdim); + lplc.Resize(xdim); + swall.Resize(xdim); + lwall.Resize((xdim + 4)); + radarang2.Resize(xdim); + dotp1.Resize(clamped_ydim); + dotp2.Resize(clamped_ydim); + lastx.Resize(clamped_ydim); + mirrorBuffer.Resize(xdim * ydim); ysavecnt = YSAVES; nodesperline = tabledivide32_noinline(YSAVES, ydim); @@ -9941,16 +9927,14 @@ int32_t videoSetGameMode(char davidoption, int32_t daupscaledxdim, int32_t daups videoAllocateBuffers(); #ifdef HIGH_PRECISION_SPRITE - swallf = (float *) Xrealloc(swallf, xdim * sizeof(float)); + swallf.Resize(xdim); #endif - Xfree(lookups); - j = ydim*4; //Leave room for horizlookup&horizlookup2 - lookups = (int32_t *)Xmalloc(2*j*sizeof(lookups[0])); + lookups.Resize(2 * j); - horizlookup = lookups; - horizlookup2 = lookups + j; + horizlookup = lookups.Data(); + horizlookup2 = lookups.Data() + j; horizycent = ((ydim*4)>>1); //Force drawrooms to call dosetaspect & recalculate stuff @@ -11700,7 +11684,7 @@ void renderCompleteMirror(void) int const height = mirrorsy2-mirrorsy1; // Address of the mirror wall's top left corner in the source scene: - intptr_t s = (intptr_t) mirrorBuffer + ylookup[windowxy1.y+mirrorsy1] + windowxy1.x+mirrorsx1; + intptr_t s = (intptr_t) mirrorBuffer.Data() + ylookup[windowxy1.y+mirrorsy1] + windowxy1.x+mirrorsx1; // Pointer to the mirror line's left corner in the destination: intptr_t d = (intptr_t) frameplace + ylookup[windowxy1.y+mirrorsy1] + windowxy2.x-mirrorsx2; diff --git a/source/build/src/engine_priv.h b/source/build/src/engine_priv.h index c02ed8425..490fee68a 100644 --- a/source/build/src/engine_priv.h +++ b/source/build/src/engine_priv.h @@ -92,7 +92,7 @@ extern int16_t thesector[MAXWALLSB], thewall[MAXWALLSB]; extern int16_t bunchfirst[MAXWALLSB], bunchlast[MAXWALLSB]; extern int16_t maskwall[MAXWALLSB], maskwallcnt; extern tspriteptr_t tspriteptr[MAXSPRITESONSCREEN + 1]; -extern uint8_t* mirrorBuffer; +extern TArray mirrorBuffer; extern int32_t xdimen, xdimenrecip, halfxdimen, xdimenscale, xdimscale, ydimen; extern float fxdimen; extern intptr_t frameoffset; diff --git a/source/build/src/sdlayer.cpp b/source/build/src/sdlayer.cpp index 8f124b3d8..3096cf1db 100644 --- a/source/build/src/sdlayer.cpp +++ b/source/build/src/sdlayer.cpp @@ -236,12 +236,12 @@ void videoBeginDrawing(void) { if (!backupFrameplace) backupFrameplace = frameplace; - else if (frameplace != (intptr_t)mirrorBuffer && + else if (frameplace != (intptr_t)mirrorBuffer.Data() && frameplace != backupFrameplace) return; } - frameplace = (intptr_t)mirrorBuffer; + frameplace = (intptr_t)mirrorBuffer.Data(); if (offscreenrendering) return; diff --git a/source/common/console/c_console.cpp b/source/common/console/c_console.cpp index 05ace1d53..024cc2d27 100644 --- a/source/common/console/c_console.cpp +++ b/source/common/console/c_console.cpp @@ -726,6 +726,7 @@ void C_DeinitConsole () // Make sure all tab commands are cleared before the memory for // their names is deallocated. C_ClearTabCommands (); + C_ClearDynCCmds(); // Free AddToConsole()'s work buffer if (work != NULL) diff --git a/source/common/console/c_dispatch.cpp b/source/common/console/c_dispatch.cpp index f739693de..342bd7a31 100644 --- a/source/common/console/c_dispatch.cpp +++ b/source/common/console/c_dispatch.cpp @@ -1055,6 +1055,16 @@ int OSD_RegisterFunction(const char* pszName, const char* pszDesc, int (*func)(o return 0; } + +void C_ClearDynCCmds() +{ + for (auto ccmd : dynccmds) + { + delete ccmd; + } + dynccmds.Clear(); +} + CCMD (quit) { throw ExitEvent(0); diff --git a/source/common/console/c_dispatch.h b/source/common/console/c_dispatch.h index 43b3869bd..40004f2b7 100644 --- a/source/common/console/c_dispatch.h +++ b/source/common/console/c_dispatch.h @@ -70,6 +70,7 @@ void C_DoCommand (const char *cmd, int keynum=0); FExecList *C_ParseExecFile(const char *file, FExecList *source); bool C_ExecFile(const char *file); +void C_ClearDynCCmds(); // Write out alias commands to a file for all current aliases. void C_ArchiveAliases (FConfigFile *f); diff --git a/source/common/gamecontrol.cpp b/source/common/gamecontrol.cpp index 554ffc7f4..802ed4daf 100644 --- a/source/common/gamecontrol.cpp +++ b/source/common/gamecontrol.cpp @@ -51,6 +51,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "v_video.h" #include "st_start.h" #include "s_music.h" +#include "i_video.h" +#include "glbackend/glbackend.h" #ifndef NETCODE_DISABLE #include "enet.h" #endif @@ -60,6 +62,9 @@ MapRecord *currentLevel; // level that is currently played. (The real level, not MapRecord* lastLevel; // Same here, for the last level. MapRecord userMapRecord; // stand-in for the user map. +FMemArena dump; // this is for memory blocks than cannot be deallocated without some huge effort. Put them in here so that they do not register on shutdown. + + void C_CON_SetAliases(); InputState inputState; void SetClipshapes(); @@ -305,10 +310,17 @@ int GameMain() } S_StopMusic(true); if (soundEngine) delete soundEngine; + soundEngine = nullptr; + I_CloseSound(); I_ShutdownInput(); G_SaveConfig(); C_DeinitConsole(); V_ClearFonts(); + TileFiles.ClearTextureCache(); + TileFiles.CloseAll(); // do this before shutting down graphics. + GLInterface.Deinit(); + I_ShutdownGraphics(); + gi->FreeGameData(); if (gi) delete gi; #ifndef NETCODE_DISABLE if (gHaveNetworking) enet_deinitialize(); diff --git a/source/common/gamecontrol.h b/source/common/gamecontrol.h index d79eddaa7..3e1b52380 100644 --- a/source/common/gamecontrol.h +++ b/source/common/gamecontrol.h @@ -6,6 +6,7 @@ #include "gamecvars.h" #include "tarray.h" #include "name.h" +#include "memarena.h" EXTERN_CVAR(Int, cl_defaultconfiguration) @@ -13,6 +14,8 @@ extern FString currentGame; extern FString LumpFilter; class FArgs; +extern FMemArena dump; // this is for memory blocks than cannot be deallocated without some huge effort. Put them in here so that they do not register on shutdown. + extern TMap NameToTileIndex; void D_AddWildFile(TArray& wadfiles, const char* value); diff --git a/source/common/utility/zstring.h b/source/common/utility/zstring.h index f5b718fa8..248d4d549 100644 --- a/source/common/utility/zstring.h +++ b/source/common/utility/zstring.h @@ -469,3 +469,10 @@ template<> struct THashTraits // Compares two keys, returning zero if they are the same. int Compare(const FString &left, const FString &right) { return left.Compare(right); } }; + +struct StringNoCaseHashTraits +{ + hash_t Hash(const FString& key) { return (hash_t)SuperFastHashI(key.GetChars(), key.Len()); } + // Compares two keys, returning zero if they are the same. + int Compare(const FString& left, const FString& right) { return left.CompareNoCase(right); } +}; diff --git a/source/duke3d/src/anim.cpp b/source/duke3d/src/anim.cpp index 4b1ed8b2d..87e67601c 100644 --- a/source/duke3d/src/anim.cpp +++ b/source/duke3d/src/anim.cpp @@ -208,7 +208,7 @@ void Anim_Init(void) if (anm.numsounds) { - anim->sounds = (animsound_t *)Xmalloc(anm.numsounds * sizeof(animsound_t)); + anim->sounds = (animsound_t *)dump.Alloc(anm.numsounds * sizeof(animsound_t)); int const numsounds = anm.numsounds; for (int i = 0; i < numsounds; ++i) { diff --git a/source/duke3d/src/duke3d.h b/source/duke3d/src/duke3d.h index 9de7ea892..0fd7fb128 100644 --- a/source/duke3d/src/duke3d.h +++ b/source/duke3d/src/duke3d.h @@ -32,8 +32,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "pragmas.h" #include "polymost.h" #include "gamecvars.h" +#include "gamecontrol.h" #include "menu/menu.h" - +#include "memarena.h" #define HEAD2 APPNAME @@ -144,6 +145,7 @@ static inline int32_t G_DefaultActorHealth(int spriteNum) struct GameInterface : ::GameInterface { int app_main() override; + void FreeGameData() override; bool validate_hud(int) override; void set_hud_layout(int size) override; void set_hud_scale(int size) override; diff --git a/source/duke3d/src/game.cpp b/source/duke3d/src/game.cpp index 919b4c6f4..fc35aa29d 100644 --- a/source/duke3d/src/game.cpp +++ b/source/duke3d/src/game.cpp @@ -259,11 +259,6 @@ void G_GameExit(const char *msg) G_DisplayExtraScreens(); } - if (*msg != 0) initprintf("%s\n",msg); - - if (in3dmode()) - G_Shutdown(); - if (*msg != 0) { if (!(msg[0] == ' ' && msg[1] == 0)) @@ -5316,6 +5311,7 @@ static void G_Cleanup(void) #if !defined LUNATIC if (label != (char *)&sprite[0]) Xfree(label); if (labelcode != (int32_t *)§or[0]) Xfree(labelcode); + if (labeltype != (int32_t*)&wall[0]) Xfree(labeltype); Xfree(apScript); Xfree(bitptr); @@ -5342,8 +5338,6 @@ static void G_Cleanup(void) void G_Shutdown(void) { - engineUnInit(); - G_Cleanup(); } /* @@ -5513,21 +5507,13 @@ void G_PostCreateGameState(void) static void G_HandleMemErr(int32_t lineNum, const char *fileName, const char *funcName) { - static char msg[128]; - Bsnprintf(msg, sizeof(msg), "Out of memory in %s:%d (%s)\n", fileName, lineNum, funcName); -#ifdef DEBUGGINGAIDS - Bassert(0); -#endif - G_GameExit(msg); + I_FatalError("Out of memory in %s:%d (%s)\n", fileName, lineNum, funcName); } static void G_FatalEngineError(void) { - wm_msgbox("Fatal Engine Initialization Error", + I_FatalError("Fatal Engine Initialization Error", "There was a problem initializing the engine: %s\n\nThe application will now close.", engineerrstr); - G_Cleanup(); - ERRprintf("G_Startup: There was a problem initializing the engine: %s\n", engineerrstr); - exit(6); } static void G_Startup(void) @@ -5734,6 +5720,7 @@ void G_MaybeAllocPlayer(int32_t pnum) } + // TODO: reorder (net)actor_t to eliminate slop and update assertion EDUKE32_STATIC_ASSERT(sizeof(actor_t)%4 == 0); EDUKE32_STATIC_ASSERT(sizeof(DukePlayer_t)%4 == 0); @@ -6430,7 +6417,8 @@ void GameInterface::SendMessage(const char* msg) typebuf[0] = 0; } } - else + +void nix() { int32_t const hitstate = I_EnterText(typebuf, 120, 0); @@ -6466,9 +6454,15 @@ void GameInterface::SendMessage(const char* msg) else pub = NUMPAGES; } - +} #endif +void GameInterface::FreeGameData() +{ + engineUnInit(); + G_Cleanup(); +} + ::GameInterface* CreateInterface() { return new GameInterface; diff --git a/source/duke3d/src/gamevars.cpp b/source/duke3d/src/gamevars.cpp index 091d83256..406a89a89 100644 --- a/source/duke3d/src/gamevars.cpp +++ b/source/duke3d/src/gamevars.cpp @@ -1385,9 +1385,7 @@ void Gv_InitWeaponPointers(void) if (!aplWeaponClip[i]) { - initprintf("ERROR: NULL weapon! WTF?! %s\n", aszBuf); - // Bexit(EXIT_SUCCESS); - G_Shutdown(); + I_FatalError("ERROR: NULL weapon! WTF?! %s\n", aszBuf); } Bsprintf(aszBuf, "WEAPON%d_RELOAD", i); diff --git a/source/platform/win32/i_main.cpp b/source/platform/win32/i_main.cpp index 7597b68ba..aeb1dcf1c 100644 --- a/source/platform/win32/i_main.cpp +++ b/source/platform/win32/i_main.cpp @@ -1172,7 +1172,8 @@ int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE nothing, LPWSTR cmdline, int _CrtSetDbgFlag (_CrtSetDbgFlag(0) | _CRTDBG_LEAK_CHECK_DF); // Use this to break at a specific allocation number. - //_crtBreakAlloc = 10563; + +// _crtBreakAlloc = 257481; #endif int ret = DoMain (hInstance); diff --git a/source/rr/src/duke3d.h b/source/rr/src/duke3d.h index 64339250f..b71040bc9 100644 --- a/source/rr/src/duke3d.h +++ b/source/rr/src/duke3d.h @@ -148,6 +148,7 @@ static inline int32_t G_DefaultActorHealth(int spriteNum) struct GameInterface : ::GameInterface { int app_main() override; + void FreeGameData() override; bool validate_hud(int) override; void set_hud_layout(int size) override; void set_hud_scale(int size) override; diff --git a/source/rr/src/game.cpp b/source/rr/src/game.cpp index 2744d0b56..47dcbba3a 100644 --- a/source/rr/src/game.cpp +++ b/source/rr/src/game.cpp @@ -367,11 +367,6 @@ void G_GameExit(const char *msg) G_DisplayExtraScreens(); } - if (*msg != 0) initprintf("%s\n",msg); - - if (in3dmode()) - G_Shutdown(); - if (*msg != 0) { if (!(msg[0] == ' ' && msg[1] == 0)) @@ -6732,6 +6727,7 @@ static void G_Cleanup(void) if (label != (char *)&sprite[0]) Bfree(label); if (labelcode != (int32_t *)§or[0]) Bfree(labelcode); + if (labeltype != (int32_t*)&wall[0]) Bfree(labeltype); Bfree(apScript); Bfree(bitptr); @@ -6743,21 +6739,6 @@ static void G_Cleanup(void) hash_free(&h_dukeanim); } -/* -=================== -= -= ShutDown -= -=================== -*/ - -void G_Shutdown(void) -{ - G_SetFog(0); - engineUnInit(); - G_Cleanup(); -} - /* =================== = @@ -7933,6 +7914,13 @@ void A_SpawnRandomGlass(int spriteNum, int wallNum, int glassCnt) } } +void GameInterface::FreeGameData() +{ + G_SetFog(0); + engineUnInit(); + G_Cleanup(); +} + ::GameInterface* CreateInterface() { return new GameInterface; diff --git a/source/sw/src/border.cpp b/source/sw/src/border.cpp index e6ea9db38..e1d982cf5 100644 --- a/source/sw/src/border.cpp +++ b/source/sw/src/border.cpp @@ -180,7 +180,7 @@ void ClearStartMost(void) for (i = 0; i < xdim; i++) startdmost[i] = ydim; - memset(startumost, 0, xdim * sizeof(int16_t)); + memset(startumost.Data(), 0, xdim * sizeof(int16_t)); } void diff --git a/source/sw/src/game.h b/source/sw/src/game.h index c28f98132..b0ad3e303 100644 --- a/source/sw/src/game.h +++ b/source/sw/src/game.h @@ -2423,7 +2423,7 @@ void LoadSaveMsg(const char *msg); struct GameInterface : ::GameInterface { int app_main() override; - bool validate_hud(int) override; + bool validate_hud(int) override; void set_hud_layout(int size) override; void set_hud_scale(int size) override; void DrawNativeMenuText(int fontnum, int state, double xpos, double ypos, float fontscale, const char* text, int flags) override;