foxygit / doom Log in
commit 48e96443151db631e1153d459e850c49a96ccb29
Author:     Simon Howard <fraggle@gmail.com>
AuthorDate: Sat Apr 19 03:32:38 2014 -0400
Commit:     Simon Howard <fraggle@gmail.com>
CommitDate: Sat Apr 19 03:32:38 2014 -0400

    Exit with error on startup if using the wrong IWAD.

    Having multiple binaries can cause some confusion - some users try to
    run chocolate-doom with hexen.wad, thinking it is supported. Add a
    startup check that makes sure the user is not trying to start the game
    using the wrong IWAD file for the binary being run.

    This fixes #382.
---
 src/d_iwad.c         |  9 +++++----
 src/d_iwad.h         |  3 ++-
 src/d_mode.c         | 27 +++++++++++++++++++++++++++
 src/d_mode.h         |  1 +
 src/doom/d_main.c    |  2 ++
 src/heretic/d_main.c |  1 +
 src/hexen/h2_main.c  |  1 +
 src/strife/d_main.c  |  1 +
 src/w_wad.c          | 43 +++++++++++++++++++++++++++++++++++++++++++
 src/w_wad.h          |  2 ++
 10 files changed, 85 insertions(+), 5 deletions(-)

diff --git a/src/d_iwad.c b/src/d_iwad.c
index 3794164c..6f45c98c 100644
--- a/src/d_iwad.c
+++ b/src/d_iwad.c
@@ -39,7 +39,7 @@
 #include "w_wad.h"
 #include "z_zone.h"

-static iwad_t iwads[] =
+static const iwad_t iwads[] =
 {
     { "doom2.wad",    doom2,     commercial, "Doom II" },
     { "plutonia.wad", pack_plut, commercial, "Final Doom: Plutonia Experiment" },
@@ -749,9 +749,9 @@ char *D_FindIWAD(int mask, GameMission_t *mission)

 // Find all IWADs in the IWAD search path matching the given mask.

-iwad_t **D_FindAllIWADs(int mask)
+const iwad_t **D_FindAllIWADs(int mask)
 {
-    iwad_t **result;
+    const iwad_t **result;
     int result_len;
     char *filename;
     int i;
@@ -833,7 +833,8 @@ char *D_SuggestGameName(GameMission_t mission, GameMode_t mode)

     for (i = 0; i < arrlen(iwads); ++i)
     {
-        if (iwads[i].mission == mission && iwads[i].mode == mode)
+        if (iwads[i].mission == mission
+         && (mode == indetermined || iwads[i].mode == mode))
         {
             return iwads[i].description;
         }
diff --git a/src/d_iwad.h b/src/d_iwad.h
index 97eaf3eb..fc6fb8a3 100644
--- a/src/d_iwad.h
+++ b/src/d_iwad.h
@@ -50,10 +50,11 @@ typedef struct
 char *D_FindWADByName(char *filename);
 char *D_TryFindWADByName(char *filename);
 char *D_FindIWAD(int mask, GameMission_t *mission);
-iwad_t **D_FindAllIWADs(int mask);
+const iwad_t **D_FindAllIWADs(int mask);
 char *D_SaveGameIWADName(GameMission_t gamemission);
 char *D_SuggestIWADName(GameMission_t mission, GameMode_t mode);
 char *D_SuggestGameName(GameMission_t mission, GameMode_t mode);
+void D_CheckCorrectIWAD(GameMission_t mission);

 #endif

diff --git a/src/d_mode.c b/src/d_mode.c
index ec3bea44..84e3bf6a 100644
--- a/src/d_mode.c
+++ b/src/d_mode.c
@@ -187,3 +187,30 @@ boolean D_IsEpisodeMap(GameMission_t mission)
     }
 }

+char *D_GameMissionString(GameMission_t mission)
+{
+    switch (mission)
+    {
+        case none:
+            return "none";
+        case doom:
+            return "doom";
+        case doom2:
+            return "doom2";
+        case pack_tnt:
+            return "tnt";
+        case pack_plut:
+            return "plutonia";
+        case pack_hacx:
+            return "hacx";
+        case pack_chex:
+            return "chex";
+        case heretic:
+            return "heretic";
+        case hexen:
+            return "hexen";
+        case strife:
+            return "strife";
+    }
+}
+
diff --git a/src/d_mode.h b/src/d_mode.h
index dedcdf88..e73d40c0 100644
--- a/src/d_mode.h
+++ b/src/d_mode.h
@@ -100,6 +100,7 @@ boolean D_ValidEpisodeMap(GameMission_t mission, GameMode_t mode,
                           int episode, int map);
 int D_GetNumEpisodes(GameMission_t mission, GameMode_t mode);
 boolean D_IsEpisodeMap(GameMission_t mission);
+char *D_GameMissionString(GameMission_t mission);

 #endif /* #ifndef __D_MODE__ */

diff --git a/src/doom/d_main.c b/src/doom/d_main.c
index 2a4fe236..c58306f2 100644
--- a/src/doom/d_main.c
+++ b/src/doom/d_main.c
@@ -1305,6 +1305,8 @@ void D_DoomMain (void)
     DEH_printf("W_Init: Init WADfiles.\n");
     D_AddFile(iwadfile);

+    W_CheckCorrectIWAD(doom);
+
     // Doom 3: BFG Edition includes modified versions of the classic
     // IWADs which can be identified by an additional DMENUPIC lump.
     // Furthermore, the M_GDHIGH lumps have been modified in a way that
diff --git a/src/heretic/d_main.c b/src/heretic/d_main.c
index 89c88108..bb3b4f08 100644
--- a/src/heretic/d_main.c
+++ b/src/heretic/d_main.c
@@ -979,6 +979,7 @@ void D_DoomMain(void)
     }

     D_AddFile(iwadfile);
+    W_CheckCorrectIWAD(heretic);
     W_ParseCommandLine();

     //!
diff --git a/src/hexen/h2_main.c b/src/hexen/h2_main.c
index a7c3dee3..76050802 100644
--- a/src/hexen/h2_main.c
+++ b/src/hexen/h2_main.c
@@ -304,6 +304,7 @@ void D_DoomMain(void)
     }

     D_AddFile(iwadfile);
+    W_CheckCorrectIWAD(hexen);

     HandleArgs();

diff --git a/src/strife/d_main.c b/src/strife/d_main.c
index db5e40f2..a0ce8eb6 100644
--- a/src/strife/d_main.c
+++ b/src/strife/d_main.c
@@ -1560,6 +1560,7 @@ void D_DoomMain (void)
     if(devparm) // [STRIFE] Devparm only
         DEH_printf("W_Init: Init WADfiles.\n");
     D_AddFile(iwadfile);
+    W_CheckCorrectIWAD(strife);
     modifiedgame = W_ParseCommandLine();

     // [STRIFE] serial number output
diff --git a/src/w_wad.c b/src/w_wad.c
index 4f944fee..1bb01774 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -34,6 +34,8 @@

 #include "doomtype.h"

+#include "config.h"
+#include "d_iwad.h"
 #include "i_swap.h"
 #include "i_system.h"
 #include "i_video.h"
@@ -537,3 +539,44 @@ void W_GenerateHashTable(void)
     // All done!
 }

+// Lump names that are unique to particular game types. This lets us check
+// the user is not trying to play with the wrong executable, eg.
+// chocolate-doom -iwad hexen.wad.
+static const struct
+{
+    GameMission_t mission;
+    char *lumpname;
+} unique_lumps[] = {
+    { doom,    "POSSA1" },
+    { heretic, "IMPXA1" },
+    { hexen,   "ETTNA1" },
+    { strife,  "AGRDA1" },
+};
+
+void W_CheckCorrectIWAD(GameMission_t mission)
+{
+    int i;
+    int lumpnum;
+
+    for (i = 0; i < arrlen(unique_lumps); ++i)
+    {
+        if (mission != unique_lumps[i].mission)
+        {
+            lumpnum = W_CheckNumForName(unique_lumps[i].lumpname);
+
+            if (lumpnum >= 0)
+            {
+                I_Error("\nYou are trying to use a %s IWAD file with "
+                        "the %s%s binary.\nThis isn't going to work.\n"
+                        "You probably want to use the %s%s binary.",
+                        D_SuggestGameName(unique_lumps[i].mission,
+                                          indetermined),
+                        PROGRAM_PREFIX,
+                        D_GameMissionString(mission),
+                        PROGRAM_PREFIX,
+                        D_GameMissionString(unique_lumps[i].mission));
+            }
+        }
+    }
+}
+
diff --git a/src/w_wad.h b/src/w_wad.h
index d2626426..a7dda363 100644
--- a/src/w_wad.h
+++ b/src/w_wad.h
@@ -31,6 +31,7 @@
 #include <stdio.h>

 #include "doomtype.h"
+#include "d_mode.h"

 #include "w_file.h"

@@ -80,5 +81,6 @@ extern unsigned int W_LumpNameHash(const char *s);
 void    W_ReleaseLumpNum(int lump);
 void    W_ReleaseLumpName(char *name);

+void W_CheckCorrectIWAD(GameMission_t mission);

 #endif