From 627838f379904585a24b2a279a890993cdfc6dfd Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 31 May 2009 10:49:47 +0000 Subject: [PATCH] - Added loading directories into the lump directory. - fixed: The Dehacked parser could not parse flag values with the highest bit set because it used atoi to convert the string into a number. SVN r1624 (trunk) --- docs/rh-log.txt | 8 +- src/CMakeLists.txt | 1 + src/c_dispatch.cpp | 2 +- src/d_dehacked.cpp | 2 +- src/d_main.cpp | 9 +- src/d_main.h | 2 +- src/resourcefiles/file_directory.cpp | 331 ++++++++++++ src/resourcefiles/file_zip.cpp | 2 +- src/resourcefiles/resourcefile.cpp | 15 +- src/resourcefiles/resourcefile.h | 3 +- src/w_wad.cpp | 12 +- src/w_wad.h | 4 +- zdoom.vcproj | 754 ++++++++++++++------------- 13 files changed, 751 insertions(+), 394 deletions(-) create mode 100644 src/resourcefiles/file_directory.cpp diff --git a/docs/rh-log.txt b/docs/rh-log.txt index c6ac4845f..e234fee0f 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,10 @@ -May 30, 2009 (Changes by Graf Zahl) +May 31, 2009 (Changes by Graf Zahl) +- Added loading directories into the lump directory. +- fixed: The Dehacked parser could not parse flag values with the highest bit + set because it used atoi to convert the string into a number. +- fixed: bouncing sounds were limited to inventory items. + +May 30, 2009 (Changes by Graf Zahl) - Rewrote IWAD detection code to use the ResourceFile classes instead of reading the WAD directory directly. As a side effect it should now be possible to use Zip and 7z for IWADs, too. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ab9281586..544fc2af0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -666,6 +666,7 @@ add_executable( zdoom WIN32 resourcefiles/file_wad.cpp resourcefiles/file_zip.cpp resourcefiles/file_pak.cpp + resourcefiles/file_directory.cpp resourcefiles/resourcefile.cpp sfmt/SFMT.cpp sound/fmodsound.cpp diff --git a/src/c_dispatch.cpp b/src/c_dispatch.cpp index adb833357..91bf72509 100644 --- a/src/c_dispatch.cpp +++ b/src/c_dispatch.cpp @@ -52,6 +52,7 @@ #include "m_crc32.h" #include "v_text.h" #include "d_net.h" +#include "d_main.h" // MACROS ------------------------------------------------------------------ @@ -1367,7 +1368,6 @@ void FConsoleAlias::SafeDelete () } } -extern void D_AddFile (const char *file); static BYTE PullinBad = 2; static const char *PullinFile; diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index f671b01d0..444e3cd18 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -802,7 +802,7 @@ static int PatchThing (int thingy) // Force the top 4 bits to 0 so that the user is forced // to use the mnemonics to change them. And MF_SLIDE doesn't // exist anymore, so 0 that too. - value[0] |= atoi(strval) & 0x0fffdfff; + value[0] |= strtoul(strval, NULL, 10) & 0x0fffdfff; vchanged[0] = true; } else diff --git a/src/d_main.cpp b/src/d_main.cpp index ddf7c1a7c..8c694cee9 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1182,14 +1182,14 @@ CCMD (endgame) // //========================================================================== -void D_AddFile (const char *file) +void D_AddFile (const char *file, bool check) { if (file == NULL) { return; } - if (!FileExists (file)) + if (check && !FileExists (file)) { const char *f = BaseFileSearch (file, ".wad"); if (f == NULL) @@ -1702,8 +1702,11 @@ void D_DoomMain (void) files2->Destroy(); files3->Destroy(); + const char *loaddir = Args->CheckValue("-dir"); + // FIXME: consider the search path list for directory, too. + Printf ("W_Init: Init WADfiles.\n"); - Wads.InitMultipleFiles (&wadfiles); + Wads.InitMultipleFiles (&wadfiles, loaddir); // [RH] Initialize localizable strings. GStrings.LoadStrings (false); diff --git a/src/d_main.h b/src/d_main.h index a577a5d4f..dac990bd3 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -49,7 +49,7 @@ void D_PageTicker (void); void D_PageDrawer (void); void D_AdvanceDemo (void); void D_StartTitle (void); -void D_AddFile (const char *file); +void D_AddFile (const char *file, bool check = true); // [RH] Set this to something to draw an icon during the next screen refresh. diff --git a/src/resourcefiles/file_directory.cpp b/src/resourcefiles/file_directory.cpp new file mode 100644 index 000000000..f2bf77ae3 --- /dev/null +++ b/src/resourcefiles/file_directory.cpp @@ -0,0 +1,331 @@ +/* +** file_directory.cpp +** +**--------------------------------------------------------------------------- +** Copyright 2008-2009 Randy Heit +** Copyright 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. +**--------------------------------------------------------------------------- +** +** +*/ + + +#include +#include +#ifdef _WIN32 +#include +#define stat _stat +#else +#include +#include +#endif +#include +#include +#include +#include +#include +#include + +#include "doomtype.h" +#include "tarray.h" +#include "resourcefile.h" +#include "zstring.h" +#include "cmdlib.h" +#include "doomerrors.h" + + + +//========================================================================== +// +// Zip Lump +// +//========================================================================== + +struct FDirectoryLump : public FResourceLump +{ + virtual FileReader *NewReader(); + virtual int FillCache(); + +private: +}; + + +//========================================================================== +// +// Zip file +// +//========================================================================== + +class FDirectory : public FResourceFile +{ + TArray Lumps; + + static int STACK_ARGS lumpcmp(const void * a, const void * b); + + int AddDirectory(const char *dirpath); + void AddEntry(const char *fullpath, int size); + +public: + FDirectory(const char * dirname); + bool Open(bool quiet); + virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } +}; + + + +//========================================================================== +// +// +// +//========================================================================== + +FDirectory::FDirectory(const char * directory) +: FResourceFile(NULL, NULL) +{ + FString dirname; + + #ifdef _WIN32 + directory = _fullpath(NULL, directory, _MAX_PATH); + #else + // Todo for Linux: Resolve the path befire using it + #endif + dirname = directory; + dirname.ReplaceChars('\\', '/'); + if (dirname[dirname.Len()-1] != '/') dirname += '/'; + free((void*)directory); + Filename = copystring(dirname); +} + + +//========================================================================== +// +// +// +//========================================================================== + +int STACK_ARGS FDirectory::lumpcmp(const void * a, const void * b) +{ + FDirectoryLump * rec1 = (FDirectoryLump *)a; + FDirectoryLump * rec2 = (FDirectoryLump *)b; + + return stricmp(rec1->FullName, rec2->FullName); +} + +#ifdef _WIN32 +//========================================================================== +// +// Windows version +// +//========================================================================== + +int FDirectory::AddDirectory(const char *dirpath) +{ + struct _finddata_t fileinfo; + intptr_t handle; + FString dirmatch; + int count = 0; + + dirmatch = dirpath; + dirmatch += '*'; + + if ((handle = _findfirst(dirmatch, &fileinfo)) == -1) + { + Printf("Could not scan '%s': %s\n", dirpath, strerror(errno)); + } + else + { + do + { + if (fileinfo.attrib & _A_HIDDEN) + { + // Skip hidden files and directories. (Prevents SVN bookkeeping + // info from being included.) + continue; + } + if (fileinfo.attrib & _A_SUBDIR) + { + + if (fileinfo.name[0] == '.' && + (fileinfo.name[1] == '\0' || + (fileinfo.name[1] == '.' && fileinfo.name[2] == '\0'))) + { + // Do not record . and .. directories. + continue; + } + FString newdir = dirpath; + newdir << fileinfo.name << '/'; + count += AddDirectory(newdir); + } + else + { + if (strstr(fileinfo.name, ".orig") || strstr(fileinfo.name, ".bak")) + { + // We shuuldn't add backup files to the lump directory + continue; + } + + AddEntry(FString(dirpath) + fileinfo.name, fileinfo.size); + count++; + } + } while (_findnext(handle, &fileinfo) == 0); + _findclose(handle); + } + return count; +} + +#else + +//========================================================================== +// +// add_dirs +// 4.4BSD version +// +//========================================================================== + +int FDirectory::AddDirectory(const char *dirpath) +{ + char *argv [2] = {dirpath, NULL }; + FTS *fts; + FTSENT *ent; + int count = 0; + + fts = fts_open(argv, FTS_LOGICAL, NULL); + if (fts == NULL) + { + Printf "Failed to start directory traversal: %s\n", strerror(errno)); + return NULL; + } + while ((ent = fts_read(fts)) != NULL) + { + if (ent->fts_info == FTS_D && ent->fts_name[0] == '.') + { + // Skip hidden directories. (Prevents SVN bookkeeping + // info from being included.) + fts_set(fts, ent, FTS_SKIP); + } + if (ent->fts_info == FTS_D && ent->fts_level == 0) + { + continue; + } + if (ent->fts_info != FTS_F) + { + // We're only interested in remembering files. + continue; + } + AddEntry(ent->fts_path, ent->fts_statp->st_size); + count++; + } + fts_close(fts); + return count; +} +#endif + + +//========================================================================== +// +// +// +//========================================================================== + +bool FDirectory::Open(bool quiet) +{ + NumLumps = AddDirectory(Filename); + if (!quiet) Printf(", %d lumps\n", NumLumps); + // Entries in Zips are sorted alphabetically. + qsort(&Lumps[0], NumLumps, sizeof(FDirectoryLump), lumpcmp); + return true; +} + +//========================================================================== +// +// +// +//========================================================================== + +void FDirectory::AddEntry(const char *fullpath, int size) +{ + FDirectoryLump *lump_p = &Lumps[Lumps.Reserve(1)]; + + // The lump's name is only the part relative to the main directory + lump_p->LumpNameSetup(fullpath + strlen(Filename)); + lump_p->LumpSize = size; + lump_p->Owner = this; + lump_p->Flags = 0; + lump_p->CheckEmbedded(); +} + + +//========================================================================== +// +// +// +//========================================================================== + +FileReader *FDirectoryLump::NewReader() +{ + try + { + FString fullpath = Owner->Filename; + fullpath += FullName; + return new FileReader(fullpath); + } + catch (CRecoverableError &) + { + return NULL; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +int FDirectoryLump::FillCache() +{ + Cache = new char[LumpSize]; + FileReader *reader = NewReader(); + reader->Read(Cache, LumpSize); + delete reader; + RefCount = 1; + return 1; +} + +//========================================================================== +// +// File open +// +//========================================================================== + +FResourceFile *CheckDir(const char *filename, FileReader *file, bool quiet) +{ + FResourceFile *rf = new FDirectory(filename); + if (rf->Open(quiet)) return rf; + delete rf; + return NULL; +} + diff --git a/src/resourcefiles/file_zip.cpp b/src/resourcefiles/file_zip.cpp index 3a90efe1e..e33938144 100644 --- a/src/resourcefiles/file_zip.cpp +++ b/src/resourcefiles/file_zip.cpp @@ -267,7 +267,7 @@ bool FZipFile::Open(bool quiet) // Resize the lump record array to its actual size NumLumps -= skipped; free(directory); - //LumpInfo.Resize(NumLumps); + if (!quiet) Printf(", %d lumps\n", NumLumps); // Entries in Zips are sorted alphabetically. diff --git a/src/resourcefiles/resourcefile.cpp b/src/resourcefiles/resourcefile.cpp index dcf6b9a29..9831ec70c 100644 --- a/src/resourcefiles/resourcefile.cpp +++ b/src/resourcefiles/resourcefile.cpp @@ -94,10 +94,10 @@ FResourceLump::~FResourceLump() // //========================================================================== -void FResourceLump::LumpNameSetup(char *iname) +void FResourceLump::LumpNameSetup(const char *iname) { char base[256]; - char *lname = strrchr(iname,'/'); + const char *lname = strrchr(iname,'/'); lname = (lname == NULL) ? iname : lname + 1; strcpy(base, lname); char *dot = strrchr(base, '.'); @@ -258,6 +258,7 @@ FResourceFile *CheckPak(const char *filename, FileReader *file, bool quiet); FResourceFile *CheckZip(const char *filename, FileReader *file, bool quiet); FResourceFile *Check7Z(const char *filename, FileReader *file, bool quiet); FResourceFile *CheckLump(const char *filename, FileReader *file, bool quiet); +FResourceFile *CheckDir(const char *filename, FileReader *file, bool quiet); static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckLump }; @@ -282,6 +283,11 @@ FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader return NULL; } +FResourceFile *FResourceFile::OpenDirectory(const char *filename) +{ + return CheckDir(filename, NULL, false); +} + //========================================================================== // // Resource file base class @@ -290,14 +296,15 @@ FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader FResourceFile::FResourceFile(const char *filename, FileReader *r) { - Filename = copystring(filename); + if (filename != NULL) Filename = copystring(filename); + else Filename = NULL; Reader = r; } FResourceFile::~FResourceFile() { - delete [] Filename; + if (Filename != NULL) delete [] Filename; delete Reader; } diff --git a/src/resourcefiles/resourcefile.h b/src/resourcefiles/resourcefile.h index 716083f54..03a0be4d8 100644 --- a/src/resourcefiles/resourcefile.h +++ b/src/resourcefiles/resourcefile.h @@ -35,7 +35,7 @@ struct FResourceLump virtual FileReader *GetReader(); virtual FileReader *NewReader(); virtual int GetFileOffset() { return -1; } - void LumpNameSetup(char *iname); + void LumpNameSetup(const char *iname); void CheckEmbedded(); void *CacheLump(); @@ -61,6 +61,7 @@ private: public: static FResourceFile *OpenResourceFile(const char *filename, FileReader *file, bool quiet = false); + static FResourceFile *FResourceFile::OpenDirectory(const char *filename); virtual ~FResourceFile(); FileReader *GetReader() const { return Reader; } DWORD LumpCount() const { return NumLumps; } diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 1ca14ffba..de3486a29 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -160,7 +160,7 @@ void FWadCollection::DeleteAll () // //========================================================================== -void FWadCollection::InitMultipleFiles (wadlist_t **filenames) +void FWadCollection::InitMultipleFiles (wadlist_t **filenames, const char *loaddir) { int numfiles; @@ -183,6 +183,7 @@ void FWadCollection::InitMultipleFiles (wadlist_t **filenames) M_Free (*filenames); *filenames = next; } + AddFile(loaddir, NULL, true); NumLumps = LumpInfo.Size(); if (NumLumps == 0) @@ -229,11 +230,11 @@ int FWadCollection::AddExternalFile(const char *filename) // [RH] Removed reload hack //========================================================================== -void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) +void FWadCollection::AddFile (const char *filename, FileReader *wadinfo, bool isdir) { int startlump; - if (wadinfo == NULL) + if (wadinfo == NULL && !isdir) { try { @@ -250,7 +251,10 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) Printf (" adding %s", filename); startlump = NumLumps; - FResourceFile *resfile = FResourceFile::OpenResourceFile(filename, wadinfo); + FResourceFile *resfile; + + if (!isdir) resfile = FResourceFile::OpenResourceFile(filename, wadinfo); + else resfile = FResourceFile::OpenDirectory(filename); if (resfile != NULL) { diff --git a/src/w_wad.h b/src/w_wad.h index 293a328f5..dfc1a4a29 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -153,8 +153,8 @@ public: // The wadnum for the IWAD enum { IWAD_FILENUM = 1 }; - void InitMultipleFiles (wadlist_t **filenames); - void AddFile (const char *filename, FileReader *wadinfo = NULL); + void InitMultipleFiles (wadlist_t **filenames, const char *loaddir); + void AddFile (const char *filename, FileReader *wadinfo = NULL, bool isdir = false); int CheckIfWadLoaded (const char *name); const char *GetWadName (int wadnum) const; diff --git a/zdoom.vcproj b/zdoom.vcproj index 4c2d8f67b..9b4d9db96 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -1,7 +1,7 @@ + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + @@ -1856,14 +1864,6 @@ Outputs="$(IntDir)/$(InputName).obj" /> - - - @@ -2041,14 +2041,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -2059,6 +2051,14 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + - - - + + + - - - @@ -5371,6 +5363,14 @@ AdditionalIncludeDirectories="src\win32;$(NoInherit)" /> + + + @@ -5649,7 +5649,7 @@ /> + +