diff --git a/cgdoom/cgdoom-ui.c b/cgdoom/cgdoom-ui.c index 1b77bf3..4474615 100644 --- a/cgdoom/cgdoom-ui.c +++ b/cgdoom/cgdoom-ui.c @@ -169,11 +169,11 @@ void UI_Checkbox(int x, int y, int checked) } } -void UI_FileMappingProgressBar(int size_mapped, int size_total) +void UI_ProgressBar(int y0, int current, int total) { const int w=192, h=5; - const int x0=(WIDTH-w)/2, y0=HEIGHT-10; - const int pos = x0 + (w * size_mapped) / size_total; + const int x0=(WIDTH-w)/2; + const int pos = x0 + (w * current) / total; for(int x = x0; x < x0+w; x++) { diff --git a/cgdoom/cgdoom-ui.h b/cgdoom/cgdoom-ui.h index 1244e92..a5f9c07 100644 --- a/cgdoom/cgdoom-ui.h +++ b/cgdoom/cgdoom-ui.h @@ -14,8 +14,8 @@ enum { UI_RIGHT = 2, }; -/* Show a progress bar of file mapping at the bottom of the screen. */ -void UI_FileMappingProgressBar(int size_mapped, int size_total); +/* Show a progress bar at the bottom of the screen. */ +void UI_ProgressBar(int y, int current, int total); /* Print text with a cleaner font. */ void UI_Print(int x, int y, int fg, int halign, char const *text, int length); diff --git a/cgdoom/cgdoom.c b/cgdoom/cgdoom.c index 926c552..b278ccd 100644 --- a/cgdoom/cgdoom.c +++ b/cgdoom/cgdoom.c @@ -3,7 +3,9 @@ #include "cgdoom.h" #include #include "libprof.h" + #include "doomtype.h" +#include "m_misc.h" #ifndef CG_EMULATOR # include "cgdoom-alloc.h" @@ -387,6 +389,9 @@ int CGD_2MBLineMemory = 0; int CGD_Frameskip = 1; const char *CGD_WADFileName = NULL; +/* Delayed file accesses */ +CGD_DelayedFileWrite CGD_DelayedSaves[6] = { 0 }; + /* Performance counters */ struct CGD_Perf CGD_Perf; /* Developer statistics */ @@ -499,7 +504,7 @@ int CreateFileMapping(int fd, FileMapping *pMap) { /* Don't show this too often, or it will eat several seconds */ if((pMap->miTotalLength - iLastProgress) * 20 > iFileSize) { - UI_FileMappingProgressBar(pMap->miTotalLength, iFileSize); + UI_ProgressBar(HEIGHT-10, pMap->miTotalLength, iFileSize); iLastProgress = pMap->miTotalLength; } @@ -732,7 +737,7 @@ int main(void) int fd = Bfile_OpenFile_OS(wads[choice].path, 0, 0); int size = CreateFileMapping(fd, &gWADMap); Bfile_CloseFile_OS(fd); - UI_FileMappingProgressBar(1, 1); + UI_ProgressBar(HEIGHT-10, 1, 1); ms_mmap = (RTC_GetTicks() - time) * 8; if(size == -1) { @@ -782,6 +787,14 @@ int main(void) if(gWADfd >= 0) Bfile_CloseFile_OS(gWADfd); + int delayed_writes = sizeof(CGD_DelayedSaves) / sizeof(CGD_DelayedSaves[0]); + for(int i = 0; i < delayed_writes; i++) { + CGD_DelayedFileWrite *dfw = &CGD_DelayedSaves[i]; + if(dfw->data != NULL) { + M_WriteFile(dfw->filename, dfw->data, dfw->size); + } + } + if(dev_info) { Layout l; Layout_Init(&l); diff --git a/cgdoom/cgdoom.h b/cgdoom/cgdoom.h index 3755501..ee99b49 100644 --- a/cgdoom/cgdoom.h +++ b/cgdoom/cgdoom.h @@ -19,6 +19,17 @@ typedef struct int size; } WADFileInfo; +/* Description of a file write that has been delated. */ +typedef struct +{ + char filename[32]; + const void *data; + int size; +} CGD_DelayedFileWrite; + +/* Delay file saves until exit to avoid quitting immediately */ +#define CGDOOM_DELAY_SAVES + /* CGDoom statistics */ extern struct CGD_Perf CGD_Perf; extern struct CGD_Stats CGD_Stats; @@ -32,13 +43,16 @@ extern int CGD_EnableDemos; extern int CGD_SingleEpisodeUltimate; /* Skip this amount of frames after every rendered frame (default 1) */ extern int CGD_Frameskip; -/* WAD file name (without .wad), used to avoid save file conflicts */ -extern const char *CGD_WADFileName; // Global variables interfacing with Doom itself. /* Map and episode to start at when loading the game. */ extern int startmap, startepisode; +/* WAD file name (without .wad), used to avoid save file conflicts */ +extern const char *CGD_WADFileName; +/* Save Game operations delayed until closing the add-in (one per save) */ +extern CGD_DelayedFileWrite CGD_DelayedSaves[6]; + // Keyboard interface. diff --git a/cgdoom/d_englsh.h b/cgdoom/d_englsh.h index 1bfc0b4..3649248 100644 --- a/cgdoom/d_englsh.h +++ b/cgdoom/d_englsh.h @@ -135,7 +135,7 @@ // // G_game.C // -#define GGSAVED "game saved." +#define GGSAVED "Game will save on exit" // // HU_stuff.C diff --git a/cgdoom/g_game.c b/cgdoom/g_game.c index 90d65a0..7abb1f1 100644 --- a/cgdoom/g_game.c +++ b/cgdoom/g_game.c @@ -88,7 +88,7 @@ void G_DoPlayDemo (void); void G_DoCompleted (void); void G_DoVictory (void); void G_DoWorldDone (void); -void G_DoSaveGame (void); +boolean G_DoSaveGame (void); gameaction_t gameaction; @@ -460,11 +460,13 @@ void G_Ticker (void) G_DoLoadGame (); break; case ga_savegame: - G_DoSaveGame (); /* After saving the game, the storage memory is shuffled, we need to leave and we need to do it quickly */ - I_Quit(); - return; + if (G_DoSaveGame ()) { + I_Quit(); + return; + } + break; case ga_playdemo: G_DoPlayDemo (); break; @@ -999,7 +1001,7 @@ void G_SaveGame( int slot, char* description ) sendsave = true; } -void G_DoSaveGame (void) +boolean G_DoSaveGame (void) { char name[50]; char name2[VERSIONSIZE]; @@ -1039,14 +1041,43 @@ void G_DoSaveGame (void) if (length > SAVEGAMESIZE) I_Error ("Savegame buffer overrun"); - M_WriteFile (name, savebuffer, length); + boolean save_now = false; + void *delayed_copy = NULL; + +#ifndef CGDOOM_DELAY_SAVES + save_now = true; +#endif + + /* Allocate memory to hold the data while delaying */ + if (!save_now) { + delayed_copy = Z_Malloc(length, PU_STATIC, 0); + if (delayed_copy == NULL) + save_now = true; + else + memcpy(delayed_copy, savebuffer, length); + } + + if (save_now) { + M_WriteFile (name, savebuffer, length); + } + else { + CGD_DelayedFileWrite *dfw = &CGD_DelayedSaves[savegameslot]; + if (dfw->data) + Z_Free(dfw->data); + + CGDstrcpy(dfw->filename, name); + dfw->data = delayed_copy; + dfw->size = length; + } gameaction = ga_nothing; savedescription[0] = 0; - static char msg[32]; + static char msg[40]; sprintf(msg, GGSAVED " (%d kB)", length >> 10); players[consoleplayer].message = msg; + + return save_now; } // diff --git a/cgdoom/m_misc.c b/cgdoom/m_misc.c index b5e0e36..8dbbf89 100644 --- a/cgdoom/m_misc.c +++ b/cgdoom/m_misc.c @@ -90,7 +90,7 @@ int M_DrawText ( int x, int y, boolean direct, char* string ) // // M_WriteFile // -boolean M_WriteFile(char const *name, void *source, int length) +boolean M_WriteFile(char const *name, const void *source, int length) { uint16_t fc_path[100] = u"\\\\fls0\\"; size_t size = length; diff --git a/cgdoom/m_misc.h b/cgdoom/m_misc.h index 2b4edee..20c7e91 100644 --- a/cgdoom/m_misc.h +++ b/cgdoom/m_misc.h @@ -29,7 +29,7 @@ // // MISC // -boolean M_WriteFile ( char const* name, void* source, int length ); +boolean M_WriteFile ( char const* name, const void* source, int length ); int M_ReadFile ( char const* name, byte** buffer );