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 */
+