WAD merging code

Subversion-branch: /trunk/chocolate-doom
Subversion-revision: 168
This commit is contained in:
Simon Howard 2005-10-08 18:23:18 +00:00
parent 968c30b024
commit 3519b53f17
5 changed files with 461 additions and 3 deletions

26
README
View file

@ -75,10 +75,36 @@ options are supported.
"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 ==
* Chocolate Doom is not perfect. See the BUGS file for a list of

View file

@ -30,7 +30,7 @@ dstrings.h i_system.c p_doors.c p_switch.c r_state.h mmus2mid.c \
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

View file

@ -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 @@ static const char rcsid[] = "$Id: d_main.c 161 2005-10-04 00:41:49Z fraggle $";
#include "z_zone.h"
#include "w_wad.h"
#include "w_merge.h"
#include "s_sound.h"
#include "v_video.h"
@ -1049,6 +1053,16 @@ void D_DoomMain (void)
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();

374
src/w_merge.c Normal file
View file

@ -0,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();
}

44
src/w_merge.h Normal file
View file

@ -0,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 */