diff --git a/cgdoom/cgdoom-ui.c b/cgdoom/cgdoom-ui.c index cc48600..6cc64a6 100644 --- a/cgdoom/cgdoom-ui.c +++ b/cgdoom/cgdoom-ui.c @@ -392,7 +392,7 @@ int Layout_Event(Layout *l, int key) return 0; } -void UI_AdvancedOptions(CGDoom_Options *o) +static void UI_AdvancedOptions(CGDoom_Options *o) { Layout l; Layout_Init(&l); @@ -438,7 +438,7 @@ void UI_AdvancedOptions(CGDoom_Options *o) } } -void UI_Controls(CGDoom_Keymap map) +static void UI_Controls(CGDoom_Keymap map) { int focus_x=0, focus_y=-1; int dflt = 0; @@ -549,7 +549,41 @@ void UI_Controls(CGDoom_Keymap map) } } -int UI_Main(CGDoom_FileInfo *wads, int wad_count, CGDoom_Options *o, +static int UI_DemoSelection(CGDoom_FileInfo *demos, int demo_count) +{ + Layout l; + Layout_Init(&l); + + while(1) + { + Bdisp_AllClr_VRAM(); + Layout_StartFrame(&l); + Layout_CenteredText(&l, "Select a demo file"); + Layout_Spacing(&l, 10); + + for(int i = 0; i < demo_count; i++) + Layout_Text(&l, demos[i].name, "(%dk)", demos[i].size >> 10); + + Layout_EndFrame(&l); + Bdisp_PutDisp_DD(); + + int key; + GetKey(&key); + + if(Layout_Event(&l, key)) + {} + else if(key == KEY_CTRL_EXIT) + return -1; + else if(key == KEY_CTRL_EXE) { + return l.focus; + } + } +} + +CGDoom_FileInfo *UI_Main( + CGDoom_FileInfo *wads, int wad_count, + CGDoom_FileInfo *demos, int demo_count, + CGDoom_Options *o, int *startmap, int *startepisode, int *recorddemo, int allow_experimental_memory) { @@ -602,8 +636,12 @@ int UI_Main(CGDoom_FileInfo *wads, int wad_count, CGDoom_Options *o, if(allow_experimental_memory) Layout_Checkbox(&l, "Use experimental RAM:", &o->EnableExperimentalMemory); - int i_demo = Layout_Text(&l, "Record demo:", - (*recorddemo < 0) ? "None" : "DEMO%02d.lmp", *recorddemo); + int i_demo = Layout_Text(&l, "Record on demo slot:", + (*recorddemo < 0) ? "None >" : "< %d%s", *recorddemo, + (*recorddemo < 99) ? " >" : ""); + int i_replay = -1; + if(demo_count > 0) + i_replay = Layout_Text(&l, "Replay demo...", ""); int i_controls = Layout_Text(&l, "Customize controls...", ""); int i_advanced = Layout_Text(&l, "Advanced options...", ""); Layout_EndFrame(&l); @@ -626,6 +664,11 @@ int UI_Main(CGDoom_FileInfo *wads, int wad_count, CGDoom_Options *o, else if(key == KEY_CTRL_RIGHT && l.focus == i_title) title += (title < TS_FULL); /* Submenus */ + else if(key == KEY_CTRL_EXE && l.focus == i_replay) { + int n = UI_DemoSelection(demos, demo_count); + if(n >= 0) + return &demos[n]; + } else if(key == KEY_CTRL_EXE && l.focus == i_controls) { UI_Controls(o->Keymap); } @@ -641,7 +684,7 @@ int UI_Main(CGDoom_FileInfo *wads, int wad_count, CGDoom_Options *o, } /* Start game */ else if(key == KEY_CTRL_EXE && l.focus < wad_count) { - return l.focus; + return &wads[l.focus]; } if(*startmap < 1) @@ -653,7 +696,7 @@ int UI_Main(CGDoom_FileInfo *wads, int wad_count, CGDoom_Options *o, o->EnableDemos = (title == TS_FULL); } - return -1; + return NULL; } static int isspace_(int c) @@ -661,7 +704,7 @@ static int isspace_(int c) return (c == ' ' || c == '\t' || c == '\n'); } -void UI_Error(const char *fmt, va_list args) +void UI_Errorv(const char *fmt, va_list args) { char message[256], *str=message; vsnprintf(message, 256, fmt, args); @@ -715,6 +758,14 @@ void UI_Error(const char *fmt, va_list args) GetKey(&key); } +void UI_Error(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + UI_Errorv(fmt, args); + va_end(args); +} + void UI_DelayedWrites(CGDoom_DelayedFileWrite const *dfw, int count, int current_file, int current_file_done) { diff --git a/cgdoom/cgdoom-ui.h b/cgdoom/cgdoom-ui.h index 5d4e570..27e86c3 100644 --- a/cgdoom/cgdoom-ui.h +++ b/cgdoom/cgdoom-ui.h @@ -64,7 +64,9 @@ int Layout_Event(Layout *l, int key); /* Larger-scale functions. */ /* Show the program's main screen; returns index of selected WAD file. */ -int UI_Main(CGDoom_FileInfo *wads, int wad_count, +CGDoom_FileInfo *UI_Main( + CGDoom_FileInfo *wads, int wad_count, + CGDoom_FileInfo *demos, int demo_count, CGDoom_Options *options, int *startmap, /* Warp to this map (autostart only) */ int *startepisode, /* Warp to this episode (autostart only) */ @@ -73,7 +75,8 @@ int UI_Main(CGDoom_FileInfo *wads, int wad_count, ); /* Show an error with custom formatting. */ -void UI_Error(const char *fmt, va_list args); +void UI_Error(const char *fmt, ...); +void UI_Errorv(const char *fmt, va_list args); /* Show a file save with a progress bar. */ void UI_DelayedWrites(CGDoom_DelayedFileWrite const *dfw, int count, diff --git a/cgdoom/cgdoom.c b/cgdoom/cgdoom.c index 6a5119f..89ca496 100644 --- a/cgdoom/cgdoom.c +++ b/cgdoom/cgdoom.c @@ -128,7 +128,8 @@ int CGD_SingleEpisodeUltimate = 0; int CGD_2MBLineMemory = 0; int CGD_Frameskip = 1; const char *CGD_WADFileName = NULL; -const char *CGD_RecordDemoName = NULL; +int CGD_RecordDemoSlot = -1; +int CGD_PlayDemoOnly = 0; /* Delayed file accesses */ CGDoom_DelayedFileWrite CGD_DelayedSaves[CGD_DELAYEDSAVES_COUNT] = { 0 }; @@ -395,14 +396,14 @@ int Flash_ReadFile(void *buf, int size, int readpos) return iRet; } -/* Find WAD files in the filesystem. */ -int FindWADs(CGDoom_FileInfo *files, int max) +/* Find files in the filesystem based on a pattern. */ +static int FindFiles(const uint16_t *wildcard, CGDoom_FileInfo *files, int max) { uint16_t path[32]; Bfile_FileInfo info; int sd, rc, total=0; - rc = Bfile_FindFirst(u"\\\\fls0\\*.wad", &sd, path, &info); + rc = Bfile_FindFirst(wildcard, &sd, path, &info); while(rc != -16 && total < max) { @@ -628,8 +629,6 @@ int main(void) extern int startepisode; startmap = 1; startepisode = 1; - /* Don't record demos by default */ - int recorddemo = -1; //--- // Run main menu and apply settings @@ -637,12 +636,39 @@ int main(void) /* Look for WAD files at the root of the filesystem */ CGDoom_FileInfo wads[16]; - int wad_count = FindWADs(wads, 16); + int wad_count = FindFiles(u"\\\\fls0\\*.wad", wads, 16); - int choice = UI_Main(wads, wad_count, &CGD_Options, - &startmap, &startepisode, &recorddemo, allow_experimental_RAM); - if(choice < 0) - return 1; + /* Look for demo files to replay, also at the root */ + CGDoom_FileInfo demos[32]; + int demo_count = FindFiles(u"\\\\fls0\\*_demo*.lmp", demos, 32); + + CGDoom_FileInfo *selection = UI_Main(wads, wad_count, demos, demo_count, + &CGD_Options, &startmap, &startepisode, &CGD_RecordDemoSlot, + allow_experimental_RAM); + + int choice = -1; + if(selection >= demos && selection < demos + demo_count) { + /* Find the WAD file with the correct name */ + for(int i = 0; i < wad_count; i++) { + int len = strlen(wads[i].name) - 4; /* omit ".wad" */ + if(!strncmp(selection->name, wads[i].name, len) + && !strncmp(selection->name + len, "_demo", 5)) { + choice = i; + break; + } + } + if(choice == -1) { + UI_Error("The WAD file for %s has been removed or renamed!", + selection->name); + return 1; + } + G_DeferedPlayDemoFile(selection->name); + CGD_PlayDemoOnly = 1; + } + else if(selection >= wads && selection < wads + wad_count) { + choice = selection - wads; + } + else return 1; /* Override parameters unavailable on the SDL2 build */ #ifdef CG_EMULATOR @@ -766,13 +792,6 @@ int main(void) /* Initialize the PRAM allocator */ CGD_PRAM_Init(PRAM0_alloc_start, PRAM0_END); - /* Set up demo recording for this session */ - if(recorddemo >= 0) { - static char demoname[20]; - sprintf(demoname, "DEMO%02d", recorddemo); - CGD_RecordDemoName = demoname; - } - memset(VRAM, 0, WIDTH*HEIGHT*2); D_DoomMain(); diff --git a/cgdoom/cgdoom.h b/cgdoom/cgdoom.h index bd921db..812c795 100644 --- a/cgdoom/cgdoom.h +++ b/cgdoom/cgdoom.h @@ -103,8 +103,10 @@ extern int CGD_SingleEpisodeUltimate; extern int CGD_Frameskip; /* WAD file name (without .wad), used to name save and demo files */ extern const char *CGD_WADFileName; -/* Name of record demo file */ -extern const char *CGD_RecordDemoName; +/* Slot of demo file to record */ +extern int CGD_RecordDemoSlot; +/* Whether we're only playing a demo and leaving */ +extern int CGD_PlayDemoOnly; //--- // Control functions (mapped to special keys) diff --git a/cgdoom/d_main.c b/cgdoom/d_main.c index f3d1154..86bdb4e 100644 --- a/cgdoom/d_main.c +++ b/cgdoom/d_main.c @@ -557,10 +557,16 @@ void D_DoomMain() ST_Init (); printf ("Engage... \n"); - if (CGD_RecordDemoName) - G_RecordDemo(CGD_RecordDemoName); + if (CGD_RecordDemoSlot >= 0) { + static char filename[32]; + sprintf(filename, "%s_demo%02d", CGD_WADFileName, CGD_RecordDemoSlot); + G_RecordDemo(filename); + } - if (autostart) + /* CGDoom: Demo file was specified from main menu */ + if (gameaction == ga_playdemo) + {} + else if (autostart) G_DeferedInitNew (startskill, startepisode, startmap); else D_StartTitle (); diff --git a/cgdoom/g_game.c b/cgdoom/g_game.c index b65fa3e..9981b51 100644 --- a/cgdoom/g_game.c +++ b/cgdoom/g_game.c @@ -1296,8 +1296,8 @@ void G_RecordDemo (const char* name) usergame = false; strcpy (demoname, name); strcat (demoname, ".lmp"); - /* CGDoom: Maximum is 64 kiB instead of 128 kiB */ - maxsize = 0x10000; + /* CGDoom: Maximum is 64 kiB instead of 128 kiB to save RAM */ + maxsize = CGD_Options.EnableExperimentalMemory ? 0x20000 : 0x10000; demobuffer = Z_Malloc (maxsize,PU_STATIC,NULL); if (demobuffer) { @@ -1333,20 +1333,38 @@ void G_BeginRecording (void) // char* defdemoname; +char* defdemofilename; void G_DeferedPlayDemo (char* name) { defdemoname = name; + defdemofilename = NULL; gameaction = ga_playdemo; } +void G_DeferedPlayDemoFile (char* name) +{ + defdemoname = NULL; + defdemofilename = name; + gameaction = ga_playdemo; +} + void G_DoPlayDemo (void) { skill_t skill; int i, episode, map; gameaction = ga_nothing; - demobuffer = demo_p = (byte *)W_CacheLumpNameConst (defdemoname, PU_STATIC); + if (defdemoname) + { + demobuffer = demo_p = (byte *)W_CacheLumpNameConst(defdemoname, PU_STATIC); + } + else if (defdemofilename) + { + demobuffer = NULL; + M_ReadFile(defdemofilename, &demobuffer, 1); + demo_p = demobuffer; + } /* CGDoom: We have old WADs with demos at versions 108 and 109. The decoding work similarly, it's probably enemy position/AI that mess up */ @@ -1422,6 +1440,12 @@ boolean G_CheckDemoStatus (void) if (demoplayback) { + if(CGD_PlayDemoOnly) + { + fuck = true; + return true; + } + Z_ChangeTag (demobuffer, PU_CACHE); demoplayback = false; netdemo = false; diff --git a/cgdoom/g_game.h b/cgdoom/g_game.h index d9daff2..c87b1e7 100644 --- a/cgdoom/g_game.h +++ b/cgdoom/g_game.h @@ -41,6 +41,7 @@ void G_InitNew (skill_t skill, int episode, int map); void G_DeferedInitNew (skill_t skill, int episode, int map); void G_DeferedPlayDemo (char* demo); +void G_DeferedPlayDemoFile (char* file); // Can be called by the startup code or M_Responder, // calls P_SetupLevel or W_EnterWorld. diff --git a/cgdoom/i_system.c b/cgdoom/i_system.c index 9426aee..86bf113 100644 --- a/cgdoom/i_system.c +++ b/cgdoom/i_system.c @@ -205,7 +205,7 @@ void I_Error (const char *error, ...) G_CheckDemoStatus(); I_ShutdownGraphics(); - UI_Error(error, args); + UI_Errorv(error, args); I_ReinitAfterError(); va_end(args);