mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-12-04 01:41:42 +00:00
FileSystem cleanup.
* split off the Doom specific lookup with short 8 character names into its own class and cleaned up the interface a bit. * get rid of all short name aliasing 'optimization' - modern compilers are capable of optimizing memcmp and memcpy to use equally efficient code so none of these hacks are needed anymore. * added reader for Descent 3's HOG2 format - yet another of these endless uncompressed formats with just a different directory structure...
This commit is contained in:
parent
634a646c2d
commit
a3475d3973
23 changed files with 1187 additions and 945 deletions
|
@ -1096,6 +1096,7 @@ set (PCH_SOURCES
|
|||
common/engine/cycler.cpp
|
||||
common/engine/d_event.cpp
|
||||
common/engine/date.cpp
|
||||
common/engine/filesys_doom.cpp
|
||||
common/engine/stats.cpp
|
||||
common/engine/sc_man.cpp
|
||||
common/engine/palettecontainer.cpp
|
||||
|
@ -1230,6 +1231,7 @@ set( GAME_SOURCES
|
|||
common/filesystem/source/file_whres.cpp
|
||||
common/filesystem/source/file_ssi.cpp
|
||||
common/filesystem/source/file_hog.cpp
|
||||
common/filesystem/source/file_hog2.cpp
|
||||
common/filesystem/source/file_mvl.cpp
|
||||
common/filesystem/source/file_directory.cpp
|
||||
common/filesystem/source/resourcefile.cpp
|
||||
|
|
648
src/common/engine/filesys_doom.cpp
Normal file
648
src/common/engine/filesys_doom.cpp
Normal file
|
@ -0,0 +1,648 @@
|
|||
/*
|
||||
** filesys_doom.cpp
|
||||
**
|
||||
** the very special lump name lookup code for Doom's short names.
|
||||
** Not useful in a generic system.
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2016 Randy Heit
|
||||
** Copyright 2005-2024 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 "filesystem.h"
|
||||
#include "printf.h"
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FileSystem::InitHashChains()
|
||||
{
|
||||
Super::InitHashChains();
|
||||
unsigned NumEntries = GetNumEntries();
|
||||
for (unsigned i = 0; i < (unsigned)NumEntries; i++)
|
||||
{
|
||||
files[i].HashFirst = files[i].HashNext = NULL_INDEX;
|
||||
}
|
||||
// Now set up the chains
|
||||
for (unsigned i = 0; i < (unsigned)NumEntries; i++)
|
||||
{
|
||||
if (files[i].Namespace == ns_hidden || files[i].ShortName[0] == 0) continue;
|
||||
unsigned j = FileSys::MakeHash(files[i].ShortName, 8) % NumEntries;
|
||||
files[i].HashNext = files[j].HashFirst;
|
||||
files[j].HashFirst = i;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static 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;
|
||||
to[8] = 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FileSystem::SetupName(int fileindex)
|
||||
{
|
||||
const char* name = GetFileName(fileindex);
|
||||
int containerflags = GetResourceFileFlags(GetFileContainer(fileindex));
|
||||
int lflags = GetFileFlags(fileindex);
|
||||
|
||||
if ((containerflags & wadflags) == wadflags)
|
||||
{
|
||||
UpperCopy(files[fileindex].ShortName, name);
|
||||
}
|
||||
else if ((lflags & FileSys::RESFF_EMBEDDED) || !*name)
|
||||
{
|
||||
files[fileindex].Namespace = ns_hidden;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lflags & FileSys::RESFF_FULLPATH) files[fileindex].Flags |= LUMPF_FULLPATH; // copy for easier access in lookup function.
|
||||
auto slash = strrchr(name, '/');
|
||||
auto base = slash ? (slash + 1) : name;
|
||||
UpperCopy(files[fileindex].ShortName, base);
|
||||
auto dot = strrchr(files[fileindex].ShortName, '.');
|
||||
if (dot) while (*dot) *dot++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// IsMarker
|
||||
//
|
||||
// (from BOOM)
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
inline bool FileSystem::IsMarker(int lump, const char* marker) noexcept
|
||||
{
|
||||
auto name = files[lump].ShortName;
|
||||
if (name[0] == marker[0])
|
||||
{
|
||||
return (!strcmp(name, marker) ||
|
||||
(marker[1] == '_' && !strcmp(name + 1, marker)));
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SetNameSpace
|
||||
//
|
||||
// Sets namespace information for the lumps. It always looks for the first
|
||||
// x_START and the last x_END lump, except when loading flats. In this case
|
||||
// F_START may be absent and if that is the case all lumps with a size of
|
||||
// 4096 will be flagged appropriately.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
// This class was supposed to be local in the function but GCC
|
||||
// does not like that.
|
||||
struct Marker
|
||||
{
|
||||
int markertype;
|
||||
int index;
|
||||
};
|
||||
|
||||
void FileSystem::SetNamespace(int filenum, const char* startmarker, const char* endmarker, namespace_t space, FileSys::FileSystemMessageFunc Printf, bool flathack)
|
||||
{
|
||||
using FileSys::FSMessageLevel;
|
||||
bool warned = false;
|
||||
int numstartmarkers = 0, numendmarkers = 0;
|
||||
TArray<Marker> markers;
|
||||
int FirstLump = GetFirstEntry(filenum);
|
||||
int LastLump = GetLastEntry(filenum);
|
||||
auto FileName = GetResourceFileName(filenum);
|
||||
|
||||
for (int i = FirstLump; i <= LastLump; i++)
|
||||
{
|
||||
if (IsMarker(i, startmarker))
|
||||
{
|
||||
Marker m = { 0, i };
|
||||
markers.push_back(m);
|
||||
numstartmarkers++;
|
||||
}
|
||||
else if (IsMarker(i, endmarker))
|
||||
{
|
||||
Marker m = { 1, i };
|
||||
markers.push_back(m);
|
||||
numendmarkers++;
|
||||
}
|
||||
}
|
||||
|
||||
if (numstartmarkers == 0)
|
||||
{
|
||||
if (numendmarkers == 0) return; // no markers found
|
||||
|
||||
if (Printf)
|
||||
Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, endmarker, startmarker);
|
||||
|
||||
|
||||
if (flathack)
|
||||
{
|
||||
// We have found no F_START but one or more F_END markers.
|
||||
// mark all lumps before the last F_END marker as potential flats.
|
||||
unsigned int end = markers[markers.size() - 1].index;
|
||||
for (int ii = FirstLump; ii <= LastLump; ii++)
|
||||
{
|
||||
if (FileLength(ii) == 4096)
|
||||
{
|
||||
// We can't add this to the flats namespace but
|
||||
// it needs to be flagged for the texture manager.
|
||||
if (Printf) Printf(FSMessageLevel::DebugNotify, "%s: Marking %s as potential flat\n", FileName, files[ii].ShortName);
|
||||
files[ii].Namespace = ns_maybeflat;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
while (i < markers.size())
|
||||
{
|
||||
int start, end;
|
||||
if (markers[i].markertype != 0)
|
||||
{
|
||||
if (Printf) Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, endmarker, startmarker);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
start = int(i++);
|
||||
|
||||
// skip over subsequent x_START markers
|
||||
while (i < markers.size() && markers[i].markertype == 0)
|
||||
{
|
||||
if (Printf) Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName, startmarker);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
// same for x_END markers
|
||||
while (i < markers.size() - 1 && (markers[i].markertype == 1 && markers[i + 1].markertype == 1))
|
||||
{
|
||||
if (Printf) Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName, endmarker);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
// We found a starting marker but no end marker. Ignore this block.
|
||||
if (i >= markers.size())
|
||||
{
|
||||
if (Printf) Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, startmarker, endmarker);
|
||||
end = LastLump + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
end = markers[i++].index;
|
||||
}
|
||||
|
||||
// we found a marked block
|
||||
if (Printf) Printf(FSMessageLevel::DebugNotify, "%s: Found %s block at (%d-%d)\n", FileName, startmarker, markers[start].index, end);
|
||||
for (int j = markers[start].index + 1; j < end; j++)
|
||||
{
|
||||
if (files[j].Namespace != ns_global)
|
||||
{
|
||||
if (!warned && Printf)
|
||||
{
|
||||
Printf(FSMessageLevel::Warning, "%s: Overlapping namespaces found (lump %d)\n", FileName, j);
|
||||
}
|
||||
warned = true;
|
||||
}
|
||||
else if (space == ns_sprites && FileLength(j) < 8)
|
||||
{
|
||||
// sf 26/10/99:
|
||||
// ignore sprite lumps smaller than 8 bytes (the smallest possible)
|
||||
// in size -- this was used by some dmadds wads
|
||||
// as an 'empty' graphics resource
|
||||
if (Printf) Printf(FSMessageLevel::DebugWarn, "%s: Skipped empty sprite %s (lump %d)\n", FileName, files[j].ShortName, j);
|
||||
}
|
||||
else
|
||||
{
|
||||
files[j].Namespace = space;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// W_SkinHack
|
||||
//
|
||||
// Tests a wad file to see if it contains an S_SKIN marker. If it does,
|
||||
// every lump in the wad is moved into a new namespace. Because skins are
|
||||
// only supposed to replace player sprites, sounds, or faces, this should
|
||||
// not be a problem. Yes, there are skins that replace more than that, but
|
||||
// they are such a pain, and breaking them like this was done on purpose.
|
||||
// This also renames any S_SKINxx lumps to just S_SKIN.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FileSystem::SkinHack(int filenum, FileSys::FileSystemMessageFunc Printf)
|
||||
{
|
||||
using FileSys::FSMessageLevel;
|
||||
// this being static is not a problem. The only relevant thing is that each skin gets a different number.
|
||||
bool skinned = false;
|
||||
bool hasmap = false;
|
||||
|
||||
int FirstLump = GetFirstEntry(filenum);
|
||||
int LastLump = GetLastEntry(filenum);
|
||||
auto FileName = GetResourceFileName(filenum);
|
||||
|
||||
for (int i = FirstLump; i <= LastLump; i++)
|
||||
{
|
||||
auto lump = &files[i];
|
||||
|
||||
if (!strnicmp(lump->ShortName, "S_SKIN", 6))
|
||||
{ // Wad has at least one skin.
|
||||
lump->ShortName[6] = 0;
|
||||
lump->ShortName[7] = 0;
|
||||
if (!skinned)
|
||||
{
|
||||
skinned = true;
|
||||
|
||||
for (int j = FirstLump; j <= LastLump; j++)
|
||||
{
|
||||
files[j].Namespace = skin_namespc;
|
||||
}
|
||||
skin_namespc++;
|
||||
}
|
||||
}
|
||||
// needless to say, this check is entirely useless these days as map names can be more diverse..
|
||||
if ((lump->ShortName[0] == 'M' &&
|
||||
lump->ShortName[1] == 'A' &&
|
||||
lump->ShortName[2] == 'P' &&
|
||||
lump->ShortName[3] >= '0' && lump->ShortName[3] <= '9' &&
|
||||
lump->ShortName[4] >= '0' && lump->ShortName[4] <= '9' &&
|
||||
lump->ShortName[5] == '\0')
|
||||
||
|
||||
(lump->ShortName[0] == 'E' &&
|
||||
lump->ShortName[1] >= '0' && lump->ShortName[1] <= '9' &&
|
||||
lump->ShortName[2] == 'M' &&
|
||||
lump->ShortName[3] >= '0' && lump->ShortName[3] <= '9' &&
|
||||
lump->ShortName[4] == '\0'))
|
||||
{
|
||||
hasmap = true;
|
||||
}
|
||||
}
|
||||
if (skinned && hasmap && Printf)
|
||||
{
|
||||
Printf(FSMessageLevel::Attention, "%s: The maps will not be loaded because it has a skin.\n", FileName);
|
||||
Printf(FSMessageLevel::Attention, "You should remove the skin from the wad to play these maps.\n");
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FileSystem::SetupNamespace(int filenum, FileSys::FileSystemMessageFunc Printf)
|
||||
{
|
||||
int flags = GetResourceFileFlags(filenum);
|
||||
|
||||
// Set namespace for entries from WADs.
|
||||
if ((flags & wadflags) == wadflags)
|
||||
{
|
||||
SetNamespace(filenum, "S_START", "S_END", ns_sprites, Printf);
|
||||
SetNamespace(filenum, "F_START", "F_END", ns_flats, Printf, true);
|
||||
SetNamespace(filenum, "C_START", "C_END", ns_colormaps, Printf);
|
||||
SetNamespace(filenum, "A_START", "A_END", ns_acslibrary, Printf);
|
||||
SetNamespace(filenum, "TX_START", "TX_END", ns_newtextures, Printf);
|
||||
SetNamespace(filenum, "V_START", "V_END", ns_strifevoices, Printf);
|
||||
SetNamespace(filenum, "HI_START", "HI_END", ns_hires, Printf);
|
||||
SetNamespace(filenum, "VX_START", "VX_END", ns_voxels, Printf);
|
||||
SkinHack(filenum, Printf);
|
||||
}
|
||||
else if (!(flags & FResourceFile::NO_FOLDERS))
|
||||
{
|
||||
int FirstLump = GetFirstEntry(filenum);
|
||||
int LastLump = GetLastEntry(filenum);
|
||||
auto FileName = GetResourceFileName(filenum);
|
||||
|
||||
for (int i = FirstLump; i <= LastLump; i++)
|
||||
{
|
||||
auto lump = &files[i];
|
||||
|
||||
auto LongName = GetFileName(i);
|
||||
// Map some directories to WAD namespaces.
|
||||
// Note that some of these namespaces don't exist in WADS.
|
||||
// CheckNumForName will handle any request for these namespaces accordingly.
|
||||
int Namespace = !strncmp(LongName, "flats/", 6) ? ns_flats :
|
||||
!strncmp(LongName, "textures/", 9) ? ns_newtextures :
|
||||
!strncmp(LongName, "hires/", 6) ? ns_hires :
|
||||
!strncmp(LongName, "sprites/", 8) ? ns_sprites :
|
||||
!strncmp(LongName, "voxels/", 7) ? ns_voxels :
|
||||
!strncmp(LongName, "colormaps/", 10) ? ns_colormaps :
|
||||
!strncmp(LongName, "acs/", 4) ? ns_acslibrary :
|
||||
!strncmp(LongName, "voices/", 7) ? ns_strifevoices :
|
||||
!strncmp(LongName, "patches/", 8) ? ns_patches :
|
||||
!strncmp(LongName, "graphics/", 9) ? ns_graphics :
|
||||
!strncmp(LongName, "sounds/", 7) ? ns_sounds :
|
||||
!strncmp(LongName, "music/", 6) ? ns_music :
|
||||
!strchr(LongName, '/') ? ns_global :
|
||||
ns_hidden;
|
||||
|
||||
lump->Namespace = Namespace;
|
||||
|
||||
switch (Namespace)
|
||||
{
|
||||
case ns_hidden:
|
||||
memset(lump->ShortName, 0, sizeof(lump->ShortName));
|
||||
break;
|
||||
|
||||
case ns_sprites:
|
||||
case ns_voxels:
|
||||
case ns_hires:
|
||||
// Since '\' can't be used as a file name's part inside a ZIP
|
||||
// we have to work around this for sprites because it is a valid
|
||||
// frame character.
|
||||
for (auto& c : lump->ShortName)
|
||||
{
|
||||
if (c == '^') c = '\\';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FileSystem::InitFiles(std::vector<std::string>& filenames, FileSys::FileSystemFilterInfo* filter, FileSys::FileSystemMessageFunc Printf, bool allowduplicates)
|
||||
{
|
||||
if (!Super::InitFiles(filenames, filter, Printf, allowduplicates)) return false;
|
||||
files.Resize(GetNumEntries());
|
||||
memset(files.Data(), 0, sizeof(files[0]) * files.size());
|
||||
int numfiles = GetNumEntries();
|
||||
for (int i = 0; i < numfiles; i++)
|
||||
{
|
||||
SetupName(i);
|
||||
}
|
||||
|
||||
int numresfiles = GetNumWads();
|
||||
for (int i = 0; i < numresfiles; i++)
|
||||
{
|
||||
SetupNamespace(i, Printf);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// 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 FileSystem::CheckNumForName(const char* name, int space) const
|
||||
{
|
||||
char uname[9];
|
||||
uint32_t i;
|
||||
|
||||
if (name == nullptr)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
UpperCopy(uname, name);
|
||||
i = files[FileSys::MakeHash(uname, 8) % files.Size()].HashFirst;
|
||||
|
||||
while (i != NULL_INDEX)
|
||||
{
|
||||
auto& lump = files[i];
|
||||
|
||||
if (!memcmp(lump.ShortName, uname, 8))
|
||||
{
|
||||
if (lump.Namespace == space) break;
|
||||
// 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.
|
||||
if (space > ns_specialzipdirectory && lump.Namespace == ns_global && !(lump.Flags & LUMPF_FULLPATH))
|
||||
break;
|
||||
}
|
||||
i = lump.HashNext;
|
||||
}
|
||||
|
||||
return i != NULL_INDEX ? i : -1;
|
||||
}
|
||||
|
||||
int FileSystem::CheckNumForName(const char* name, int space, int rfnum, bool exact) const
|
||||
{
|
||||
char uname[9];
|
||||
uint32_t i;
|
||||
|
||||
if (rfnum < 0)
|
||||
{
|
||||
return CheckNumForName(name, space);
|
||||
}
|
||||
|
||||
UpperCopy(uname, name);
|
||||
i = files[FileSys::MakeHash(uname, 8) % files.Size()].HashFirst;
|
||||
|
||||
// If exact is true if will only find lumps in the same WAD, otherwise
|
||||
// also those in earlier WADs.
|
||||
|
||||
while (i != NULL_INDEX &&
|
||||
(memcmp(files[i].ShortName, uname, 8) || files[i].Namespace != space ||
|
||||
(exact ? (GetFileContainer(i) != rfnum) : (GetFileContainer(i) > rfnum))))
|
||||
{
|
||||
i = files[i].HashNext;
|
||||
}
|
||||
|
||||
return i != NULL_INDEX ? i : -1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// GetNumForName
|
||||
//
|
||||
// Calls CheckNumForName, but bombs out if not found.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FileSystem::GetNumForName(const char* name, int space) const
|
||||
{
|
||||
int i;
|
||||
|
||||
i = CheckNumForName(name, space);
|
||||
|
||||
if (i == -1)
|
||||
throw FileSys::FileSystemException("GetNumForName: %s not found!", name);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// returns a modifiable pointer to the short name
|
||||
//
|
||||
// should only be called before the hash chains are set up.
|
||||
// If done later this needs rehashing.
|
||||
//
|
||||
// This is for custom setup through postprocessFunc
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
char* FileSystem::GetShortName(int i)
|
||||
{
|
||||
if ((unsigned)i >= files.Size())
|
||||
throw FileSys::FileSystemException("GetShortName: Invalid index");
|
||||
return files[i].ShortName;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// W_FindLump
|
||||
//
|
||||
// Find a named lump. Specifically allows duplicates for merging of e.g.
|
||||
// SNDINFO lumps.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FileSystem::FindLump(const char* name, int* lastlump, bool anyns)
|
||||
{
|
||||
if ((size_t)*lastlump >= files.size()) return -1;
|
||||
char name8[9];
|
||||
UpperCopy(name8, name);
|
||||
|
||||
assert(lastlump != nullptr && *lastlump >= 0);
|
||||
|
||||
const int last = (int)files.size();
|
||||
|
||||
for(int lump = *lastlump; lump < last; lump++)
|
||||
{
|
||||
const FileEntry* const lump_p = &files[lump];
|
||||
if ((anyns || lump_p->Namespace == ns_global) && !memcmp(lump_p->ShortName, name8, 8))
|
||||
{
|
||||
*lastlump = lump + 1;
|
||||
return lump;
|
||||
}
|
||||
}
|
||||
|
||||
*lastlump = last;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// 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 FileSystem::FindLumpMulti(const char** names, int* lastlump, bool anyns, int* nameindex)
|
||||
{
|
||||
assert(lastlump != nullptr && *lastlump >= 0);
|
||||
|
||||
int last = files.Size();
|
||||
|
||||
for (int lump = *lastlump; lump < last; lump++)
|
||||
{
|
||||
auto lump_p = &files[lump];
|
||||
if (anyns || lump_p->Namespace == ns_global)
|
||||
{
|
||||
for (const char** name = names; *name != nullptr; name++)
|
||||
{
|
||||
if (!strnicmp(*name, lump_p->ShortName, 8))
|
||||
{
|
||||
*lastlump = lump + 1;
|
||||
if (nameindex != nullptr) *nameindex = int(name - names);
|
||||
return lump;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*lastlump = last;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// This function combines lookup from regular lists and Doom's special one.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FileSystem::CheckNumForAnyName(const char* name, namespace_t namespc) const
|
||||
{
|
||||
if (name != NULL)
|
||||
{
|
||||
// Check short names first to avoid interference from short names in the real file system.
|
||||
if (strlen(name) <= 8 && !strpbrk(name, "./"))
|
||||
{
|
||||
return CheckNumForName(name, namespc);
|
||||
}
|
||||
|
||||
int lookup = Super::CheckNumForFullName(name, false);
|
||||
if (lookup >= 0) return lookup;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1,7 +1,129 @@
|
|||
#pragma once
|
||||
#include "fs_filesystem.h"
|
||||
|
||||
using FileSys::FileSystem;
|
||||
using FileSys::FResourceFile;
|
||||
|
||||
inline FileSys::FileSystem fileSystem;
|
||||
// [RH] Namespaces from BOOM.
|
||||
// These are needed here in the low level part so that WAD files can be properly set up.
|
||||
enum namespace_t : int {
|
||||
ns_hidden = -1,
|
||||
|
||||
ns_global = 0,
|
||||
ns_sprites,
|
||||
ns_flats,
|
||||
ns_colormaps,
|
||||
ns_acslibrary,
|
||||
ns_newtextures,
|
||||
ns_bloodraw, // no longer used - kept for ZScript.
|
||||
ns_bloodsfx, // no longer used - kept for ZScript.
|
||||
ns_bloodmisc, // no longer used - kept for ZScript.
|
||||
ns_strifevoices,
|
||||
ns_hires,
|
||||
ns_voxels,
|
||||
ns_maybeflat,
|
||||
|
||||
// These namespaces are only used to mark lumps in special subdirectories
|
||||
// so that their contents doesn't interfere with the global namespace.
|
||||
// searching for data in these namespaces works differently for lumps coming
|
||||
// from Zips or other files.
|
||||
ns_specialzipdirectory,
|
||||
ns_sounds,
|
||||
ns_patches,
|
||||
ns_graphics,
|
||||
ns_music,
|
||||
|
||||
ns_firstskin,
|
||||
};
|
||||
|
||||
|
||||
// extended class that adds Doom's very special short name lookup to the file system.
|
||||
class FileSystem : public FileSys::FileSystem
|
||||
{
|
||||
private:
|
||||
struct FileEntry
|
||||
{
|
||||
char ShortName[9];
|
||||
uint8_t Namespace;
|
||||
uint8_t Flags;
|
||||
uint32_t HashFirst;
|
||||
uint32_t HashNext;
|
||||
};
|
||||
|
||||
const int wadflags = FileSys::FResourceFile::NO_EXTENSIONS | FileSys::FResourceFile::NO_FOLDERS | FileSys::FResourceFile::SHORTNAMES;
|
||||
const uint32_t NULL_INDEX = 0xffffffff;
|
||||
|
||||
TArray<FileEntry> files;
|
||||
int skin_namespc = ns_firstskin;
|
||||
|
||||
|
||||
void Start(FileSys::FileSystemMessageFunc Printf);
|
||||
void SetupName(int fileindex);
|
||||
bool IsMarker(int lump, const char* marker) noexcept;
|
||||
void SetNamespace(int filenum, const char* startmarker, const char* endmarker, namespace_t space, FileSys::FileSystemMessageFunc Printf, bool flathack = false);
|
||||
void SkinHack(int filenum, FileSys::FileSystemMessageFunc Printf);
|
||||
void SetupNamespace(int filenum, FileSys::FileSystemMessageFunc Printf);
|
||||
|
||||
using Super = FileSys::FileSystem;
|
||||
|
||||
public:
|
||||
enum
|
||||
{
|
||||
LUMPF_MAYBEFLAT = 1,
|
||||
LUMPF_FULLPATH = 2,
|
||||
};
|
||||
|
||||
bool InitFiles(std::vector<std::string>& filenames, FileSys::FileSystemFilterInfo* filter = nullptr, FileSys::FileSystemMessageFunc Printf = nullptr, bool allowduplicates = false) override;
|
||||
void InitHashChains() override;
|
||||
|
||||
int CheckNumForAnyName(const char* cname, namespace_t namespc = ns_global) const;
|
||||
|
||||
int CheckNumForName(const char* name, int namespc) const;
|
||||
int CheckNumForName(const char* name, int namespc, int wadfile, bool exact = true) const;
|
||||
int GetNumForName(const char* name, int namespc) const;
|
||||
|
||||
inline int CheckNumForName(const uint8_t* name) const { return CheckNumForName((const char*)name, ns_global); }
|
||||
inline int CheckNumForName(const char* name) const { return CheckNumForName(name, ns_global); }
|
||||
inline int CheckNumForName(const uint8_t* name, int ns) const { return CheckNumForName((const char*)name, ns); }
|
||||
inline int GetNumForName(const char* name) const { return GetNumForName(name, ns_global); }
|
||||
inline int GetNumForName(const uint8_t* name) const { return GetNumForName((const char*)name); }
|
||||
inline int GetNumForName(const uint8_t* name, int ns) const { return GetNumForName((const char*)name, ns); }
|
||||
|
||||
int FindLump(const char* name, int* lastlump, bool anyns = false); // [RH] Find lumps with duplication
|
||||
int FindLumpMulti(const char** names, int* lastlump, bool anyns = false, int* nameindex = nullptr); // same with multiple possible names
|
||||
|
||||
bool CheckFileName(int lump, const char* name) const noexcept
|
||||
{
|
||||
if ((size_t)lump >= files.size())
|
||||
return false;
|
||||
|
||||
return !strnicmp(files[lump].ShortName, name, 8);
|
||||
}
|
||||
|
||||
const char* GetFileShortName(int lump) const noexcept
|
||||
{
|
||||
if ((size_t)lump >= files.size())
|
||||
return nullptr;
|
||||
else
|
||||
return files[lump].ShortName;
|
||||
}
|
||||
|
||||
int GetFileNamespace(int lump) const noexcept
|
||||
{
|
||||
if ((size_t)lump >= files.size())
|
||||
return ns_global;
|
||||
else
|
||||
return files[lump].Namespace;
|
||||
}
|
||||
|
||||
void SetFileNamespace(int lump, int ns) noexcept
|
||||
{
|
||||
if ((size_t)lump < files.size()) files[lump].Namespace = ns;
|
||||
}
|
||||
|
||||
// This is only for code that wants to edit the names before the game starts.
|
||||
char* GetShortName(int i);
|
||||
|
||||
};
|
||||
|
||||
inline FileSystem fileSystem;
|
||||
|
||||
|
|
|
@ -13,15 +13,6 @@
|
|||
|
||||
namespace FileSys {
|
||||
|
||||
union LumpShortName
|
||||
{
|
||||
char String[9];
|
||||
|
||||
uint32_t dword; // These are for accessing the first 4 or 8 chars of
|
||||
uint64_t qword; // Name as a unit without breaking strict aliasing rules
|
||||
};
|
||||
|
||||
|
||||
struct FolderEntry
|
||||
{
|
||||
const char *name;
|
||||
|
@ -32,7 +23,12 @@ class FileSystem
|
|||
{
|
||||
public:
|
||||
FileSystem();
|
||||
~FileSystem ();
|
||||
virtual ~FileSystem ();
|
||||
// do not copy!
|
||||
FileSystem(const FileSystem& other) = delete;
|
||||
FileSystem& operator =(const FileSystem& other) = delete;
|
||||
|
||||
bool Initialize(std::vector<std::string>& filenames, FileSystemFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, bool allowduplicates = false);
|
||||
|
||||
// The wadnum for the IWAD
|
||||
int GetIwadNum() { return IwadIndex; }
|
||||
|
@ -41,9 +37,6 @@ public:
|
|||
int GetMaxIwadNum() { return MaxIwadIndex; }
|
||||
void SetMaxIwadNum(int x) { MaxIwadIndex = x; }
|
||||
|
||||
bool InitSingleFile(const char *filename, FileSystemMessageFunc Printf = nullptr);
|
||||
bool InitMultipleFiles (std::vector<std::string>& filenames, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, bool allowduplicates = false);
|
||||
void AddFile (const char *filename, FileReader *wadinfo, LumpFilterInfo* filter, FileSystemMessageFunc Printf);
|
||||
int CheckIfResourceFileLoaded (const char *name) noexcept;
|
||||
void AddAdditionalFile(const char* filename, FileReader* wadinfo = NULL) {}
|
||||
|
||||
|
@ -53,31 +46,17 @@ public:
|
|||
int GetFirstEntry(int wadnum) const noexcept;
|
||||
int GetLastEntry(int wadnum) const noexcept;
|
||||
int GetEntryCount(int wadnum) const noexcept;
|
||||
int GetResourceFileFlags(int wadnum) const noexcept;
|
||||
|
||||
int CheckNumForName (const char *name, int namespc) const;
|
||||
int CheckNumForName (const char *name, int namespc, int wadfile, bool exact = true) const;
|
||||
int GetNumForName (const char *name, int namespc) const;
|
||||
|
||||
inline int CheckNumForName (const uint8_t *name) const { return CheckNumForName ((const char *)name, ns_global); }
|
||||
inline int CheckNumForName (const char *name) const { return CheckNumForName (name, ns_global); }
|
||||
inline int CheckNumForName (const uint8_t *name, int ns) const { return CheckNumForName ((const char *)name, ns); }
|
||||
inline int GetNumForName (const char *name) const { return GetNumForName (name, ns_global); }
|
||||
inline int GetNumForName (const uint8_t *name) const { return GetNumForName ((const char *)name); }
|
||||
inline int GetNumForName (const uint8_t *name, int ns) const { return GetNumForName ((const char *)name, ns); }
|
||||
|
||||
int CheckNumForFullName (const char *cname, bool trynormal = false, int namespc = ns_global, bool ignoreext = false) const;
|
||||
int CheckNumForFullName (const char *cname, bool ignoreext = false) const;
|
||||
int CheckNumForFullNameInFile (const char *name, int wadfile) const;
|
||||
int GetNumForFullName (const char *name) const;
|
||||
int CheckNumForAnyName(const char* cname, namespace_t namespc = ns_global) const
|
||||
{
|
||||
return CheckNumForFullName(cname, true, namespc);
|
||||
}
|
||||
|
||||
int FindFile(const char* name) const
|
||||
{
|
||||
return CheckNumForFullName(name);
|
||||
}
|
||||
|
||||
|
||||
bool FileExists(const char* name) const
|
||||
{
|
||||
return FindFile(name) >= 0;
|
||||
|
@ -88,14 +67,12 @@ public:
|
|||
return FindFile(name.c_str()) >= 0;
|
||||
}
|
||||
|
||||
LumpShortName& GetShortName(int i); // may only be called before the hash chains are set up.
|
||||
void RenameFile(int num, const char* fn);
|
||||
bool CreatePathlessCopy(const char* name, int id, int flags);
|
||||
|
||||
void ReadFile (int lump, void *dest);
|
||||
// These should only be used if the file data really needs padding.
|
||||
FileData ReadFile (int lump);
|
||||
FileData ReadFile (const char *name) { return ReadFile (GetNumForName (name)); }
|
||||
FileData ReadFileFullName(const char* name) { return ReadFile(GetNumForFullName(name)); }
|
||||
|
||||
FileReader OpenFileReader(int lump, int readertype, int readerflags); // opens a reader that redirects to the containing file's one.
|
||||
|
@ -112,29 +89,21 @@ public:
|
|||
}
|
||||
|
||||
|
||||
int FindLump (const char *name, int *lastlump, bool anyns=false); // [RH] Find lumps with duplication
|
||||
int FindLumpMulti (const char **names, int *lastlump, bool anyns = false, int *nameindex = NULL); // same with multiple possible names
|
||||
int FindLumpFullName(const char* name, int* lastlump, bool noext = false);
|
||||
bool CheckFileName (int lump, const char *name); // [RH] True if lump's name == name
|
||||
|
||||
int FindFileWithExtensions(const char* name, const char* const* exts, int count) const;
|
||||
int FindResource(int resid, const char* type, int filenum = -1) const noexcept;
|
||||
int GetResource(int resid, const char* type, int filenum = -1) const;
|
||||
|
||||
|
||||
static uint32_t LumpNameHash (const char *name); // [RH] Create hash key from an 8-char name
|
||||
|
||||
ptrdiff_t FileLength (int lump) const;
|
||||
ptrdiff_t FileLength(int lump) const;
|
||||
int GetFileFlags (int lump); // Return the flags for this lump
|
||||
const char* GetFileShortName(int lump) const;
|
||||
const char *GetFileName (int lump, bool returnshort = true) const; // [RH] Returns the lump's full name
|
||||
const char* GetFileName(int lump) const; // Gets uninterpreted name from the FResourceFile
|
||||
std::string GetFileFullPath (int lump) const; // [RH] Returns wad's name + lump's full name
|
||||
int GetFileContainer (int lump) const; // [RH] Returns wadnum for a specified lump
|
||||
int GetFileNamespace (int lump) const; // [RH] Returns the namespace a lump belongs to
|
||||
void SetFileNamespace(int lump, int ns);
|
||||
int GetFileContainer (int lump) const;
|
||||
// [RH] Returns wadnum for a specified lump
|
||||
int GetResourceId(int lump) const; // Returns the RFF index number for this lump
|
||||
const char* GetResourceType(int lump) const;
|
||||
bool CheckFileName (int lump, const char *name) const; // [RH] Returns true if the names match
|
||||
unsigned GetFilesInFolder(const char *path, std::vector<FolderEntry> &result, bool atomic) const;
|
||||
|
||||
int GetNumEntries() const
|
||||
|
@ -149,18 +118,16 @@ public:
|
|||
|
||||
int AddFromBuffer(const char* name, char* data, int size, int id, int flags);
|
||||
FileReader* GetFileReader(int wadnum); // Gets a FileReader object to the entire WAD
|
||||
void InitHashChains();
|
||||
|
||||
protected:
|
||||
|
||||
struct LumpRecord;
|
||||
const uint32_t NULL_INDEX = 0xffffffff;
|
||||
|
||||
std::vector<FResourceFile *> Files;
|
||||
std::vector<LumpRecord> FileInfo;
|
||||
|
||||
std::vector<uint32_t> Hashes; // one allocation for all hash lists.
|
||||
uint32_t *FirstLumpIndex = nullptr; // [RH] Hashing stuff moved out of lumpinfo structure
|
||||
uint32_t *NextLumpIndex = nullptr;
|
||||
|
||||
uint32_t *FirstLumpIndex_FullName = nullptr; // The same information for fully qualified paths from .zips
|
||||
uint32_t *NextLumpIndex_FullName = nullptr;
|
||||
|
@ -182,7 +149,24 @@ protected:
|
|||
private:
|
||||
void DeleteAll();
|
||||
void MoveLumpsInFolder(const char *);
|
||||
void AddFile(const char* filename, FileReader* wadinfo, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf);
|
||||
protected:
|
||||
|
||||
// These two functions must be overridden by subclasses which want to extend the file system.
|
||||
virtual bool InitFiles(std::vector<std::string>& filenames, FileSystemFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, bool allowduplicates = false);
|
||||
public:
|
||||
virtual void InitHashChains();
|
||||
|
||||
};
|
||||
|
||||
//djb2 hash algorithm with case insensitivity hack
|
||||
inline static uint32_t MakeHash(const char* str, size_t length = SIZE_MAX)
|
||||
{
|
||||
uint32_t hash = 5381;
|
||||
uint32_t c;
|
||||
while (length-- > 0 && (c = *str++)) hash = hash * 33 + (c | 32);
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -16,7 +16,7 @@ std::string ExtractBaseName(const char* path, bool include_extension = false);
|
|||
void strReplace(std::string& str, const char* from, const char* to);
|
||||
|
||||
// user context in which the file system gets opened. This also contains a few callbacks to avoid direct dependencies on the engine.
|
||||
struct LumpFilterInfo
|
||||
struct FileSystemFilterInfo
|
||||
{
|
||||
std::vector<std::string> gameTypeFilter; // this can contain multiple entries
|
||||
|
||||
|
@ -45,45 +45,10 @@ using FileSystemMessageFunc = int(*)(FSMessageLevel msglevel, const char* format
|
|||
|
||||
class FResourceFile;
|
||||
|
||||
}
|
||||
|
||||
// [RH] Namespaces from BOOM.
|
||||
// These are needed here in the low level part so that WAD files can be properly set up.
|
||||
typedef enum {
|
||||
ns_hidden = -1,
|
||||
|
||||
ns_global = 0,
|
||||
ns_sprites,
|
||||
ns_flats,
|
||||
ns_colormaps,
|
||||
ns_acslibrary,
|
||||
ns_newtextures,
|
||||
ns_bloodraw, // no longer used - kept for ZScript.
|
||||
ns_bloodsfx, // no longer used - kept for ZScript.
|
||||
ns_bloodmisc, // no longer used - kept for ZScript.
|
||||
ns_strifevoices,
|
||||
ns_hires,
|
||||
ns_voxels,
|
||||
|
||||
// These namespaces are only used to mark lumps in special subdirectories
|
||||
// so that their contents doesn't interfere with the global namespace.
|
||||
// searching for data in these namespaces works differently for lumps coming
|
||||
// from Zips or other files.
|
||||
ns_specialzipdirectory,
|
||||
ns_sounds,
|
||||
ns_patches,
|
||||
ns_graphics,
|
||||
ns_music,
|
||||
|
||||
ns_firstskin,
|
||||
} namespace_t;
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
enum ELumpFlags
|
||||
{
|
||||
RESFF_MAYBEFLAT = 1, // might be a flat inside a WAD outside F_START/END
|
||||
RESFF_FULLPATH = 2, // contains a full path. This will trigger extended namespace checks when looking up short names.
|
||||
RESFF_FULLPATH = 2, // contains a full path.
|
||||
RESFF_EMBEDDED = 4, // marks an embedded resource file for later processing.
|
||||
RESFF_SHORTNAME = 8, // the stored name is a short extension-less name
|
||||
RESFF_COMPRESSED = 16, // compressed or encrypted, i.e. cannot be read with the container file's reader.
|
||||
|
@ -104,11 +69,10 @@ struct FResourceEntry
|
|||
size_t CompressedSize;
|
||||
const char* FileName;
|
||||
size_t Position;
|
||||
int ResourceID;
|
||||
int ResourceID; // Only Blood RFF uses this natively.
|
||||
uint32_t CRC32;
|
||||
uint16_t Flags;
|
||||
uint16_t Method;
|
||||
int16_t Namespace;
|
||||
};
|
||||
|
||||
void SetMainThread();
|
||||
|
@ -116,17 +80,25 @@ void SetMainThread();
|
|||
class FResourceFile
|
||||
{
|
||||
public:
|
||||
FResourceFile(const char* filename, StringPool* sp);
|
||||
FResourceFile(const char* filename, FileReader& r, StringPool* sp);
|
||||
const char* NormalizeFileName(const char* fn, int fallbackcp = 0);
|
||||
enum
|
||||
{
|
||||
// descibes which kind of limitations this file type has.
|
||||
NO_FOLDERS = 1, // no paths - only one rpot folder (e.g. Build GRP, Blood RFF, Descent HOG
|
||||
NO_EXTENSIONS = 2, // no extensions for file names (e.g. Doom WADs.)
|
||||
SHORTNAMES = 4, // Name is (at most) 8.3 DOS ASCII format, (8.0 in case of WAD)
|
||||
};
|
||||
FResourceFile(const char* filename, StringPool* sp, int flags);
|
||||
FResourceFile(const char* filename, FileReader& r, StringPool* sp, int flags);
|
||||
const char* NormalizeFileName(const char* fn, int fallbackcp = 0, bool allowbackslash = false);
|
||||
FResourceEntry* AllocateEntries(int count);
|
||||
void GenerateHash();
|
||||
void PostProcessArchive(LumpFilterInfo* filter);
|
||||
void PostProcessArchive(FileSystemFilterInfo* filter);
|
||||
protected:
|
||||
FileReader Reader;
|
||||
const char* FileName;
|
||||
FResourceEntry* Entries = nullptr;
|
||||
uint32_t NumLumps;
|
||||
int flags = 0;
|
||||
char Hash[48];
|
||||
StringPool* stringpool;
|
||||
|
||||
|
@ -136,7 +108,7 @@ protected:
|
|||
Entries[entry].Flags &= ~RESFF_NEEDFILESTART;
|
||||
}
|
||||
bool IsFileInFolder(const char* const resPath);
|
||||
void CheckEmbedded(uint32_t entry, LumpFilterInfo* lfi);
|
||||
void CheckEmbedded(uint32_t entry, FileSystemFilterInfo* lfi);
|
||||
|
||||
private:
|
||||
uint32_t FirstLump;
|
||||
|
@ -144,18 +116,19 @@ private:
|
|||
int FilterLumps(const std::string& filtername, uint32_t max);
|
||||
bool FindPrefixRange(const char* filter, uint32_t max, uint32_t &start, uint32_t &end);
|
||||
void JunkLeftoverFilters(uint32_t max);
|
||||
void FindCommonFolder(LumpFilterInfo* filter);
|
||||
static FResourceFile *DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
void FindCommonFolder(FileSystemFilterInfo* filter);
|
||||
static FResourceFile *DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
|
||||
public:
|
||||
static FResourceFile *OpenResourceFile(const char *filename, FileReader &file, bool containeronly = false, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr);
|
||||
static FResourceFile *OpenResourceFile(const char *filename, bool containeronly = false, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr);
|
||||
static FResourceFile *OpenDirectory(const char *filename, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr);
|
||||
static FResourceFile *OpenResourceFile(const char *filename, FileReader &file, bool containeronly = false, FileSystemFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr);
|
||||
static FResourceFile *OpenResourceFile(const char *filename, bool containeronly = false, FileSystemFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr);
|
||||
static FResourceFile *OpenDirectory(const char *filename, FileSystemFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr);
|
||||
virtual ~FResourceFile();
|
||||
// If this FResourceFile represents a directory, the Reader object is not usable so don't return it.
|
||||
FileReader *GetContainerReader() { return Reader.isOpen()? &Reader : nullptr; }
|
||||
const char* GetFileName() const { return FileName; }
|
||||
uint32_t GetFirstEntry() const { return FirstLump; }
|
||||
int GetFlags() const noexcept { return flags; }
|
||||
void SetFirstLump(uint32_t f) { FirstLump = f; }
|
||||
const char* GetHash() const { return Hash; }
|
||||
|
||||
|
@ -179,11 +152,6 @@ public:
|
|||
return (entry < NumLumps) ? Entries[entry].Flags : 0;
|
||||
}
|
||||
|
||||
int GetEntryNamespace(uint32_t entry)
|
||||
{
|
||||
return (entry < NumLumps) ? Entries[entry].Namespace : (int)ns_hidden;
|
||||
}
|
||||
|
||||
int GetEntryResourceID(uint32_t entry)
|
||||
{
|
||||
return (entry < NumLumps) ? Entries[entry].ResourceID : -1;
|
||||
|
|
|
@ -177,7 +177,7 @@ class F7ZFile : public FResourceFile
|
|||
|
||||
public:
|
||||
F7ZFile(const char * filename, FileReader &filer, StringPool* sp);
|
||||
bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf);
|
||||
bool Open(FileSystemFilterInfo* filter, FileSystemMessageFunc Printf);
|
||||
virtual ~F7ZFile();
|
||||
FileData Read(uint32_t entry) override;
|
||||
FileReader GetEntryReader(uint32_t entry, int, int) override;
|
||||
|
@ -192,7 +192,7 @@ public:
|
|||
//==========================================================================
|
||||
|
||||
F7ZFile::F7ZFile(const char * filename, FileReader &filer, StringPool* sp)
|
||||
: FResourceFile(filename, filer, sp)
|
||||
: FResourceFile(filename, filer, sp, 0)
|
||||
{
|
||||
Archive = nullptr;
|
||||
}
|
||||
|
@ -204,7 +204,7 @@ F7ZFile::F7ZFile(const char * filename, FileReader &filer, StringPool* sp)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool F7ZFile::Open(LumpFilterInfo *filter, FileSystemMessageFunc Printf)
|
||||
bool F7ZFile::Open(FileSystemFilterInfo *filter, FileSystemMessageFunc Printf)
|
||||
{
|
||||
Archive = new C7zArchive(Reader);
|
||||
int skipped = 0;
|
||||
|
@ -268,7 +268,6 @@ bool F7ZFile::Open(LumpFilterInfo *filter, FileSystemMessageFunc Printf)
|
|||
Entries[j].Length = SzArEx_GetFileSize(archPtr, i);
|
||||
Entries[j].Flags = RESFF_FULLPATH|RESFF_COMPRESSED;
|
||||
Entries[j].ResourceID = -1;
|
||||
Entries[j].Namespace = ns_global;
|
||||
Entries[j].Method = METHOD_INVALID;
|
||||
Entries[j].Position = i;
|
||||
j++;
|
||||
|
@ -351,7 +350,7 @@ FileReader F7ZFile::GetEntryReader(uint32_t entry, int, int)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile *Check7Z(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
FResourceFile *Check7Z(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
{
|
||||
char head[k7zSignatureSize];
|
||||
|
||||
|
|
|
@ -57,11 +57,11 @@ class FDirectory : public FResourceFile
|
|||
const char** SystemFilePath;
|
||||
|
||||
|
||||
int AddDirectory(const char* dirpath, LumpFilterInfo* filter, FileSystemMessageFunc Printf);
|
||||
int AddDirectory(const char* dirpath, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf);
|
||||
|
||||
public:
|
||||
FDirectory(const char * dirname, StringPool* sp, bool nosubdirflag = false);
|
||||
bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf);
|
||||
bool Open(FileSystemFilterInfo* filter, FileSystemMessageFunc Printf);
|
||||
FileReader GetEntryReader(uint32_t entry, int, int) override;
|
||||
};
|
||||
|
||||
|
@ -74,7 +74,7 @@ public:
|
|||
//==========================================================================
|
||||
|
||||
FDirectory::FDirectory(const char * directory, StringPool* sp, bool nosubdirflag)
|
||||
: FResourceFile("", sp), nosubdir(nosubdirflag)
|
||||
: FResourceFile("", sp, 0), nosubdir(nosubdirflag)
|
||||
{
|
||||
auto fn = FS_FullPath(directory);
|
||||
if (fn.back() != '/') fn += '/';
|
||||
|
@ -87,7 +87,7 @@ FDirectory::FDirectory(const char * directory, StringPool* sp, bool nosubdirflag
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int FDirectory::AddDirectory(const char *dirpath, LumpFilterInfo* filter, FileSystemMessageFunc Printf)
|
||||
int FDirectory::AddDirectory(const char *dirpath, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
|
@ -141,7 +141,6 @@ int FDirectory::AddDirectory(const char *dirpath, LumpFilterInfo* filter, FileSy
|
|||
Entries[count].Flags = RESFF_FULLPATH;
|
||||
Entries[count].ResourceID = -1;
|
||||
Entries[count].Method = METHOD_STORED;
|
||||
Entries[count].Namespace = ns_global;
|
||||
Entries[count].Position = count;
|
||||
count++;
|
||||
}
|
||||
|
@ -157,7 +156,7 @@ int FDirectory::AddDirectory(const char *dirpath, LumpFilterInfo* filter, FileSy
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FDirectory::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
|
||||
bool FDirectory::Open(FileSystemFilterInfo* filter, FileSystemMessageFunc Printf)
|
||||
{
|
||||
NumLumps = AddDirectory(FileName, filter, Printf);
|
||||
PostProcessArchive(filter);
|
||||
|
@ -193,7 +192,7 @@ FileReader FDirectory::GetEntryReader(uint32_t entry, int readertype, int)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile *CheckDir(const char *filename, bool nosubdirflag, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
FResourceFile *CheckDir(const char *filename, bool nosubdirflag, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
{
|
||||
auto rf = new FDirectory(filename, sp, nosubdirflag);
|
||||
if (rf->Open(filter, Printf)) return rf;
|
||||
|
|
|
@ -71,7 +71,7 @@ struct GrpLump
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static bool OpenGrp(FResourceFile* file, LumpFilterInfo* filter)
|
||||
static bool OpenGrp(FResourceFile* file, FileSystemFilterInfo* filter)
|
||||
{
|
||||
GrpHeader header;
|
||||
|
||||
|
@ -91,7 +91,6 @@ static bool OpenGrp(FResourceFile* file, LumpFilterInfo* filter)
|
|||
Entries[i].CompressedSize = Entries[i].Length = LittleLong(fileinfo[i].Size);
|
||||
Position += fileinfo[i].Size;
|
||||
Entries[i].Flags = 0;
|
||||
Entries[i].Namespace = ns_global;
|
||||
fileinfo[i].NameWithZero[12] = '\0'; // Be sure filename is null-terminated
|
||||
Entries[i].ResourceID = -1;
|
||||
Entries[i].Method = METHOD_STORED;
|
||||
|
@ -109,7 +108,7 @@ static bool OpenGrp(FResourceFile* file, LumpFilterInfo* filter)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile *CheckGRP(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
FResourceFile *CheckGRP(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
{
|
||||
char head[12];
|
||||
|
||||
|
@ -120,7 +119,7 @@ FResourceFile *CheckGRP(const char *filename, FileReader &file, LumpFilterInfo*
|
|||
file.Seek(0, FileReader::SeekSet);
|
||||
if (!memcmp(head, "KenSilverman", 12))
|
||||
{
|
||||
auto rf = new FResourceFile(filename, file, sp);
|
||||
auto rf = new FResourceFile(filename, file, sp, FResourceFile::NO_FOLDERS | FResourceFile::SHORTNAMES);
|
||||
if (OpenGrp(rf, filter)) return rf;
|
||||
file = rf->Destroy();
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace FileSys {
|
|||
|
||||
|
||||
|
||||
static bool OpenHog(FResourceFile* rf, LumpFilterInfo* filter)
|
||||
static bool OpenHog(FResourceFile* rf, FileSystemFilterInfo* filter)
|
||||
{
|
||||
auto Reader = rf->GetContainerReader();
|
||||
FileReader::Size length = Reader->GetLength();
|
||||
|
@ -66,7 +66,6 @@ static bool OpenHog(FResourceFile* rf, LumpFilterInfo* filter)
|
|||
Entry.CompressedSize = Entry.Length = elength;
|
||||
Entry.Flags = 0;
|
||||
Entry.CRC32 = 0;
|
||||
Entry.Namespace = ns_global;
|
||||
Entry.ResourceID = -1;
|
||||
Entry.Method = METHOD_STORED;
|
||||
Entry.FileName = rf->NormalizeFileName(name);
|
||||
|
@ -86,7 +85,7 @@ static bool OpenHog(FResourceFile* rf, LumpFilterInfo* filter)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile* CheckHog(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
FResourceFile* CheckHog(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
{
|
||||
char head[3];
|
||||
|
||||
|
@ -96,7 +95,7 @@ FResourceFile* CheckHog(const char* filename, FileReader& file, LumpFilterInfo*
|
|||
file.Read(&head, 3);
|
||||
if (!memcmp(head, "DHF", 3))
|
||||
{
|
||||
auto rf = new FResourceFile(filename, file, sp);
|
||||
auto rf = new FResourceFile(filename, file, sp, FResourceFile::NO_FOLDERS | FResourceFile::SHORTNAMES);
|
||||
if (OpenHog(rf, filter)) return rf;
|
||||
file = rf->Destroy();
|
||||
}
|
||||
|
|
107
src/common/filesystem/source/file_hog2.cpp
Normal file
107
src/common/filesystem/source/file_hog2.cpp
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
** file_hog.cpp
|
||||
**
|
||||
** reads Descent 3 .hog2 files
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2024 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 "resourcefile.h"
|
||||
#include "fs_swap.h"
|
||||
|
||||
namespace FileSys {
|
||||
using namespace byteswap;
|
||||
|
||||
|
||||
|
||||
static bool OpenHog2(FResourceFile* rf, FileSystemFilterInfo* filter)
|
||||
{
|
||||
auto Reader = rf->GetContainerReader();
|
||||
FileReader::Size length = Reader->GetLength();
|
||||
|
||||
uint32_t numfiles = Reader->ReadUInt32();
|
||||
uint32_t offset = Reader->ReadUInt32(); // offset to first file (end of file list)
|
||||
Reader->Seek(56, FileReader::SeekEnd); // filled with FF
|
||||
auto Entries = rf->AllocateEntries((int)numfiles);
|
||||
|
||||
for(uint32_t i = 0; i < numfiles; i++)
|
||||
{
|
||||
char name[37];
|
||||
Reader->Read(name, 36);
|
||||
name[36] = 0;
|
||||
Reader->ReadUInt32();
|
||||
uint32_t size = Reader->ReadUInt32();;
|
||||
Reader->ReadUInt32();
|
||||
|
||||
FResourceEntry& Entry = Entries[i];
|
||||
Entry.Position = offset;
|
||||
Entry.CompressedSize = Entry.Length = size;
|
||||
Entry.Flags = RESFF_FULLPATH;
|
||||
Entry.CRC32 = 0;
|
||||
Entry.ResourceID = -1;
|
||||
Entry.Method = METHOD_STORED;
|
||||
Entry.FileName = rf->NormalizeFileName(name);
|
||||
offset += size;
|
||||
}
|
||||
rf->GenerateHash();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// File open
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile* CheckHog2(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
{
|
||||
char head[4];
|
||||
|
||||
if (file.GetLength() >= 68)
|
||||
{
|
||||
file.Seek(0, FileReader::SeekSet);
|
||||
file.Read(&head, 4);
|
||||
if (!memcmp(head, "HOG2", 4))
|
||||
{
|
||||
auto rf = new FResourceFile(filename, file, sp, 0);
|
||||
if (OpenHog2(rf, filter)) return rf;
|
||||
file = rf->Destroy();
|
||||
}
|
||||
file.Seek(0, FileReader::SeekSet);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -41,11 +41,10 @@ namespace FileSys {
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static bool OpenLump(FResourceFile* file, LumpFilterInfo*)
|
||||
static bool OpenLump(FResourceFile* file, FileSystemFilterInfo*)
|
||||
{
|
||||
auto Entries = file->AllocateEntries(1);
|
||||
Entries[0].FileName = file->NormalizeFileName(ExtractBaseName(file->GetFileName(), true).c_str());
|
||||
Entries[0].Namespace = ns_global;
|
||||
Entries[0].ResourceID = -1;
|
||||
Entries[0].Position = 0;
|
||||
Entries[0].CompressedSize = Entries[0].Length = file->GetContainerReader()->GetLength();
|
||||
|
@ -60,10 +59,10 @@ static bool OpenLump(FResourceFile* file, LumpFilterInfo*)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile *CheckLump(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
FResourceFile *CheckLump(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
{
|
||||
// always succeeds
|
||||
auto rf = new FResourceFile(filename, file, sp);
|
||||
auto rf = new FResourceFile(filename, file, sp, FResourceFile::NO_FOLDERS);
|
||||
if (OpenLump(rf, filter)) return rf;
|
||||
file = rf->Destroy();
|
||||
return NULL;
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace FileSys {
|
|||
|
||||
|
||||
|
||||
static bool OpenMvl(FResourceFile* rf, LumpFilterInfo* filter)
|
||||
static bool OpenMvl(FResourceFile* rf, FileSystemFilterInfo* filter)
|
||||
{
|
||||
auto Reader = rf->GetContainerReader();
|
||||
auto count = Reader->ReadUInt32();
|
||||
|
@ -75,7 +75,7 @@ static bool OpenMvl(FResourceFile* rf, LumpFilterInfo* filter)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile* CheckMvl(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
FResourceFile* CheckMvl(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
{
|
||||
char head[4];
|
||||
|
||||
|
@ -85,7 +85,7 @@ FResourceFile* CheckMvl(const char* filename, FileReader& file, LumpFilterInfo*
|
|||
file.Read(&head, 4);
|
||||
if (!memcmp(head, "DMVL", 4))
|
||||
{
|
||||
auto rf = new FResourceFile(filename, file, sp);
|
||||
auto rf = new FResourceFile(filename, file, sp, FResourceFile::NO_FOLDERS | FResourceFile::SHORTNAMES);
|
||||
if (OpenMvl(rf, filter)) return rf;
|
||||
file = rf->Destroy();
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ struct dpackheader_t
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static bool OpenPak(FResourceFile* file, LumpFilterInfo* filter)
|
||||
static bool OpenPak(FResourceFile* file, FileSystemFilterInfo* filter)
|
||||
{
|
||||
dpackheader_t header;
|
||||
|
||||
|
@ -82,7 +82,6 @@ static bool OpenPak(FResourceFile* file, LumpFilterInfo* filter)
|
|||
Entries[i].Position = LittleLong(fileinfo[i].filepos);
|
||||
Entries[i].CompressedSize = Entries[i].Length = LittleLong(fileinfo[i].filelen);
|
||||
Entries[i].Flags = RESFF_FULLPATH;
|
||||
Entries[i].Namespace = ns_global;
|
||||
Entries[i].ResourceID = -1;
|
||||
Entries[i].Method = METHOD_STORED;
|
||||
Entries[i].FileName = file->NormalizeFileName(fileinfo[i].name);
|
||||
|
@ -99,7 +98,7 @@ static bool OpenPak(FResourceFile* file, LumpFilterInfo* filter)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
FResourceFile *CheckPak(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
{
|
||||
char head[4];
|
||||
|
||||
|
@ -110,7 +109,7 @@ FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo*
|
|||
file.Seek(0, FileReader::SeekSet);
|
||||
if (!memcmp(head, "PACK", 4))
|
||||
{
|
||||
auto rf = new FResourceFile(filename, file, sp);
|
||||
auto rf = new FResourceFile(filename, file, sp, 0);
|
||||
if (OpenPak(rf, filter)) return rf;
|
||||
file = rf->Destroy();
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ void BloodCrypt (void *data, int key, int len)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static bool OpenRFF(FResourceFile* file, LumpFilterInfo*)
|
||||
static bool OpenRFF(FResourceFile* file, FileSystemFilterInfo*)
|
||||
{
|
||||
RFFLump *lumps;
|
||||
RFFInfo header;
|
||||
|
@ -123,7 +123,6 @@ static bool OpenRFF(FResourceFile* file, LumpFilterInfo*)
|
|||
Entries[i].Flags = 0;
|
||||
Entries[i].Method = METHOD_STORED;
|
||||
}
|
||||
Entries[i].Namespace = ns_global;
|
||||
Entries[i].ResourceID = LittleLong(lumps[i].IndexNum);
|
||||
|
||||
// Rearrange the name and extension to construct the fullname.
|
||||
|
@ -150,7 +149,7 @@ static bool OpenRFF(FResourceFile* file, LumpFilterInfo*)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile *CheckRFF(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
FResourceFile *CheckRFF(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
{
|
||||
char head[4];
|
||||
|
||||
|
@ -161,7 +160,7 @@ FResourceFile *CheckRFF(const char *filename, FileReader &file, LumpFilterInfo*
|
|||
file.Seek(0, FileReader::SeekSet);
|
||||
if (!memcmp(head, "RFF\x1a", 4))
|
||||
{
|
||||
auto rf = new FResourceFile(filename, file, sp);
|
||||
auto rf = new FResourceFile(filename, file, sp, FResourceFile::NO_FOLDERS | FResourceFile::SHORTNAMES);
|
||||
if (OpenRFF(rf, filter)) return rf;
|
||||
file = rf->Destroy();
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace FileSys {
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static bool OpenSSI(FResourceFile* file, int version, int EntryCount, LumpFilterInfo*)
|
||||
static bool OpenSSI(FResourceFile* file, int version, int EntryCount, FileSystemFilterInfo*)
|
||||
{
|
||||
uint32_t NumLumps = EntryCount * 2;
|
||||
auto Entries = file->AllocateEntries(NumLumps);
|
||||
|
@ -65,7 +65,6 @@ static bool OpenSSI(FResourceFile* file, int version, int EntryCount, LumpFilter
|
|||
Entries[i].Position = j;
|
||||
Entries[i].CompressedSize = Entries[i].Length = flength;
|
||||
Entries[i].Flags = 0;
|
||||
Entries[i].Namespace = ns_global;
|
||||
Entries[i].Method = METHOD_STORED;
|
||||
Entries[i].ResourceID = -1;
|
||||
Entries[i].FileName = file->NormalizeFileName(fn);
|
||||
|
@ -78,7 +77,6 @@ static bool OpenSSI(FResourceFile* file, int version, int EntryCount, LumpFilter
|
|||
Entries[i + 1].Position = j;
|
||||
Entries[i + 1].CompressedSize = Entries[i + 1].Length = flength;
|
||||
Entries[i + 1].Flags = 0;
|
||||
Entries[i + 1].Namespace = ns_global;
|
||||
Entries[i + 1].ResourceID = -1;
|
||||
Entries[i + 1].FileName = file->NormalizeFileName(fn);
|
||||
Entries[i + 1].Method = METHOD_STORED;
|
||||
|
@ -99,7 +97,7 @@ static bool OpenSSI(FResourceFile* file, int version, int EntryCount, LumpFilter
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
FResourceFile* CheckSSI(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
{
|
||||
char zerobuf[72];
|
||||
char buf[72];
|
||||
|
@ -129,7 +127,7 @@ FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo*
|
|||
{
|
||||
if (!skipstring(70)) return nullptr;
|
||||
}
|
||||
auto ssi = new FResourceFile(filename, file, sp);
|
||||
auto ssi = new FResourceFile(filename, file, sp, FResourceFile::NO_FOLDERS | FResourceFile::SHORTNAMES);
|
||||
if (OpenSSI(ssi, version, numfiles, filter)) return ssi;
|
||||
file = ssi->Destroy();
|
||||
}
|
||||
|
|
|
@ -58,52 +58,22 @@ struct wadlump_t
|
|||
char Name[8];
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Wad file
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FWadFile : public FResourceFile
|
||||
{
|
||||
bool IsMarker(int lump, const char *marker);
|
||||
void SetNamespace(const char *startmarker, const char *endmarker, namespace_t space, FileSystemMessageFunc Printf, bool flathack=false);
|
||||
void SkinHack (FileSystemMessageFunc Printf);
|
||||
|
||||
public:
|
||||
FWadFile(const char * filename, FileReader &file, StringPool* sp);
|
||||
bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf);
|
||||
};
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FWadFile::FWadFile
|
||||
//
|
||||
// Initializes a WAD file
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FWadFile::FWadFile(const char *filename, FileReader &file, StringPool* sp)
|
||||
: FResourceFile(filename, file, sp)
|
||||
{
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Open it
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FWadFile::Open(LumpFilterInfo*, FileSystemMessageFunc Printf)
|
||||
static bool OpenWAD(FResourceFile* file, FileSystemFilterInfo*, FileSystemMessageFunc Printf)
|
||||
{
|
||||
wadinfo_t header;
|
||||
uint32_t InfoTableOfs;
|
||||
bool isBigEndian = false; // Little endian is assumed until proven otherwise
|
||||
auto wadSize = Reader.GetLength();
|
||||
auto Reader = file->GetContainerReader();
|
||||
auto wadSize = Reader->GetLength();
|
||||
|
||||
Reader.Read(&header, sizeof(header));
|
||||
NumLumps = LittleLong(header.NumLumps);
|
||||
Reader->Read(&header, sizeof(header));
|
||||
uint32_t NumLumps = LittleLong(header.NumLumps);
|
||||
InfoTableOfs = LittleLong(header.InfoTableOfs);
|
||||
|
||||
// Check to see if the little endian interpretation is valid
|
||||
|
@ -117,16 +87,16 @@ bool FWadFile::Open(LumpFilterInfo*, FileSystemMessageFunc Printf)
|
|||
// Check again to detect broken wads
|
||||
if (InfoTableOfs + NumLumps*sizeof(wadlump_t) > (unsigned)wadSize)
|
||||
{
|
||||
Printf(FSMessageLevel::Error, "%s: Bad directory offset.\n", FileName);
|
||||
Printf(FSMessageLevel::Error, "%s: Bad directory offset.\n", file->GetFileName());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reader.Seek(InfoTableOfs, FileReader::SeekSet);
|
||||
auto fd = Reader.Read(NumLumps * sizeof(wadlump_t));
|
||||
Reader->Seek(InfoTableOfs, FileReader::SeekSet);
|
||||
auto fd = Reader->Read(NumLumps * sizeof(wadlump_t));
|
||||
auto fileinfo = (const wadlump_t*)fd.data();
|
||||
|
||||
AllocateEntries(NumLumps);
|
||||
auto Entries = file->AllocateEntries(NumLumps);
|
||||
|
||||
for(uint32_t i = 0; i < NumLumps; i++)
|
||||
{
|
||||
|
@ -143,17 +113,17 @@ bool FWadFile::Open(LumpFilterInfo*, FileSystemMessageFunc Printf)
|
|||
else if (ishigh > 1)
|
||||
{
|
||||
// This may not end up printing something proper because we do not know what encoding might have been used.
|
||||
Printf(FSMessageLevel::Warning, "%s: Lump name %.8s contains invalid characters\n", FileName, fileinfo[i].Name);
|
||||
Printf(FSMessageLevel::Warning, "%s: Lump name %.8s contains invalid characters\n", file->GetFileName(), fileinfo[i].Name);
|
||||
n[0] = 0;
|
||||
}
|
||||
|
||||
Entries[i].FileName = nullptr;
|
||||
Entries[i].Position = isBigEndian ? BigLong(fileinfo[i].FilePos) : LittleLong(fileinfo[i].FilePos);
|
||||
Entries[i].CompressedSize = Entries[i].Length = isBigEndian ? BigLong(fileinfo[i].Size) : LittleLong(fileinfo[i].Size);
|
||||
|
||||
Entries[i].Namespace = ns_global;
|
||||
Entries[i].Flags = ishigh? RESFF_SHORTNAME | RESFF_COMPRESSED : RESFF_SHORTNAME;
|
||||
Entries[i].Method = ishigh == 1? METHOD_LZSS : METHOD_STORED;
|
||||
Entries[i].FileName = stringpool->Strdup(n);
|
||||
Entries[i].FileName = file->NormalizeFileName(n, 0, true);
|
||||
// This doesn't set up the namespace yet.
|
||||
}
|
||||
for (uint32_t i = 0; i < NumLumps; i++)
|
||||
|
@ -161,250 +131,21 @@ bool FWadFile::Open(LumpFilterInfo*, FileSystemMessageFunc Printf)
|
|||
if (Entries[i].Method == METHOD_LZSS)
|
||||
{
|
||||
// compressed size is implicit.
|
||||
Entries[i].CompressedSize = (i == NumLumps - 1 ? Reader.GetLength() : Entries[i + 1].Position) - Entries[i].Position;
|
||||
Entries[i].CompressedSize = (i == NumLumps - 1 ? Reader->GetLength() : Entries[i + 1].Position) - Entries[i].Position;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GenerateHash(); // Do this before the lump processing below.
|
||||
|
||||
SetNamespace("s_start", "s_end", ns_sprites, Printf);
|
||||
SetNamespace("f_start", "f_end", ns_flats, Printf, true);
|
||||
SetNamespace("c_start", "c_end", ns_colormaps, Printf);
|
||||
SetNamespace("a_start", "a_end", ns_acslibrary, Printf);
|
||||
SetNamespace("tx_start", "tx_end", ns_newtextures, Printf);
|
||||
SetNamespace("v_start", "v_end", ns_strifevoices, Printf);
|
||||
SetNamespace("hi_start", "hi_end", ns_hires, Printf);
|
||||
SetNamespace("vx_start", "vx_end", ns_voxels, Printf);
|
||||
SkinHack(Printf);
|
||||
|
||||
file->GenerateHash(); // Do this before the lump processing below.
|
||||
return true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// IsMarker
|
||||
//
|
||||
// (from BOOM)
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
inline bool FWadFile::IsMarker(int lump, const char *marker)
|
||||
{
|
||||
if (Entries[lump].FileName[0] == marker[0])
|
||||
{
|
||||
return (!strcmp(Entries[lump].FileName, marker) ||
|
||||
(marker[1] == '_' && !strcmp(Entries[lump].FileName +1, marker)));
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SetNameSpace
|
||||
//
|
||||
// Sets namespace information for the lumps. It always looks for the first
|
||||
// x_START and the last x_END lump, except when loading flats. In this case
|
||||
// F_START may be absent and if that is the case all lumps with a size of
|
||||
// 4096 will be flagged appropriately.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
// This class was supposed to be local in the function but GCC
|
||||
// does not like that.
|
||||
struct Marker
|
||||
{
|
||||
int markertype;
|
||||
unsigned int index;
|
||||
};
|
||||
|
||||
void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, namespace_t space, FileSystemMessageFunc Printf, bool flathack)
|
||||
{
|
||||
bool warned = false;
|
||||
int numstartmarkers = 0, numendmarkers = 0;
|
||||
unsigned int i;
|
||||
std::vector<Marker> markers;
|
||||
|
||||
for(i = 0; i < NumLumps; i++)
|
||||
{
|
||||
if (IsMarker(i, startmarker))
|
||||
{
|
||||
Marker m = { 0, i };
|
||||
markers.push_back(m);
|
||||
numstartmarkers++;
|
||||
}
|
||||
else if (IsMarker(i, endmarker))
|
||||
{
|
||||
Marker m = { 1, i };
|
||||
markers.push_back(m);
|
||||
numendmarkers++;
|
||||
}
|
||||
}
|
||||
|
||||
if (numstartmarkers == 0)
|
||||
{
|
||||
if (numendmarkers == 0) return; // no markers found
|
||||
|
||||
Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, endmarker, startmarker);
|
||||
|
||||
|
||||
if (flathack)
|
||||
{
|
||||
// We have found no F_START but one or more F_END markers.
|
||||
// mark all lumps before the last F_END marker as potential flats.
|
||||
unsigned int end = markers[markers.size()-1].index;
|
||||
for(unsigned int ii = 0; ii < end; ii++)
|
||||
{
|
||||
if (Entries[ii].Length == 4096)
|
||||
{
|
||||
// We can't add this to the flats namespace but
|
||||
// it needs to be flagged for the texture manager.
|
||||
Printf(FSMessageLevel::DebugNotify, "%s: Marking %s as potential flat\n", FileName, Entries[ii].FileName);
|
||||
Entries[ii].Flags |= RESFF_MAYBEFLAT;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (i < markers.size())
|
||||
{
|
||||
int start, end;
|
||||
if (markers[i].markertype != 0)
|
||||
{
|
||||
Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, endmarker, startmarker);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
start = i++;
|
||||
|
||||
// skip over subsequent x_START markers
|
||||
while (i < markers.size() && markers[i].markertype == 0)
|
||||
{
|
||||
Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName, startmarker);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
// same for x_END markers
|
||||
while (i < markers.size()-1 && (markers[i].markertype == 1 && markers[i+1].markertype == 1))
|
||||
{
|
||||
Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName, endmarker);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
// We found a starting marker but no end marker. Ignore this block.
|
||||
if (i >= markers.size())
|
||||
{
|
||||
Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, startmarker, endmarker);
|
||||
end = NumLumps;
|
||||
}
|
||||
else
|
||||
{
|
||||
end = markers[i++].index;
|
||||
}
|
||||
|
||||
// we found a marked block
|
||||
Printf(FSMessageLevel::DebugNotify, "%s: Found %s block at (%d-%d)\n", FileName, startmarker, markers[start].index, end);
|
||||
for(int j = markers[start].index + 1; j < end; j++)
|
||||
{
|
||||
if (Entries[j].Namespace != ns_global)
|
||||
{
|
||||
if (!warned)
|
||||
{
|
||||
Printf(FSMessageLevel::Warning, "%s: Overlapping namespaces found (lump %d)\n", FileName, j);
|
||||
}
|
||||
warned = true;
|
||||
}
|
||||
else if (space == ns_sprites && Entries[j].Length < 8)
|
||||
{
|
||||
// sf 26/10/99:
|
||||
// ignore sprite lumps smaller than 8 bytes (the smallest possible)
|
||||
// in size -- this was used by some dmadds wads
|
||||
// as an 'empty' graphics resource
|
||||
Printf(FSMessageLevel::DebugWarn, "%s: Skipped empty sprite %s (lump %d)\n", FileName, Entries[j].FileName, j);
|
||||
}
|
||||
else
|
||||
{
|
||||
Entries[j].Namespace = space;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// W_SkinHack
|
||||
//
|
||||
// Tests a wad file to see if it contains an S_SKIN marker. If it does,
|
||||
// every lump in the wad is moved into a new namespace. Because skins are
|
||||
// only supposed to replace player sprites, sounds, or faces, this should
|
||||
// not be a problem. Yes, there are skins that replace more than that, but
|
||||
// they are such a pain, and breaking them like this was done on purpose.
|
||||
// This also renames any S_SKINxx lumps to just S_SKIN.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FWadFile::SkinHack (FileSystemMessageFunc Printf)
|
||||
{
|
||||
// this being static is not a problem. The only relevant thing is that each skin gets a different number.
|
||||
static int namespc = ns_firstskin;
|
||||
bool skinned = false;
|
||||
bool hasmap = false;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < NumLumps; i++)
|
||||
{
|
||||
auto lump = &Entries[i];
|
||||
|
||||
if (!strnicmp(lump->FileName, "S_SKIN", 6))
|
||||
{ // Wad has at least one skin.
|
||||
lump->FileName = "S_SKIN";
|
||||
if (!skinned)
|
||||
{
|
||||
skinned = true;
|
||||
uint32_t j;
|
||||
|
||||
for (j = 0; j < NumLumps; j++)
|
||||
{
|
||||
Entries[j].Namespace = namespc;
|
||||
}
|
||||
namespc++;
|
||||
}
|
||||
}
|
||||
// needless to say, this check is entirely useless these days as map names can be more diverse..
|
||||
if ((lump->FileName[0] == 'M' &&
|
||||
lump->FileName[1] == 'A' &&
|
||||
lump->FileName[2] == 'P' &&
|
||||
lump->FileName[3] >= '0' && lump->FileName[3] <= '9' &&
|
||||
lump->FileName[4] >= '0' && lump->FileName[4] <= '9' &&
|
||||
lump->FileName[5] == '\0')
|
||||
||
|
||||
(lump->FileName[0] == 'E' &&
|
||||
lump->FileName[1] >= '0' && lump->FileName[1] <= '9' &&
|
||||
lump->FileName[2] == 'M' &&
|
||||
lump->FileName[3] >= '0' && lump->FileName[3] <= '9' &&
|
||||
lump->FileName[4] == '\0'))
|
||||
{
|
||||
hasmap = true;
|
||||
}
|
||||
}
|
||||
if (skinned && hasmap)
|
||||
{
|
||||
Printf(FSMessageLevel::Attention, "%s: The maps will not be loaded because it has a skin.\n", FileName);
|
||||
Printf(FSMessageLevel::Attention, "You should remove the skin from the wad to play these maps.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// File open
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile *CheckWad(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
FResourceFile *CheckWad(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
{
|
||||
char head[4];
|
||||
|
||||
|
@ -415,8 +156,8 @@ FResourceFile *CheckWad(const char *filename, FileReader &file, LumpFilterInfo*
|
|||
file.Seek(0, FileReader::SeekSet);
|
||||
if (!memcmp(head, "IWAD", 4) || !memcmp(head, "PWAD", 4))
|
||||
{
|
||||
auto rf = new FWadFile(filename, file, sp);
|
||||
if (rf->Open(filter, Printf)) return rf;
|
||||
auto rf = new FResourceFile(filename, file, sp, FResourceFile::NO_FOLDERS | FResourceFile::NO_EXTENSIONS | FResourceFile::SHORTNAMES);
|
||||
if (OpenWAD(rf, filter, Printf)) return rf;
|
||||
|
||||
file = rf->Destroy();
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace FileSys {
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool OpenWHRes(FResourceFile* file, LumpFilterInfo*)
|
||||
bool OpenWHRes(FResourceFile* file, FileSystemFilterInfo*)
|
||||
{
|
||||
uint32_t directory[1024];
|
||||
|
||||
|
@ -83,7 +83,6 @@ bool OpenWHRes(FResourceFile* file, LumpFilterInfo*)
|
|||
Entries[i].Position = offset;
|
||||
Entries[i].CompressedSize = Entries[i].Length = length;
|
||||
Entries[i].Flags = RESFF_FULLPATH;
|
||||
Entries[i].Namespace = ns_global;
|
||||
Entries[i].ResourceID = -1;
|
||||
Entries[i].Method = METHOD_STORED;
|
||||
Entries[i].FileName = file->NormalizeFileName(synthname.c_str());
|
||||
|
@ -99,7 +98,7 @@ bool OpenWHRes(FResourceFile* file, LumpFilterInfo*)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile *CheckWHRes(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
FResourceFile *CheckWHRes(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
{
|
||||
if (file.GetLength() >= 8192) // needs to be at least 8192 to contain one file and the directory.
|
||||
{
|
||||
|
@ -119,7 +118,7 @@ FResourceFile *CheckWHRes(const char *filename, FileReader &file, LumpFilterInfo
|
|||
if (offset != checkpos || length == 0 || offset + length >= (size_t)size - 4096 ) return nullptr;
|
||||
checkpos += (length+4095) / 4096;
|
||||
}
|
||||
auto rf = new FResourceFile(filename, file, sp);
|
||||
auto rf = new FResourceFile(filename, file, sp, FResourceFile::NO_EXTENSIONS);
|
||||
if (OpenWHRes(rf, filter)) return rf;
|
||||
file = rf->Destroy();
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@ class FZipFile : public FResourceFile
|
|||
|
||||
public:
|
||||
FZipFile(const char* filename, FileReader& file, StringPool* sp);
|
||||
bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf);
|
||||
bool Open(FileSystemFilterInfo* filter, FileSystemMessageFunc Printf);
|
||||
FCompressedBuffer GetRawData(uint32_t entry) override;
|
||||
};
|
||||
|
||||
|
@ -124,11 +124,11 @@ public:
|
|||
//==========================================================================
|
||||
|
||||
FZipFile::FZipFile(const char * filename, FileReader &file, StringPool* sp)
|
||||
: FResourceFile(filename, file, sp)
|
||||
: FResourceFile(filename, file, sp, 0)
|
||||
{
|
||||
}
|
||||
|
||||
bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
|
||||
bool FZipFile::Open(FileSystemFilterInfo* filter, FileSystemMessageFunc Printf)
|
||||
{
|
||||
bool zip64 = false;
|
||||
uint32_t centraldir = Zip_FindCentralDir(Reader, &zip64);
|
||||
|
@ -376,7 +376,7 @@ void FZipFile::SetEntryAddress(uint32_t entry)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile *CheckZip(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
FResourceFile *CheckZip(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
{
|
||||
char head[4];
|
||||
|
||||
|
|
|
@ -52,28 +52,6 @@ namespace FileSys {
|
|||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
#define NULL_INDEX (0xffffffff)
|
||||
|
||||
static 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;
|
||||
}
|
||||
|
||||
|
||||
//djb2
|
||||
static uint32_t MakeHash(const char* str, size_t length = SIZE_MAX)
|
||||
{
|
||||
uint32_t hash = 5381;
|
||||
uint32_t c;
|
||||
while (length-- > 0 && (c = *str++)) hash = hash * 33 + (c | 32);
|
||||
return hash;
|
||||
}
|
||||
|
||||
static void md5Hash(FileReader& reader, uint8_t* digest)
|
||||
{
|
||||
using namespace md5;
|
||||
|
@ -92,11 +70,9 @@ static void md5Hash(FileReader& reader, uint8_t* digest)
|
|||
struct FileSystem::LumpRecord
|
||||
{
|
||||
FResourceFile *resfile;
|
||||
LumpShortName shortName;
|
||||
const char* LongName;
|
||||
const char* Name;
|
||||
int resindex;
|
||||
int16_t rfnum; // this is not necessarily the same as resfile's index!
|
||||
int16_t Namespace;
|
||||
int resourceId;
|
||||
int flags;
|
||||
|
||||
|
@ -109,52 +85,24 @@ struct FileSystem::LumpRecord
|
|||
|
||||
auto lflags = file->GetEntryFlags(fileindex);
|
||||
if (!name) name = file->getName(fileindex);
|
||||
if (lflags & RESFF_SHORTNAME)
|
||||
if ((lflags & RESFF_EMBEDDED) || !name || !*name)
|
||||
{
|
||||
UpperCopy(shortName.String, name);
|
||||
shortName.String[8] = 0;
|
||||
LongName = "";
|
||||
Namespace = file->GetEntryNamespace(fileindex);
|
||||
resourceId = -1;
|
||||
}
|
||||
else if ((lflags & RESFF_EMBEDDED) || !name || !*name)
|
||||
{
|
||||
shortName.qword = 0;
|
||||
LongName = "";
|
||||
Namespace = ns_hidden;
|
||||
Name = "";
|
||||
resourceId = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
LongName = name;
|
||||
Name = name;
|
||||
resourceId = file->GetEntryResourceID(fileindex);
|
||||
|
||||
// Map some directories to WAD namespaces.
|
||||
// Note that some of these namespaces don't exist in WADS.
|
||||
// CheckNumForName will handle any request for these namespaces accordingly.
|
||||
Namespace = !strncmp(LongName, "flats/", 6) ? ns_flats :
|
||||
!strncmp(LongName, "textures/", 9) ? ns_newtextures :
|
||||
!strncmp(LongName, "hires/", 6) ? ns_hires :
|
||||
!strncmp(LongName, "sprites/", 8) ? ns_sprites :
|
||||
!strncmp(LongName, "voxels/", 7) ? ns_voxels :
|
||||
!strncmp(LongName, "colormaps/", 10) ? ns_colormaps :
|
||||
!strncmp(LongName, "acs/", 4) ? ns_acslibrary :
|
||||
!strncmp(LongName, "voices/", 7) ? ns_strifevoices :
|
||||
!strncmp(LongName, "patches/", 8) ? ns_patches :
|
||||
!strncmp(LongName, "graphics/", 9) ? ns_graphics :
|
||||
!strncmp(LongName, "sounds/", 7) ? ns_sounds :
|
||||
!strncmp(LongName, "music/", 6) ? ns_music :
|
||||
!strchr(LongName, '/') ? ns_global :
|
||||
ns_hidden;
|
||||
|
||||
if (Namespace == ns_hidden) shortName.qword = 0;
|
||||
else if (strstr(LongName, ".{"))
|
||||
// allow embedding a resource ID in the name - we need to strip that out here.
|
||||
if (strstr(Name, ".{"))
|
||||
{
|
||||
std::string longName = LongName;
|
||||
std::string longName = Name;
|
||||
ptrdiff_t encodedResID = longName.find_last_of(".{");
|
||||
if (resourceId == -1 && (size_t)encodedResID != std::string::npos)
|
||||
{
|
||||
const char* p = LongName + encodedResID;
|
||||
const char* p = Name + encodedResID;
|
||||
char* q;
|
||||
int id = (int)strtoull(p + 2, &q, 10); // only decimal numbers allowed here.
|
||||
if (q[0] == '}' && (q[1] == '.' || q[1] == 0))
|
||||
|
@ -162,27 +110,13 @@ struct FileSystem::LumpRecord
|
|||
longName.erase(longName.begin() + encodedResID, longName.begin() + (q - p) + 1);
|
||||
resourceId = id;
|
||||
}
|
||||
LongName = sp->Strdup(longName.c_str());
|
||||
Name = sp->Strdup(longName.c_str());
|
||||
}
|
||||
}
|
||||
auto slash = strrchr(LongName, '/');
|
||||
std::string base = slash ? (slash + 1) : LongName;
|
||||
auto slash = strrchr(Name, '/');
|
||||
std::string base = slash ? (slash + 1) : Name;
|
||||
auto dot = base.find_last_of('.');
|
||||
if (dot != std::string::npos) base.resize(dot);
|
||||
UpperCopy(shortName.String, base.c_str());
|
||||
|
||||
// Since '\' can't be used as a file name's part inside a ZIP
|
||||
// we have to work around this for sprites because it is a valid
|
||||
// frame character.
|
||||
if (Namespace == ns_sprites || Namespace == ns_voxels || Namespace == ns_hires)
|
||||
{
|
||||
char* c;
|
||||
|
||||
while ((c = (char*)memchr(shortName.String, '^', 8)))
|
||||
{
|
||||
*c = '\\';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -223,22 +157,16 @@ void FileSystem::DeleteAll ()
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// InitMultipleFiles
|
||||
// Initialize
|
||||
//
|
||||
// Pass a null terminated list of files to use. All files are optional,
|
||||
// Pass a vector of files to use. All files are optional,
|
||||
// but at least one file must be found. File names can appear multiple
|
||||
// times. The name searcher looks backwards, so a later file can
|
||||
// override an earlier one.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FileSystem::InitSingleFile(const char* filename, FileSystemMessageFunc Printf)
|
||||
{
|
||||
std::vector<std::string> filenames = { filename };
|
||||
return InitMultipleFiles(filenames, nullptr, Printf);
|
||||
}
|
||||
|
||||
bool FileSystem::InitMultipleFiles (std::vector<std::string>& filenames, LumpFilterInfo* filter, FileSystemMessageFunc Printf, bool allowduplicates)
|
||||
bool FileSystem::InitFiles(std::vector<std::string>& filenames, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, bool allowduplicates)
|
||||
{
|
||||
int numfiles;
|
||||
|
||||
|
@ -254,9 +182,9 @@ bool FileSystem::InitMultipleFiles (std::vector<std::string>& filenames, LumpFil
|
|||
// first, check for duplicates
|
||||
if (!allowduplicates)
|
||||
{
|
||||
for (size_t i=0;i<filenames.size(); i++)
|
||||
for (size_t i = 0; i < filenames.size(); i++)
|
||||
{
|
||||
for (size_t j=i+1;j<filenames.size(); j++)
|
||||
for (size_t j = i + 1; j < filenames.size(); j++)
|
||||
{
|
||||
if (filenames[i] == filenames[j])
|
||||
{
|
||||
|
@ -267,7 +195,7 @@ bool FileSystem::InitMultipleFiles (std::vector<std::string>& filenames, LumpFil
|
|||
}
|
||||
}
|
||||
|
||||
for(size_t i=0;i<filenames.size(); i++)
|
||||
for (size_t i = 0; i < filenames.size(); i++)
|
||||
{
|
||||
AddFile(filenames[i].c_str(), nullptr, filter, Printf);
|
||||
|
||||
|
@ -282,6 +210,12 @@ bool FileSystem::InitMultipleFiles (std::vector<std::string>& filenames, LumpFil
|
|||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileSystem::Initialize(std::vector<std::string>& filenames, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, bool allowduplicates)
|
||||
{
|
||||
if (!InitFiles(filenames, filter, Printf, allowduplicates)) return false;
|
||||
if (filter && filter->postprocessFunc) filter->postprocessFunc();
|
||||
|
||||
// [RH] Set up hash table
|
||||
|
@ -304,7 +238,7 @@ int FileSystem::AddFromBuffer(const char* name, char* data, int size, int id, in
|
|||
fr.OpenMemoryArray(blob);
|
||||
|
||||
// wrap this into a single lump resource file (should be done a little better later.)
|
||||
auto rf = new FResourceFile(name, fr, stringpool);
|
||||
auto rf = new FResourceFile(name, fr, stringpool, 0);
|
||||
auto Entries = rf->AllocateEntries(1);
|
||||
Entries[0].FileName = rf->NormalizeFileName(ExtractBaseName(name, true).c_str());
|
||||
Entries[0].ResourceID = -1;
|
||||
|
@ -327,7 +261,7 @@ int FileSystem::AddFromBuffer(const char* name, char* data, int size, int id, in
|
|||
// [RH] Removed reload hack
|
||||
//==========================================================================
|
||||
|
||||
void FileSystem::AddFile (const char *filename, FileReader *filer, LumpFilterInfo* filter, FileSystemMessageFunc Printf)
|
||||
void FileSystem::AddFile (const char *filename, FileReader *filer, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf)
|
||||
{
|
||||
int startlump;
|
||||
bool isdir = false;
|
||||
|
@ -443,114 +377,6 @@ int FileSystem::CheckIfResourceFileLoaded (const char *name) noexcept
|
|||
return -1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// 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 FileSystem::CheckNumForName (const char *name, int space) const
|
||||
{
|
||||
union
|
||||
{
|
||||
char uname[8];
|
||||
uint64_t qname;
|
||||
};
|
||||
uint32_t i;
|
||||
|
||||
if (name == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
UpperCopy (uname, name);
|
||||
i = FirstLumpIndex[MakeHash(uname, 8) % NumEntries];
|
||||
|
||||
while (i != NULL_INDEX)
|
||||
{
|
||||
|
||||
if (FileInfo[i].shortName.qword == qname)
|
||||
{
|
||||
auto &lump = FileInfo[i];
|
||||
if (lump.Namespace == space) break;
|
||||
// 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.
|
||||
auto lflags = lump.resfile->GetEntryFlags(lump.resindex);
|
||||
if (space > ns_specialzipdirectory && lump.Namespace == ns_global &&
|
||||
!((lflags ^lump.flags) & RESFF_FULLPATH)) break;
|
||||
}
|
||||
i = NextLumpIndex[i];
|
||||
}
|
||||
|
||||
return i != NULL_INDEX ? i : -1;
|
||||
}
|
||||
|
||||
int FileSystem::CheckNumForName (const char *name, int space, int rfnum, bool exact) const
|
||||
{
|
||||
union
|
||||
{
|
||||
char uname[8];
|
||||
uint64_t qname;
|
||||
};
|
||||
uint32_t i;
|
||||
|
||||
if (rfnum < 0)
|
||||
{
|
||||
return CheckNumForName (name, space);
|
||||
}
|
||||
|
||||
UpperCopy (uname, name);
|
||||
i = FirstLumpIndex[MakeHash (uname, 8) % NumEntries];
|
||||
|
||||
// If exact is true if will only find lumps in the same WAD, otherwise
|
||||
// also those in earlier WADs.
|
||||
|
||||
while (i != NULL_INDEX &&
|
||||
(FileInfo[i].shortName.qword != qname || FileInfo[i].Namespace != space ||
|
||||
(exact? (FileInfo[i].rfnum != rfnum) : (FileInfo[i].rfnum > rfnum)) ))
|
||||
{
|
||||
i = NextLumpIndex[i];
|
||||
}
|
||||
|
||||
return i != NULL_INDEX ? i : -1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// GetNumForName
|
||||
//
|
||||
// Calls CheckNumForName, but bombs out if not found.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FileSystem::GetNumForName (const char *name, int space) const
|
||||
{
|
||||
int i;
|
||||
|
||||
i = CheckNumForName (name, space);
|
||||
|
||||
if (i == -1)
|
||||
throw FileSystemException("GetNumForName: %s not found!", name);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CheckNumForFullName
|
||||
|
@ -561,7 +387,7 @@ int FileSystem::GetNumForName (const char *name, int space) const
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int FileSystem::CheckNumForFullName (const char *name, bool trynormal, int namespc, bool ignoreext) const
|
||||
int FileSystem::CheckNumForFullName (const char *name, bool ignoreext) const
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
|
@ -576,21 +402,16 @@ int FileSystem::CheckNumForFullName (const char *name, bool trynormal, int names
|
|||
|
||||
for (i = fli[MakeHash(name) % NumEntries]; i != NULL_INDEX; i = nli[i])
|
||||
{
|
||||
if (strnicmp(name, FileInfo[i].LongName, len)) continue;
|
||||
if (FileInfo[i].LongName[len] == 0) break; // this is a full match
|
||||
if (ignoreext && FileInfo[i].LongName[len] == '.')
|
||||
if (strnicmp(name, FileInfo[i].Name, len)) continue;
|
||||
if (FileInfo[i].Name[len] == 0) break; // this is a full match
|
||||
if (ignoreext && FileInfo[i].Name[len] == '.')
|
||||
{
|
||||
// is this the last '.' in the last path element, indicating that the remaining part of the name is only an extension?
|
||||
if (strpbrk(FileInfo[i].LongName + len + 1, "./") == nullptr) break;
|
||||
if (strpbrk(FileInfo[i].Name + len + 1, "./") == nullptr) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i != NULL_INDEX) return i;
|
||||
|
||||
if (trynormal && strlen(name) <= 8 && !strpbrk(name, "./"))
|
||||
{
|
||||
return CheckNumForName(name, namespc);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -606,7 +427,7 @@ int FileSystem::CheckNumForFullNameInFile (const char *name, int rfnum) const
|
|||
i = FirstLumpIndex_FullName[MakeHash (name) % NumEntries];
|
||||
|
||||
while (i != NULL_INDEX &&
|
||||
(stricmp(name, FileInfo[i].LongName) || FileInfo[i].rfnum != rfnum))
|
||||
(stricmp(name, FileInfo[i].Name) || FileInfo[i].rfnum != rfnum))
|
||||
{
|
||||
i = NextLumpIndex_FullName[i];
|
||||
}
|
||||
|
@ -657,10 +478,10 @@ int FileSystem::FindFileWithExtensions(const char* name, const char *const *exts
|
|||
|
||||
for (i = fli[MakeHash(name) % NumEntries]; i != NULL_INDEX; i = nli[i])
|
||||
{
|
||||
if (strnicmp(name, FileInfo[i].LongName, len)) continue;
|
||||
if (FileInfo[i].LongName[len] != '.') continue; // we are looking for extensions but this file doesn't have one.
|
||||
if (strnicmp(name, FileInfo[i].Name, len)) continue;
|
||||
if (FileInfo[i].Name[len] != '.') continue; // we are looking for extensions but this file doesn't have one.
|
||||
|
||||
auto cp = FileInfo[i].LongName + len + 1;
|
||||
auto cp = FileInfo[i].Name + len + 1;
|
||||
// is this the last '.' in the last path element, indicating that the remaining part of the name is only an extension?
|
||||
if (strpbrk(cp, "./") != nullptr) continue; // No, so it cannot be a valid entry.
|
||||
|
||||
|
@ -696,7 +517,7 @@ int FileSystem::FindResource (int resid, const char *type, int filenum) const no
|
|||
{
|
||||
if (filenum > 0 && FileInfo[i].rfnum != filenum) continue;
|
||||
if (FileInfo[i].resourceId != resid) continue;
|
||||
auto extp = strrchr(FileInfo[i].LongName, '.');
|
||||
auto extp = strrchr(FileInfo[i].Name, '.');
|
||||
if (!extp) continue;
|
||||
if (!stricmp(extp + 1, type)) return i;
|
||||
}
|
||||
|
@ -773,34 +594,28 @@ void FileSystem::InitHashChains (void)
|
|||
unsigned int i, j;
|
||||
|
||||
NumEntries = (uint32_t)FileInfo.size();
|
||||
Hashes.resize(8 * NumEntries);
|
||||
Hashes.resize(6 * NumEntries);
|
||||
// Mark all buckets as empty
|
||||
memset(Hashes.data(), -1, Hashes.size() * sizeof(Hashes[0]));
|
||||
FirstLumpIndex = &Hashes[0];
|
||||
NextLumpIndex = &Hashes[NumEntries];
|
||||
FirstLumpIndex_FullName = &Hashes[NumEntries * 2];
|
||||
NextLumpIndex_FullName = &Hashes[NumEntries * 3];
|
||||
FirstLumpIndex_NoExt = &Hashes[NumEntries * 4];
|
||||
NextLumpIndex_NoExt = &Hashes[NumEntries * 5];
|
||||
FirstLumpIndex_ResId = &Hashes[NumEntries * 6];
|
||||
NextLumpIndex_ResId = &Hashes[NumEntries * 7];
|
||||
FirstLumpIndex_FullName = &Hashes[NumEntries * 0];
|
||||
NextLumpIndex_FullName = &Hashes[NumEntries * 1];
|
||||
FirstLumpIndex_NoExt = &Hashes[NumEntries * 2];
|
||||
NextLumpIndex_NoExt = &Hashes[NumEntries * 3];
|
||||
FirstLumpIndex_ResId = &Hashes[NumEntries * 4];
|
||||
NextLumpIndex_ResId = &Hashes[NumEntries * 5];
|
||||
|
||||
|
||||
// Now set up the chains
|
||||
for (i = 0; i < (unsigned)NumEntries; i++)
|
||||
{
|
||||
j = MakeHash (FileInfo[i].shortName.String, 8) % NumEntries;
|
||||
NextLumpIndex[i] = FirstLumpIndex[j];
|
||||
FirstLumpIndex[j] = i;
|
||||
|
||||
// Do the same for the full paths
|
||||
if (FileInfo[i].LongName[0] != 0)
|
||||
if (FileInfo[i].Name[0] != 0)
|
||||
{
|
||||
j = MakeHash(FileInfo[i].LongName) % NumEntries;
|
||||
j = MakeHash(FileInfo[i].Name) % NumEntries;
|
||||
NextLumpIndex_FullName[i] = FirstLumpIndex_FullName[j];
|
||||
FirstLumpIndex_FullName[j] = i;
|
||||
|
||||
std::string nameNoExt = FileInfo[i].LongName;
|
||||
std::string nameNoExt = FileInfo[i].Name;
|
||||
auto dot = nameNoExt.find_last_of('.');
|
||||
auto slash = nameNoExt.find_last_of('/');
|
||||
if ((dot > slash || slash == std::string::npos) && dot != std::string::npos) nameNoExt.resize(dot);
|
||||
|
@ -819,24 +634,10 @@ void FileSystem::InitHashChains (void)
|
|||
Files.shrink_to_fit();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// should only be called before the hash chains are set up.
|
||||
// If done later this needs rehashing.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
LumpShortName& FileSystem::GetShortName(int i)
|
||||
{
|
||||
if ((unsigned)i >= NumEntries) throw FileSystemException("GetShortName: Invalid index");
|
||||
return FileInfo[i].shortName;
|
||||
}
|
||||
|
||||
void FileSystem::RenameFile(int num, const char* newfn)
|
||||
{
|
||||
if ((unsigned)num >= NumEntries) throw FileSystemException("RenameFile: Invalid index");
|
||||
FileInfo[num].LongName = stringpool->Strdup(newfn);
|
||||
// This does not alter the short name - call GetShortname to do that!
|
||||
FileInfo[num].Name = stringpool->Strdup(newfn);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -867,14 +668,13 @@ void FileSystem::MoveLumpsInFolder(const char *path)
|
|||
{
|
||||
auto& li = FileInfo[i];
|
||||
if (li.rfnum >= GetIwadNum()) break;
|
||||
if (strnicmp(li.LongName, path, len) == 0)
|
||||
if (strnicmp(li.Name, path, len) == 0)
|
||||
{
|
||||
auto lic = li; // make a copy before pushing.
|
||||
FileInfo.push_back(lic);
|
||||
li.LongName = ""; //nuke the name of the old record.
|
||||
li.shortName.qword = 0;
|
||||
li.Name = ""; //nuke the name of the old record.
|
||||
auto &ln = FileInfo.back();
|
||||
ln.SetFromLump(li.resfile, li.resindex, rfnum, stringpool, ln.LongName + len);
|
||||
ln.SetFromLump(li.resfile, li.resindex, rfnum, stringpool, ln.Name + len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -888,87 +688,6 @@ void FileSystem::MoveLumpsInFolder(const char *path)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int FileSystem::FindLump (const char *name, int *lastlump, bool anyns)
|
||||
{
|
||||
if ((size_t)*lastlump >= FileInfo.size()) return -1;
|
||||
union
|
||||
{
|
||||
char name8[8];
|
||||
uint64_t qname;
|
||||
};
|
||||
|
||||
UpperCopy (name8, name);
|
||||
|
||||
assert(lastlump != NULL && *lastlump >= 0);
|
||||
|
||||
const LumpRecord * last = FileInfo.data() + FileInfo.size();
|
||||
|
||||
LumpRecord * lump_p = FileInfo.data() + *lastlump;
|
||||
|
||||
while (lump_p < last)
|
||||
{
|
||||
if ((anyns || lump_p->Namespace == ns_global) && lump_p->shortName.qword == qname)
|
||||
{
|
||||
int lump = int(lump_p - FileInfo.data());
|
||||
*lastlump = lump + 1;
|
||||
return lump;
|
||||
}
|
||||
lump_p++;
|
||||
}
|
||||
|
||||
*lastlump = NumEntries;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// 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 FileSystem::FindLumpMulti (const char **names, int *lastlump, bool anyns, int *nameindex)
|
||||
{
|
||||
assert(lastlump != NULL && *lastlump >= 0);
|
||||
|
||||
const LumpRecord * last = FileInfo.data() + FileInfo.size();
|
||||
|
||||
LumpRecord * lump_p = FileInfo.data() + *lastlump;
|
||||
|
||||
while (lump_p < last)
|
||||
{
|
||||
if (anyns || lump_p->Namespace == ns_global)
|
||||
{
|
||||
|
||||
for(const char **name = names; *name != NULL; name++)
|
||||
{
|
||||
if (!strnicmp(*name, lump_p->shortName.String, 8))
|
||||
{
|
||||
int lump = int(lump_p - FileInfo.data());
|
||||
*lastlump = lump + 1;
|
||||
if (nameindex != NULL) *nameindex = int(name - names);
|
||||
return lump;
|
||||
}
|
||||
}
|
||||
}
|
||||
lump_p++;
|
||||
}
|
||||
|
||||
*lastlump = NumEntries;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// W_FindLump
|
||||
//
|
||||
// Find a named lump. Specifically allows duplicates for merging of e.g.
|
||||
// SNDINFO lumps.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FileSystem::FindLumpFullName(const char* name, int* lastlump, bool noext)
|
||||
{
|
||||
assert(lastlump != NULL && *lastlump >= 0);
|
||||
|
@ -981,7 +700,7 @@ int FileSystem::FindLumpFullName(const char* name, int* lastlump, bool noext)
|
|||
{
|
||||
while (lump_p < last)
|
||||
{
|
||||
if (!stricmp(name, lump_p->LongName))
|
||||
if (!stricmp(name, lump_p->Name))
|
||||
{
|
||||
int lump = int(lump_p - FileInfo.data());
|
||||
*lastlump = lump + 1;
|
||||
|
@ -995,10 +714,10 @@ int FileSystem::FindLumpFullName(const char* name, int* lastlump, bool noext)
|
|||
auto len = strlen(name);
|
||||
while (lump_p <= &FileInfo.back())
|
||||
{
|
||||
auto res = strnicmp(name, lump_p->LongName, len);
|
||||
auto res = strnicmp(name, lump_p->Name, len);
|
||||
if (res == 0)
|
||||
{
|
||||
auto p = lump_p->LongName + len;
|
||||
auto p = lump_p->Name + len;
|
||||
if (*p == 0 || (*p == '.' && strpbrk(p + 1, "./") == 0))
|
||||
{
|
||||
int lump = int(lump_p - FileInfo.data());
|
||||
|
@ -1017,49 +736,17 @@ int FileSystem::FindLumpFullName(const char* name, int* lastlump, bool noext)
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// W_CheckLumpName
|
||||
// FileSystem :: GetFileName
|
||||
//
|
||||
// Returns the lump's internal name
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FileSystem::CheckFileName (int lump, const char *name)
|
||||
{
|
||||
if ((size_t)lump >= NumEntries)
|
||||
return false;
|
||||
|
||||
return !strnicmp (FileInfo[lump].shortName.String, name, 8);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// GetLumpName
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
const char* FileSystem::GetFileShortName(int lump) const
|
||||
{
|
||||
if ((size_t)lump >= NumEntries)
|
||||
return nullptr;
|
||||
else
|
||||
return FileInfo[lump].shortName.String;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FileSystem :: GetFileFullName
|
||||
//
|
||||
// Returns the lump's full name if it has one or its short name if not.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
const char *FileSystem::GetFileName (int lump, bool returnshort) const
|
||||
const char* FileSystem::GetFileName(int lump) const
|
||||
{
|
||||
if ((size_t)lump >= NumEntries)
|
||||
return NULL;
|
||||
else if (FileInfo[lump].LongName[0] != 0)
|
||||
return FileInfo[lump].LongName;
|
||||
else if (returnshort)
|
||||
return FileInfo[lump].shortName.String;
|
||||
else return nullptr;
|
||||
else return FileInfo[lump].Name;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -1083,25 +770,6 @@ std::string FileSystem::GetFileFullPath(int lump) const
|
|||
return foo;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// GetFileNamespace
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FileSystem::GetFileNamespace (int lump) const
|
||||
{
|
||||
if ((size_t)lump >= NumEntries)
|
||||
return ns_global;
|
||||
else
|
||||
return FileInfo[lump].Namespace;
|
||||
}
|
||||
|
||||
void FileSystem::SetFileNamespace(int lump, int ns)
|
||||
{
|
||||
if ((size_t)lump < NumEntries) FileInfo[lump].Namespace = ns;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FileSystem :: GetResourceId
|
||||
|
@ -1134,7 +802,7 @@ const char *FileSystem::GetResourceType(int lump) const
|
|||
return nullptr;
|
||||
else
|
||||
{
|
||||
auto p = strrchr(FileInfo[lump].LongName, '.');
|
||||
auto p = strrchr(FileInfo[lump].Name, '.');
|
||||
if (!p) return ""; // has no extension
|
||||
if (strchr(p, '/')) return ""; // the '.' is part of a directory.
|
||||
return p + 1;
|
||||
|
@ -1186,12 +854,12 @@ unsigned FileSystem::GetFilesInFolder(const char *inpath, std::vector<FolderEntr
|
|||
result.clear();
|
||||
for (size_t i = 0; i < FileInfo.size(); i++)
|
||||
{
|
||||
if (strncmp(FileInfo[i].LongName, path.c_str(), path.length()) == 0)
|
||||
if (strncmp(FileInfo[i].Name, path.c_str(), path.length()) == 0)
|
||||
{
|
||||
// Only if it hasn't been replaced.
|
||||
if ((unsigned)CheckNumForFullName(FileInfo[i].LongName) == i)
|
||||
if ((unsigned)CheckNumForFullName(FileInfo[i].Name) == i)
|
||||
{
|
||||
FolderEntry fe{ FileInfo[i].LongName, (uint32_t)i };
|
||||
FolderEntry fe{ FileInfo[i].Name, (uint32_t)i };
|
||||
result.push_back(fe);
|
||||
}
|
||||
}
|
||||
|
@ -1235,7 +903,7 @@ void FileSystem::ReadFile (int lump, void *dest)
|
|||
if (numread != size)
|
||||
{
|
||||
throw FileSystemException("W_ReadFile: only read %td of %td on '%s'\n",
|
||||
numread, size, FileInfo[lump].LongName);
|
||||
numread, size, FileInfo[lump].Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1354,6 +1022,21 @@ int FileSystem::GetFirstEntry (int rfnum) const noexcept
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int FileSystem::GetResourceFileFlags(int rfnum) const noexcept
|
||||
{
|
||||
if ((uint32_t)rfnum >= Files.size())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Files[rfnum]->GetFlags();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FileSystem::GetLastEntry (int rfnum) const noexcept
|
||||
{
|
||||
if ((uint32_t)rfnum >= Files.size())
|
||||
|
@ -1415,7 +1098,7 @@ bool FileSystem::CreatePathlessCopy(const char *name, int id, int /*flags*/)
|
|||
if (lump < 0) return false; // Does not exist.
|
||||
|
||||
auto oldlump = FileInfo[lump];
|
||||
auto slash = strrchr(oldlump.LongName, '/');
|
||||
auto slash = strrchr(oldlump.Name, '/');
|
||||
|
||||
if (slash == nullptr)
|
||||
{
|
||||
|
@ -1425,7 +1108,7 @@ bool FileSystem::CreatePathlessCopy(const char *name, int id, int /*flags*/)
|
|||
|
||||
|
||||
// just create a new reference to the original data with a different name.
|
||||
oldlump.LongName = slash + 1;
|
||||
oldlump.Name = slash + 1;
|
||||
oldlump.resourceId = id;
|
||||
oldlump.flags = RESFF_FULLPATH;
|
||||
FileInfo.push_back(oldlump);
|
||||
|
|
|
@ -113,7 +113,7 @@ bool FResourceFile::IsFileInFolder(const char* const resPath)
|
|||
return 0 == stricmp(filePath.c_str(), resPath);
|
||||
}
|
||||
|
||||
void FResourceFile::CheckEmbedded(uint32_t entry, LumpFilterInfo* lfi)
|
||||
void FResourceFile::CheckEmbedded(uint32_t entry, FileSystemFilterInfo* lfi)
|
||||
{
|
||||
// Checks for embedded archives
|
||||
auto FullName = Entries[entry].FileName;
|
||||
|
@ -138,29 +138,30 @@ void FResourceFile::CheckEmbedded(uint32_t entry, LumpFilterInfo* lfi)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
typedef FResourceFile * (*CheckFunc)(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
typedef FResourceFile * (*CheckFunc)(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
|
||||
FResourceFile *CheckWad(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile *CheckGRP(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile *CheckRFF(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile *CheckZip(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile *Check7Z(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile* CheckHog(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile* CheckMvl(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile* CheckWHRes(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile *CheckLump(const char *filename,FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile *CheckDir(const char *filename, bool nosub, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile *CheckWad(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile *CheckGRP(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile *CheckRFF(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile *CheckPak(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile *CheckZip(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile *Check7Z(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile* CheckSSI(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile* CheckHog(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile* CheckHog2(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile* CheckMvl(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile* CheckWHRes(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile *CheckLump(const char *filename,FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
FResourceFile *CheckDir(const char *filename, bool nosub, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
||||
|
||||
static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckSSI, CheckHog, CheckMvl, CheckWHRes, CheckLump };
|
||||
static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckHog, CheckMvl, CheckHog2, CheckSSI, CheckWHRes, CheckLump };
|
||||
|
||||
static int nulPrintf(FSMessageLevel msg, const char* fmt, ...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
{
|
||||
if (!file.isOpen()) return nullptr;
|
||||
if (Printf == nullptr) Printf = nulPrintf;
|
||||
|
@ -173,20 +174,20 @@ FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileReade
|
|||
return NULL;
|
||||
}
|
||||
|
||||
FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader &file, bool containeronly, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
{
|
||||
return DoOpenResourceFile(filename, file, containeronly, filter, Printf, sp);
|
||||
}
|
||||
|
||||
|
||||
FResourceFile *FResourceFile::OpenResourceFile(const char *filename, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
FResourceFile *FResourceFile::OpenResourceFile(const char *filename, bool containeronly, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
{
|
||||
FileReader file;
|
||||
if (!file.OpenFile(filename)) return nullptr;
|
||||
return DoOpenResourceFile(filename, file, containeronly, filter, Printf, sp);
|
||||
}
|
||||
|
||||
FResourceFile *FResourceFile::OpenDirectory(const char *filename, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
FResourceFile *FResourceFile::OpenDirectory(const char *filename, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
|
||||
{
|
||||
if (Printf == nullptr) Printf = nulPrintf;
|
||||
return CheckDir(filename, false, filter, Printf, sp);
|
||||
|
@ -198,14 +199,15 @@ FResourceFile *FResourceFile::OpenDirectory(const char *filename, LumpFilterInfo
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile::FResourceFile(const char *filename, StringPool* sp)
|
||||
FResourceFile::FResourceFile(const char *filename, StringPool* sp, int flags_)
|
||||
:flags(flags_)
|
||||
{
|
||||
stringpool = sp ? sp : new StringPool(false);
|
||||
FileName = stringpool->Strdup(filename);
|
||||
}
|
||||
|
||||
FResourceFile::FResourceFile(const char *filename, FileReader &r, StringPool* sp)
|
||||
: FResourceFile(filename,sp)
|
||||
FResourceFile::FResourceFile(const char *filename, FileReader &r, StringPool* sp, int flags)
|
||||
: FResourceFile(filename,sp, flags)
|
||||
{
|
||||
Reader = std::move(r);
|
||||
}
|
||||
|
@ -250,7 +252,7 @@ FCompressedBuffer FResourceFile::GetRawData(uint32_t entry)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
const char* FResourceFile::NormalizeFileName(const char* fn, int fallbackcp)
|
||||
const char* FResourceFile::NormalizeFileName(const char* fn, int fallbackcp, bool allowbackslash)
|
||||
{
|
||||
if (!fn || !*fn) return "";
|
||||
auto norm = tolower_normalize(fn);
|
||||
|
@ -274,7 +276,8 @@ const char* FResourceFile::NormalizeFileName(const char* fn, int fallbackcp)
|
|||
norm = tolower_normalize(&ffn.front());
|
||||
}
|
||||
}
|
||||
FixPathSeparator(norm);
|
||||
// The WAD format can have legal backslashes in its names so this must be optional.
|
||||
if (!allowbackslash) FixPathSeparator(norm);
|
||||
auto pooled = stringpool->Strdup(norm);
|
||||
free(norm);
|
||||
return pooled;
|
||||
|
@ -354,7 +357,7 @@ void FResourceFile::GenerateHash()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FResourceFile::PostProcessArchive(LumpFilterInfo *filter)
|
||||
void FResourceFile::PostProcessArchive(FileSystemFilterInfo *filter)
|
||||
{
|
||||
// only do this for archive types which contain full file names. All others are assumed to be pre-sorted.
|
||||
if (NumLumps == 0 || !(Entries[0].Flags & RESFF_FULLPATH)) return;
|
||||
|
@ -416,7 +419,7 @@ void FResourceFile::PostProcessArchive(LumpFilterInfo *filter)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FResourceFile::FindCommonFolder(LumpFilterInfo* filter)
|
||||
void FResourceFile::FindCommonFolder(FileSystemFilterInfo* filter)
|
||||
{
|
||||
std::string name0, name1;
|
||||
bool foundspeciallump = false;
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
#include "basics.h"
|
||||
#include "cmdlib.h"
|
||||
|
||||
using namespace FileSys;
|
||||
FTextureManager TexMan;
|
||||
|
||||
|
||||
|
@ -585,7 +584,7 @@ void FTextureManager::AddGroup(int wadnum, int ns, ETextureType usetype)
|
|||
}
|
||||
progressFunc();
|
||||
}
|
||||
else if (ns == ns_flats && fileSystem.GetFileFlags(firsttx) & RESFF_MAYBEFLAT)
|
||||
else if (ns == ns_flats && fileSystem.GetFileNamespace(firsttx) == ns_maybeflat)
|
||||
{
|
||||
if (fileSystem.CheckNumForName(Name, ns) < firsttx)
|
||||
{
|
||||
|
@ -1421,12 +1420,11 @@ int FTextureManager::GuesstimateNumTextures ()
|
|||
case ns_hires:
|
||||
case ns_patches:
|
||||
case ns_graphics:
|
||||
case ns_maybeflat:
|
||||
numtex++;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (fileSystem.GetFileFlags(i) & RESFF_MAYBEFLAT) numtex++;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -314,7 +314,7 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize,
|
|||
// Look for IWAD definition lump
|
||||
//
|
||||
//==========================================================================
|
||||
void GetReserved(FileSys::LumpFilterInfo& lfi);
|
||||
void GetReserved(FileSys::FileSystemFilterInfo& lfi);
|
||||
|
||||
FIWadManager::FIWadManager(const char *firstfn, const char *optfn)
|
||||
{
|
||||
|
@ -322,10 +322,10 @@ FIWadManager::FIWadManager(const char *firstfn, const char *optfn)
|
|||
std::vector<std::string> fns;
|
||||
fns.push_back(firstfn);
|
||||
if (optfn) fns.push_back(optfn);
|
||||
FileSys::LumpFilterInfo lfi;
|
||||
FileSys::FileSystemFilterInfo lfi;
|
||||
GetReserved(lfi);
|
||||
|
||||
if (check.InitMultipleFiles(fns, &lfi, nullptr))
|
||||
if (check.Initialize(fns, &lfi, nullptr))
|
||||
{
|
||||
// this is for the IWAD picker. As we have a filesystem open here that contains the base files, it is the easiest place to load the strings early.
|
||||
GStrings.LoadStrings(check, language);
|
||||
|
@ -350,7 +350,8 @@ FIWadManager::FIWadManager(const char *firstfn, const char *optfn)
|
|||
int FIWadManager::ScanIWAD (const char *iwad)
|
||||
{
|
||||
FileSystem check;
|
||||
check.InitSingleFile(iwad, nullptr);
|
||||
std::vector<std::string> list({ iwad });
|
||||
check.Initialize(list, nullptr);
|
||||
|
||||
mLumpsFound.Resize(mIWadInfos.Size());
|
||||
|
||||
|
@ -373,14 +374,13 @@ int FIWadManager::ScanIWAD (const char *iwad)
|
|||
memset(&mLumpsFound[0], 0, mLumpsFound.Size() * sizeof(mLumpsFound[0]));
|
||||
for(int ii = 0; ii < check.GetNumEntries(); ii++)
|
||||
{
|
||||
|
||||
CheckFileName(check.GetFileShortName(ii));
|
||||
auto full = check.GetFileName(ii, false);
|
||||
auto full = check.GetFileName(ii);
|
||||
if (full && strnicmp(full, "maps/", 5) == 0)
|
||||
{
|
||||
FString mapname(&full[5], strcspn(&full[5], "."));
|
||||
CheckFileName(mapname.GetChars());
|
||||
}
|
||||
else CheckFileName(full);
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i< mIWadInfos.Size(); i++)
|
||||
|
@ -404,11 +404,11 @@ int FIWadManager::CheckIWADInfo(const char* fn)
|
|||
{
|
||||
FileSystem check;
|
||||
|
||||
FileSys::LumpFilterInfo lfi;
|
||||
FileSys::FileSystemFilterInfo lfi;
|
||||
GetReserved(lfi);
|
||||
|
||||
std::vector<std::string> filenames = { fn };
|
||||
if (check.InitMultipleFiles(filenames, &lfi, nullptr))
|
||||
if (check.Initialize(filenames, &lfi, nullptr))
|
||||
{
|
||||
int num = check.CheckNumForName("IWADINFO");
|
||||
if (num >= 0)
|
||||
|
|
162
src/d_main.cpp
162
src/d_main.cpp
|
@ -123,8 +123,6 @@
|
|||
#include "i_system.h" // for SHARE_DIR
|
||||
#endif // __unix__
|
||||
|
||||
using namespace FileSys;
|
||||
|
||||
EXTERN_CVAR(Bool, hud_althud)
|
||||
EXTERN_CVAR(Int, vr_mode)
|
||||
EXTERN_CVAR(Bool, cl_customizeinvulmap)
|
||||
|
@ -1265,7 +1263,7 @@ void D_DoomLoop ()
|
|||
}
|
||||
D_ErrorCleanup ();
|
||||
}
|
||||
catch (const FileSystemException& error) // in case this propagates up to here it should be treated as a recoverable error.
|
||||
catch (const FileSys::FileSystemException& error) // in case this propagates up to here it should be treated as a recoverable error.
|
||||
{
|
||||
if (error.what())
|
||||
{
|
||||
|
@ -1945,7 +1943,7 @@ static FString ParseGameInfo(std::vector<std::string> &pwads, const char *fn, co
|
|||
return iwad;
|
||||
}
|
||||
|
||||
void GetReserved(LumpFilterInfo& lfi)
|
||||
void GetReserved(FileSys::FileSystemFilterInfo& lfi)
|
||||
{
|
||||
lfi.reservedFolders = { "flats/", "textures/", "hires/", "sprites/", "voxels/", "colormaps/", "acs/", "maps/", "voices/", "patches/", "graphics/", "sounds/", "music/",
|
||||
"materials/", "models/", "fonts/", "brightmaps/" };
|
||||
|
@ -1957,11 +1955,11 @@ static FString CheckGameInfo(std::vector<std::string> & pwads)
|
|||
{
|
||||
FileSystem check;
|
||||
|
||||
LumpFilterInfo lfi;
|
||||
FileSys::FileSystemFilterInfo lfi;
|
||||
GetReserved(lfi);
|
||||
|
||||
// Open the entire list as a temporary file system and look for a GAMEINFO lump. The last one will automatically win.
|
||||
if (check.InitMultipleFiles(pwads, &lfi, nullptr))
|
||||
if (check.Initialize(pwads, &lfi, nullptr))
|
||||
{
|
||||
int num = check.CheckNumForName("GAMEINFO");
|
||||
if (num >= 0)
|
||||
|
@ -2250,48 +2248,48 @@ static void RenameSprites(FileSystem &fileSystem, const TArray<FString>& deletel
|
|||
bool MNTRZfound = false;
|
||||
const char* altbigfont = gameinfo.gametype == GAME_Strife ? "SBIGFONT" : (gameinfo.gametype & GAME_Raven) ? "HBIGFONT" : "DBIGFONT";
|
||||
|
||||
static const uint32_t HereticRenames[] =
|
||||
{ MAKE_ID('H','E','A','D'), MAKE_ID('L','I','C','H'), // Ironlich
|
||||
static const char HereticRenames[][4] =
|
||||
{ {'H','E','A','D'}, {'L','I','C','H'}, // Ironlich
|
||||
};
|
||||
|
||||
static const uint32_t 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
|
||||
MAKE_ID('I','N','V','U'), MAKE_ID('D','E','F','N'), // Icon of the Defender
|
||||
static const char HexenRenames[][4] =
|
||||
{ {'B','A','R','L'}, {'Z','B','A','R'}, // ZBarrel
|
||||
{'A','R','M','1'}, {'A','R','_','1'}, // MeshArmor
|
||||
{'A','R','M','2'}, {'A','R','_','2'}, // FalconShield
|
||||
{'A','R','M','3'}, {'A','R','_','3'}, // PlatinumHelm
|
||||
{'A','R','M','4'}, {'A','R','_','4'}, // AmuletOfWarding
|
||||
{'S','U','I','T'}, {'Z','S','U','I'}, // ZSuitOfArmor and ZArmorChunk
|
||||
{'T','R','E','1'}, {'Z','T','R','E'}, // ZTree and ZTreeDead
|
||||
{'T','R','E','2'}, {'T','R','E','S'}, // ZTreeSwamp150
|
||||
{'C','A','N','D'}, {'B','C','A','N'}, // ZBlueCandle
|
||||
{'R','O','C','K'}, {'R','O','K','K'}, // rocks and dirt in a_debris.cpp
|
||||
{'W','A','T','R'}, {'H','W','A','T'}, // Strife also has WATR
|
||||
{'G','I','B','S'}, {'P','O','L','5'}, // RealGibs
|
||||
{'E','G','G','M'}, {'P','R','K','M'}, // PorkFX
|
||||
{'I','N','V','U'}, {'D','E','F','N'}, // Icon of the Defender
|
||||
};
|
||||
|
||||
static const uint32_t 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
|
||||
static const char StrifeRenames[][4] =
|
||||
{ {'M','I','S','L'}, {'S','M','I','S'}, // lots of places
|
||||
{'A','R','M','1'}, {'A','R','M','3'}, // MetalArmor
|
||||
{'A','R','M','2'}, {'A','R','M','4'}, // LeatherArmor
|
||||
{'P','M','A','P'}, {'S','M','A','P'}, // StrifeMap
|
||||
{'T','L','M','P'}, {'T','E','C','H'}, // TechLampSilver and TechLampBrass
|
||||
{'T','R','E','1'}, {'T','R','E','T'}, // TreeStub
|
||||
{'B','A','R','1'}, {'B','A','R','C'}, // BarricadeColumn
|
||||
{'S','H','T','2'}, {'M','P','U','F'}, // MaulerPuff
|
||||
{'B','A','R','L'}, {'B','B','A','R'}, // StrifeBurningBarrel
|
||||
{'T','R','C','H'}, {'T','R','H','L'}, // SmallTorchLit
|
||||
{'S','H','R','D'}, {'S','H','A','R'}, // glass shards
|
||||
{'B','L','S','T'}, {'M','A','U','L'}, // Mauler
|
||||
{'L','O','G','G'}, {'L','O','G','W'}, // StickInWater
|
||||
{'V','A','S','E'}, {'V','A','Z','E'}, // Pot and Pitcher
|
||||
{'C','N','D','L'}, {'K','N','D','L'}, // Candle
|
||||
{'P','O','T','1'}, {'M','P','O','T'}, // MetalPot
|
||||
{'S','P','I','D'}, {'S','T','L','K'}, // Stalker
|
||||
};
|
||||
|
||||
const uint32_t* renames;
|
||||
const char (*renames)[4];
|
||||
int numrenames;
|
||||
|
||||
switch (gameinfo.gametype)
|
||||
|
@ -2327,8 +2325,8 @@ static void RenameSprites(FileSystem &fileSystem, const TArray<FString>& deletel
|
|||
// some frames need to be renamed.
|
||||
if (fileSystem.GetFileNamespace(i) == ns_sprites)
|
||||
{
|
||||
auto& shortName = fileSystem.GetShortName(i);
|
||||
if (shortName.dword == MAKE_ID('M', 'N', 'T', 'R') && shortName.String[4] == 'Z')
|
||||
auto shortName = fileSystem.GetShortName(i);
|
||||
if (!memcmp(shortName, "MNTRZ", 5))
|
||||
{
|
||||
MNTRZfound = true;
|
||||
break;
|
||||
|
@ -2340,7 +2338,7 @@ static void RenameSprites(FileSystem &fileSystem, const TArray<FString>& deletel
|
|||
|
||||
for (uint32_t i = 0; i < NumFiles; i++)
|
||||
{
|
||||
auto& shortName = fileSystem.GetShortName(i);
|
||||
auto shortName = fileSystem.GetShortName(i);
|
||||
if (fileSystem.GetFileNamespace(i) == ns_sprites)
|
||||
{
|
||||
// Only sprites in the IWAD normally get renamed
|
||||
|
@ -2348,30 +2346,30 @@ static void RenameSprites(FileSystem &fileSystem, const TArray<FString>& deletel
|
|||
{
|
||||
for (int j = 0; j < numrenames; ++j)
|
||||
{
|
||||
if (shortName.dword == renames[j * 2])
|
||||
if (!memcmp(shortName, &renames[j * 8], 4))
|
||||
{
|
||||
shortName.dword = renames[j * 2 + 1];
|
||||
memcpy(shortName, renames[j * 8 + 4], 4);
|
||||
}
|
||||
}
|
||||
if (gameinfo.gametype == GAME_Hexen)
|
||||
{
|
||||
if (fileSystem.CheckFileName(i, "ARTIINVU"))
|
||||
{
|
||||
shortName.String[4] = 'D'; shortName.String[5] = 'E';
|
||||
shortName.String[6] = 'F'; shortName.String[7] = 'N';
|
||||
shortName[4] = 'D'; shortName[5] = 'E';
|
||||
shortName[6] = 'F'; shortName[7] = 'N';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!MNTRZfound)
|
||||
{
|
||||
if (shortName.dword == MAKE_ID('M', 'N', 'T', 'R'))
|
||||
if (!memcmp(shortName, "MNTR", 4))
|
||||
{
|
||||
for (size_t fi : {4, 6})
|
||||
{
|
||||
if (shortName.String[fi] >= 'F' && shortName.String[fi] <= 'K')
|
||||
if (shortName[fi] >= 'F' && shortName[fi] <= 'K')
|
||||
{
|
||||
shortName.String[fi] += 'U' - 'F';
|
||||
shortName[fi] += 'U' - 'F';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2381,23 +2379,23 @@ static void RenameSprites(FileSystem &fileSystem, const TArray<FString>& deletel
|
|||
// the same blood states can be used everywhere
|
||||
if (!(gameinfo.gametype & GAME_DoomChex))
|
||||
{
|
||||
if (shortName.dword == MAKE_ID('B', 'L', 'O', 'D'))
|
||||
if (!memcmp(shortName, "BLOD", 4))
|
||||
{
|
||||
shortName.dword = MAKE_ID('B', 'L', 'U', 'D');
|
||||
memcpy(shortName, "BLUD", 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (fileSystem.GetFileNamespace(i) == ns_global)
|
||||
{
|
||||
int fn = fileSystem.GetFileContainer(i);
|
||||
if (fn >= fileSystem.GetIwadNum() && fn <= fileSystem.GetMaxIwadNum() && deletelumps.Find(shortName.String) < deletelumps.Size())
|
||||
if (fn >= fileSystem.GetIwadNum() && fn <= fileSystem.GetMaxIwadNum() && deletelumps.Find(shortName) < deletelumps.Size())
|
||||
{
|
||||
shortName.String[0] = 0; // Lump must be deleted from directory.
|
||||
shortName[0] = 0; // Lump must be deleted from directory.
|
||||
}
|
||||
// Rename the game specific big font lumps so that the font manager does not have to do problematic special checks for them.
|
||||
else if (!strcmp(shortName.String, altbigfont))
|
||||
else if (!strcmp(shortName, altbigfont))
|
||||
{
|
||||
strcpy(shortName.String, "BIGFONT");
|
||||
strcpy(shortName, "BIGFONT");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2467,18 +2465,16 @@ void RenameNerve(FileSystem& fileSystem)
|
|||
|
||||
for (int i = fileSystem.GetFirstEntry(w); i <= fileSystem.GetLastEntry(w); i++)
|
||||
{
|
||||
auto& shortName = fileSystem.GetShortName(i);
|
||||
auto shortName = fileSystem.GetShortName(i);
|
||||
// Only rename the maps from NERVE.WAD
|
||||
if (shortName.dword == MAKE_ID('C', 'W', 'I', 'L'))
|
||||
if (!memcmp(shortName, "CWILV", 5))
|
||||
{
|
||||
shortName.String[0] = 'N';
|
||||
shortName[0] = 'N';
|
||||
}
|
||||
else if (shortName.dword == MAKE_ID('M', 'A', 'P', '0'))
|
||||
else if (!memcmp(shortName, "MAP0", 4))
|
||||
{
|
||||
shortName.String[6] = shortName.String[4];
|
||||
shortName.String[5] = '0';
|
||||
shortName.String[4] = 'L';
|
||||
shortName.dword = MAKE_ID('L', 'E', 'V', 'E');
|
||||
shortName[6] = shortName[4];
|
||||
memcpy(shortName, "LEVEL0", 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2560,8 +2556,8 @@ void FixMacHexen(FileSystem& fileSystem)
|
|||
|
||||
for (int i = lastLump - EXTRA_LUMPS + 1; i <= lastLump; ++i)
|
||||
{
|
||||
auto& shortName = fileSystem.GetShortName(i);
|
||||
shortName.String[0] = '\0';
|
||||
auto shortName = fileSystem.GetShortName(i);
|
||||
memcpy(shortName, "\0\0\0\0\0\0\0", 8); // these get compared with memcmp so all 8 bytes need to get cleared.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2572,21 +2568,21 @@ static void FindStrifeTeaserVoices(FileSystem& fileSystem)
|
|||
unsigned NumFiles = fileSystem.GetNumEntries();
|
||||
for (uint32_t i = 0; i < NumFiles; i++)
|
||||
{
|
||||
auto& shortName = fileSystem.GetShortName(i);
|
||||
auto shortName = fileSystem.GetShortName(i);
|
||||
if (fileSystem.GetFileNamespace(i) == ns_global)
|
||||
{
|
||||
// Only sprites in the IWAD normally get renamed
|
||||
// Strife teaser voices are not in the expected namespace.
|
||||
if (fileSystem.GetFileContainer(i) == fileSystem.GetIwadNum())
|
||||
{
|
||||
if (shortName.String[0] == 'V' &&
|
||||
shortName.String[1] == 'O' &&
|
||||
shortName.String[2] == 'C')
|
||||
if (shortName[0] == 'V' &&
|
||||
shortName[1] == 'O' &&
|
||||
shortName[2] == 'C')
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = 3; j < 8; ++j)
|
||||
{
|
||||
if (shortName.String[j] != 0 && !isdigit(shortName.String[j]))
|
||||
if (shortName[j] != 0 && !isdigit(shortName[j]))
|
||||
break;
|
||||
}
|
||||
if (j == 8)
|
||||
|
@ -3048,7 +3044,7 @@ static bool FileNameCheck(const char* base, const char* path)
|
|||
return true;
|
||||
}
|
||||
|
||||
static int FileSystemPrintf(FSMessageLevel level, const char* fmt, ...)
|
||||
static int FileSystemPrintf(FileSys::FSMessageLevel level, const char* fmt, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, fmt);
|
||||
|
@ -3056,22 +3052,22 @@ static int FileSystemPrintf(FSMessageLevel level, const char* fmt, ...)
|
|||
text.VFormat(fmt, arg);
|
||||
switch (level)
|
||||
{
|
||||
case FSMessageLevel::Error:
|
||||
case FileSys::FSMessageLevel::Error:
|
||||
return Printf(TEXTCOLOR_RED "%s", text.GetChars());
|
||||
break;
|
||||
case FSMessageLevel::Warning:
|
||||
case FileSys::FSMessageLevel::Warning:
|
||||
Printf(TEXTCOLOR_YELLOW "%s", text.GetChars());
|
||||
break;
|
||||
case FSMessageLevel::Attention:
|
||||
case FileSys::FSMessageLevel::Attention:
|
||||
Printf(TEXTCOLOR_BLUE "%s", text.GetChars());
|
||||
break;
|
||||
case FSMessageLevel::Message:
|
||||
case FileSys::FSMessageLevel::Message:
|
||||
Printf("%s", text.GetChars());
|
||||
break;
|
||||
case FSMessageLevel::DebugWarn:
|
||||
case FileSys::FSMessageLevel::DebugWarn:
|
||||
DPrintf(DMSG_WARNING, "%s", text.GetChars());
|
||||
break;
|
||||
case FSMessageLevel::DebugNotify:
|
||||
case FileSys::FSMessageLevel::DebugNotify:
|
||||
DPrintf(DMSG_NOTIFY, "%s", text.GetChars());
|
||||
break;
|
||||
}
|
||||
|
@ -3143,7 +3139,7 @@ static int D_InitGame(const FIWADInfo* iwad_info, std::vector<std::string>& allw
|
|||
|
||||
if (!batchrun) Printf ("W_Init: Init WADfiles.\n");
|
||||
|
||||
LumpFilterInfo lfi;
|
||||
FileSys::FileSystemFilterInfo lfi;
|
||||
|
||||
static const struct { int match; const char* name; } blanket[] =
|
||||
{
|
||||
|
@ -3184,7 +3180,7 @@ static int D_InitGame(const FIWADInfo* iwad_info, std::vector<std::string>& allw
|
|||
);
|
||||
|
||||
bool allowduplicates = Args->CheckParm("-allowduplicates");
|
||||
if (!fileSystem.InitMultipleFiles(allwads, &lfi, FileSystemPrintf, allowduplicates))
|
||||
if (!fileSystem.Initialize(allwads, &lfi, FileSystemPrintf, allowduplicates))
|
||||
{
|
||||
I_FatalError("FileSystem: no files found");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue