foxygit / doom Log in
commit 52cee8eac843c5488cfe03fc1717dea5d2eb307c
Author:     Thomas A. Birkel <capnclever@gmail.com>
AuthorDate: Fri Oct 28 20:50:14 2016 -0400
Commit:     Thomas A. Birkel <capnclever@gmail.com>
CommitDate: Fri Oct 28 20:50:14 2016 -0400

    Add compatibility options to Heretic/Hexen

    Includes unlimited demo support for both games, savegame buffer overrun
    suppression for Heretic, and CopyFile allocation fix for Hexen.
---
 NEWS.md                   |  2 ++
 src/heretic/d_main.c      |  2 ++
 src/heretic/doomdef.h     |  3 +++
 src/heretic/g_game.c      | 50 ++++++++++++++++++++++++++++++++++++++++++++---
 src/heretic/p_saveg.c     |  4 +++-
 src/hexen/g_game.c        | 50 ++++++++++++++++++++++++++++++++++++++++++++---
 src/hexen/h2_main.c       |  2 ++
 src/hexen/h2def.h         |  3 +++
 src/hexen/sv_save.c       |  9 +++++++--
 src/setup/compatibility.c |  7 ++-----
 src/setup/mainmenu.c      | 15 ++------------
 11 files changed, 120 insertions(+), 27 deletions(-)

diff --git a/NEWS.md b/NEWS.md
index 1d2e0d99..aa36c942 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -52,12 +52,14 @@
 ### Heretic
   * Added map names for Episode 6, fixing a crash after completing a
     level in this episode. (thanks J.Benaim)
+  * Add unlimited demo/savegame support. (thanks CapnClever)

 ### Hexen
   * The MRJONES cheat code returns an identical string as vanilla, and
     enables fully reproducable builds. (thanks Fabian)
   * Fixed an issue where the game crashed while killing the
     Wraithverge in 64-bit builds. (thanks J.Benaim)
+  * Add unlimited demo/savegame support. (thanks CapnClever)

 ### Strife
   * Support added for automatic loading of the IWAD from the GOG.com
diff --git a/src/heretic/d_main.c b/src/heretic/d_main.c
index ebc7b628..b63a2489 100644
--- a/src/heretic/d_main.c
+++ b/src/heretic/d_main.c
@@ -764,6 +764,8 @@ void D_BindVariables(void)
     M_BindIntVariable("music_volume",           &snd_MusicVolume);
     M_BindIntVariable("screenblocks",           &screenblocks);
     M_BindIntVariable("snd_channels",           &snd_Channels);
+    M_BindIntVariable("vanilla_savegame_limit", &vanilla_savegame_limit);
+    M_BindIntVariable("vanilla_demo_limit",     &vanilla_demo_limit);
     M_BindIntVariable("show_endoom",            &show_endoom);
     M_BindIntVariable("graphical_startup",      &graphical_startup);

diff --git a/src/heretic/doomdef.h b/src/heretic/doomdef.h
index db82a76b..5e3dc59b 100644
--- a/src/heretic/doomdef.h
+++ b/src/heretic/doomdef.h
@@ -569,6 +569,9 @@ extern boolean autostart;
 extern boolean testcontrols;
 extern int testcontrols_mousespeed;

+extern int vanilla_savegame_limit;
+extern int vanilla_demo_limit;
+
 /*
 ===============================================================================

diff --git a/src/heretic/g_game.c b/src/heretic/g_game.c
index 09558846..da144433 100644
--- a/src/heretic/g_game.c
+++ b/src/heretic/g_game.c
@@ -198,6 +198,8 @@ boolean *joybuttons = &joyarray[1];     // allow [-1]
 int savegameslot;
 char savedescription[32];

+int vanilla_demo_limit = 1;
+
 int inventoryTics;

 // haleyjd: removed WATCOMC
@@ -1683,6 +1685,38 @@ void G_ReadDemoTiccmd(ticcmd_t * cmd)
     cmd->arti = (unsigned char) *demo_p++;
 }

+// Increase the size of the demo buffer to allow unlimited demos
+
+static void IncreaseDemoBuffer(void)
+{
+    int current_length;
+    byte *new_demobuffer;
+    byte *new_demop;
+    int new_length;
+
+    // Find the current size
+
+    current_length = demoend - demobuffer;
+
+    // Generate a new buffer twice the size
+    new_length = current_length * 2;
+
+    new_demobuffer = Z_Malloc(new_length, PU_STATIC, 0);
+    new_demop = new_demobuffer + (demo_p - demobuffer);
+
+    // Copy over the old data
+
+    memcpy(new_demobuffer, demobuffer, current_length);
+
+    // Free the old buffer and point the demo pointers at the new buffer.
+
+    Z_Free(demobuffer);
+
+    demobuffer = new_demobuffer;
+    demo_p = new_demop;
+    demoend = demobuffer + new_length;
+}
+
 void G_WriteDemoTiccmd(ticcmd_t * cmd)
 {
     byte *demo_start;
@@ -1716,9 +1750,19 @@ void G_WriteDemoTiccmd(ticcmd_t * cmd)

     if (demo_p > demoend - 16)
     {
-        // no more space
-        G_CheckDemoStatus();
-        return;
+        if (vanilla_demo_limit)
+        {
+            // no more space
+            G_CheckDemoStatus();
+            return;
+        }
+        else
+        {
+            // Vanilla demo limit disabled: unlimited
+            // demo lengths!
+
+            IncreaseDemoBuffer();
+        }
     }

     G_ReadDemoTiccmd(cmd);      // make SURE it is exactly the same
diff --git a/src/heretic/p_saveg.c b/src/heretic/p_saveg.c
index b8d268f4..e21e6689 100644
--- a/src/heretic/p_saveg.c
+++ b/src/heretic/p_saveg.c
@@ -31,6 +31,8 @@
 static FILE *SaveGameFP;
 static byte *savebuffer, *save_p;

+int vanilla_savegame_limit = 1;
+

 //==========================================================================
 //
@@ -82,7 +84,7 @@ void SV_Close(char *fileName)

     // Enforce the same savegame size limit as in Vanilla Heretic

-    if (ftell(SaveGameFP) > SAVEGAMESIZE)
+    if (vanilla_savegame_limit && ftell(SaveGameFP) > SAVEGAMESIZE)
     {
         I_Error("Savegame buffer overrun");
     }
diff --git a/src/hexen/g_game.c b/src/hexen/g_game.c
index 270b4d08..f1904d87 100644
--- a/src/hexen/g_game.c
+++ b/src/hexen/g_game.c
@@ -165,6 +165,8 @@ boolean *joybuttons = &joyarray[1];     // allow [-1]
 int savegameslot;
 char savedescription[32];

+int vanilla_demo_limit = 1;
+
 int inventoryTics;

 // haleyjd: removed externdriver crap
@@ -1842,6 +1844,38 @@ void G_ReadDemoTiccmd(ticcmd_t * cmd)
     cmd->arti = (unsigned char) *demo_p++;
 }

+// Increase the size of the demo buffer to allow unlimited demos
+
+static void IncreaseDemoBuffer(void)
+{
+    int current_length;
+    byte *new_demobuffer;
+    byte *new_demop;
+    int new_length;
+
+    // Find the current size
+
+    current_length = demoend - demobuffer;
+
+    // Generate a new buffer twice the size
+    new_length = current_length * 2;
+
+    new_demobuffer = Z_Malloc(new_length, PU_STATIC, 0);
+    new_demop = new_demobuffer + (demo_p - demobuffer);
+
+    // Copy over the old data
+
+    memcpy(new_demobuffer, demobuffer, current_length);
+
+    // Free the old buffer and point the demo pointers at the new buffer.
+
+    Z_Free(demobuffer);
+
+    demobuffer = new_demobuffer;
+    demo_p = new_demop;
+    demoend = demobuffer + new_length;
+}
+
 void G_WriteDemoTiccmd(ticcmd_t * cmd)
 {
     byte *demo_start;
@@ -1875,9 +1909,19 @@ void G_WriteDemoTiccmd(ticcmd_t * cmd)

     if (demo_p > demoend - 16)
     {
-        // no more space
-        G_CheckDemoStatus();
-        return;
+        if (vanilla_demo_limit)
+        {
+            // no more space
+            G_CheckDemoStatus();
+            return;
+        }
+        else
+        {
+            // Vanilla demo limit disabled: unlimited
+            // demo lengths!
+
+            IncreaseDemoBuffer();
+        }
     }

     G_ReadDemoTiccmd(cmd);      // make SURE it is exactly the same
diff --git a/src/hexen/h2_main.c b/src/hexen/h2_main.c
index dd3be14b..ef6ea9e9 100644
--- a/src/hexen/h2_main.c
+++ b/src/hexen/h2_main.c
@@ -161,6 +161,8 @@ void D_BindVariables(void)
     M_BindIntVariable("messageson",             &messageson);
     M_BindIntVariable("screenblocks",           &screenblocks);
     M_BindIntVariable("snd_channels",           &snd_Channels);
+    M_BindIntVariable("vanilla_savegame_limit", &vanilla_savegame_limit);
+    M_BindIntVariable("vanilla_demo_limit",     &vanilla_demo_limit);

     M_BindStringVariable("savedir", &SavePath);

diff --git a/src/hexen/h2def.h b/src/hexen/h2def.h
index 7ceaeeb6..b57cedd9 100644
--- a/src/hexen/h2def.h
+++ b/src/hexen/h2def.h
@@ -682,6 +682,9 @@ extern boolean autostart;
 extern boolean testcontrols;
 extern int testcontrols_mousespeed;

+extern int vanilla_savegame_limit;
+extern int vanilla_demo_limit;
+
 /*
 ===============================================================================

diff --git a/src/hexen/sv_save.c b/src/hexen/sv_save.c
index 2cdc65be..a8df4d90 100644
--- a/src/hexen/sv_save.c
+++ b/src/hexen/sv_save.c
@@ -142,6 +142,8 @@ static void SV_WritePtr(void *ptr);

 char *SavePath = DEFAULT_SAVEPATH;

+int vanilla_savegame_limit = 1;
+
 // PRIVATE DATA DEFINITIONS ------------------------------------------------

 static int MobjCount;
@@ -3270,8 +3272,11 @@ static void CopyFile(char *source_name, char *dest_name)
     // in memory: Chocolate Hexen should force an allocation error here
     // whenever it's appropriate.

-    buffer = Z_Malloc(file_length, PU_STATIC, NULL);
-    Z_Free(buffer);
+    if (vanilla_savegame_limit)
+    {
+        buffer = Z_Malloc(file_length, PU_STATIC, NULL);
+        Z_Free(buffer);
+    }

     write_handle = fopen(dest_name, "wb");
     if (write_handle == NULL)
diff --git a/src/setup/compatibility.c b/src/setup/compatibility.c
index 8cb2525f..31a48e91 100644
--- a/src/setup/compatibility.c
+++ b/src/setup/compatibility.c
@@ -45,10 +45,7 @@ void CompatibilitySettings(void)

 void BindCompatibilityVariables(void)
 {
-    if (gamemission == doom || gamemission == strife)
-    {
-        M_BindIntVariable("vanilla_savegame_limit", &vanilla_savegame_limit);
-        M_BindIntVariable("vanilla_demo_limit",     &vanilla_demo_limit);
-    }
+    M_BindIntVariable("vanilla_savegame_limit", &vanilla_savegame_limit);
+    M_BindIntVariable("vanilla_demo_limit",     &vanilla_demo_limit);
 }

diff --git a/src/setup/mainmenu.c b/src/setup/mainmenu.c
index 2a794ba0..974f4bba 100644
--- a/src/setup/mainmenu.c
+++ b/src/setup/mainmenu.c
@@ -226,21 +226,10 @@ void MainMenu(void)
                          (TxtWidgetSignalFunc) ConfigMouse, NULL),
           TXT_NewButton2("Configure Gamepad/Joystick",
                          (TxtWidgetSignalFunc) ConfigJoystick, NULL),
+          TXT_NewButton2("Compatibility",
+                         (TxtWidgetSignalFunc) CompatibilitySettings, NULL),
           NULL);

-    // The compatibility window is only appropriate for Doom/Strife.
-
-    if (gamemission == doom || gamemission == strife)
-    {
-        txt_button_t *button;
-
-        button = TXT_NewButton2("Compatibility",
-                                (TxtWidgetSignalFunc) CompatibilitySettings,
-                                NULL);
-
-        TXT_AddWidget(window, button);
-    }
-
     TXT_AddWidgets(window,
           GetLaunchButton(),
           TXT_NewStrut(0, 1),