diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 07c756d53..7efe8cf6f 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1141,29 +1141,26 @@ static boolean SV_ResendingSavegameToAnyone(void) static void SV_SendSaveGame(INT32 node, boolean resending) { size_t length, compressedlen; - savebuffer_t save; + savebuffer_t save = {0}; UINT8 *compressedsave; UINT8 *buffertosend; // first save it in a malloced buffer - save.size = NETSAVEGAMESIZE; - save.buffer = (UINT8 *)malloc(save.size); - if (!save.buffer) + if (P_SaveBufferAlloc(&save, NETSAVEGAMESIZE) == false) { CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); return; } // Leave room for the uncompressed length. - save.p = save.buffer + sizeof(UINT32); - save.end = save.buffer + save.size; + save.p += sizeof(UINT32); P_SaveNetGame(&save, resending); length = save.p - save.buffer; if (length > NETSAVEGAMESIZE) { - free(save.buffer); + P_SaveBufferFree(&save); I_Error("Savegame buffer overrun"); } @@ -1180,7 +1177,7 @@ static void SV_SendSaveGame(INT32 node, boolean resending) if ((compressedlen = lzf_compress(save.buffer + sizeof(UINT32), length - sizeof(UINT32), compressedsave + sizeof(UINT32), length - sizeof(UINT32) - 1))) { // Compressing succeeded; send compressed data - free(save.buffer); + P_SaveBufferFree(&save); // State that we're compressed. buffertosend = compressedsave; @@ -1211,7 +1208,7 @@ static consvar_t cv_dumpconsistency = CVAR_INIT ("dumpconsistency", "Off", CV_SA static void SV_SavedGame(void) { size_t length; - savebuffer_t save; + savebuffer_t save = {0}; char tmpsave[256]; if (!cv_dumpconsistency.value) @@ -1220,22 +1217,18 @@ static void SV_SavedGame(void) sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); // first save it in a malloced buffer - save.size = NETSAVEGAMESIZE; - save.p = save.buffer = (UINT8 *)malloc(save.size); - if (!save.p) + if (P_SaveBufferAlloc(&save, NETSAVEGAMESIZE) == false) { CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); return; } - save.end = save.buffer + save.size; - P_SaveNetGame(&save, false); length = save.p - save.buffer; if (length > NETSAVEGAMESIZE) { - free(save.buffer); + P_SaveBufferFree(&save); I_Error("Savegame buffer overrun"); } @@ -1243,7 +1236,7 @@ static void SV_SavedGame(void) if (!FIL_WriteFile(tmpsave, save.buffer, length)) CONS_Printf(M_GetText("Didn't save %s for netgame"), tmpsave); - free(save.buffer); + P_SaveBufferFree(&save); } #undef TMPSAVENAME @@ -1253,37 +1246,31 @@ static void SV_SavedGame(void) static void CL_LoadReceivedSavegame(boolean reloading) { - savebuffer_t save; + savebuffer_t save = {0}; size_t length, decompressedlen; char tmpsave[256]; sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); - length = FIL_ReadFile(tmpsave, &save.buffer); - - CONS_Printf(M_GetText("Loading savegame length %s\n"), sizeu1(length)); - if (!length) + if (P_SaveBufferFromFile(&save, tmpsave) == false) { I_Error("Can't read savegame sent"); return; } - save.p = save.buffer; - save.size = length; - save.end = save.buffer + save.size; + length = save.size; + CONS_Printf(M_GetText("Loading savegame length %s\n"), sizeu1(length)); // Decompress saved game if necessary. decompressedlen = READUINT32(save.p); - if(decompressedlen > 0) + if (decompressedlen > 0) { UINT8 *decompressedbuffer = Z_Malloc(decompressedlen, PU_STATIC, NULL); lzf_decompress(save.p, length - sizeof(UINT32), decompressedbuffer, decompressedlen); - Z_Free(save.buffer); - save.p = save.buffer = decompressedbuffer; - save.size = decompressedlen; - save.end = save.buffer + decompressedlen; + P_SaveBufferFree(&save); + P_SaveBufferFromExisting(&save, decompressedbuffer, decompressedlen); } paused = false; @@ -1315,10 +1302,13 @@ static void CL_LoadReceivedSavegame(boolean reloading) } // done - Z_Free(save.buffer); - save.p = NULL; + P_SaveBufferFree(&save); + if (unlink(tmpsave) == -1) + { CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), tmpsave); + } + consistancy[gametic%BACKUPTICS] = Consistancy(); CON_ToggleOff(); @@ -6067,7 +6057,7 @@ void CL_ClearRewinds(void) rewind_t *CL_SaveRewindPoint(size_t demopos) { - savebuffer_t save; + savebuffer_t save = {0}; rewind_t *rewind; if (rewindhead && rewindhead->leveltime + REWIND_POINT_INTERVAL > leveltime) @@ -6077,10 +6067,7 @@ rewind_t *CL_SaveRewindPoint(size_t demopos) if (!rewind) return NULL; - save.buffer = save.p = rewind->savebuffer; - save.size = NETSAVEGAMESIZE; - save.end = save.buffer + save.size; - + P_SaveBufferFromExisting(&save, rewind->savebuffer, NETSAVEGAMESIZE); P_SaveNetGame(&save, false); rewind->leveltime = leveltime; @@ -6093,7 +6080,7 @@ rewind_t *CL_SaveRewindPoint(size_t demopos) rewind_t *CL_RewindToTime(tic_t time) { - savebuffer_t save; + savebuffer_t save = {0}; rewind_t *rewind; while (rewindhead && rewindhead->leveltime > time) @@ -6106,10 +6093,7 @@ rewind_t *CL_RewindToTime(tic_t time) if (!rewindhead) return NULL; - save.buffer = save.p = rewindhead->savebuffer; - save.size = NETSAVEGAMESIZE; - save.end = save.buffer + save.size; - + P_SaveBufferFromExisting(&save, rewindhead->savebuffer, NETSAVEGAMESIZE); P_LoadNetGame(&save, false); wipegamestate = gamestate; // No fading back in! diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 975c165ad..61b737ce9 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -5778,7 +5778,7 @@ static void Command_Togglemodified_f(void) static void Command_Archivetest_f(void) { - savebuffer_t save; + savebuffer_t save = {0}; UINT32 i, wrote; thinker_t *th; if (gamestate != GS_LEVEL) @@ -5794,9 +5794,11 @@ static void Command_Archivetest_f(void) ((mobj_t *)th)->mobjnum = i++; // allocate buffer - save.size = 1024; - save.buffer = save.p = ZZ_Alloc(save.size); - save.end = save.buffer + save.size; + if (P_SaveBufferAlloc(&save, 1024) == false) + { + CONS_Printf("Unable to allocate buffer.\n"); + return; + } // test archive CONS_Printf("LUA_Archive...\n"); @@ -5814,10 +5816,12 @@ static void Command_Archivetest_f(void) LUA_UnArchive(&save, true); i = READUINT8(save.p); if (i != 0x7F || wrote != (UINT32)(save.p - save.buffer)) + { CONS_Printf("Savegame corrupted. (write %u, read %u)\n", wrote, (UINT32)(save.p - save.buffer)); + } // free buffer - Z_Free(save.buffer); + P_SaveBufferFree(&save); CONS_Printf("Done. No crash.\n"); } #endif diff --git a/src/g_demo.c b/src/g_demo.c index 579d786f5..5e39d83fc 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -70,7 +70,7 @@ boolean noblit; // for comparative timing purposes tic_t demostarttime; // for comparative timing purposes static char demoname[MAX_WADPATH]; -static savebuffer_t demobuf; +static savebuffer_t demobuf = {0}; static UINT8 *demotime_p, *demoinfo_p; static UINT8 demoflags; boolean demosynced = true; // console warning message @@ -2019,10 +2019,8 @@ void G_RecordDemo(const char *name) // if (demobuf.buffer) // P_SaveBufferFree(&demobuf); - demobuf.size = maxsize; - demobuf.buffer = (UINT8 *)malloc(maxsize); + P_SaveBufferAlloc(&demobuf, maxsize); demobuf.p = NULL; - demobuf.end = demobuf.buffer + demobuf.size; demo.recording = true; } @@ -2034,10 +2032,8 @@ void G_RecordMetal(void) if (M_CheckParm("-maxdemo") && M_IsNextParm()) maxsize = atoi(M_GetNextParm()) * 1024; - demobuf.size = maxsize; - demobuf.buffer = (UINT8 *)malloc(maxsize); + P_SaveBufferAlloc(&demobuf, maxsize); demobuf.p = NULL; - demobuf.end = demobuf.buffer + demobuf.size; metalrecording = true; } @@ -2982,7 +2978,7 @@ void G_DoPlayDemo(char *defdemoname) if (FIL_CheckExtension(defdemoname)) { //FIL_DefaultExtension(defdemoname, ".lmp"); - if (!FIL_ReadFile(defdemoname, &demobuf.buffer)) + if (P_SaveBufferFromFile(&demobuf, defdemoname) == false) { snprintf(msg, 1024, M_GetText("Failed to read file '%s'.\n"), defdemoname); CONS_Alert(CONS_ERROR, "%s", msg); @@ -2990,20 +2986,20 @@ void G_DoPlayDemo(char *defdemoname) M_StartMessage(msg, NULL, MM_NOTHING); return; } - demobuf.p = demobuf.buffer; } // load demo resource from WAD - else if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR) + else { - snprintf(msg, 1024, M_GetText("Failed to read lump '%s'.\n"), defdemoname); - CONS_Alert(CONS_ERROR, "%s", msg); - gameaction = ga_nothing; - M_StartMessage(msg, NULL, MM_NOTHING); - return; - } - else // it's an internal demo - { - demobuf.buffer = demobuf.p = W_CacheLumpNum(l, PU_STATIC); + if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR) + { + snprintf(msg, 1024, M_GetText("Failed to read lump '%s'.\n"), defdemoname); + CONS_Alert(CONS_ERROR, "%s", msg); + gameaction = ga_nothing; + M_StartMessage(msg, NULL, MM_NOTHING); + return; + } + + P_SaveBufferFromLump(&demobuf, l); #if defined(SKIPERRORS) && !defined(DEVELOP) skiperrors = true; // SRB2Kart: Don't print warnings for staff ghosts, since they'll inevitably happen when we make bugfixes/changes... #endif @@ -3945,7 +3941,7 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill) WriteDemoChecksum(); saved = FIL_WriteFile(va("%sMS.LMP", G_BuildMapName(gamemap)), demobuf.buffer, demobuf.p - demobuf.buffer); // finally output the file. } - free(demobuf.buffer); + Z_Free(demobuf.buffer); metalrecording = false; if (saved) I_Error("Saved to %sMS.LMP", G_BuildMapName(gamemap)); @@ -4165,7 +4161,7 @@ void G_SaveDemo(void) if (FIL_WriteFile(demoname, demobuf.buffer, demobuf.p - demobuf.buffer)) // finally output the file. demo.savemode = DSM_SAVED; - free(demobuf.buffer); + Z_Free(demobuf.buffer); demo.recording = false; if (!modeattacking) diff --git a/src/g_game.c b/src/g_game.c index da3a58986..3c11de495 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4303,12 +4303,11 @@ void G_LoadGameSettings(void) // Loads the main data file, which stores information such as emblems found, etc. void G_LoadGameData(void) { - size_t length; UINT32 i, j; UINT32 versionID; UINT8 versionMinor; UINT8 rtemp; - savebuffer_t save; + savebuffer_t save = {0}; //For records UINT32 numgamedatamapheaders; @@ -4337,16 +4336,13 @@ void G_LoadGameData(void) return; } - length = FIL_ReadFile(va(pandf, srb2home, gamedatafilename), &save.buffer); - if (!length) + if (P_SaveBufferFromFile(&save, va(pandf, srb2home, gamedatafilename)) == false) { // No gamedata. We can save a new one. gamedata->loaded = true; return; } - save.p = save.buffer; - // Version check versionID = READUINT32(save.p); if (versionID != GD_VERSIONCHECK) @@ -4355,16 +4351,14 @@ void G_LoadGameData(void) if (strcmp(srb2home,".")) gdfolder = srb2home; - Z_Free(save.buffer); - save.p = NULL; + P_SaveBufferFree(&save); I_Error("Game data is not for Ring Racers v2.0.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder); } versionMinor = READUINT8(save.p); if (versionMinor > GD_VERSIONMINOR) { - Z_Free(save.buffer); - save.p = NULL; + P_SaveBufferFree(&save); I_Error("Game data is from the future! (expected %d, got %d)", GD_VERSIONMINOR, versionMinor); } @@ -4475,8 +4469,7 @@ void G_LoadGameData(void) } // done - Z_Free(save.buffer); - save.p = NULL; + P_SaveBufferFree(&save); // Don't consider loaded until it's a success! // It used to do this much earlier, but this would cause the gamedata to @@ -4496,8 +4489,7 @@ void G_LoadGameData(void) if (strcmp(srb2home,".")) gdfolder = srb2home; - Z_Free(save.buffer); - save.p = NULL; + P_SaveBufferFree(&save); I_Error("Corrupt game data file.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder); } @@ -4510,7 +4502,7 @@ void G_SaveGameData(void) size_t length; INT32 i, j; UINT8 btemp; - savebuffer_t save; + savebuffer_t save = {0}; if (!gamedata->loaded) return; // If never loaded (-nodata), don't save @@ -4530,14 +4522,11 @@ void G_SaveGameData(void) } length += nummapheaders * (MAXMAPLUMPNAME+1+4+4); - save.size = length; - save.p = save.buffer = (UINT8 *)malloc(save.size); - if (!save.p) + if (P_SaveBufferAlloc(&save, length) == false) { CONS_Alert(CONS_ERROR, M_GetText("No more free memory for saving game data\n")); return; } - save.end = save.buffer + save.size; // Version test @@ -4624,7 +4613,7 @@ void G_SaveGameData(void) length = save.p - save.buffer; FIL_WriteFile(va(pandf, srb2home, gamedatafilename), save.buffer, length); - free(save.buffer); + P_SaveBufferFree(&save); // Also save profiles here. PR_SaveProfiles(); @@ -4638,10 +4627,9 @@ void G_SaveGameData(void) // void G_LoadGame(UINT32 slot, INT16 mapoverride) { - size_t length; char vcheck[VERSIONSIZE]; char savename[255]; - savebuffer_t save; + savebuffer_t save = {0}; // memset savedata to all 0, fixes calling perfectly valid saves corrupt because of bots memset(&savedata, 0, sizeof(savedata)); @@ -4656,17 +4644,12 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) else sprintf(savename, savegamename, slot); - length = FIL_ReadFile(savename, &save.buffer); - if (!length) + if (P_SaveBufferFromFile(&save, savename) == false) { CONS_Printf(M_GetText("Couldn't read file %s\n"), savename); return; } - save.p = save.buffer; - save.size = length; - save.end = save.buffer + save.size; - memset(vcheck, 0, sizeof (vcheck)); sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION); if (strcmp((const char *)save.p, (const char *)vcheck)) @@ -4679,7 +4662,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) M_ClearMenus(true); // so ESC backs out to title M_StartMessage(M_GetText("Save game from different version\n\nPress ESC\n"), NULL, MM_NOTHING); Command_ExitGame_f(); - Z_Free(save.buffer); + P_SaveBufferFree(&save); // no cheating! memset(&savedata, 0, sizeof(savedata)); @@ -4714,7 +4697,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) } // done - Z_Free(save.buffer); + P_SaveBufferFree(&save); // gameaction = ga_nothing; // G_SetGamestate(GS_LEVEL); @@ -4740,7 +4723,7 @@ void G_SaveGame(UINT32 slot, INT16 mapnum) boolean saved; char savename[256] = ""; const char *backup; - savebuffer_t save; + savebuffer_t save = {0}; if (marathonmode) strcpy(savename, liveeventbackup); @@ -4753,14 +4736,11 @@ void G_SaveGame(UINT32 slot, INT16 mapnum) char name[VERSIONSIZE]; size_t length; - save.size = SAVEGAMESIZE; - save.p = save.buffer = (UINT8 *)malloc(save.size); - if (!save.p) + if (P_SaveBufferAlloc(&save, SAVEGAMESIZE) == false) { CONS_Alert(CONS_ERROR, M_GetText("No more free memory for saving game data\n")); return; } - save.end = save.buffer + save.size; memset(name, 0, sizeof (name)); sprintf(name, (marathonmode ? "back-up %d" : "version %d"), VERSION); @@ -4778,7 +4758,7 @@ void G_SaveGame(UINT32 slot, INT16 mapnum) length = save.p - save.buffer; saved = FIL_WriteFile(backup, save.buffer, length); - free(save.buffer); + P_SaveBufferFree(&save); } gameaction = ga_nothing; @@ -4798,7 +4778,7 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives) char vcheck[VERSIONSIZE]; char savename[255]; const char *backup; - savebuffer_t save; + savebuffer_t save = {0}; if (marathonmode) strcpy(savename, liveeventbackup); @@ -4806,22 +4786,19 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives) sprintf(savename, savegamename, slot); backup = va("%s",savename); - length = FIL_ReadFile(savename, &save.buffer); - if (!length) + if (P_SaveBufferFromFile(&save, savename) == false) { CONS_Printf(M_GetText("Couldn't read file %s\n"), savename); return; } + length = save.size; + { char temp[sizeof(timeattackfolder)]; UINT8 *lives_p; SINT8 pllives; - save.p = save.buffer; - save.size = length; - save.end = save.buffer + save.size; - // Version check memset(vcheck, 0, sizeof (vcheck)); sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION); @@ -4892,9 +4869,8 @@ cleanup: CONS_Printf(M_GetText("Game saved.\n")); else if (!saved) CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, slot, (marathonmode ? liveeventbackup : savegamename)); - Z_Free(save.buffer); - save.p = save.buffer = NULL; + P_SaveBufferFree(&save); } #undef CHECKPOS #undef BADSAVE diff --git a/src/k_profiles.c b/src/k_profiles.c index 1163b1f8d..313dc84f8 100644 --- a/src/k_profiles.c +++ b/src/k_profiles.c @@ -217,16 +217,13 @@ void PR_SaveProfiles(void) size_t length = 0; const size_t headerlen = strlen(PROFILEHEADER); UINT8 i, j, k; - savebuffer_t save; + savebuffer_t save = {0}; - save.size = sizeof(UINT32) + (numprofiles * sizeof(profile_t)); - save.p = save.buffer = (UINT8 *)malloc(save.size); - if (!save.p) + if (P_SaveBufferAlloc(&save, sizeof(UINT32) + (numprofiles * sizeof(profile_t))) == false) { I_Error("No more free memory for saving profiles\n"); return; } - save.end = save.buffer + save.size; // Add header. WRITESTRINGN(save.p, PROFILEHEADER, headerlen); @@ -278,7 +275,6 @@ void PR_SaveProfiles(void) void PR_LoadProfiles(void) { - size_t length = 0; const size_t headerlen = strlen(PROFILEHEADER); UINT8 i, j, k, version; profile_t *dprofile = PR_MakeProfile( @@ -289,18 +285,15 @@ void PR_LoadProfiles(void) gamecontroldefault, true ); - savebuffer_t save; + savebuffer_t save = {0}; - length = FIL_ReadFile(va(pandf, srb2home, PROFILESFILE), &save.buffer); - if (!length) + if (P_SaveBufferFromFile(&save, va(pandf, srb2home, PROFILESFILE)) == false) { // No profiles. Add the default one. PR_AddProfile(dprofile); return; } - save.p = save.buffer; - if (strncmp(PROFILEHEADER, (const char *)save.buffer, headerlen)) { const char *gdfolder = "the Ring Racers folder"; diff --git a/src/p_saveg.c b/src/p_saveg.c index 562616b63..946e77faa 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -5226,3 +5226,92 @@ boolean P_LoadNetGame(savebuffer_t *save, boolean reloading) return P_UnArchiveLuabanksAndConsistency(save); } + +boolean P_SaveBufferZAlloc(savebuffer_t *save, size_t alloc_size, INT32 tag, void *user) +{ + I_Assert(save->buffer == NULL); + save->buffer = (UINT8 *)Z_Malloc(alloc_size, tag, user); + + if (save->buffer == NULL) + { + return false; + } + + save->size = alloc_size; + save->p = save->buffer; + save->end = save->buffer + save->size; + + return true; +} + +boolean P_SaveBufferFromExisting(savebuffer_t *save, UINT8 *existing_buffer, size_t existing_size) +{ + I_Assert(save->buffer == NULL); + + if (existing_buffer == NULL || existing_size == 0) + { + return false; + } + + save->buffer = existing_buffer; + save->size = existing_size; + + save->p = save->buffer; + save->end = save->buffer + save->size; + + return true; +} + +boolean P_SaveBufferFromLump(savebuffer_t *save, lumpnum_t lump) +{ + I_Assert(save->buffer == NULL); + + if (lump == LUMPERROR) + { + return false; + } + + save->buffer = (UINT8 *)W_CacheLumpNum(lump, PU_STATIC); + + if (save->buffer == NULL) + { + return false; + } + + save->size = W_LumpLength(lump); + + save->p = save->buffer; + save->end = save->buffer + save->size; + + return true; +} + +boolean P_SaveBufferFromFile(savebuffer_t *save, char const *name) +{ + size_t len = 0; + + I_Assert(save->buffer == NULL); + len = FIL_ReadFile(name, &save->buffer); + + if (len != 0) + { + save->size = len; + + save->p = save->buffer; + save->end = save->buffer + save->size; + } + + return len; +} + +static void P_SaveBufferInvalidate(savebuffer_t *save) +{ + save->buffer = save->p = save->end = NULL; + save->size = 0; +} + +void P_SaveBufferFree(savebuffer_t *save) +{ + Z_Free(save->buffer); + P_SaveBufferInvalidate(save); +} diff --git a/src/p_saveg.h b/src/p_saveg.h index a0b0f8587..66ba58b00 100644 --- a/src/p_saveg.h +++ b/src/p_saveg.h @@ -57,6 +57,13 @@ struct savebuffer_t size_t size; }; +boolean P_SaveBufferZAlloc(savebuffer_t *save, size_t alloc_size, INT32 tag, void *user); +#define P_SaveBufferAlloc(a,b) P_SaveBufferZAlloc(a, b, PU_STATIC, NULL) +boolean P_SaveBufferFromExisting(savebuffer_t *save, UINT8 *existing_buffer, size_t existing_size); +boolean P_SaveBufferFromLump(savebuffer_t *save, lumpnum_t lump); +boolean P_SaveBufferFromFile(savebuffer_t *save, char const *name); +void P_SaveBufferFree(savebuffer_t *save); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/p_setup.c b/src/p_setup.c index e2e11a613..407f9f42f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -722,20 +722,15 @@ void P_WriteThings(void) const char * filename; size_t i, length; mapthing_t *mt; - savebuffer_t save; + savebuffer_t save = {0}; INT16 temp; - save.size = nummapthings * sizeof (mapthing_t); - save.p = save.buffer = (UINT8 *)malloc(nummapthings * sizeof (mapthing_t)); - - if (!save.p) + if (P_SaveBufferAlloc(&save, nummapthings * sizeof (mapthing_t)) == false) { CONS_Alert(CONS_ERROR, M_GetText("No more free memory for thing writing!\n")); return; } - save.end = save.buffer + save.size; - mt = mapthings; for (i = 0; i < nummapthings; i++, mt++) {