shithub: choc

Download patch

ref: 3519b53f176697dc8fdc6321e32b0eb598a2e9f4
parent: 968c30b02484585d03ed757b317a39b2f6a15556
author: Simon Howard <[email protected]>
date: Sat Oct 8 14:23:18 EDT 2005

WAD merging code

Subversion-branch: /trunk/chocolate-doom
Subversion-revision: 168

--- a/README
+++ b/README
@@ -75,9 +75,35 @@
                        "Doom v1.91" format to avoid losing turning
                        resolution.
 
+  -merge <file>        Loads a PWAD but simulates merging it into the main
+                       IWAD (see below)
+
   -novert              Turns on novert (see above)
 
   -nonovert            Turns off novert (see above)
+
+== Playing TCs ==
+
+With Vanilla Doom there is no way to include sprites in PWAD files.  
+Chocolate Doom's '-file' command line option behaves exactly the
+same as Vanilla Doom, and trying to play TCs by adding the WAD files
+using '-file' will not work.
+
+Many Total Conversions (TCs) are distributed as a PWAD file which must
+be merged into the main IWAD.  Typically a copy of DEUSF.EXE is
+included which performs this merge.  Chocolate Doom includes a new
+option, '-merge', which will simulate this merge.  Essentially, the 
+WAD directory is merged in memory, removing the need to modify the 
+IWAD on disk.
+
+To play TCs using Chocolate Doom, run like this:
+
+  chocolate-doom -merge thetc.wad
+
+Here are some examples:
+
+  chocolate-doom -merge batman.wad -deh batman.deh      (Batman Doom)
+  chocolate-doom -merge aoddoom1.wad -deh aoddoom1.deh  (Army of Darkness Doom)
 
 == Other information ==
 
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -30,7 +30,7 @@
 d_textur.h  i_system.h  p_enemy.c   p_telept.c  r_things.c  mmus2mid.h  \
 deh_defs.h  deh_frame.c deh_main.c  deh_ptr.c   deh_text.c  deh_thing.c \
 deh_io.c    deh_io.h    deh_ammo.c  deh_cheat.c deh_weapon.c            \
-deh_misc.c  deh_mapping.c deh_mapping.h
+deh_misc.c  deh_mapping.c deh_mapping.h         w_merge.c   w_merge.h
 
 
 if HAVE_WINDRES
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -1,7 +1,7 @@
 // Emacs style mode select   -*- C++ -*- 
 //-----------------------------------------------------------------------------
 //
-// $Id: d_main.c 161 2005-10-04 00:41:49Z fraggle $
+// $Id: d_main.c 168 2005-10-08 18:23:18Z fraggle $
 //
 // Copyright(C) 1993-1996 Id Software, Inc.
 // Copyright(C) 2005 Simon Howard
@@ -22,6 +22,9 @@
 // 02111-1307, USA.
 //
 // $Log$
+// Revision 1.19  2005/10/08 18:23:18  fraggle
+// WAD merging code
+//
 // Revision 1.18  2005/10/04 00:41:49  fraggle
 // Move call to dehacked entrypoint to stop crashes
 //
@@ -96,7 +99,7 @@
 //-----------------------------------------------------------------------------
 
 
-static const char rcsid[] = "$Id: d_main.c 161 2005-10-04 00:41:49Z fraggle $";
+static const char rcsid[] = "$Id: d_main.c 168 2005-10-08 18:23:18Z fraggle $";
 
 #define	BGCOLOR		7
 #define	FGCOLOR		8
@@ -125,6 +128,7 @@
 
 #include "z_zone.h"
 #include "w_wad.h"
+#include "w_merge.h"
 #include "s_sound.h"
 #include "v_video.h"
 
@@ -1049,6 +1053,16 @@
 
     printf ("W_Init: Init WADfiles.\n");
     W_InitMultipleFiles (wadfiles);
+
+    p = M_CheckParm("-merge");
+
+    if (p > 0)
+    {
+        for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
+        {
+            W_MergeFile(myargv[p]);
+        }
+    }
     
     IdentifyVersion();
 
--- /dev/null
+++ b/src/w_merge.c
@@ -1,0 +1,374 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// $Id: w_merge.c 168 2005-10-08 18:23:18Z fraggle $
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// $Log$
+// Revision 1.1  2005/10/08 18:23:18  fraggle
+// WAD merging code
+//
+//
+// DESCRIPTION:
+// Handles merging of PWADs, similar to deutex's -merge option
+//
+// Ideally this should work exactly the same as in deutex, but trying to
+// read the deutex source code made my brain hurt.
+//
+//-----------------------------------------------------------------------------
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "i_system.h"
+#include "w_wad.h"
+#include "z_zone.h"
+
+typedef enum 
+{ 
+    SECTION_NORMAL, 
+    SECTION_FLATS, 
+    SECTION_SPRITES,
+} section_t;
+
+typedef struct
+{
+    lumpinfo_t *lumps;
+    int numlumps;
+} searchlist_t;
+
+static searchlist_t iwad;
+static searchlist_t pwad;
+
+static searchlist_t iwad_flats;
+static searchlist_t pwad_sprites;
+static searchlist_t pwad_flats;
+
+// Search in a list to find a lump with a particular name
+// Linear search (slow!)
+//
+// Returns -1 if not found
+
+static int FindInList(searchlist_t *list, char *name)
+{
+    int i;
+
+    for (i=0; i<list->numlumps; ++i)
+    {
+        if (!strncasecmp(list->lumps[i].name, name, 8))
+            return i;
+    }
+
+    return -1;
+}
+
+// Sets up the sprite/flat search lists
+
+static void SetupLists(void)
+{
+    int startlump, endlump;
+    
+    // IWAD
+    // look for the flats section
+
+    startlump = FindInList(&iwad, "F_START");
+    endlump = FindInList(&iwad, "F_END");
+
+    if (startlump < 0 || endlump < 0)
+    {
+        I_Error("Flats section not found in IWAD");
+    }
+
+    iwad_flats.lumps = iwad.lumps + startlump + 1;
+    iwad_flats.numlumps = endlump - startlump - 1;
+
+    // PWAD
+    // look for a flats section
+
+    pwad_flats.numlumps = 0;
+    startlump = FindInList(&pwad, "FF_START");
+
+    if (startlump < 0)
+    {
+        startlump = FindInList(&pwad, "F_START");
+    }
+
+    if (startlump >= 0)
+    {
+        endlump = FindInList(&pwad, "FF_END");
+
+        if (endlump < 0)
+        {
+            endlump = FindInList(&pwad, "F_END");
+        }
+
+        if (endlump > startlump)
+        {
+            pwad_flats.lumps = pwad.lumps + startlump + 1;
+            pwad_flats.numlumps = endlump - startlump - 1;
+        }
+    }
+
+    // look for a sprites section
+
+    pwad_sprites.numlumps = 0;
+    startlump = FindInList(&pwad, "SS_START");
+
+    if (startlump < 0)
+    {
+        startlump = FindInList(&pwad, "S_START");
+    }
+
+    if (startlump >= 0)
+    {
+        endlump = FindInList(&pwad, "SS_END");
+
+        if (endlump < startlump)
+        {
+            endlump = FindInList(&pwad, "S_END");
+        }
+
+        if (endlump > startlump)
+        {
+            pwad_sprites.lumps = pwad.lumps + startlump + 1;
+            pwad_sprites.numlumps = endlump - startlump - 1;
+        }
+    }
+}
+
+// Perform the merge.
+//
+// The merge code creates a new lumpinfo list, adding entries from the
+// IWAD first followed by the PWAD.
+//
+// For the IWAD:
+//  * Flats are added.  If a flat with the same name is in the PWAD, 
+//    it is ignored.  At the end of the section, all flats in the PWAD 
+//    are inserted.  This is consistent with the behavior of deutex/deusf.
+//  * Sprites are added.  If a sprite with the same name exists in the PWAD,
+//    it is used to replace the sprite.
+// 
+// For the PWAD:
+//  * All Sprites and Flats are ignored, with the assumption they have 
+//    already been merged into the IWAD's sections.
+
+static void DoMerge(void)
+{
+    section_t current_section;
+    lumpinfo_t *newlumps;
+    int num_newlumps;
+    int lumpindex;
+    int i, n;
+    
+    // Can't ever have more lumps than we already have
+    newlumps = malloc(sizeof(lumpinfo_t) * numlumps);
+    num_newlumps = 0;
+
+    // Add IWAD lumps
+    current_section = SECTION_NORMAL;
+
+    for (i=0; i<iwad.numlumps; ++i)
+    {
+        lumpinfo_t *lump = &iwad.lumps[i];
+
+        switch (current_section)
+        {
+            case SECTION_NORMAL:
+                if (!strncasecmp(lump->name, "F_START", 8))
+                {
+                    current_section = SECTION_FLATS;
+                }
+                else if (!strncasecmp(lump->name, "S_START", 8))
+                {
+                    current_section = SECTION_SPRITES;
+                }
+
+                newlumps[num_newlumps++] = *lump;
+
+                break;
+
+            case SECTION_FLATS:
+
+                // Have we reached the end of the section?
+
+                if (!strncasecmp(lump->name, "F_END", 8))
+                {
+                    // Add all new flats from the PWAD to the end
+                    // of the section
+
+                    for (n=0; n<pwad_flats.numlumps; ++n)
+                    {
+                        newlumps[num_newlumps++] = pwad_flats.lumps[n];
+                    }
+
+                    newlumps[num_newlumps++] = *lump;
+
+                    // back to normal reading
+                    current_section = SECTION_NORMAL;
+                }
+                else
+                {
+                    // If there is a flat in the PWAD with the same name,
+                    // do not add it now.  All PWAD flats are added to the
+                    // end of the section. Otherwise, if it is only in the
+                    // IWAD, add it now
+
+                    lumpindex = FindInList(&pwad_flats, lump->name);
+
+                    if (lumpindex < 0)
+                    {
+                        newlumps[num_newlumps++] = *lump;
+                    }
+                }
+
+                break;
+
+            case SECTION_SPRITES:
+
+                // Have we reached the end of the section?
+
+                if (!strncasecmp(lump->name, "S_END", 8))
+                {
+                    newlumps[num_newlumps++] = *lump;
+
+                    // back to normal reading
+                    current_section = SECTION_NORMAL;
+                }
+                else
+                {
+                    // If there is a sprite in the PWAD with the same name,
+                    // replace this sprite
+
+                    // Note: This is rather limited.  A PWAD sprite has to
+                    // have EXACTLY the same name as that in the IWAD.  It
+                    // does not allow the number of sides per frame to be
+                    // changed in the PWAD. FIXME?
+
+                    lumpindex = FindInList(&pwad_sprites, lump->name);
+
+                    if (lumpindex >= 0)
+                    {
+                        newlumps[num_newlumps++] = pwad_sprites.lumps[lumpindex];
+                    }
+                    else
+                    {
+                        newlumps[num_newlumps++] = *lump;
+                    }
+                }
+
+                break;
+        }
+    }
+   
+    // Add PWAD lumps
+    current_section = SECTION_NORMAL;
+
+    for (i=0; i<pwad.numlumps; ++i)
+    {
+        lumpinfo_t *lump = &pwad.lumps[i];
+
+        switch (current_section)
+        {
+            case SECTION_NORMAL:
+                if (!strncasecmp(lump->name, "F_START", 8)
+                 || !strncasecmp(lump->name, "FF_START", 8))
+                {
+                    current_section = SECTION_FLATS;
+                }
+                else if (!strncasecmp(lump->name, "S_START", 8)
+                      || !strncasecmp(lump->name, "SS_START", 8))
+                {
+                    current_section = SECTION_SPRITES;
+                }
+                else
+                {
+                    // Don't include the headers of sections
+       
+                    newlumps[num_newlumps++] = *lump;
+                }
+                break;
+
+            case SECTION_FLATS:
+
+                // PWAD flats are ignored (already merged)
+  
+                if (!strncasecmp(lump->name, "FF_END", 8)
+                 || !strncasecmp(lump->name, "F_END", 8))
+                {
+                    // end of section
+                    current_section = SECTION_NORMAL;
+                }
+                break;
+
+            case SECTION_SPRITES:
+
+                // PWAD sprites are ignored (already merged)
+
+                if (!strncasecmp(lump->name, "SS_END", 8)
+                 || !strncasecmp(lump->name, "S_END", 8))
+                {
+                    // end of section
+                    current_section = SECTION_NORMAL;
+                }
+                break;
+        }
+    }
+
+    // Switch to the new lumpinfo, and free the old one
+
+    free(lumpinfo);
+    lumpinfo = newlumps;
+    numlumps = num_newlumps;
+}
+
+// Merge in a file by name
+
+void W_MergeFile(char *filename)
+{
+    int old_numlumps;
+
+    old_numlumps = numlumps;
+
+    W_AddFile(filename);
+
+    // failed to load?
+
+    if (numlumps == old_numlumps)
+        return;
+
+    printf(" merging %s\n", filename);
+
+    // iwad is at the start, pwad was appended to the end
+
+    iwad.lumps = lumpinfo;
+    iwad.numlumps = old_numlumps;
+
+    pwad.lumps = lumpinfo + old_numlumps;
+    pwad.numlumps = numlumps - old_numlumps;
+    
+    // Setup sprite/flat lists
+
+    SetupLists();
+
+    // Perform the merge
+
+    DoMerge();
+}
+
+
--- /dev/null
+++ b/src/w_merge.h
@@ -1,0 +1,44 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// $Id: w_merge.h 168 2005-10-08 18:23:18Z fraggle $
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// $Log$
+// Revision 1.1  2005/10/08 18:23:18  fraggle
+// WAD merging code
+//
+//
+// DESCRIPTION:
+// Handles merging of PWADs, similar to deutex's -merge option
+//
+// Ideally this should work exactly the same as in deutex, but trying to
+// read the deutex source code made my brain hurt.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef W_MERGE_H
+#define W_MERGE_H
+
+// Add a new WAD and merge it into the main directory
+
+void W_MergeFile(char *filename);
+
+#endif /* #ifndef W_MERGE_H */
+