foxygit / doom Log in
commit e92f889b71eddafb30e9c64b3f17b63e73d4403d
Author:     Simon Howard <fraggle@soulsphere.org>
AuthorDate: Wed Nov 23 00:26:49 2016 -0500
Commit:     Simon Howard <fraggle@soulsphere.org>
CommitDate: Wed Nov 23 00:26:49 2016 -0500

    doom: Forbid longtics demos in WAD files.

    As per reasoning on #817, we only allow longtics demos as a feature for
    users to cleanly record vanilla gameplay without affecting the turning
    resolution. When playing back demos, we detect the different header byte
    (111) that indicates a longtics demo file and proceed accordingly.

    However, we should only support such demos when they are played manually
    on the command line by the user. Longtics demo playback support should
    not be a feature that WAD authors can use to break from Vanilla
    behavior. If such a demo is encountered inside a WAD, treat it as
    Vanilla would treat it and exit accordingly.
---
 src/doom/g_game.c  | 48 ++++++++++++++++++++++++++++++++++--------------
 src/w_file.h       | 10 +++-------
 src/w_file_posix.c |  2 ++
 src/w_file_stdc.c  |  1 +
 src/w_file_win32.c |  2 ++
 5 files changed, 42 insertions(+), 21 deletions(-)

diff --git a/src/doom/g_game.c b/src/doom/g_game.c
index 424d87e1..90032805 100644
--- a/src/doom/g_game.c
+++ b/src/doom/g_game.c
@@ -2127,6 +2127,8 @@ static char *DemoVersionDescription(int version)
             return "v1.8";
         case 109:
             return "v1.9";
+        case 111:
+            return "v1.91 hack demo?";
         default:
             break;
     }
@@ -2146,27 +2148,45 @@ static char *DemoVersionDescription(int version)
     }
 }

-void G_DoPlayDemo (void)
-{
-    skill_t skill;
-    int             i, episode, map;
+// Returns true if the given lump number corresponds to data from a .lmp
+// file, as opposed to a WAD.
+static boolean IsDemoFile(int lumpnum)
+{
+    char *lower;
+    boolean result;
+
+    lower = M_StringDuplicate(lumpinfo[lumpnum]->wad_file->path);
+    M_ForceLowercase(lower);
+    result = M_StringEndsWith(lower, ".lmp");
+    free(lower);
+
+    return result;
+}
+
+void G_DoPlayDemo (void)
+{
+    skill_t skill;
+    int i, lumpnum, episode, map;
     int demoversion;
-
-    gameaction = ga_nothing;
-    demobuffer = demo_p = W_CacheLumpName (defdemoname, PU_STATIC);
+
+    lumpnum = W_GetNumForName(defdemoname);
+    gameaction = ga_nothing;
+    demobuffer = W_CacheLumpNum(lumpnum, PU_STATIC);
+    demo_p = demobuffer;

     demoversion = *demo_p++;

-    if (demoversion == G_VanillaVersionCode())
-    {
-        longtics = false;
-    }
-    else if (demoversion == DOOM_191_VERSION)
+    longtics = false;
+
+    // Longtics demos use the modified format that is generated by cph's
+    // hacked "v1.91" doom exe. We support this format, but only if the
+    // demo is being played "manually" on the command line; such demos
+    // are forbidden inside WAD files.
+    if (IsDemoFile(lumpnum) && demoversion == DOOM_191_VERSION)
     {
-        // demo recorded with cph's modified "v1.91" doom exe
         longtics = true;
     }
-    else
+    else if (demoversion != G_VanillaVersionCode())
     {
         char *message = "Demo is from a different game version!\n"
                         "(read %i, should be %i)\n"
diff --git a/src/w_file.h b/src/w_file.h
index f5778143..a47d2a7a 100644
--- a/src/w_file.h
+++ b/src/w_file.h
@@ -28,35 +28,31 @@ typedef struct _wad_file_s wad_file_t;
 typedef struct
 {
     // Open a file for reading.
-
     wad_file_t *(*OpenFile)(char *path);

     // Close the specified file.
-
     void (*CloseFile)(wad_file_t *file);

     // Read data from the specified position in the file into the
     // provided buffer.  Returns the number of bytes read.
-
     size_t (*Read)(wad_file_t *file, unsigned int offset,
                    void *buffer, size_t buffer_len);
-
 } wad_file_class_t;

 struct _wad_file_s
 {
     // Class of this file.
-
     wad_file_class_t *file_class;

     // If this is NULL, the file cannot be mapped into memory.  If this
     // is non-NULL, it is a pointer to the mapped file.
-
     byte *mapped;

     // Length of the file, in bytes.
-
     unsigned int length;
+
+    // File's location on disk.
+    const char *path;
 };

 // Open the specified file. Returns a pointer to a new wad_file_t
diff --git a/src/w_file_posix.c b/src/w_file_posix.c
index c193ecb3..a7b53b41 100644
--- a/src/w_file_posix.c
+++ b/src/w_file_posix.c
@@ -26,6 +26,7 @@
 #include <sys/mman.h>
 #include <string.h>

+#include "m_misc.h"
 #include "w_file.h"
 #include "z_zone.h"

@@ -90,6 +91,7 @@ static wad_file_t *W_POSIX_OpenFile(char *path)
     result = Z_Malloc(sizeof(posix_wad_file_t), PU_STATIC, 0);
     result->wad.file_class = &posix_wad_file;
     result->wad.length = GetFileLength(handle);
+    result->wad.path = M_StringDuplicate(path);
     result->handle = handle;

     // Try to map the file into memory with mmap:
diff --git a/src/w_file_stdc.c b/src/w_file_stdc.c
index 829e9603..c41692fd 100644
--- a/src/w_file_stdc.c
+++ b/src/w_file_stdc.c
@@ -48,6 +48,7 @@ static wad_file_t *W_StdC_OpenFile(char *path)
     result->wad.file_class = &stdc_wad_file;
     result->wad.mapped = NULL;
     result->wad.length = M_FileLength(fstream);
+    result->wad.path = M_StringDuplicate(path);
     result->fstream = fstream;

     return &result->wad;
diff --git a/src/w_file_win32.c b/src/w_file_win32.c
index b44d9426..a370fb01 100644
--- a/src/w_file_win32.c
+++ b/src/w_file_win32.c
@@ -26,6 +26,7 @@
 #include <windows.h>

 #include "i_system.h"
+#include "m_misc.h"
 #include "w_file.h"
 #include "z_zone.h"

@@ -115,6 +116,7 @@ static wad_file_t *W_Win32_OpenFile(char *path)
     result = Z_Malloc(sizeof(win32_wad_file_t), PU_STATIC, 0);
     result->wad.file_class = &win32_wad_file;
     result->wad.length = GetFileLength(handle);
+    result->wad.path = M_StringDuplicate(path);
     result->handle = handle;

     // Try to map the file into memory with mmap: