diff --git a/src/d_main.cpp b/src/d_main.cpp index d320ecb78..8dde75335 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -90,8 +90,8 @@ #define ASSET_HASH_TEXTURES_KART 0xb4211b2f32b6a291 #define ASSET_HASH_CHARS_KART 0x1e68a3e01aa5c68b #define ASSET_HASH_MAPS_KART 0x38558ed00da41ce9 -#define ASSET_HASH_MAIN_PK3 0x3d5cb0195efa4f84 -#define ASSET_HASH_MAPPATCH_PK3 0xefe28bb9de73a31c +#define ASSET_HASH_MAIN_PK3 0xeaa452402eb0fcc9 +#define ASSET_HASH_MAPPATCH_PK3 0xb15b03c61e08d93b #define ASSET_HASH_BONUSCHARS_KART 0x60e6f13d822a7461 #ifdef USE_PATCH_FILE #define ASSET_HASH_PATCH_PK3 0x0000000000000000 diff --git a/src/doomdef.h b/src/doomdef.h index 8355f8528..02a2bfd1e 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -475,6 +475,12 @@ UINT32 quickncasehash (const char *p, size_t n) #endif #endif +// the GNU cleanup attribute: plugging memory leaks since 2003! +// on scope exit, the cleanup function is called with a pointer to the declared variable, +// essentially behaving like a C++ destructor +// NOTE: you WILL have nasal troubles if the variable is not initialized +#define CLEANUP(f) __attribute__((__cleanup__(f))) + // An assert-type mechanism. // NOTE: USE SRB2_ASSERT FOR C++ CODE INSTEAD #ifdef PARANOIA diff --git a/src/g_demo.c b/src/g_demo.c index 9e4ddb426..791efa19c 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -649,7 +649,7 @@ static UINT8 *G_ReadRawExtraData(extradata_t *extra, UINT8 *dp, UINT16 version) } // parses a demo header from the given byte pointer -// remember to call G_FreeDemoHeader! (unless an error occurs) +// remember to call G_FreeDemoHeader! static headerstatus_e G_ReadDemoHeader(UINT8 *dp, demoheader_t *header) { UINT8 *startdp = dp; @@ -3184,13 +3184,11 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) I_Assert(bufsize != 0); // read demo header - demoheader_t header; + CLEANUP(G_FreeDemoHeader) demoheader_t header; headerstatus_e status = G_ReadDemoHeader(buffer, &header); (void)status; - I_Assert(status == HEADER_OK); - I_Assert(header.version == VERSION); - I_Assert(header.subversion == SUBVERSION); - I_Assert(header.demoversion == DEMOVERSION); + I_Assert(status == HEADER_OK && header.version == VERSION + && header.subversion == SUBVERSION && header.demoversion == DEMOVERSION); Z_Free(buffer); @@ -3206,8 +3204,6 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) else newlap = UINT32_MAX; - G_FreeDemoHeader(&header); - // load old file FIL_DefaultExtension(oldname, ".lmp"); if (!FIL_ReadFile(oldname, &buffer)) @@ -3217,7 +3213,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) } // read demo header - demoheader_t oldheader; + CLEANUP(G_FreeDemoHeader) demoheader_t oldheader; if (G_ReadDemoHeader(buffer, &oldheader) != HEADER_OK) { CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname); @@ -3230,7 +3226,6 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) if (!(oldheader.demoflags & aflags)) { CONS_Alert(CONS_NOTICE, M_GetText("File '%s' not from same game mode. It will be overwritten.\n"), oldname); - G_FreeDemoHeader(&oldheader); return UINT8_MAX; } @@ -3240,8 +3235,6 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) else oldlap = 0; - G_FreeDemoHeader(&oldheader); - c = 0; if (uselaps) @@ -3264,20 +3257,20 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) void G_LoadDemoInfo(menudemo_t *pdemo) { - UINT8 *infobuffer, *extrainfo_p; + CLEANUP(Z_Pfree) UINT8 *infobuffer = NULL; + const UINT8 *extrainfo_p; if (!FIL_ReadFile(pdemo->filepath, &infobuffer)) { CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), pdemo->filepath); pdemo->type = MD_INVALID; sprintf(pdemo->title, "INVALID REPLAY"); - return; } pdemo->type = MD_LOADED; - demoheader_t header; + CLEANUP(G_FreeDemoHeader) demoheader_t header; switch (G_ReadDemoHeader(infobuffer, &header)) { case HEADER_OK: @@ -3287,21 +3280,18 @@ void G_LoadDemoInfo(menudemo_t *pdemo) CONS_Alert(CONS_ERROR, M_GetText("%s is not a SRB2Kart replay file.\n"), pdemo->filepath); pdemo->type = MD_INVALID; sprintf(pdemo->title, "INVALID REPLAY"); - Z_Free(infobuffer); return; case HEADER_BADVERSION: CONS_Alert(CONS_ERROR, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemo->filepath); pdemo->type = MD_INVALID; sprintf(pdemo->title, "INVALID REPLAY"); - Z_Free(infobuffer); return; case HEADER_BADFORMAT: CONS_Alert(CONS_ERROR, M_GetText("%s is the wrong type of recording and cannot be played.\n"), pdemo->filepath); pdemo->type = MD_INVALID; sprintf(pdemo->title, "INVALID REPLAY"); - Z_Free(infobuffer); return; } @@ -3316,7 +3306,6 @@ void G_LoadDemoInfo(menudemo_t *pdemo) if (!(header.demoflags & DF_MULTIPLAYER)) { CONS_Alert(CONS_ERROR, M_GetText("%s is not a multiplayer replay and can't be listed on this menu fully yet.\n"), pdemo->filepath); - Z_Free(infobuffer); return; } @@ -3389,10 +3378,6 @@ void G_LoadDemoInfo(menudemo_t *pdemo) if (count >= MAXPLAYERS) break; //@TODO still cycle through the rest of these if extra demo data is ever used } - - // I think that's everything we need? - Z_Free(infobuffer); - G_FreeDemoHeader(&header); } // @@ -3415,7 +3400,8 @@ void G_DoPlayDemo(char *defdemoname) { UINT16 i, j; lumpnum_t l; - char *n,*pdemoname; + CLEANUP(Z_Pfree) char *pdemoname = NULL; + const char *n; char msg[1024]; UINT8 pnum; @@ -3513,12 +3499,21 @@ void G_DoPlayDemo(char *defdemoname) } } + goto wemadeit; // :face_holding_back_tears: + +lumperror: + CONS_Alert(CONS_ERROR, "%s", msg); + demo.playback = false; + demo.title = false; + if (!CON_Ready()) // In the console they'll just see the notice there! No point pulling them out. + M_StartMessage(msg, NULL, MM_NOTHING); + +wemadeit: // read demo header demo.playback = true; demo.buffer = &demobuf; - demoheader_t header; - + CLEANUP(G_FreeDemoHeader) demoheader_t header; switch (G_ReadDemoHeader(demobuf.p, &header)) { case HEADER_OK: @@ -3527,15 +3522,15 @@ void G_DoPlayDemo(char *defdemoname) case HEADER_BADMAGIC: snprintf(msg, 1024, M_GetText("%s is not a SRB2Kart replay file.\n"), pdemoname); - goto headererror; + goto error; case HEADER_BADVERSION: snprintf(msg, 1024, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemoname); - goto headererror; + goto error; case HEADER_BADFORMAT: snprintf(msg, 1024, M_GetText("%s is the wrong type of recording and cannot be played.\n"), pdemoname); - goto headererror; + goto error; } demo.version = header.demoversion; @@ -3662,8 +3657,6 @@ void G_DoPlayDemo(char *defdemoname) // Load "mapmusrng" used for altmusic selection mapmusrng = header.mapmusrng; - Z_Free(pdemoname); - memset(&oldcmd,0,sizeof(oldcmd)); memset(&oldghost,0,sizeof(oldghost)); memset(&ghostext,0,sizeof(ghostext)); @@ -3811,16 +3804,11 @@ void G_DoPlayDemo(char *defdemoname) } demo.deferstart = true; - G_FreeDemoHeader(&header); return; error: - G_FreeDemoHeader(&header); -headererror: P_SaveBufferFree(&demobuf); -lumperror: CONS_Alert(CONS_ERROR, "%s", msg); - Z_Free(pdemoname); demo.playback = false; demo.title = false; if (!CON_Ready()) // In the console they'll just see the notice there! No point pulling them out. @@ -3839,11 +3827,12 @@ void G_AddGhost(char *defdemoname) { INT32 i; lumpnum_t l; - char *n,*pdemoname; + CLEANUP(Z_Pfree) char *pdemoname = NULL; + const char *n; UINT64 demohash; demoghost *gh; UINT8 flags; - UINT8 *buffer; + CLEANUP(Z_Pfree) UINT8 *buffer = NULL; mapthing_t *mthing; skin_t *ghskin = &skins[0]; @@ -3862,7 +3851,6 @@ void G_AddGhost(char *defdemoname) if (!FIL_ReadFileTag(defdemoname, &buffer, PU_LEVEL)) { CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), defdemoname); - Z_Free(pdemoname); return; } } @@ -3870,13 +3858,12 @@ void G_AddGhost(char *defdemoname) else if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR) { CONS_Alert(CONS_ERROR, M_GetText("Failed to read lump '%s'.\n"), defdemoname); - Z_Free(pdemoname); return; } else // it's an internal demo buffer = W_CacheLumpNum(l, PU_LEVEL); - demoheader_t header; + CLEANUP(G_FreeDemoHeader) demoheader_t header; switch (G_ReadDemoHeader(buffer, &header)) { case HEADER_OK: @@ -3884,20 +3871,14 @@ void G_AddGhost(char *defdemoname) case HEADER_BADMAGIC: CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Not a SRB2 replay.\n"), pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); return; case HEADER_BADVERSION: CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo version incompatible.\n"), pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); return; case HEADER_BADFORMAT: CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo format unacceptable.\n"), pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); return; } @@ -3907,9 +3888,6 @@ void G_AddGhost(char *defdemoname) if (demohash == gh->checksum) // another ghost in the game already has this checksum? { // Don't add another one, then! CONS_Debug(DBG_SETUP, "Rejecting duplicate ghost %s (hash was matched)\n", pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); - G_FreeDemoHeader(&header); return; } @@ -3918,27 +3896,18 @@ void G_AddGhost(char *defdemoname) if (!(flags & DF_GHOST)) { CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: No ghost data in this demo.\n"), pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); - G_FreeDemoHeader(&header); return; } if (flags & DF_LUAVARS) // can't be arsed to add support for grinding away ported lua material { CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Replay data contains luavars, cannot continue.\n"), pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); - G_FreeDemoHeader(&header); return; } if (header.empty) { CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Replay is empty.\n"), pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); - G_FreeDemoHeader(&header); return; } @@ -3948,9 +3917,6 @@ void G_AddGhost(char *defdemoname) if ((plr->flags & (DEMO_SPECTATOR|DEMO_BOT)) != 0) { CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot (spectator/bot)\n"), defdemoname); - Z_Free(pdemoname); - Z_Free(buffer); - G_FreeDemoHeader(&header); return; } @@ -3974,6 +3940,7 @@ void G_AddGhost(char *defdemoname) gh->buffer = buffer; gh->checksum = demohash; gh->p = buffer + header.endofs; + buffer = NULL; // buffer can't be freed now! ghosts = gh; @@ -4028,8 +3995,6 @@ void G_AddGhost(char *defdemoname) gh->oldmo.color = gh->mo->color; CONS_Printf(M_GetText("Added ghost %s from %s\n"), plr->name, pdemoname); - G_FreeDemoHeader(&header); - Z_Free(pdemoname); } // Clean up all ghosts @@ -4047,26 +4012,21 @@ void G_FreeGhosts(void) // A simplified version of G_AddGhost... void G_UpdateStaffGhostName(lumpnum_t l) { - UINT8 *buffer = W_CacheLumpNum(l, PU_CACHE); + CLEANUP(Z_Pfree) UINT8 *buffer = W_CacheLumpNum(l, PU_CACHE); - demoheader_t header; + CLEANUP(G_FreeDemoHeader) demoheader_t header; if (G_ReadDemoHeader(buffer, &header) != HEADER_OK) - goto fail; + return; if (!(header.demoflags & DF_GHOST)) - goto fail; // we don't NEED to do it here, but whatever + return; // we don't NEED to do it here, but whatever if (header.numplayers == 0 || header.playerdata[0].playernum != 0) - goto fail; + return; if (header.playerdata[0].flags & (DEMO_SPECTATOR|DEMO_BOT)) - goto fail; - strcpy(dummystaffname, header.playerdata[0].name); + return; - // Ok, no longer any reason to care, bye -fail: - G_FreeDemoHeader(&header); - Z_Free(buffer); - return; + strcpy(dummystaffname, header.playerdata[0].name); } // diff --git a/src/s_sound.c b/src/s_sound.c index c3189a790..7582ec07d 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -2514,24 +2514,6 @@ void S_ResumeAudio(void) S_AdjustMusicStackTics(); } -void S_DisableSound(void) -{ - if (sound_started && !sound_disabled) - { - sound_disabled = true; - S_StopSounds(); - } -} - -void S_EnableSound(void) -{ - if (sound_started && sound_disabled) - { - sound_disabled = false; - S_InitSfxChannels(cv_soundvolume.value); - } -} - void S_SetMusicVolume(INT32 digvolume) { if (digvolume < 0) @@ -2924,13 +2906,8 @@ static void PlaySoundIfUnfocused_OnChange(void) if (!cv_gamesounds.value) return; - if (window_notinfocus) - { - if (cv_playsoundifunfocused.value) - S_DisableSound(); - else - S_EnableSound(); - } + if (window_notinfocus && cv_playsoundifunfocused.value) + S_StopSounds(); } #ifdef HAVE_OPENMPT diff --git a/src/sdl/i_video.cpp b/src/sdl/i_video.cpp index e3dde4add..0b9f678b9 100644 --- a/src/sdl/i_video.cpp +++ b/src/sdl/i_video.cpp @@ -622,14 +622,13 @@ static void Impl_SetFocused(boolean focused) if (! cv_playmusicifunfocused.value) I_SetMusicVolume(0); if (! cv_playsoundifunfocused.value) - S_DisableSound(); + S_StopSounds(); memset(gamekeydown, 0, NUMKEYS); // TODO this is a scary memset } - else if (!paused) + else { S_InitMusicVolume(); - S_EnableSound(); } } diff --git a/src/y_inter.c b/src/y_inter.c index c16feb7ae..c79af403e 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -992,7 +992,6 @@ static void Y_FollowIntermission(void) } #define UNLOAD(x) {if ((x) != NULL) {Patch_Free(x);} x = NULL;} -#define CLEANUP(x) x = NULL; // // Y_UnloadData diff --git a/src/z_zone.h b/src/z_zone.h index f7287795f..1876fa0be 100644 --- a/src/z_zone.h +++ b/src/z_zone.h @@ -147,6 +147,12 @@ char *Z_StrDup(const char *in); #define Z_Unlock(p) (void)p // TODO: remove this now that NDS code has been removed char *zva(INT32 tag, void *user, const char *format, ...); +// for use with CLEANUP macro +FUNCINLINE static ATTRINLINE void Z_Pfree(void *p) +{ + Z_Free(*(void **)p); +} + #ifdef __cplusplus } // extern "C" #endif