2009-04-23 23:20:21 +00:00
|
|
|
/*
|
|
|
|
** w_wad.cpp
|
|
|
|
**
|
|
|
|
**---------------------------------------------------------------------------
|
|
|
|
** Copyright 1998-2009 Randy Heit
|
|
|
|
** Copyright 2005-2009 Christoph Oelckers
|
|
|
|
** All rights reserved.
|
|
|
|
**
|
|
|
|
** Redistribution and use in source and binary forms, with or without
|
|
|
|
** modification, are permitted provided that the following conditions
|
|
|
|
** are met:
|
|
|
|
**
|
|
|
|
** 1. Redistributions of source code must retain the above copyright
|
|
|
|
** notice, this list of conditions and the following disclaimer.
|
|
|
|
** 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
** notice, this list of conditions and the following disclaimer in the
|
|
|
|
** documentation and/or other materials provided with the distribution.
|
|
|
|
** 3. The name of the author may not be used to endorse or promote products
|
|
|
|
** derived from this software without specific prior written permission.
|
|
|
|
**
|
|
|
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
**---------------------------------------------------------------------------
|
|
|
|
**
|
|
|
|
**
|
|
|
|
*/
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
// HEADER FILES ------------------------------------------------------------
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "doomtype.h"
|
|
|
|
#include "m_argv.h"
|
|
|
|
#include "i_system.h"
|
|
|
|
#include "cmdlib.h"
|
2006-04-14 16:25:57 +00:00
|
|
|
#include "c_dispatch.h"
|
2006-02-24 04:48:15 +00:00
|
|
|
#include "w_wad.h"
|
2006-04-14 16:25:57 +00:00
|
|
|
#include "w_zip.h"
|
2006-02-24 04:48:15 +00:00
|
|
|
#include "m_crc32.h"
|
|
|
|
#include "v_text.h"
|
|
|
|
#include "templates.h"
|
|
|
|
#include "gi.h"
|
2009-04-23 22:49:38 +00:00
|
|
|
#include "doomerrors.h"
|
|
|
|
#include "resourcefiles/resourcefile.h"
|
2012-11-01 02:42:14 +00:00
|
|
|
#include "md5.h"
|
2015-03-17 05:07:50 +00:00
|
|
|
#include "doomstat.h"
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// MACROS ------------------------------------------------------------------
|
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
#define NULL_INDEX (0xffffffff)
|
2006-05-02 04:38:12 +00:00
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
//
|
|
|
|
// WADFILE I/O related stuff.
|
|
|
|
//
|
|
|
|
struct FWadCollection::LumpRecord
|
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
int wadnum;
|
|
|
|
FResourceLump *lump;
|
2009-04-15 03:58:10 +00:00
|
|
|
};
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
2010-08-28 17:19:48 +00:00
|
|
|
extern bool nospriterename;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
|
|
|
|
|
|
|
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
|
|
|
|
|
|
|
static void PrintLastError ();
|
|
|
|
|
|
|
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
|
|
|
|
|
|
|
FWadCollection Wads;
|
|
|
|
|
|
|
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
|
|
|
|
|
|
|
// CODE --------------------------------------------------------------------
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// uppercoppy
|
|
|
|
//
|
|
|
|
// [RH] Copy up to 8 chars, upper-casing them in the process
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void uppercopy (char *to, const char *from)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 8 && from[i]; i++)
|
|
|
|
to[i] = toupper (from[i]);
|
|
|
|
for (; i < 8; i++)
|
|
|
|
to[i] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
FWadCollection::FWadCollection ()
|
- Fixed compilation with mingw again.
- Added multiple-choice sound sequences. These overcome one of the major
deficiences of the Hexen-inherited SNDSEQ system while still being Hexen
compatible: Custom door sounds can now use different opening and closing
sequences, for both normal and blazing speeds.
- Added a serializer for TArray.
- Added a countof macro to doomtype.h. See the1's blog to find out why
it's implemented the way it is.
<http://blogs.msdn.com/the1/articles/210011.aspx>
- Added a new method to FRandom for getting random numbers larger than 255,
which lets me:
- Fixed: SNDSEQ delayrand commands could delay for no more than 255 tics.
- Fixed: If you're going to have sector_t.SoundTarget, then they need to
be included in the pointer cleanup scans.
- Ported back newer name code from 2.1.
- Fixed: Using -warp with only one parameter in Doom and Heretic to
select a map on episode 1 no longer worked.
- New: Loading a multiplayer save now restores the players based on
their names rather than on their connection order. Using connection
order was sensible when -net was the only way to start a network game,
but with -host/-join, it's not so nice. Also, if there aren't enough
players in the save, then the extra players will be spawned normally,
so you can continue a saved game with more players than you started it
with.
- Added some new SNDSEQ commands to make it possible to define Heretic's
ambient sounds in SNDSEQ: volumerel, volumerand, slot, randomsequence,
delayonce, and restart. With these, it is basically possible to obsolete
all of the $ambient SNDINFO commands.
- Fixed: Sound sequences would only execute one command each time they were
ticked.
- Fixed: No bounds checking was done on the volume sound sequences played at.
- Fixed: The tic parameter to playloop was useless and caused it to
act like a redundant playrepeat. I have removed all the logic that
caused playloop to play repeating sounds, and now it acts like an
infinite sequence of play/delay commands until the sequence is
stopped.
- Fixed: Sound sequences were ticked every frame, not every tic, so all
the delay commands were timed incorrectly and varied depending on your
framerate. Since this is useful for restarting looping sounds that got
cut off, I have not changed this. Instead, the delay commands now
record the tic when execution should resume, not the number of tics
left to delay.
SVN r57 (trunk)
2006-04-21 01:22:55 +00:00
|
|
|
: FirstLumpIndex(NULL), NextLumpIndex(NULL),
|
2006-04-14 16:25:57 +00:00
|
|
|
FirstLumpIndex_FullName(NULL), NextLumpIndex_FullName(NULL),
|
2006-08-17 22:10:50 +00:00
|
|
|
NumLumps(0)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2006-04-14 16:25:57 +00:00
|
|
|
FWadCollection::~FWadCollection ()
|
2009-03-21 09:03:08 +00:00
|
|
|
{
|
|
|
|
DeleteAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
void FWadCollection::DeleteAll ()
|
2006-04-14 16:25:57 +00:00
|
|
|
{
|
2006-05-09 00:02:37 +00:00
|
|
|
if (FirstLumpIndex != NULL)
|
|
|
|
{
|
|
|
|
delete[] FirstLumpIndex;
|
|
|
|
FirstLumpIndex = NULL;
|
|
|
|
}
|
|
|
|
if (NextLumpIndex != NULL)
|
|
|
|
{
|
|
|
|
delete[] NextLumpIndex;
|
|
|
|
NextLumpIndex = NULL;
|
|
|
|
}
|
|
|
|
if (FirstLumpIndex_FullName != NULL)
|
|
|
|
{
|
|
|
|
delete[] FirstLumpIndex_FullName;
|
|
|
|
FirstLumpIndex_FullName = NULL;
|
|
|
|
}
|
|
|
|
if (NextLumpIndex_FullName != NULL)
|
|
|
|
{
|
|
|
|
delete[] NextLumpIndex_FullName;
|
|
|
|
NextLumpIndex_FullName = NULL;
|
|
|
|
}
|
2009-04-23 22:49:38 +00:00
|
|
|
|
2006-08-17 22:10:50 +00:00
|
|
|
LumpInfo.Clear();
|
2009-03-21 09:03:08 +00:00
|
|
|
NumLumps = 0;
|
2006-08-17 22:10:50 +00:00
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
// we must count backward to enssure that embedded WADs are deleted before
|
|
|
|
// the ones that contain their data.
|
|
|
|
for (int i = Files.Size() - 1; i >= 0; --i)
|
2006-05-09 00:02:37 +00:00
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
delete Files[i];
|
2006-05-09 00:02:37 +00:00
|
|
|
}
|
2009-04-23 22:49:38 +00:00
|
|
|
Files.Clear();
|
2006-04-14 16:25:57 +00:00
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// W_InitMultipleFiles
|
|
|
|
//
|
|
|
|
// Pass a null terminated list of files to use. All files are optional,
|
|
|
|
// but at least one file must be found. Lump names can appear multiple
|
|
|
|
// times. The name searcher looks backwards, so a later file can
|
|
|
|
// override an earlier one.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2010-01-01 12:40:47 +00:00
|
|
|
void FWadCollection::InitMultipleFiles (TArray<FString> &filenames)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
int numfiles;
|
|
|
|
|
|
|
|
// open all the files, load headers, and count lumps
|
2009-03-21 09:03:08 +00:00
|
|
|
DeleteAll();
|
2006-02-24 04:48:15 +00:00
|
|
|
numfiles = 0;
|
|
|
|
|
2010-01-01 12:40:47 +00:00
|
|
|
for(unsigned i=0;i<filenames.Size(); i++)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
int baselump = NumLumps;
|
2010-01-01 12:40:47 +00:00
|
|
|
AddFile (filenames[i]);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
NumLumps = LumpInfo.Size();
|
2006-02-24 04:48:15 +00:00
|
|
|
if (NumLumps == 0)
|
|
|
|
{
|
|
|
|
I_FatalError ("W_InitMultipleFiles: no files found");
|
|
|
|
}
|
2012-11-01 02:42:14 +00:00
|
|
|
RenameNerve();
|
2009-04-30 11:10:38 +00:00
|
|
|
RenameSprites();
|
2015-12-14 09:47:46 +00:00
|
|
|
FixMacHexen();
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// [RH] Set up hash table
|
2009-03-21 09:03:08 +00:00
|
|
|
FirstLumpIndex = new DWORD[NumLumps];
|
|
|
|
NextLumpIndex = new DWORD[NumLumps];
|
|
|
|
FirstLumpIndex_FullName = new DWORD[NumLumps];
|
|
|
|
NextLumpIndex_FullName = new DWORD[NumLumps];
|
2006-02-24 04:48:15 +00:00
|
|
|
InitHashChains ();
|
2009-04-30 11:10:38 +00:00
|
|
|
LumpInfo.ShrinkToFit();
|
|
|
|
Files.ShrinkToFit();
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2006-08-17 22:10:50 +00:00
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Adds an external file to the lump list but not to the hash chains
|
|
|
|
// It's just a simple means to assign a lump number to some file so that
|
|
|
|
// the texture manager can read from it.
|
|
|
|
//
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
|
|
|
|
int FWadCollection::AddExternalFile(const char *filename)
|
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
FResourceLump *lump = new FExternalLump(filename);
|
2006-04-14 16:25:57 +00:00
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
FWadCollection::LumpRecord *lumprec = &LumpInfo[LumpInfo.Reserve(1)];
|
|
|
|
lumprec->lump = lump;
|
|
|
|
lumprec->wadnum = -1;
|
2009-06-16 22:04:26 +00:00
|
|
|
return LumpInfo.Size()-1; // later
|
2006-04-14 16:25:57 +00:00
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// W_AddFile
|
|
|
|
//
|
|
|
|
// Files with a .wad extension are wadlink files with multiple lumps,
|
|
|
|
// other files are single lumps with the base filename for the lump name.
|
|
|
|
//
|
|
|
|
// [RH] Removed reload hack
|
|
|
|
//==========================================================================
|
2009-04-23 22:49:38 +00:00
|
|
|
|
2010-01-01 12:40:47 +00:00
|
|
|
void FWadCollection::AddFile (const char *filename, FileReader *wadinfo)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-09-02 03:47:48 +00:00
|
|
|
int startlump;
|
2009-09-02 20:29:52 +00:00
|
|
|
bool isdir = false;
|
2009-09-02 03:47:48 +00:00
|
|
|
|
2009-09-02 20:29:52 +00:00
|
|
|
if (wadinfo == NULL)
|
2009-09-02 03:47:48 +00:00
|
|
|
{
|
2009-09-02 20:29:52 +00:00
|
|
|
// Does this exist? If so, is it a directory?
|
|
|
|
struct stat info;
|
|
|
|
if (stat(filename, &info) != 0)
|
2009-04-23 22:49:38 +00:00
|
|
|
{
|
2009-09-02 20:29:52 +00:00
|
|
|
Printf(TEXTCOLOR_RED "Could not stat %s\n", filename);
|
|
|
|
PrintLastError();
|
2006-04-14 16:25:57 +00:00
|
|
|
return;
|
|
|
|
}
|
2009-09-02 20:29:52 +00:00
|
|
|
isdir = (info.st_mode & S_IFDIR) != 0;
|
|
|
|
|
|
|
|
if (!isdir)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
wadinfo = new FileReader(filename);
|
|
|
|
}
|
|
|
|
catch (CRecoverableError &err)
|
|
|
|
{ // Didn't find file
|
|
|
|
Printf (TEXTCOLOR_RED "%s\n", err.GetMessage());
|
|
|
|
PrintLastError ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2006-04-14 16:25:57 +00:00
|
|
|
}
|
2009-04-23 22:49:38 +00:00
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
Printf (" adding %s", filename);
|
|
|
|
startlump = NumLumps;
|
|
|
|
|
2009-05-31 10:49:47 +00:00
|
|
|
FResourceFile *resfile;
|
|
|
|
|
2009-09-02 03:47:48 +00:00
|
|
|
if (!isdir)
|
|
|
|
resfile = FResourceFile::OpenResourceFile(filename, wadinfo);
|
|
|
|
else
|
|
|
|
resfile = FResourceFile::OpenDirectory(filename);
|
2006-04-14 16:25:57 +00:00
|
|
|
|
2009-05-30 09:53:38 +00:00
|
|
|
if (resfile != NULL)
|
|
|
|
{
|
|
|
|
DWORD lumpstart = LumpInfo.Size();
|
2009-04-15 03:58:10 +00:00
|
|
|
|
2009-05-30 09:53:38 +00:00
|
|
|
resfile->SetFirstLump(lumpstart);
|
|
|
|
for (DWORD i=0; i < resfile->LumpCount(); i++)
|
|
|
|
{
|
|
|
|
FResourceLump *lump = resfile->GetLump(i);
|
|
|
|
FWadCollection::LumpRecord *lump_p = &LumpInfo[LumpInfo.Reserve(1)];
|
2009-04-15 03:58:10 +00:00
|
|
|
|
2009-05-30 09:53:38 +00:00
|
|
|
lump_p->lump = lump;
|
|
|
|
lump_p->wadnum = Files.Size();
|
|
|
|
}
|
2009-04-15 03:58:10 +00:00
|
|
|
|
2009-05-30 09:53:38 +00:00
|
|
|
if (Files.Size() == IWAD_FILENUM && gameinfo.gametype == GAME_Strife && gameinfo.flags & GI_SHAREWARE)
|
|
|
|
{
|
|
|
|
resfile->FindStrifeTeaserVoices();
|
|
|
|
}
|
|
|
|
Files.Push(resfile);
|
2006-04-14 16:25:57 +00:00
|
|
|
|
2009-05-30 09:53:38 +00:00
|
|
|
for (DWORD i=0; i < resfile->LumpCount(); i++)
|
|
|
|
{
|
|
|
|
FResourceLump *lump = resfile->GetLump(i);
|
|
|
|
if (lump->Flags & LUMPF_EMBEDDED)
|
2009-04-15 03:58:10 +00:00
|
|
|
{
|
2015-04-04 00:59:42 +00:00
|
|
|
FString path;
|
|
|
|
path.Format("%s:%s", filename, lump->FullName.GetChars());
|
2009-05-30 09:53:38 +00:00
|
|
|
FileReader *embedded = lump->NewReader();
|
2009-09-02 20:29:52 +00:00
|
|
|
AddFile(path, embedded);
|
2006-04-14 16:25:57 +00:00
|
|
|
}
|
2009-04-15 03:58:10 +00:00
|
|
|
}
|
2015-03-17 05:07:50 +00:00
|
|
|
|
|
|
|
if (hashfile)
|
|
|
|
{
|
|
|
|
BYTE cksum[16];
|
|
|
|
char cksumout[33];
|
|
|
|
memset(cksumout, 0, sizeof(cksumout));
|
|
|
|
|
|
|
|
FileReader *reader = wadinfo;
|
|
|
|
|
|
|
|
if (reader != NULL)
|
|
|
|
{
|
|
|
|
MD5Context md5;
|
|
|
|
reader->Seek(0, SEEK_SET);
|
|
|
|
md5.Update(reader, reader->GetLength());
|
|
|
|
md5.Final(cksum);
|
|
|
|
|
|
|
|
for (size_t j = 0; j < sizeof(cksum); ++j)
|
|
|
|
{
|
|
|
|
sprintf(cksumout + (j * 2), "%02X", cksum[j]);
|
|
|
|
}
|
|
|
|
|
2015-04-14 23:00:20 +00:00
|
|
|
fprintf(hashfile, "file: %s, hash: %s, size: %ld\n", filename, cksumout, reader->GetLength());
|
2015-03-17 05:07:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
fprintf(hashfile, "file: %s, Directory structure\n", filename);
|
|
|
|
|
|
|
|
for (DWORD i = 0; i < resfile->LumpCount(); i++)
|
|
|
|
{
|
|
|
|
FResourceLump *lump = resfile->GetLump(i);
|
|
|
|
|
|
|
|
if (!(lump->Flags & LUMPF_EMBEDDED))
|
|
|
|
{
|
|
|
|
reader = lump->NewReader();
|
|
|
|
|
|
|
|
MD5Context md5;
|
|
|
|
md5.Update(reader, lump->LumpSize);
|
|
|
|
md5.Final(cksum);
|
|
|
|
|
|
|
|
for (size_t j = 0; j < sizeof(cksum); ++j)
|
|
|
|
{
|
|
|
|
sprintf(cksumout + (j * 2), "%02X", cksum[j]);
|
|
|
|
}
|
|
|
|
|
2015-04-04 00:59:42 +00:00
|
|
|
fprintf(hashfile, "file: %s, lump: %s, hash: %s, size: %d\n", filename,
|
|
|
|
lump->FullName.IsNotEmpty() ? lump->FullName.GetChars() : lump->Name,
|
|
|
|
cksumout, lump->LumpSize);
|
2015-03-17 05:07:50 +00:00
|
|
|
|
|
|
|
delete reader;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-05-30 09:53:38 +00:00
|
|
|
return;
|
2009-04-15 03:58:10 +00:00
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// W_CheckIfWadLoaded
|
|
|
|
//
|
|
|
|
// Returns true if the specified wad is loaded, false otherwise.
|
|
|
|
// If a fully-qualified path is specified, then the wad must match exactly.
|
|
|
|
// Otherwise, any wad with that name will work, whatever its path.
|
2006-05-03 22:45:01 +00:00
|
|
|
// Returns the wads index if found, or -1 if not.
|
2006-02-24 04:48:15 +00:00
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2006-05-03 22:45:01 +00:00
|
|
|
int FWadCollection::CheckIfWadLoaded (const char *name)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
if (strrchr (name, '/') != NULL)
|
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
for (i = 0; i < Files.Size(); ++i)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
if (stricmp (GetWadFullName (i), name) == 0)
|
|
|
|
{
|
2006-05-03 22:45:01 +00:00
|
|
|
return i;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
for (i = 0; i < Files.Size(); ++i)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
if (stricmp (GetWadName (i), name) == 0)
|
|
|
|
{
|
2006-05-03 22:45:01 +00:00
|
|
|
return i;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-05-03 22:45:01 +00:00
|
|
|
return -1;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// W_NumLumps
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
int FWadCollection::GetNumLumps () const
|
|
|
|
{
|
|
|
|
return NumLumps;
|
|
|
|
}
|
|
|
|
|
2008-01-26 23:20:34 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// GetNumFiles
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
int FWadCollection::GetNumWads () const
|
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
return Files.Size();
|
2008-01-26 23:20:34 +00:00
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// W_CheckNumForName
|
|
|
|
//
|
|
|
|
// Returns -1 if name not found. The version with a third parameter will
|
|
|
|
// look exclusively in the specified wad for the lump.
|
|
|
|
//
|
|
|
|
// [RH] Changed to use hash lookup ala BOOM instead of a linear search
|
|
|
|
// and namespace parameter
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
int FWadCollection::CheckNumForName (const char *name, int space)
|
|
|
|
{
|
2009-08-02 03:38:57 +00:00
|
|
|
union
|
|
|
|
{
|
|
|
|
char uname[8];
|
|
|
|
QWORD qname;
|
|
|
|
};
|
2009-04-23 22:49:38 +00:00
|
|
|
DWORD i;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2007-12-28 11:17:52 +00:00
|
|
|
// Let's not search for names that are longer than 8 characters and contain path separators
|
|
|
|
// They are almost certainly full path names passed to this function.
|
|
|
|
if (strlen(name) > 8 && strpbrk(name, "/."))
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
uppercopy (uname, name);
|
|
|
|
i = FirstLumpIndex[LumpNameHash (uname) % NumLumps];
|
|
|
|
|
2006-06-19 15:31:10 +00:00
|
|
|
while (i != NULL_INDEX)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
FResourceLump *lump = LumpInfo[i].lump;
|
|
|
|
|
2009-08-02 03:38:57 +00:00
|
|
|
if (lump->qwName == qname)
|
2006-06-19 15:31:10 +00:00
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
if (lump->Namespace == space) break;
|
2006-06-19 15:31:10 +00:00
|
|
|
// If the lump is from one of the special namespaces exclusive to Zips
|
|
|
|
// the check has to be done differently:
|
|
|
|
// If we find a lump with this name in the global namespace that does not come
|
|
|
|
// from a Zip return that. WADs don't know these namespaces and single lumps must
|
|
|
|
// work as well.
|
2009-04-23 22:49:38 +00:00
|
|
|
if (space > ns_specialzipdirectory && lump->Namespace == ns_global &&
|
|
|
|
!(lump->Flags & LUMPF_ZIPFILE)) break;
|
2006-06-19 15:31:10 +00:00
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
i = NextLumpIndex[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
return i != NULL_INDEX ? i : -1;
|
|
|
|
}
|
|
|
|
|
2008-01-26 23:20:34 +00:00
|
|
|
int FWadCollection::CheckNumForName (const char *name, int space, int wadnum, bool exact)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-04-30 02:41:20 +00:00
|
|
|
FResourceLump *lump;
|
2009-08-02 03:38:57 +00:00
|
|
|
union
|
|
|
|
{
|
|
|
|
char uname[8];
|
|
|
|
QWORD qname;
|
|
|
|
};
|
2009-04-23 22:49:38 +00:00
|
|
|
DWORD i;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
if (wadnum < 0)
|
|
|
|
{
|
|
|
|
return CheckNumForName (name, space);
|
|
|
|
}
|
|
|
|
|
|
|
|
uppercopy (uname, name);
|
|
|
|
i = FirstLumpIndex[LumpNameHash (uname) % NumLumps];
|
|
|
|
|
2008-01-26 23:20:34 +00:00
|
|
|
// If exact is true if will only find lumps in the same WAD, otherwise
|
|
|
|
// also those in earlier WADs.
|
2009-04-23 22:49:38 +00:00
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
while (i != NULL_INDEX &&
|
2009-08-02 03:38:57 +00:00
|
|
|
(lump = LumpInfo[i].lump, lump->qwName != qname ||
|
2009-04-23 22:49:38 +00:00
|
|
|
lump->Namespace != space ||
|
2008-01-26 23:20:34 +00:00
|
|
|
(exact? (LumpInfo[i].wadnum != wadnum) : (LumpInfo[i].wadnum > wadnum)) ))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
i = NextLumpIndex[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
return i != NULL_INDEX ? i : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// W_GetNumForName
|
|
|
|
//
|
|
|
|
// Calls W_CheckNumForName, but bombs out if not found.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2006-06-19 15:31:10 +00:00
|
|
|
int FWadCollection::GetNumForName (const char *name, int space)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2006-06-19 15:31:10 +00:00
|
|
|
i = CheckNumForName (name, space);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
if (i == -1)
|
|
|
|
I_Error ("W_GetNumForName: %s not found!", name);
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-14 16:25:57 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// W_CheckNumForFullName
|
|
|
|
//
|
|
|
|
// Same as above but looks for a fully qualified name from a .zip
|
|
|
|
// These don't care about namespaces though because those are part
|
|
|
|
// of the path.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2008-03-29 22:59:41 +00:00
|
|
|
int FWadCollection::CheckNumForFullName (const char *name, bool trynormal, int namespc)
|
2006-04-14 16:25:57 +00:00
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
DWORD i;
|
2006-04-14 16:25:57 +00:00
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-05-18 22:38:46 +00:00
|
|
|
i = FirstLumpIndex_FullName[MakeKey(name) % NumLumps];
|
2006-04-14 16:25:57 +00:00
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
while (i != NULL_INDEX && stricmp(name, LumpInfo[i].lump->FullName))
|
2006-04-14 16:25:57 +00:00
|
|
|
{
|
|
|
|
i = NextLumpIndex_FullName[i];
|
|
|
|
}
|
|
|
|
|
2008-03-19 21:09:53 +00:00
|
|
|
if (i != NULL_INDEX) return i;
|
|
|
|
|
|
|
|
if (trynormal && strlen(name) <= 8 && !strpbrk(name, "./"))
|
|
|
|
{
|
2008-03-29 22:59:41 +00:00
|
|
|
return CheckNumForName(name, namespc);
|
2008-03-19 21:09:53 +00:00
|
|
|
}
|
|
|
|
return -1;
|
2006-04-14 16:25:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int FWadCollection::CheckNumForFullName (const char *name, int wadnum)
|
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
DWORD i;
|
2006-04-14 16:25:57 +00:00
|
|
|
|
|
|
|
if (wadnum < 0)
|
|
|
|
{
|
|
|
|
return CheckNumForFullName (name);
|
|
|
|
}
|
|
|
|
|
2008-08-26 18:32:17 +00:00
|
|
|
i = FirstLumpIndex_FullName[MakeKey (name) % NumLumps];
|
2006-04-14 16:25:57 +00:00
|
|
|
|
2008-08-26 18:32:17 +00:00
|
|
|
while (i != NULL_INDEX &&
|
2009-04-23 22:49:38 +00:00
|
|
|
(stricmp(name, LumpInfo[i].lump->FullName) || LumpInfo[i].wadnum != wadnum))
|
2006-04-14 16:25:57 +00:00
|
|
|
{
|
2008-08-26 18:32:17 +00:00
|
|
|
i = NextLumpIndex_FullName[i];
|
2006-04-14 16:25:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return i != NULL_INDEX ? i : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// W_GetNumForFullName
|
|
|
|
//
|
|
|
|
// Calls W_CheckNumForFullName, but bombs out if not found.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
int FWadCollection::GetNumForFullName (const char *name)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
i = CheckNumForFullName (name);
|
|
|
|
|
|
|
|
if (i == -1)
|
|
|
|
I_Error ("GetNumForFullName: %s not found!", name);
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
//==========================================================================
|
2014-05-13 18:51:16 +00:00
|
|
|
//
|
|
|
|
// link a texture with a given lump
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void FWadCollection::SetLinkedTexture(int lump, FTexture *tex)
|
|
|
|
{
|
|
|
|
if ((size_t)lump < NumLumps)
|
|
|
|
{
|
|
|
|
FResourceLump *reslump = LumpInfo[lump].lump;
|
|
|
|
reslump->LinkedTexture = tex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// retrieve linked texture
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
FTexture *FWadCollection::GetLinkedTexture(int lump)
|
|
|
|
{
|
|
|
|
if ((size_t)lump < NumLumps)
|
|
|
|
{
|
|
|
|
FResourceLump *reslump = LumpInfo[lump].lump;
|
|
|
|
return reslump->LinkedTexture;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
2006-02-24 04:48:15 +00:00
|
|
|
//
|
|
|
|
// W_LumpLength
|
|
|
|
//
|
|
|
|
// Returns the buffer size needed to load the given lump.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
int FWadCollection::LumpLength (int lump) const
|
|
|
|
{
|
|
|
|
if ((size_t)lump >= NumLumps)
|
|
|
|
{
|
|
|
|
I_Error ("W_LumpLength: %i >= NumLumps",lump);
|
|
|
|
}
|
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
return LumpInfo[lump].lump->LumpSize;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// GetLumpOffset
|
|
|
|
//
|
|
|
|
// Returns the offset from the beginning of the file to the lump.
|
2009-04-23 22:49:38 +00:00
|
|
|
// Returns -1 if the lump is compressed or can't be read directly
|
2006-02-24 04:48:15 +00:00
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2007-04-30 08:09:51 +00:00
|
|
|
int FWadCollection::GetLumpOffset (int lump)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
if ((size_t)lump >= NumLumps)
|
|
|
|
{
|
2006-06-14 15:56:56 +00:00
|
|
|
I_Error ("GetLumpOffset: %i >= NumLumps",lump);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
return LumpInfo[lump].lump->GetFileOffset();
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
2008-01-26 23:20:34 +00:00
|
|
|
//
|
|
|
|
// GetLumpOffset
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
int FWadCollection::GetLumpFlags (int lump)
|
|
|
|
{
|
|
|
|
if ((size_t)lump >= NumLumps)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
return LumpInfo[lump].lump->Flags;
|
2008-01-26 23:20:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
2006-02-24 04:48:15 +00:00
|
|
|
//
|
|
|
|
// W_LumpNameHash
|
|
|
|
//
|
|
|
|
// NOTE: s should already be uppercase, in contrast to the BOOM version.
|
|
|
|
//
|
|
|
|
// Hash function used for lump names.
|
|
|
|
// Must be mod'ed with table size.
|
|
|
|
// Can be used for any 8-character names.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
DWORD FWadCollection::LumpNameHash (const char *s)
|
|
|
|
{
|
|
|
|
const DWORD *table = GetCRCTable ();;
|
|
|
|
DWORD hash = 0xffffffff;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 8; i > 0 && *s; --i, ++s)
|
|
|
|
{
|
|
|
|
hash = CRC1 (hash, *s, table);
|
|
|
|
}
|
|
|
|
return hash ^ 0xffffffff;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// W_InitHashChains
|
|
|
|
//
|
|
|
|
// Prepares the lumpinfos for hashing.
|
|
|
|
// (Hey! This looks suspiciously like something from Boom! :-)
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void FWadCollection::InitHashChains (void)
|
|
|
|
{
|
|
|
|
char name[8];
|
|
|
|
unsigned int i, j;
|
|
|
|
|
|
|
|
// Mark all buckets as empty
|
|
|
|
memset (FirstLumpIndex, 255, NumLumps*sizeof(FirstLumpIndex[0]));
|
2006-04-14 16:25:57 +00:00
|
|
|
memset (NextLumpIndex, 255, NumLumps*sizeof(NextLumpIndex[0]));
|
|
|
|
memset (FirstLumpIndex_FullName, 255, NumLumps*sizeof(FirstLumpIndex_FullName[0]));
|
|
|
|
memset (NextLumpIndex_FullName, 255, NumLumps*sizeof(NextLumpIndex_FullName[0]));
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// Now set up the chains
|
|
|
|
for (i = 0; i < (unsigned)NumLumps; i++)
|
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
uppercopy (name, LumpInfo[i].lump->Name);
|
2006-02-24 04:48:15 +00:00
|
|
|
j = LumpNameHash (name) % NumLumps;
|
|
|
|
NextLumpIndex[i] = FirstLumpIndex[j];
|
|
|
|
FirstLumpIndex[j] = i;
|
2006-04-14 16:25:57 +00:00
|
|
|
|
|
|
|
// Do the same for the full paths
|
2015-04-04 00:59:42 +00:00
|
|
|
if (LumpInfo[i].lump->FullName.IsNotEmpty())
|
2006-04-14 16:25:57 +00:00
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
j = MakeKey(LumpInfo[i].lump->FullName) % NumLumps;
|
2006-04-14 16:25:57 +00:00
|
|
|
NextLumpIndex_FullName[i] = FirstLumpIndex_FullName[j];
|
|
|
|
FirstLumpIndex_FullName[j] = i;
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// RenameSprites
|
|
|
|
//
|
|
|
|
// Renames sprites in IWADs so that unique actors can have unique sprites,
|
|
|
|
// making it possible to import any actor from any game into any other
|
|
|
|
// game without jumping through hoops to resolve duplicate sprite names.
|
|
|
|
// You just need to know what the sprite's new name is.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2009-04-30 11:10:38 +00:00
|
|
|
void FWadCollection::RenameSprites ()
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
bool renameAll;
|
2008-08-06 19:25:59 +00:00
|
|
|
bool MNTRZfound = false;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
static const DWORD HereticRenames[] =
|
|
|
|
{ MAKE_ID('H','E','A','D'), MAKE_ID('L','I','C','H'), // Ironlich
|
|
|
|
};
|
|
|
|
|
|
|
|
static const DWORD HexenRenames[] =
|
|
|
|
{ MAKE_ID('B','A','R','L'), MAKE_ID('Z','B','A','R'), // ZBarrel
|
|
|
|
MAKE_ID('A','R','M','1'), MAKE_ID('A','R','_','1'), // MeshArmor
|
|
|
|
MAKE_ID('A','R','M','2'), MAKE_ID('A','R','_','2'), // FalconShield
|
|
|
|
MAKE_ID('A','R','M','3'), MAKE_ID('A','R','_','3'), // PlatinumHelm
|
|
|
|
MAKE_ID('A','R','M','4'), MAKE_ID('A','R','_','4'), // AmuletOfWarding
|
|
|
|
MAKE_ID('S','U','I','T'), MAKE_ID('Z','S','U','I'), // ZSuitOfArmor and ZArmorChunk
|
|
|
|
MAKE_ID('T','R','E','1'), MAKE_ID('Z','T','R','E'), // ZTree and ZTreeDead
|
|
|
|
MAKE_ID('T','R','E','2'), MAKE_ID('T','R','E','S'), // ZTreeSwamp150
|
|
|
|
MAKE_ID('C','A','N','D'), MAKE_ID('B','C','A','N'), // ZBlueCandle
|
|
|
|
MAKE_ID('R','O','C','K'), MAKE_ID('R','O','K','K'), // rocks and dirt in a_debris.cpp
|
|
|
|
MAKE_ID('W','A','T','R'), MAKE_ID('H','W','A','T'), // Strife also has WATR
|
|
|
|
MAKE_ID('G','I','B','S'), MAKE_ID('P','O','L','5'), // RealGibs
|
|
|
|
MAKE_ID('E','G','G','M'), MAKE_ID('P','R','K','M'), // PorkFX
|
2008-08-06 19:25:59 +00:00
|
|
|
MAKE_ID('I','N','V','U'), MAKE_ID('D','E','F','N'), // Icon of the Defender
|
2006-02-24 04:48:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const DWORD StrifeRenames[] =
|
|
|
|
{ MAKE_ID('M','I','S','L'), MAKE_ID('S','M','I','S'), // lots of places
|
|
|
|
MAKE_ID('A','R','M','1'), MAKE_ID('A','R','M','3'), // MetalArmor
|
|
|
|
MAKE_ID('A','R','M','2'), MAKE_ID('A','R','M','4'), // LeatherArmor
|
|
|
|
MAKE_ID('P','M','A','P'), MAKE_ID('S','M','A','P'), // StrifeMap
|
|
|
|
MAKE_ID('T','L','M','P'), MAKE_ID('T','E','C','H'), // TechLampSilver and TechLampBrass
|
|
|
|
MAKE_ID('T','R','E','1'), MAKE_ID('T','R','E','T'), // TreeStub
|
|
|
|
MAKE_ID('B','A','R','1'), MAKE_ID('B','A','R','C'), // BarricadeColumn
|
|
|
|
MAKE_ID('S','H','T','2'), MAKE_ID('M','P','U','F'), // MaulerPuff
|
|
|
|
MAKE_ID('B','A','R','L'), MAKE_ID('B','B','A','R'), // StrifeBurningBarrel
|
|
|
|
MAKE_ID('T','R','C','H'), MAKE_ID('T','R','H','L'), // SmallTorchLit
|
|
|
|
MAKE_ID('S','H','R','D'), MAKE_ID('S','H','A','R'), // glass shards
|
|
|
|
MAKE_ID('B','L','S','T'), MAKE_ID('M','A','U','L'), // Mauler
|
|
|
|
MAKE_ID('L','O','G','G'), MAKE_ID('L','O','G','W'), // StickInWater
|
|
|
|
MAKE_ID('V','A','S','E'), MAKE_ID('V','A','Z','E'), // Pot and Pitcher
|
|
|
|
MAKE_ID('C','N','D','L'), MAKE_ID('K','N','D','L'), // Candle
|
|
|
|
MAKE_ID('P','O','T','1'), MAKE_ID('M','P','O','T'), // MetalPot
|
|
|
|
MAKE_ID('S','P','I','D'), MAKE_ID('S','T','L','K'), // Stalker
|
|
|
|
};
|
|
|
|
|
|
|
|
const DWORD *renames;
|
|
|
|
int numrenames;
|
|
|
|
|
|
|
|
switch (gameinfo.gametype)
|
|
|
|
{
|
|
|
|
case GAME_Doom:
|
|
|
|
default:
|
|
|
|
// Doom's sprites don't get renamed.
|
|
|
|
return;
|
|
|
|
|
|
|
|
case GAME_Heretic:
|
|
|
|
renames = HereticRenames;
|
|
|
|
numrenames = sizeof(HereticRenames)/8;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GAME_Hexen:
|
|
|
|
renames = HexenRenames;
|
|
|
|
numrenames = sizeof(HexenRenames)/8;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GAME_Strife:
|
|
|
|
renames = StrifeRenames;
|
|
|
|
numrenames = sizeof(StrifeRenames)/8;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-04-30 11:10:38 +00:00
|
|
|
for (DWORD i=0; i< LumpInfo.Size(); i++)
|
2008-08-06 19:25:59 +00:00
|
|
|
{
|
2009-04-30 11:10:38 +00:00
|
|
|
// check for full Minotaur animations. If this is not found
|
|
|
|
// some frames need to be renamed.
|
|
|
|
if (LumpInfo[i].lump->Namespace == ns_sprites)
|
2008-08-06 19:25:59 +00:00
|
|
|
{
|
2009-08-02 03:38:57 +00:00
|
|
|
if (LumpInfo[i].lump->dwName == MAKE_ID('M', 'N', 'T', 'R') && LumpInfo[i].lump->Name[4] == 'Z' )
|
2009-04-30 11:10:38 +00:00
|
|
|
{
|
|
|
|
MNTRZfound = true;
|
|
|
|
break;
|
|
|
|
}
|
2008-08-06 19:25:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-28 17:19:48 +00:00
|
|
|
renameAll = !!Args->CheckParm ("-oldsprites") || nospriterename;
|
2009-04-30 11:10:38 +00:00
|
|
|
|
|
|
|
for (DWORD i = 0; i < LumpInfo.Size(); i++)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-04-30 11:10:38 +00:00
|
|
|
if (LumpInfo[i].lump->Namespace == ns_sprites)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-04-30 11:10:38 +00:00
|
|
|
// Only sprites in the IWAD normally get renamed
|
|
|
|
if (renameAll || LumpInfo[i].wadnum == IWAD_FILENUM)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-04-30 11:10:38 +00:00
|
|
|
for (int j = 0; j < numrenames; ++j)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-08-02 03:38:57 +00:00
|
|
|
if (LumpInfo[i].lump->dwName == renames[j*2])
|
2009-04-30 11:10:38 +00:00
|
|
|
{
|
2009-08-02 03:38:57 +00:00
|
|
|
LumpInfo[i].lump->dwName = renames[j*2+1];
|
2009-04-30 11:10:38 +00:00
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2009-04-30 11:10:38 +00:00
|
|
|
if (gameinfo.gametype == GAME_Hexen)
|
2008-08-06 19:25:59 +00:00
|
|
|
{
|
2009-04-30 11:10:38 +00:00
|
|
|
if (CheckLumpName (i, "ARTIINVU"))
|
|
|
|
{
|
|
|
|
LumpInfo[i].lump->Name[4]='D'; LumpInfo[i].lump->Name[5]='E';
|
|
|
|
LumpInfo[i].lump->Name[6]='F'; LumpInfo[i].lump->Name[7]='N';
|
|
|
|
}
|
2008-08-06 19:25:59 +00:00
|
|
|
}
|
|
|
|
}
|
2009-04-30 11:10:38 +00:00
|
|
|
|
|
|
|
if (!MNTRZfound)
|
2008-08-06 19:25:59 +00:00
|
|
|
{
|
2009-08-02 03:38:57 +00:00
|
|
|
if (LumpInfo[i].lump->dwName == MAKE_ID('M', 'N', 'T', 'R'))
|
2008-08-06 19:25:59 +00:00
|
|
|
{
|
2009-04-30 11:10:38 +00:00
|
|
|
if (LumpInfo[i].lump->Name[4] >= 'F' && LumpInfo[i].lump->Name[4] <= 'K')
|
|
|
|
{
|
|
|
|
LumpInfo[i].lump->Name[4] += 'U' - 'F';
|
|
|
|
}
|
2008-08-06 19:25:59 +00:00
|
|
|
}
|
|
|
|
}
|
2009-04-30 11:10:38 +00:00
|
|
|
|
|
|
|
// When not playing Doom rename all BLOD sprites to BLUD so that
|
|
|
|
// the same blood states can be used everywhere
|
|
|
|
if (!(gameinfo.gametype & GAME_DoomChex))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-08-02 03:38:57 +00:00
|
|
|
if (LumpInfo[i].lump->dwName == MAKE_ID('B', 'L', 'O', 'D'))
|
2009-04-30 11:10:38 +00:00
|
|
|
{
|
2009-08-02 03:38:57 +00:00
|
|
|
LumpInfo[i].lump->dwName = MAKE_ID('B', 'L', 'U', 'D');
|
2009-04-30 11:10:38 +00:00
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-01 02:42:14 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// RenameNerve
|
|
|
|
//
|
|
|
|
// Renames map headers and map name pictures in nerve.wad so as to load it
|
|
|
|
// alongside Doom II and offer both episodes without causing conflicts.
|
|
|
|
// MD5 checksum for NERVE.WAD: 967d5ae23daf45196212ae1b605da3b0
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
void FWadCollection::RenameNerve ()
|
|
|
|
{
|
|
|
|
if (gameinfo.gametype != GAME_Doom)
|
|
|
|
return;
|
|
|
|
|
|
|
|
bool found = false;
|
|
|
|
BYTE cksum[16];
|
2012-11-03 00:38:58 +00:00
|
|
|
static const BYTE nerve[16] = { 0x96, 0x7d, 0x5a, 0xe2, 0x3d, 0xaf, 0x45, 0x19,
|
2012-11-01 02:42:14 +00:00
|
|
|
0x62, 0x12, 0xae, 0x1b, 0x60, 0x5d, 0xa3, 0xb0 };
|
|
|
|
size_t nervesize = 3819855; // NERVE.WAD's file size
|
|
|
|
int w = IWAD_FILENUM;
|
|
|
|
while (++w < GetNumWads())
|
|
|
|
{
|
|
|
|
FileReader *fr = GetFileReader(w);
|
2012-11-03 00:38:58 +00:00
|
|
|
if (fr == NULL)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2013-01-21 22:30:30 +00:00
|
|
|
if (fr->GetLength() != (long)nervesize)
|
2012-11-01 02:42:14 +00:00
|
|
|
{
|
|
|
|
// Skip MD5 computation when there is a
|
|
|
|
// cheaper way to know this is not the file
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
fr->Seek(0, SEEK_SET);
|
|
|
|
MD5Context md5;
|
|
|
|
md5.Update(fr, fr->GetLength());
|
|
|
|
md5.Final(cksum);
|
|
|
|
if (memcmp(nerve, cksum, 16) == 0)
|
|
|
|
{
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found)
|
|
|
|
return;
|
|
|
|
|
2012-11-03 00:38:58 +00:00
|
|
|
for (int i = GetFirstLump(w); i <= GetLastLump(w); i++)
|
2012-11-01 02:42:14 +00:00
|
|
|
{
|
|
|
|
// Only rename the maps from NERVE.WAD
|
2012-11-03 00:38:58 +00:00
|
|
|
assert(LumpInfo[i].wadnum == w);
|
|
|
|
if (LumpInfo[i].lump->dwName == MAKE_ID('C', 'W', 'I', 'L'))
|
2012-11-01 02:42:14 +00:00
|
|
|
{
|
2012-11-03 00:38:58 +00:00
|
|
|
LumpInfo[i].lump->Name[0] = 'N';
|
|
|
|
}
|
|
|
|
else if (LumpInfo[i].lump->dwName == MAKE_ID('M', 'A', 'P', '0'))
|
|
|
|
{
|
|
|
|
LumpInfo[i].lump->Name[6] = LumpInfo[i].lump->Name[4];
|
|
|
|
LumpInfo[i].lump->Name[5] = '0';
|
|
|
|
LumpInfo[i].lump->Name[4] = 'L';
|
|
|
|
LumpInfo[i].lump->dwName = MAKE_ID('L', 'E', 'V', 'E');
|
2012-11-01 02:42:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-14 09:47:46 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// FixMacHexen
|
|
|
|
//
|
|
|
|
// Rename unused high resolution font lumps because they are incorrectly
|
|
|
|
// treated as extended characters
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void FWadCollection::FixMacHexen()
|
|
|
|
{
|
|
|
|
if (GAME_Hexen != gameinfo.gametype)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = GetFirstLump(IWAD_FILENUM), last = GetLastLump(IWAD_FILENUM); i <= last; ++i)
|
|
|
|
{
|
|
|
|
assert(IWAD_FILENUM == LumpInfo[i].wadnum);
|
|
|
|
|
|
|
|
FResourceLump* const lump = LumpInfo[i].lump;
|
|
|
|
char* const name = lump->Name;
|
|
|
|
|
|
|
|
// Unwanted lumps are named like FONTA??1
|
|
|
|
|
|
|
|
if (8 == strlen(name)
|
|
|
|
&& MAKE_ID('F', 'O', 'N', 'T') == lump->dwName
|
|
|
|
&& 'A' == name[4] && '1' == name[7]
|
|
|
|
&& isdigit(name[5]) && isdigit(name[6]))
|
|
|
|
{
|
|
|
|
name[0] = '\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// W_FindLump
|
|
|
|
//
|
|
|
|
// Find a named lump. Specifically allows duplicates for merging of e.g.
|
|
|
|
// SNDINFO lumps.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
int FWadCollection::FindLump (const char *name, int *lastlump, bool anyns)
|
|
|
|
{
|
2009-08-02 03:38:57 +00:00
|
|
|
union
|
|
|
|
{
|
|
|
|
char name8[8];
|
|
|
|
QWORD qname;
|
|
|
|
};
|
2006-02-24 04:48:15 +00:00
|
|
|
LumpRecord *lump_p;
|
|
|
|
|
|
|
|
uppercopy (name8, name);
|
|
|
|
|
2009-11-12 02:47:28 +00:00
|
|
|
assert(lastlump != NULL && *lastlump >= 0);
|
2006-08-17 22:10:50 +00:00
|
|
|
lump_p = &LumpInfo[*lastlump];
|
|
|
|
while (lump_p < &LumpInfo[NumLumps])
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
FResourceLump *lump = lump_p->lump;
|
|
|
|
|
2009-08-02 03:38:57 +00:00
|
|
|
if ((anyns || lump->Namespace == ns_global) && lump->qwName == qname)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-05-15 10:39:40 +00:00
|
|
|
int lump = int(lump_p - &LumpInfo[0]);
|
2006-02-24 04:48:15 +00:00
|
|
|
*lastlump = lump + 1;
|
|
|
|
return lump;
|
|
|
|
}
|
|
|
|
lump_p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*lastlump = NumLumps;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-03-13 08:28:13 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// W_FindLumpMulti
|
|
|
|
//
|
|
|
|
// Find a named lump. Specifically allows duplicates for merging of e.g.
|
|
|
|
// SNDINFO lumps. Returns everything having one of the passed names.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
int FWadCollection::FindLumpMulti (const char **names, int *lastlump, bool anyns, int *nameindex)
|
|
|
|
{
|
|
|
|
LumpRecord *lump_p;
|
|
|
|
|
|
|
|
assert(lastlump != NULL && *lastlump >= 0);
|
|
|
|
lump_p = &LumpInfo[*lastlump];
|
|
|
|
while (lump_p < &LumpInfo[NumLumps])
|
|
|
|
{
|
|
|
|
FResourceLump *lump = lump_p->lump;
|
|
|
|
|
|
|
|
if (anyns || lump->Namespace == ns_global)
|
|
|
|
{
|
|
|
|
|
|
|
|
for(const char **name = names; *name != NULL; name++)
|
|
|
|
{
|
|
|
|
if (!strnicmp(*name, lump->Name, 8))
|
|
|
|
{
|
|
|
|
int lump = int(lump_p - &LumpInfo[0]);
|
|
|
|
*lastlump = lump + 1;
|
|
|
|
if (nameindex != NULL) *nameindex = int(name - names);
|
|
|
|
return lump;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lump_p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*lastlump = NumLumps;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// W_CheckLumpName
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
bool FWadCollection::CheckLumpName (int lump, const char *name)
|
|
|
|
{
|
|
|
|
if ((size_t)lump >= NumLumps)
|
|
|
|
return false;
|
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
return !strnicmp (LumpInfo[lump].lump->Name, name, 8);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// W_GetLumpName
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void FWadCollection::GetLumpName (char *to, int lump) const
|
|
|
|
{
|
|
|
|
if ((size_t)lump >= NumLumps)
|
|
|
|
*to = 0;
|
|
|
|
else
|
2009-04-23 22:49:38 +00:00
|
|
|
uppercopy (to, LumpInfo[lump].lump->Name);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2014-05-18 22:38:46 +00:00
|
|
|
void FWadCollection::GetLumpName(FString &to, int lump) const
|
|
|
|
{
|
|
|
|
if ((size_t)lump >= NumLumps)
|
|
|
|
to = FString();
|
|
|
|
else {
|
|
|
|
to = LumpInfo[lump].lump->Name;
|
|
|
|
to.ToUpper();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-03 22:45:01 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// FWadCollection :: GetLumpFullName
|
|
|
|
//
|
|
|
|
// Returns the lump's full name if it has one or its short name if not.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
const char *FWadCollection::GetLumpFullName (int lump) const
|
|
|
|
{
|
|
|
|
if ((size_t)lump >= NumLumps)
|
|
|
|
return NULL;
|
2015-04-04 00:59:42 +00:00
|
|
|
else if (LumpInfo[lump].lump->FullName.IsNotEmpty())
|
2009-04-23 22:49:38 +00:00
|
|
|
return LumpInfo[lump].lump->FullName;
|
2006-05-03 22:45:01 +00:00
|
|
|
else
|
2009-04-23 22:49:38 +00:00
|
|
|
return LumpInfo[lump].lump->Name;
|
2006-05-03 22:45:01 +00:00
|
|
|
}
|
|
|
|
|
2008-04-03 03:19:21 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// FWadCollection :: GetLumpFullPath
|
|
|
|
//
|
|
|
|
// Returns the name of the lump's wad prefixed to the lump's full name.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
FString FWadCollection::GetLumpFullPath(int lump) const
|
|
|
|
{
|
|
|
|
FString foo;
|
|
|
|
|
|
|
|
if ((size_t) lump < NumLumps)
|
|
|
|
{
|
|
|
|
foo << GetWadName(LumpInfo[lump].wadnum) << ':' << GetLumpFullName(lump);
|
|
|
|
}
|
|
|
|
return foo;
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// GetLumpNamespace
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
int FWadCollection::GetLumpNamespace (int lump) const
|
|
|
|
{
|
|
|
|
if ((size_t)lump >= NumLumps)
|
|
|
|
return ns_global;
|
|
|
|
else
|
2009-04-23 22:49:38 +00:00
|
|
|
return LumpInfo[lump].lump->Namespace;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2010-03-18 05:01:10 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// FWadCollection :: GetLumpIndexNum
|
|
|
|
//
|
|
|
|
// Returns the index number for this lump. This is *not* the lump's position
|
|
|
|
// in the lump directory, but rather a special value that RFF can associate
|
|
|
|
// with files. Other archive types will return 0, since they don't have it.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
int FWadCollection::GetLumpIndexNum(int lump) const
|
|
|
|
{
|
|
|
|
if ((size_t)lump >= NumLumps)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return LumpInfo[lump].lump->GetIndexNum();
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// W_GetLumpFile
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
int FWadCollection::GetLumpFile (int lump) const
|
|
|
|
{
|
2006-08-17 22:10:50 +00:00
|
|
|
if ((size_t)lump >= LumpInfo.Size())
|
2006-02-24 04:48:15 +00:00
|
|
|
return -1;
|
|
|
|
return LumpInfo[lump].wadnum;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// W_ReadLump
|
|
|
|
//
|
|
|
|
// Loads the lump into the given buffer, which must be >= W_LumpLength().
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void FWadCollection::ReadLump (int lump, void *dest)
|
|
|
|
{
|
|
|
|
FWadLump lumpr = OpenLumpNum (lump);
|
|
|
|
long size = lumpr.GetLength ();
|
|
|
|
long numread = lumpr.Read (dest, size);
|
|
|
|
|
|
|
|
if (numread != size)
|
|
|
|
{
|
|
|
|
I_Error ("W_ReadLump: only read %ld of %ld on lump %i\n",
|
|
|
|
numread, size, lump);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// ReadLump - variant 2
|
|
|
|
//
|
|
|
|
// Loads the lump into a newly created buffer and returns it.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
FMemLump FWadCollection::ReadLump (int lump)
|
|
|
|
{
|
2007-01-25 04:02:06 +00:00
|
|
|
return FMemLump(FString(ELumpNum(lump)));
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// OpenLumpNum
|
|
|
|
//
|
|
|
|
// Returns a copy of the file object for a lump's wad and positions its
|
|
|
|
// file pointer at the beginning of the lump.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
FWadLump FWadCollection::OpenLumpNum (int lump)
|
|
|
|
{
|
2006-08-17 22:10:50 +00:00
|
|
|
if ((unsigned)lump >= (unsigned)LumpInfo.Size())
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
I_Error ("W_OpenLumpNum: %u >= NumLumps", lump);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
return FWadLump(LumpInfo[lump].lump);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// ReopenLumpNum
|
|
|
|
//
|
|
|
|
// Similar to OpenLumpNum, except a new, independant file object is created
|
|
|
|
// for the lump's wad. Use this when you won't read the lump's data all at
|
|
|
|
// once (e.g. for streaming an Ogg Vorbis stream from a wad as music).
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
FWadLump *FWadCollection::ReopenLumpNum (int lump)
|
|
|
|
{
|
2006-08-17 22:10:50 +00:00
|
|
|
if ((unsigned)lump >= (unsigned)LumpInfo.Size())
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
Note: I have not tried compiling these recent changes under Linux. I wouldn't
be surprised if it doesn't work.
- Reorganized the network startup loops so now they are event driven. There is
a single function that gets called to drive it, and it uses callbacks to
perform the different stages of the synchronization. This lets me have a nice,
responsive abort button instead of the previous unannounced hit-escape-to-
abort behavior, and I think the rearranged code is slightly easier to
understand too.
- Increased the number of bytes for version info during D_ArbitrateNetStart(),
in preparation for the day when NETGAMEVERSION requires more than one byte.
- I noticed an issue with Vista RC1 and the new fatal error setup. Even after
releasing a DirectDraw or Direct3D interface, the DWM can still use the
last image drawn using them when it composites the window. It doesn't always
do it but it does often enough that it is a real problem. At this point, I
don't know if it's a problem with the release version of Vista or not.
After messing around, I discovered the problem was caused by ~Win32Video()
hiding the window and then having it immediately shown soon after. The DWM
kept an image of the window to do the transition effect with, and then when
it didn't get a chance to do the transition, it didn't properly forget about
its saved image and kept plastering it on top of everything else
underneath.
- Added a network synchronization panel to the window during netgame startup.
- Fixed: PClass::CreateDerivedClass() must initialize StateList to NULL.
Otherwise, classic DECORATE definitions generate a big, fat crash.
- Resurrected the R_Init progress bar, now as a standard Windows control.
- Removed the sound failure dialog. The FMOD setup already defaulted to no
sound if initialization failed, so this only applies when snd_output is set
to "alternate" which now also falls back to no sound. In addition, it wasn't
working right, and I didn't feel like fixing it for the probably 0% of users
it affected.
- Fixed: The edit control used for logging output added text in reverse order
on Win9x.
- Went back to the roots and made graphics initialization one of the last
things to happen during setup. Now the startup text is visible again. More
importantly, the main window is no longer created invisible, which seems
to cause trouble with it not always appearing in the taskbar. The fatal
error dialog is now also embedded in the main window instead of being a
separate modal dialog, so you can play with the log window to see any
problems that might be reported there.
Rather than completely restoring the original startup order, I tried to
keep things as close to the way they were with early graphics startup. In
particular, V_Init() now creates a dummy screen so that things that need
screen dimensions can get them. It gets replaced by the real screen later
in I_InitGraphics(). Will need to check this under Linux to make sure it
didn't cause any problems there.
- Removed the following stubs that just called functions in Video:
- I_StartModeIterator()
- I_NextMode()
- I_DisplayType()
I_FullscreenChanged() was also removed, and a new fullscreen parameter
was added to IVideo::StartModeIterator(), since that's all it controlled.
- Renamed I_InitHardware() back to I_InitGraphics(), since that's all it's
initialized post-1.22.
SVN r416 (trunk)
2006-12-19 04:09:10 +00:00
|
|
|
I_Error ("W_ReopenLumpNum: %u >= NumLumps", lump);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
return new FWadLump(LumpInfo[lump].lump, true);
|
2009-04-15 03:58:10 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 21:28:05 +00:00
|
|
|
FWadLump *FWadCollection::ReopenLumpNumNewFile (int lump)
|
|
|
|
{
|
|
|
|
if ((unsigned)lump >= (unsigned)LumpInfo.Size())
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return new FWadLump(lump, LumpInfo[lump].lump);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-14 15:56:56 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// GetFileReader
|
|
|
|
//
|
|
|
|
// Retrieves the FileReader object to access the given WAD
|
2006-08-17 22:10:50 +00:00
|
|
|
// Careful: This is only useful for real WAD files!
|
2006-06-14 15:56:56 +00:00
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
FileReader *FWadCollection::GetFileReader(int wadnum)
|
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
if ((DWORD)wadnum >= Files.Size())
|
2006-06-14 15:56:56 +00:00
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
2009-04-23 22:49:38 +00:00
|
|
|
return Files[wadnum]->GetReader();
|
2006-06-14 15:56:56 +00:00
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// W_GetWadName
|
|
|
|
//
|
|
|
|
// Returns the name of the given wad.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
const char *FWadCollection::GetWadName (int wadnum) const
|
|
|
|
{
|
|
|
|
const char *name, *slash;
|
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
if ((DWORD)wadnum >= Files.Size())
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
name = Files[wadnum]->Filename;
|
2006-02-24 04:48:15 +00:00
|
|
|
slash = strrchr (name, '/');
|
|
|
|
return slash != NULL ? slash+1 : name;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
int FWadCollection::GetFirstLump (int wadnum) const
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
if ((DWORD)wadnum >= Files.Size())
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
return Files[wadnum]->GetFirstLump();
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2006-04-14 12:58:52 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
int FWadCollection::GetLastLump (int wadnum) const
|
2006-04-14 12:58:52 +00:00
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
if ((DWORD)wadnum >= Files.Size())
|
2006-04-14 12:58:52 +00:00
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
return 0;
|
2006-04-14 12:58:52 +00:00
|
|
|
}
|
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
return Files[wadnum]->GetFirstLump() + Files[wadnum]->LumpCount() - 1;
|
2006-04-14 12:58:52 +00:00
|
|
|
}
|
|
|
|
|
2006-06-15 03:31:19 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
2009-04-23 22:49:38 +00:00
|
|
|
// W_GetWadFullName
|
2006-06-15 03:31:19 +00:00
|
|
|
//
|
2009-04-23 22:49:38 +00:00
|
|
|
// Returns the name of the given wad, including any path
|
2006-06-15 03:31:19 +00:00
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
const char *FWadCollection::GetWadFullName (int wadnum) const
|
2006-06-15 03:31:19 +00:00
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
if ((unsigned int)wadnum >= Files.Size())
|
2006-06-15 03:31:19 +00:00
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
return NULL;
|
2006-06-15 03:31:19 +00:00
|
|
|
}
|
2009-04-23 22:49:38 +00:00
|
|
|
|
|
|
|
return Files[wadnum]->Filename;
|
2006-06-15 03:31:19 +00:00
|
|
|
}
|
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
2009-04-23 22:49:38 +00:00
|
|
|
// IsUncompressedFile
|
2006-02-24 04:48:15 +00:00
|
|
|
//
|
2009-04-23 22:49:38 +00:00
|
|
|
// Returns true when the lump is available as an uncompressed portion of
|
|
|
|
// a file. The music player can play such lumps by streaming but anything
|
|
|
|
// else has to be loaded into memory first.
|
2006-02-24 04:48:15 +00:00
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
bool FWadCollection::IsUncompressedFile(int lump) const
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
if ((unsigned)lump >= (unsigned)NumLumps)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
I_Error ("IsUncompressedFile: %u >= NumLumps",lump);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2009-04-23 22:49:38 +00:00
|
|
|
|
|
|
|
FResourceLump *l = LumpInfo[lump].lump;
|
|
|
|
FileReader *f = l->GetReader();
|
|
|
|
|
|
|
|
// We can access the file only if we get the FILE pointer from the FileReader here.
|
|
|
|
// Any other case means it won't work.
|
|
|
|
return (f != NULL && f->GetFile() != NULL);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
2009-04-23 22:49:38 +00:00
|
|
|
// IsEncryptedFile
|
|
|
|
//
|
|
|
|
// Returns true if the first 256 bytes of the lump are encrypted for Blood.
|
2006-02-24 04:48:15 +00:00
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
bool FWadCollection::IsEncryptedFile(int lump) const
|
2006-04-14 16:25:57 +00:00
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
if ((unsigned)lump >= (unsigned)NumLumps)
|
2006-04-14 16:25:57 +00:00
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
return false;
|
2006-04-14 16:25:57 +00:00
|
|
|
}
|
2009-04-23 22:49:38 +00:00
|
|
|
return !!(LumpInfo[lump].lump->Flags & LUMPF_BLOODCRYPT);
|
2006-04-14 16:25:57 +00:00
|
|
|
}
|
2009-04-15 03:58:10 +00:00
|
|
|
|
2006-04-14 16:25:57 +00:00
|
|
|
|
|
|
|
// FWadLump -----------------------------------------------------------------
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
FWadLump::FWadLump ()
|
2009-04-23 22:49:38 +00:00
|
|
|
: FileReader(), Lump(NULL)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
FWadLump::FWadLump (const FWadLump ©)
|
2011-03-11 00:44:38 +00:00
|
|
|
: FileReader()
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-04-14 16:25:57 +00:00
|
|
|
// This must be defined isn't called.
|
2006-02-24 04:48:15 +00:00
|
|
|
File = copy.File;
|
2006-06-15 03:31:19 +00:00
|
|
|
Length = copy.Length;
|
|
|
|
FilePos = copy.FilePos;
|
|
|
|
StartPos = copy.StartPos;
|
|
|
|
CloseOnDestruct = false;
|
2009-04-23 22:49:38 +00:00
|
|
|
if ((Lump = copy.Lump)) Lump->CacheLump();
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2006-04-14 16:25:57 +00:00
|
|
|
#ifdef _DEBUG
|
|
|
|
FWadLump & FWadLump::operator= (const FWadLump ©)
|
|
|
|
{
|
|
|
|
// Only the debug build actually calls this!
|
|
|
|
File = copy.File;
|
2006-06-15 03:31:19 +00:00
|
|
|
Length = copy.Length;
|
|
|
|
FilePos = copy.FilePos;
|
|
|
|
StartPos = copy.StartPos;
|
2009-04-23 22:49:38 +00:00
|
|
|
CloseOnDestruct = false;
|
|
|
|
if ((Lump = copy.Lump)) Lump->CacheLump();
|
2006-04-14 16:25:57 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
FWadLump::FWadLump(FResourceLump *lump, bool alwayscache)
|
|
|
|
: FileReader()
|
2006-04-14 16:25:57 +00:00
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
FileReader *f = lump->GetReader();
|
2006-04-14 16:25:57 +00:00
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
if (f != NULL && f->GetFile() != NULL && !alwayscache)
|
|
|
|
{
|
|
|
|
// Uncompressed lump in a file
|
|
|
|
File = f->GetFile();
|
|
|
|
Length = lump->LumpSize;
|
|
|
|
StartPos = FilePos = lump->GetFileOffset();
|
|
|
|
Lump = NULL;
|
|
|
|
}
|
|
|
|
else
|
2006-06-15 03:31:19 +00:00
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
File = NULL;
|
|
|
|
Length = lump->LumpSize;
|
|
|
|
StartPos = FilePos = 0;
|
|
|
|
Lump = lump;
|
|
|
|
Lump->CacheLump();
|
2006-06-15 03:31:19 +00:00
|
|
|
}
|
2006-04-14 16:25:57 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 21:28:05 +00:00
|
|
|
FWadLump::FWadLump(int lumpnum, FResourceLump *lump)
|
|
|
|
: FileReader()
|
|
|
|
{
|
|
|
|
FileReader *f = lump->GetReader();
|
|
|
|
|
|
|
|
if (f != NULL && f->GetFile() != NULL)
|
|
|
|
{
|
|
|
|
// Uncompressed lump in a file. For this we will have to open a new FILE, since we need it for streaming
|
|
|
|
int fileno = Wads.GetLumpFile(lumpnum);
|
|
|
|
const char *filename = Wads.GetWadFullName(fileno);
|
|
|
|
File = fopen(filename, "rb");
|
|
|
|
if (File != NULL)
|
|
|
|
{
|
|
|
|
Length = lump->LumpSize;
|
|
|
|
StartPos = FilePos = lump->GetFileOffset();
|
|
|
|
Lump = NULL;
|
|
|
|
CloseOnDestruct = true;
|
|
|
|
Seek(0, SEEK_SET);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
File = NULL;
|
|
|
|
Length = lump->LumpSize;
|
|
|
|
StartPos = FilePos = 0;
|
|
|
|
Lump = lump;
|
|
|
|
Lump->CacheLump();
|
|
|
|
}
|
|
|
|
|
2006-04-14 16:25:57 +00:00
|
|
|
FWadLump::~FWadLump()
|
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
if (Lump != NULL)
|
2006-04-14 16:25:57 +00:00
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
Lump->ReleaseCache();
|
2006-04-14 16:25:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
long FWadLump::Seek (long offset, int origin)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
if (Lump != NULL)
|
2006-04-14 16:25:57 +00:00
|
|
|
{
|
|
|
|
switch (origin)
|
|
|
|
{
|
|
|
|
case SEEK_CUR:
|
2006-06-15 03:31:19 +00:00
|
|
|
offset += FilePos;
|
2006-04-14 16:25:57 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SEEK_END:
|
2006-06-15 03:31:19 +00:00
|
|
|
offset += Length;
|
2006-04-14 16:25:57 +00:00
|
|
|
break;
|
2006-06-15 03:31:19 +00:00
|
|
|
|
2006-04-14 16:25:57 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2006-06-15 03:31:19 +00:00
|
|
|
FilePos = clamp<long> (offset, 0, Length);
|
2006-04-14 16:25:57 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2006-06-15 03:31:19 +00:00
|
|
|
return FileReader::Seek(offset, origin);
|
2006-04-14 16:25:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
long FWadLump::Read (void *buffer, long len)
|
|
|
|
{
|
2006-06-15 03:31:19 +00:00
|
|
|
long numread;
|
|
|
|
long startread = FilePos;
|
|
|
|
|
2009-04-23 22:49:38 +00:00
|
|
|
if (Lump != NULL)
|
2006-04-14 16:25:57 +00:00
|
|
|
{
|
2006-06-15 03:31:19 +00:00
|
|
|
if (FilePos + len > Length)
|
|
|
|
{
|
|
|
|
len = Length - FilePos;
|
|
|
|
}
|
2009-04-23 22:49:38 +00:00
|
|
|
memcpy(buffer, Lump->Cache + FilePos, len);
|
2006-06-15 03:31:19 +00:00
|
|
|
FilePos += len;
|
|
|
|
numread = len;
|
2006-04-14 16:25:57 +00:00
|
|
|
}
|
2006-06-15 03:31:19 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
numread = FileReader::Read(buffer, len);
|
|
|
|
}
|
|
|
|
return numread;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2008-04-11 10:16:29 +00:00
|
|
|
char *FWadLump::Gets(char *strbuf, int len)
|
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
if (Lump != NULL)
|
2008-04-11 10:16:29 +00:00
|
|
|
{
|
2009-04-23 22:49:38 +00:00
|
|
|
return GetsFromBuffer(Lump->Cache, strbuf, len);
|
2008-04-11 10:16:29 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return FileReader::Gets(strbuf, len);
|
|
|
|
}
|
|
|
|
return strbuf;
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
// FMemLump -----------------------------------------------------------------
|
|
|
|
|
|
|
|
FMemLump::FMemLump ()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
FMemLump::FMemLump (const FMemLump ©)
|
|
|
|
{
|
|
|
|
Block = copy.Block;
|
|
|
|
}
|
|
|
|
|
|
|
|
FMemLump &FMemLump::operator = (const FMemLump ©)
|
|
|
|
{
|
|
|
|
Block = copy.Block;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2007-01-25 04:02:06 +00:00
|
|
|
FMemLump::FMemLump (const FString &source)
|
|
|
|
: Block (source)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
FMemLump::~FMemLump ()
|
|
|
|
{
|
2007-01-25 04:02:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
FString::FString (ELumpNum lumpnum)
|
|
|
|
{
|
|
|
|
FWadLump lumpr = Wads.OpenLumpNum ((int)lumpnum);
|
|
|
|
long size = lumpr.GetLength ();
|
|
|
|
AllocBuffer (1 + size);
|
|
|
|
long numread = lumpr.Read (&Chars[0], size);
|
|
|
|
Chars[size] = '\0';
|
|
|
|
|
|
|
|
if (numread != size)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2007-01-25 04:02:06 +00:00
|
|
|
I_Error ("ConstructStringFromLump: Only read %ld of %ld bytes on lump %i (%s)\n",
|
|
|
|
numread, size, lumpnum, Wads.GetLumpFullName((int)lumpnum));
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
2006-09-14 00:02:31 +00:00
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// PrintLastError
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
//#define WIN32_LEAN_AND_MEAN
|
|
|
|
//#include <windows.h>
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
__declspec(dllimport) unsigned long __stdcall FormatMessageA(
|
|
|
|
unsigned long dwFlags,
|
|
|
|
const void *lpSource,
|
|
|
|
unsigned long dwMessageId,
|
|
|
|
unsigned long dwLanguageId,
|
|
|
|
char **lpBuffer,
|
|
|
|
unsigned long nSize,
|
|
|
|
va_list *Arguments
|
|
|
|
);
|
|
|
|
__declspec(dllimport) void * __stdcall LocalFree (void *);
|
|
|
|
__declspec(dllimport) unsigned long __stdcall GetLastError ();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void PrintLastError ()
|
|
|
|
{
|
|
|
|
char *lpMsgBuf;
|
|
|
|
FormatMessageA(0x1300 /*FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
|
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
|
|
FORMAT_MESSAGE_IGNORE_INSERTS*/,
|
|
|
|
NULL,
|
|
|
|
GetLastError(),
|
|
|
|
1 << 10 /*MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)*/, // Default language
|
|
|
|
&lpMsgBuf,
|
|
|
|
0,
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
Printf (TEXTCOLOR_RED " %s\n", lpMsgBuf);
|
|
|
|
// Free the buffer.
|
|
|
|
LocalFree( lpMsgBuf );
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static void PrintLastError ()
|
|
|
|
{
|
|
|
|
Printf (TEXTCOLOR_RED " %s\n", strerror(errno));
|
|
|
|
}
|
|
|
|
#endif
|
2015-04-04 03:42:22 +00:00
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// CCMD LumpNum
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
CCMD(lumpnum)
|
|
|
|
{
|
|
|
|
for (int i = 1; i < argv.argc(); ++i)
|
|
|
|
{
|
|
|
|
Printf("%s: %d\n", argv[i], Wads.CheckNumForName(argv[i]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// CCMD LumpNumFull
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
CCMD(lumpnumfull)
|
|
|
|
{
|
|
|
|
for (int i = 1; i < argv.argc(); ++i)
|
|
|
|
{
|
|
|
|
Printf("%s: %d\n", argv[i], Wads.CheckNumForFullName(argv[i]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|