diff --git a/src/d_event.h b/src/d_event.h index 1079ce39..63e67adb 100644 --- a/src/d_event.h +++ b/src/d_event.h @@ -119,6 +119,9 @@ typedef enum // Savegame slot numbers occupy the second byte of buttons. BTS_SAVEMASK = (4+8+16), BTS_SAVESHIFT = 2, + + // [crispy] demo joined. + BT_JOIN = 64 } buttoncode_t; diff --git a/src/d_main.c b/src/d_main.c index 00d03ac4..225a43b3 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -2648,7 +2648,8 @@ void D_DoomMain(void) if (autostart || netgame) { G_InitNew(startskill, startepisode, startmap); - if (demorecording) + // [crispy] no need to write a demo header in demo continue mode + if (demorecording && gameaction != ga_playdemo) G_BeginRecording(); } else diff --git a/src/g_game.c b/src/g_game.c index 3b5b7988..03a4aa6e 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -96,6 +96,7 @@ boolean paused; boolean sendpause; // send a pause event next tic boolean sendsave; // send a save event next tic boolean sendreload; // send a reload level event next tic +boolean sendjoin; boolean usergame; // ok to save / end game boolean timingdemo; // if true, exit with report on completion boolean fastdemo; // if true, run at full speed -- killough @@ -135,6 +136,9 @@ int default_complevel; boolean strictmode, default_strictmode; +// [crispy] store last cmd to track joins +static ticcmd_t* last_cmd = NULL; + // // controls (have defaults) // @@ -617,6 +621,12 @@ void G_BuildTiccmd(ticcmd_t* cmd) cmd->buttons = BT_SPECIAL | (BTS_RELOAD & BT_SPECIALMASK); } + if (sendjoin) + { + sendjoin = false; + cmd->buttons |= BT_JOIN; + } + // low-res turning if (lowres_turn) @@ -860,6 +870,12 @@ boolean G_Responder(event_t* ev) return true; } + if (M_InputActivated(input_demo_join)) + { + sendjoin = true; + return true; + } + // killough 10/98: // Don't pop up menu, if paused in middle // of demo playback, or if automap active. @@ -967,12 +983,41 @@ boolean G_Responder(event_t* ev) // [crispy] demo progress bar int defdemotics = 0, deftotaldemotics; +static char *defdemoname; + #define DEMOMARKER 0x80 +// Stay in the game, hand over controls to the player and continue recording the +// demo under a different name +static void G_JoinDemo(void) +{ + byte *actualbuffer = demobuffer; + int actualsize = maxdemosize; + + // [crispy] find a new name for the continued demo + G_RecordDemo(defdemoname); + + // [crispy] discard the newly allocated demo buffer + Z_Free(demobuffer); + demobuffer = actualbuffer; + maxdemosize = actualsize; + + // [crispy] continue recording + demoplayback = false; + + // clear progress demo bar + ST_Start(); + + doomprintf("Demo recording: %s", demoname); +} + static void G_ReadDemoTiccmd(ticcmd_t *cmd) { if (*demo_p == DEMOMARKER) + { + last_cmd = cmd; // [crispy] remember last cmd to track joins G_CheckDemoStatus(); // end of demo data stream + } else { cmd->forwardmove = ((signed char)*demo_p++); @@ -1002,12 +1047,21 @@ static void G_ReadDemoTiccmd(ticcmd_t *cmd) } } +static void CheckDemoBuffer(size_t size) +{ + ptrdiff_t position = demo_p - demobuffer; + if (position + size > maxdemosize) + { + maxdemosize += size + 128 * 1024; // add another 128K + demobuffer = Z_Realloc(demobuffer, maxdemosize, PU_STATIC, 0); + demo_p = position + demobuffer; + } +} + // Demo limits removed -- killough static void G_WriteDemoTiccmd(ticcmd_t* cmd) { - ptrdiff_t position = demo_p - demobuffer; - if (M_InputGameActive(input_demo_quit)) // press to end demo recording G_CheckDemoStatus(); @@ -1025,14 +1079,7 @@ static void G_WriteDemoTiccmd(ticcmd_t* cmd) demo_p[4] = cmd->buttons; } - if (position+16 > maxdemosize) // killough 8/23/98 - { - // no more space - maxdemosize += 128*1024; // add another 128K -- killough - demobuffer = Z_Realloc(demobuffer,maxdemosize, PU_STATIC, 0); - demo_p = position + demobuffer; // back on track - // end of main demo limit changes -- killough - } + CheckDemoBuffer(16); // killough 8/23/98 G_ReadDemoTiccmd (cmd); // make SURE it is exactly the same } @@ -1351,8 +1398,6 @@ static void G_DoWorldDone(void) #define MIN_MAXPLAYERS 32 -static char *defdemoname; - #define INVALID_DEMO(a, b) \ do \ { \ @@ -1375,6 +1420,13 @@ static void G_DoPlayDemo(void) if (gameaction != ga_loadgame) // killough 12/98: support -loadgame basetic = gametic; // killough 9/29/98 + // [crispy] in demo continue mode free the obsolete demo buffer + // of size 'maxdemosize' previously allocated in G_RecordDemo() + if (demorecording) + { + Z_Free(demobuffer); + } + ExtractFileBase(defdemoname,basename); // killough lumpnum = W_GetNumForName(basename); @@ -1583,6 +1635,8 @@ static void G_DoPlayDemo(void) gameaction = ga_nothing; + maxdemosize = lumplength; + // [crispy] demo progress bar { byte *demo_ptr = demo_p; @@ -2120,10 +2174,16 @@ void G_Ticker(void) memcpy(cmd, &netcmds[i], sizeof *cmd); + // catch BT_JOIN before G_ReadDemoTiccmd overwrites it + if (demoplayback && cmd->buttons & BT_JOIN) + G_JoinDemo(); + if (demoplayback) G_ReadDemoTiccmd(cmd); - if (demorecording) + // [crispy] do not record tics while still playing back in demo + // continue mode + if (demorecording && !demoplayback) G_WriteDemoTiccmd(cmd); // check for turbo cheats @@ -3130,7 +3190,11 @@ void G_RecordDemo(char *name) for(; j <= 99999 && !M_access(demoname, F_OK); ++j) { - M_snprintf(demoname, demoname_size, "%s-%05d.lmp", name, j); + char *str = M_StringDuplicate(name); + if (M_StringCaseEndsWith(str, ".lmp")) + str[strlen(str) - 4] = '\0'; + M_snprintf(demoname, demoname_size, "%s-%05d.lmp", str, j); + free(str); } //! @@ -3569,7 +3633,6 @@ extern char **dehfiles; static void G_AddDemoFooter(void) { - ptrdiff_t position = demo_p - demobuffer; char *tmp = NULL; size_t len = 0; int i; @@ -3636,12 +3699,7 @@ static void G_AddDemoFooter(void) mem_get_buf(stream, (void **)&tmp, &len); - if (position + len > maxdemosize) - { - maxdemosize += len; - demobuffer = Z_Realloc(demobuffer, maxdemosize, PU_STATIC, 0); - demo_p = position + demobuffer; - } + CheckDemoBuffer(len); memcpy(demo_p, tmp, len); demo_p += len; @@ -3659,6 +3717,44 @@ static void G_AddDemoFooter(void) boolean G_CheckDemoStatus(void) { + // [crispy] catch the last cmd to track joins + ticcmd_t* cmd = last_cmd; + last_cmd = NULL; + + if (demoplayback) + { + if (demorecording) + { + demoplayback = false; + + // clear progress demo bar + ST_Start(); + + // [crispy] record demo join + if (cmd != NULL) + { + cmd->buttons |= BT_JOIN; + } + + return true; + } + + if (singledemo) + I_SafeExit(0); // killough + + // [FG] ignore empty demo lumps + if (demobuffer) + { + Z_ChangeTag(demobuffer, PU_CACHE); + } + + G_ReloadDefaults(); // killough 3/1/98 + netgame = false; // killough 3/29/98 + deathmatch = false; + D_AdvanceDemo(); + return true; + } + if (demorecording) { demorecording = false; @@ -3691,22 +3787,6 @@ boolean G_CheckDemoStatus(void) (unsigned) gametic * (double) TICRATE / realtics); } - if (demoplayback) - { - if (singledemo) - I_SafeExit(0); // killough - - // [FG] ignore empty demo lumps - if (demobuffer) - { - Z_ChangeTag(demobuffer, PU_CACHE); - } - G_ReloadDefaults(); // killough 3/1/98 - netgame = false; // killough 3/29/98 - deathmatch = false; - D_AdvanceDemo(); - return true; - } return false; } diff --git a/src/m_input.h b/src/m_input.h index 700ce0bd..d48583b9 100644 --- a/src/m_input.h +++ b/src/m_input.h @@ -91,6 +91,7 @@ enum input_spy, input_demo_quit, input_demo_fforward, + input_demo_join, input_speed_up, input_speed_down, input_speed_default, diff --git a/src/m_menu.c b/src/m_menu.c index ef3c81f9..bfd87577 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2893,11 +2893,12 @@ setup_menu_t keys_settings4[] = // Key Binding screen strings {"DEMOS" ,S_SKIP|S_TITLE,m_null,KB_X,M_Y+5*M_SPC}, {"FAST-FORWARD" ,S_INPUT,m_scrn,KB_X,M_Y+6*M_SPC,{0},input_demo_fforward}, {"FINISH DEMO" ,S_INPUT,m_scrn,KB_X,M_Y+7*M_SPC,{0},input_demo_quit}, + {"JOIN DEMO" ,S_INPUT,m_scrn,KB_X,M_Y+8*M_SPC,{0},input_demo_join}, // [FG] reload current level / go to next level - {"MISCELLANEOUS",S_SKIP|S_TITLE,m_null,KB_X,M_Y+9*M_SPC}, - {"RELOAD LEVEL" ,S_INPUT,m_scrn,KB_X,M_Y+10*M_SPC,{0},input_menu_reloadlevel}, - {"NEXT LEVEL" ,S_INPUT,m_scrn,KB_X,M_Y+11*M_SPC,{0},input_menu_nextlevel}, + {"MISCELLANEOUS",S_SKIP|S_TITLE,m_null,KB_X,M_Y+10*M_SPC}, + {"RELOAD LEVEL" ,S_INPUT,m_scrn,KB_X,M_Y+11*M_SPC,{0},input_menu_reloadlevel}, + {"NEXT LEVEL" ,S_INPUT,m_scrn,KB_X,M_Y+12*M_SPC,{0},input_menu_nextlevel}, {"<- PREV", S_SKIP|S_PREV,m_null,M_X_PREV,M_Y_PREVNEXT, {keys_settings3}}, {"NEXT ->", S_SKIP|S_NEXT,m_null,M_X_NEXT,M_Y_PREVNEXT, {keys_settings5}}, diff --git a/src/m_misc.c b/src/m_misc.c index 07fec8cc..59745954 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -903,6 +903,14 @@ default_t defaults[] = { input_demo_quit, { {0, 0} } }, + { + "input_demo_join", + NULL, NULL, + {0}, {UL,UL}, input, ss_keys, wad_no, + "key to continue recording current demo", + input_demo_join, { {0, 0} } + }, + { "input_demo_fforward", NULL, NULL,