diff --git a/source/common/utility/files.h b/source/common/utility/files.h index 92d6eccc3..8cf17bfd8 100644 --- a/source/common/utility/files.h +++ b/source/common/utility/files.h @@ -325,6 +325,11 @@ public: virtual long Tell(); virtual long Seek(long offset, int mode); size_t Printf(const char *fmt, ...) GCCPRINTF(2,3); + void Close() + { + if (File != NULL) fclose(File); + File = nullptr; + } protected: @@ -343,6 +348,7 @@ public: BufferWriter() {} virtual size_t Write(const void *buffer, size_t len) override; TArray *GetBuffer() { return &mBuffer; } + TArray&& TakeBuffer() { return std::move(mBuffer); } }; #endif diff --git a/source/duke3d/src/demo.cpp b/source/duke3d/src/demo.cpp index 37045ef45..82ce7a1d7 100644 --- a/source/duke3d/src/demo.cpp +++ b/source/duke3d/src/demo.cpp @@ -38,7 +38,7 @@ BEGIN_DUKE_NS char g_firstDemoFile[BMAX_PATH]; -buildvfs_FILE g_demo_filePtr{}; // write +FileWriter *g_demo_filePtr{}; // write FileReader g_demo_recFilePtr; // read int32_t g_demo_cnt; @@ -163,23 +163,24 @@ void G_OpenDemoWrite(void) demonum++; - g_demo_filePtr = buildvfs_fopen_read(demofn); + g_demo_filePtr = FileWriter::Open(demofn); if (g_demo_filePtr == NULL) break; - MAYBE_FCLOSE_AND_NULL(g_demo_filePtr); + delete g_demo_filePtr; } while (1); - g_demo_filePtr = buildvfs_fopen_write(demofn); + g_demo_filePtr = FileWriter::Open(demofn); if (g_demo_filePtr == NULL) return; - i=sv_saveandmakesnapshot(g_demo_filePtr, nullptr, -1, demorec_diffs_cvar, demorec_diffcompress_cvar, + i=sv_saveandmakesnapshot(*g_demo_filePtr, nullptr, -1, demorec_diffs_cvar, demorec_diffcompress_cvar, (demorec_seeds_cvar<<1)); if (i) { - MAYBE_FCLOSE_AND_NULL(g_demo_filePtr); + delete g_demo_filePtr; + g_demo_filePtr = nullptr; error_wopen_demo: Bstrcpy(apStrings[QUOTE_RESERVED4], "FAILED STARTING DEMO RECORDING. SEE CONSOLE FOR DETAILS."); P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps); @@ -232,13 +233,13 @@ static void Demo_WriteSync() { int16_t tmpreccnt; - buildvfs_fwrite("sYnC", 4, 1, g_demo_filePtr); + g_demo_filePtr->Write("sYnC", 4); tmpreccnt = (int16_t)ud.reccnt; - buildvfs_fwrite(&tmpreccnt, sizeof(int16_t), 1, g_demo_filePtr); + g_demo_filePtr->Write(&tmpreccnt, sizeof(int16_t)); if (demorec_seeds) - buildvfs_fwrite(g_demo_seedbuf, 1, ud.reccnt, g_demo_filePtr); + g_demo_filePtr->Write(g_demo_seedbuf, ud.reccnt); - buildvfs_fwrite(recsync, sizeof(input_t), ud.reccnt, g_demo_filePtr); + g_demo_filePtr->Write(recsync, sizeof(input_t)* ud.reccnt); ud.reccnt = 0; } @@ -275,16 +276,17 @@ void G_CloseDemoWrite(void) if (ud.reccnt > 0) Demo_WriteSync(); - buildvfs_fwrite("EnD!", 4, 1, g_demo_filePtr); + g_demo_filePtr->Write("EnD!", 4); // lastly, we need to write the number of written recsyncs to the demo file - if (buildvfs_fseek_abs(g_demo_filePtr, offsetof(savehead_t, reccnt))) - perror("G_CloseDemoWrite: final fseek"); + if (g_demo_filePtr->Write(g_demo_filePtr, offsetof(savehead_t, reccnt))) + Printf("G_CloseDemoWrite: final fseek\n"); else - buildvfs_fwrite(&g_demo_cnt, sizeof(g_demo_cnt), 1, g_demo_filePtr); + g_demo_filePtr->Write(&g_demo_cnt, sizeof(g_demo_cnt)); ud.recstat = ud.m_recstat = 0; - MAYBE_FCLOSE_AND_NULL(g_demo_filePtr); + delete g_demo_filePtr; + g_demo_filePtr = nullptr; sv_freemem(); diff --git a/source/duke3d/src/demo.h b/source/duke3d/src/demo.h index 95d73570a..8e9c2b3ad 100644 --- a/source/duke3d/src/demo.h +++ b/source/duke3d/src/demo.h @@ -32,7 +32,7 @@ BEGIN_DUKE_NS #define DEMOFN_FMT "edemo%03d.edm" #define MAXDEMOS 1000 -extern buildvfs_FILE g_demo_filePtr; +extern FileWriter * g_demo_filePtr; extern char g_firstDemoFile[BMAX_PATH]; extern int32_t g_demo_cnt; diff --git a/source/duke3d/src/game.cpp b/source/duke3d/src/game.cpp index ea2b3892b..ef0730eb4 100644 --- a/source/duke3d/src/game.cpp +++ b/source/duke3d/src/game.cpp @@ -261,8 +261,11 @@ void G_GameExit(const char *msg) if (ud.recstat == 1) G_CloseDemoWrite(); - else if (ud.recstat == 2) - MAYBE_FCLOSE_AND_NULL(g_demo_filePtr); + else if (ud.recstat == 2) + { + delete g_demo_filePtr; + g_demo_filePtr = nullptr; + } // JBF: fixes crash on demo playback // PK: modified from original diff --git a/source/duke3d/src/gamevars.cpp b/source/duke3d/src/gamevars.cpp index 92f773388..75f05f97b 100644 --- a/source/duke3d/src/gamevars.cpp +++ b/source/duke3d/src/gamevars.cpp @@ -236,34 +236,34 @@ corrupt: } // Note that this entire function is totally architecture dependent and needs to be fixed (which won't be easy...) -void Gv_WriteSave(buildvfs_FILE fil) +void Gv_WriteSave(FileWriter &fil) { // AddLog("Saving Game Vars to File"); - buildvfs_fwrite("BEG: EDuke32", 12, 1, fil); + fil.Write("BEG: EDuke32", 12); - buildvfs_fwrite(&g_gameVarCount,sizeof(g_gameVarCount),1,fil); + fil.Write(&g_gameVarCount,sizeof(g_gameVarCount)); for (bssize_t i = 0; i < g_gameVarCount; i++) { - buildvfs_fwrite(&(aGameVars[i]), sizeof(gamevar_t), 1, fil); - buildvfs_fwrite(aGameVars[i].szLabel, sizeof(uint8_t) * MAXVARLABEL, 1, fil); + fil.Write(&(aGameVars[i]), sizeof(gamevar_t)); + fil.Write(aGameVars[i].szLabel, sizeof(uint8_t) * MAXVARLABEL); if (aGameVars[i].flags & GAMEVAR_PERPLAYER) - buildvfs_fwrite(aGameVars[i].pValues, sizeof(intptr_t) * MAXPLAYERS, 1, fil); + fil.Write(aGameVars[i].pValues, sizeof(intptr_t) * MAXPLAYERS); else if (aGameVars[i].flags & GAMEVAR_PERACTOR) - buildvfs_fwrite(aGameVars[i].pValues, sizeof(intptr_t) * MAXSPRITES, 1, fil); + fil.Write(aGameVars[i].pValues, sizeof(intptr_t) * MAXSPRITES); } - buildvfs_fwrite(&g_gameArrayCount,sizeof(g_gameArrayCount),1,fil); + fil.Write(&g_gameArrayCount,sizeof(g_gameArrayCount)); for (bssize_t i = 0; i < g_gameArrayCount; i++) { // write for .size and .dwFlags (the rest are pointers): - buildvfs_fwrite(&aGameArrays[i], sizeof(gamearray_t), 1, fil); - buildvfs_fwrite(aGameArrays[i].szLabel, sizeof(uint8_t) * MAXARRAYLABEL, 1, fil); + fil.Write(&aGameArrays[i], sizeof(gamearray_t)); + fil.Write(aGameArrays[i].szLabel, sizeof(uint8_t) * MAXARRAYLABEL); if ((aGameArrays[i].flags & GAMEARRAY_SYSTEM) != GAMEARRAY_SYSTEM) - buildvfs_fwrite(aGameArrays[i].pValues, Gv_GetArrayAllocSize(i), 1, fil); + fil.Write(aGameArrays[i].pValues, Gv_GetArrayAllocSize(i)); } uint8_t savedstate[MAXVOLUMES * MAXLEVELS]; @@ -273,7 +273,7 @@ void Gv_WriteSave(buildvfs_FILE fil) if (g_mapInfo[i].savedstate != NULL) savedstate[i] = 1; - buildvfs_fwrite(savedstate, sizeof(savedstate), 1, fil); + fil.Write(savedstate, sizeof(savedstate)); for (bssize_t i = 0; i < (MAXVOLUMES * MAXLEVELS); i++) { @@ -281,27 +281,27 @@ void Gv_WriteSave(buildvfs_FILE fil) mapstate_t &sv = *g_mapInfo[i].savedstate; - buildvfs_fwrite(g_mapInfo[i].savedstate, sizeof(mapstate_t), 1, fil); + fil.Write(g_mapInfo[i].savedstate, sizeof(mapstate_t)); for (bssize_t j = 0; j < g_gameVarCount; j++) { if (aGameVars[j].flags & GAMEVAR_NORESET) continue; if (aGameVars[j].flags & GAMEVAR_PERPLAYER) - buildvfs_fwrite(sv.vars[j], sizeof(intptr_t) * MAXPLAYERS, 1, fil); + fil.Write(sv.vars[j], sizeof(intptr_t) * MAXPLAYERS); else if (aGameVars[j].flags & GAMEVAR_PERACTOR) - buildvfs_fwrite(sv.vars[j], sizeof(intptr_t) * MAXSPRITES, 1, fil); + fil.Write(sv.vars[j], sizeof(intptr_t) * MAXSPRITES); } - buildvfs_fwrite(sv.arraysiz, sizeof(sv.arraysiz), 1, fil); + fil.Write(sv.arraysiz, sizeof(sv.arraysiz)); for (bssize_t j = 0; j < g_gameArrayCount; j++) if (aGameArrays[j].flags & GAMEARRAY_RESTORE) { - buildvfs_fwrite(sv.arrays[j], Gv_GetArrayAllocSizeForCount(j, sv.arraysiz[j]), 1, fil); + fil.Write(sv.arrays[j], Gv_GetArrayAllocSizeForCount(j, sv.arraysiz[j])); } } - buildvfs_fwrite("EOF: EDuke32", 12, 1, fil); + fil.Write("EOF: EDuke32", 12); } void Gv_DumpValues(void) diff --git a/source/duke3d/src/gamevars.h b/source/duke3d/src/gamevars.h index 6a15a1799..42761cf83 100644 --- a/source/duke3d/src/gamevars.h +++ b/source/duke3d/src/gamevars.h @@ -159,7 +159,7 @@ void Gv_InitWeaponPointers(void); void Gv_RefreshPointers(void); void Gv_ResetVars(void); int Gv_ReadSave(FileReader &kFile); -void Gv_WriteSave(buildvfs_FILE fil); +void Gv_WriteSave(FileWriter &fil); void Gv_Clear(void); #else extern int32_t g_noResetVars; diff --git a/source/duke3d/src/savegame.cpp b/source/duke3d/src/savegame.cpp index 8a3876140..090447874 100644 --- a/source/duke3d/src/savegame.cpp +++ b/source/duke3d/src/savegame.cpp @@ -738,92 +738,75 @@ int32_t G_SavePlayer(savebrief_t & sv, bool isAutoSave) Net_WaitForServer(); ready2send = 0; - char fn[BMAX_PATH]; + FString fn; - errno = 0; - buildvfs_FILE fil; + errno = 0; + buildvfs_FILE fil; - if (sv.isValid()) - { - if (snprintf(fn, sizeof(fn), "%s%s", M_GetSavegamesPath().GetChars(), sv.path)) - { - OSD_Printf("G_SavePlayer: file name \"%s\" too long\n", sv.path); - goto saveproblem; - } - fil = buildvfs_fopen_write(fn); - } - else - { - static char const SaveName[] = "save0000.esv"; - int const len = snprintf(fn, ARRAY_SIZE(fn), "%s%s", M_GetSavegamesPath().GetChars(), SaveName); - if (len >= ARRAY_SSIZE(fn)-1) - { - OSD_Printf("G_SavePlayer: could not form automatic save path\n"); - goto saveproblem; - } - char * zeros = fn + (len-8); - fil = savecounter.opennextfile(fn, zeros); - savecounter.count++; - // don't copy the mod dir into sv.path - Bstrcpy(sv.path, fn + (len-(ARRAY_SIZE(SaveName)-1))); - } + if (sv.isValid()) + { + fn.Format("%s%s", M_GetSavegamesPath().GetChars(), sv.path); + fil = fopen(fn, "wb"); + } + else + { + static char const SaveName[] = "save0000.svz"; + fn.Format("%s%s", M_GetSavegamesPath().GetChars(), SaveName); - if (!fil) - { - OSD_Printf("G_SavePlayer: failed opening \"%s\" for writing: %s\n", - fn, strerror(errno)); - goto saveproblem; - } + auto fnp = fn.LockBuffer(); + char* zeros = fnp + (fn.Len() - 8); + fil = savecounter.opennextfile(fnp, zeros); + fn.UnlockBuffer(); + savecounter.count++; + // don't copy the mod dir into sv.path + Bstrcpy(sv.path, fn + (fn.Len() - (ARRAY_SIZE(SaveName) - 1))); + } - sv.isExt = 0; + FileWriter fw(fil); + if (!fil) + { + OSD_Printf("G_SavePlayer: failed opening \"%s\" for writing: %s\n", + fn, strerror(errno)); + ready2send = 1; + Net_WaitForServer(); - // temporary hack - ud.user_map = G_HaveUserMap(); + G_RestoreTimers(); + ototalclock = totalclock; + return -1; + } + else + { + sv.isExt = 0; -#ifdef POLYMER - if (videoGetRenderMode() == REND_POLYMER) - polymer_resetlights(); -#endif + // temporary hack + ud.user_map = G_HaveUserMap(); - VM_OnEvent(EVENT_SAVEGAME, g_player[myconnectindex].ps->i, myconnectindex); + VM_OnEvent(EVENT_SAVEGAME, g_player[myconnectindex].ps->i, myconnectindex); - portableBackupSave(sv.path, sv.name, ud.last_stateless_volume, ud.last_stateless_level); + portableBackupSave(sv.path, sv.name, ud.last_stateless_volume, ud.last_stateless_level); - // SAVE! - sv_saveandmakesnapshot(fil, sv.name, 0, 0, 0, 0, isAutoSave); + // SAVE! + sv_saveandmakesnapshot(fw, sv.name, 0, 0, 0, 0, isAutoSave); - buildvfs_fclose(fil); + fw.Close(); - if (!g_netServer && ud.multimode < 2) - { - OSD_Printf("Saved: %s\n", fn); -#ifdef LUNATIC - if (!g_savedOK) - Bstrcpy(apStrings[QUOTE_RESERVED4], "^10Failed Saving Game"); - else -#endif - Bstrcpy(apStrings[QUOTE_RESERVED4], "Game Saved"); - P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps); - } + if (!g_netServer && ud.multimode < 2) + { + OSD_Printf("Saved: %s\n", fn); + strcpy(apStrings[QUOTE_RESERVED4], "Game Saved"); + P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps); + } - ready2send = 1; - Net_WaitForServer(); + ready2send = 1; + Net_WaitForServer(); - G_RestoreTimers(); - ototalclock = totalclock; + G_RestoreTimers(); + ototalclock = totalclock; - VM_OnEvent(EVENT_POSTSAVEGAME, g_player[myconnectindex].ps->i, myconnectindex); + VM_OnEvent(EVENT_POSTSAVEGAME, g_player[myconnectindex].ps->i, myconnectindex); - return 0; - -saveproblem: - ready2send = 1; - Net_WaitForServer(); - - G_RestoreTimers(); - ototalclock = totalclock; - - return -1; + return 0; + } } int32_t G_LoadPlayerMaybeMulti(savebrief_t & sv) @@ -917,7 +900,7 @@ static inline void ds_get(const dataspec_t *spec, void **ptr, int32_t *cnt) } // write state to file and/or to dump -static uint8_t *writespecdata(const dataspec_t *spec, buildvfs_FILE fil, uint8_t *dump) +static uint8_t *writespecdata(const dataspec_t *spec, FileWriter *fil, uint8_t *dump) { for (; spec->flags != DS_END; spec++) { @@ -932,7 +915,7 @@ static uint8_t *writespecdata(const dataspec_t *spec, buildvfs_FILE fil, uint8_t continue; else if (spec->flags & DS_STRING) { - buildvfs_fwrite(spec->ptr, Bstrlen((const char *)spec->ptr), 1, fil); // not null-terminated! + fil->Write(spec->ptr, Bstrlen((const char *)spec->ptr)); // not null-terminated! continue; } @@ -952,7 +935,7 @@ static uint8_t *writespecdata(const dataspec_t *spec, buildvfs_FILE fil, uint8_t if (fil) { - buildvfs_fwrite(ptr, spec->size, cnt, fil); + fil->Write(ptr, spec->size * cnt); } if (dump && (spec->flags & (DS_NOCHK|DS_CMP)) == 0) @@ -1522,10 +1505,8 @@ static const dataspec_t svgm_anmisc[] = { DS_END, 0, 0, 0 } }; -#if !defined LUNATIC static dataspec_gv_t *svgm_vars=NULL; -#endif -static uint8_t *dosaveplayer2(buildvfs_FILE fil, uint8_t *mem); +static uint8_t *dosaveplayer2(FileWriter &fil, uint8_t *mem); static int32_t doloadplayer2(FileReader &fil, uint8_t **memptr); static void postloadplayer(int32_t savegamep); @@ -1629,7 +1610,7 @@ static void SV_AllocSnap(int32_t allocinit) } // make snapshot only if spot < 0 (demo) -int32_t sv_saveandmakesnapshot(buildvfs_FILE fil, char const *name, int8_t spot, int8_t recdiffsp, int8_t diffcompress, int8_t synccompress, bool isAutoSave) +int32_t sv_saveandmakesnapshot(FileWriter &fil, char const *name, int8_t spot, int8_t recdiffsp, int8_t diffcompress, int8_t synccompress, bool isAutoSave) { savehead_t h; @@ -1699,24 +1680,24 @@ int32_t sv_saveandmakesnapshot(buildvfs_FILE fil, char const *name, int8_t spot, // write header - buildvfs_fwrite(&h, sizeof(savehead_t), 1, fil); + fil.Write(&h, sizeof(savehead_t)); // for savegames, the file offset after the screenshot goes here; // for demos, we keep it 0 to signify that we didn't save one - buildvfs_fwrite("\0\0\0\0", 4, 1, fil); if (spot >= 0 && tileData(TILE_SAVESHOT)) { - int32_t ofs; - + + int v = 64000; + fil.Write(&v, 4); // write the screenshot compressed - buildvfs_fwrite(tileData(TILE_SAVESHOT), 320, 200, fil); + fil.Write(tileData(TILE_SAVESHOT), 320*200); - // write the current file offset right after the header - ofs = buildvfs_ftell(fil); - buildvfs_fseek_abs(fil, sizeof(savehead_t)); - buildvfs_fwrite(&ofs, 4, 1, fil); - buildvfs_fseek_abs(fil, ofs); } + else + { + int v = 64000; + fil.Write(&v, 4); + } if (spot >= 0) @@ -1883,7 +1864,7 @@ int32_t sv_loadsnapshot(FileReader &fil, int32_t spot, savehead_t *h) } -uint32_t sv_writediff(buildvfs_FILE fil) +uint32_t sv_writediff(FileWriter *fil) { uint8_t *p = svsnapshot; uint8_t *d = svdiff; @@ -1901,10 +1882,10 @@ uint32_t sv_writediff(buildvfs_FILE fil) uint32_t const diffsiz = d - svdiff; - buildvfs_fwrite("dIfF",4,1,fil); - buildvfs_fwrite(&diffsiz, sizeof(diffsiz), 1, fil); + fil->Write("dIfF",4); + fil->Write(&diffsiz, sizeof(diffsiz)); - buildvfs_fwrite(svdiff, 1, diffsiz, fil); + fil->Write(svdiff, diffsiz); return diffsiz; } @@ -2168,19 +2149,19 @@ static void sv_restload() LUNATIC_CB const char *(*El_SerializeGamevars)(int32_t *slenptr, int32_t levelnum); #endif -static uint8_t *dosaveplayer2(buildvfs_FILE fil, uint8_t *mem) +static uint8_t *dosaveplayer2(FileWriter &fil, uint8_t *mem) { #ifdef DEBUGGINGAIDS uint8_t *tmem = mem; int32_t t=timerGetTicks(); #endif - mem=writespecdata(svgm_udnetw, fil, mem); // user settings, players & net + mem=writespecdata(svgm_udnetw, &fil, mem); // user settings, players & net PRINTSIZE("ud"); - mem=writespecdata(svgm_secwsp, fil, mem); // sector, wall, sprite + mem=writespecdata(svgm_secwsp, &fil, mem); // sector, wall, sprite PRINTSIZE("sws"); - mem=writespecdata(svgm_script, fil, mem); // script + mem=writespecdata(svgm_script, &fil, mem); // script PRINTSIZE("script"); - mem=writespecdata(svgm_anmisc, fil, mem); // animates, quotes & misc. + mem=writespecdata(svgm_anmisc, &fil, mem); // animates, quotes & misc. PRINTSIZE("animisc"); #if !defined LUNATIC diff --git a/source/duke3d/src/savegame.h b/source/duke3d/src/savegame.h index 4f5133572..165a38c0d 100644 --- a/source/duke3d/src/savegame.h +++ b/source/duke3d/src/savegame.h @@ -121,10 +121,10 @@ extern uint16_t g_nummenusaves; int32_t sv_updatestate(int32_t frominit); int32_t sv_readdiff(FileReader& fil); -uint32_t sv_writediff(buildvfs_FILE fil); +uint32_t sv_writediff(FileWriter *fil); int32_t sv_loadheader(FileReader &fil, int32_t spot, savehead_t *h); int32_t sv_loadsnapshot(FileReader &fil, int32_t spot, savehead_t *h); -int32_t sv_saveandmakesnapshot(buildvfs_FILE fil, char const *name, int8_t spot, int8_t recdiffsp, int8_t diffcompress, int8_t synccompress, bool isAutoSave = false); +int32_t sv_saveandmakesnapshot(FileWriter &fil, char const *name, int8_t spot, int8_t recdiffsp, int8_t diffcompress, int8_t synccompress, bool isAutoSave = false); void sv_freemem(); void G_DeleteSave(savebrief_t const & sv); void G_DeleteOldSaves(void);