This commit is contained in:
Christoph Oelckers 2015-04-04 10:30:37 +02:00
commit 747e160c96
17 changed files with 1506 additions and 1340 deletions

View file

@ -253,7 +253,7 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize)
//==========================================================================
//
// Lool for IWAD definition lump
// Look for IWAD definition lump
//
//==========================================================================
@ -302,11 +302,11 @@ int FIWadManager::ScanIWAD (const char *iwad)
FResourceLump *lump = iwadfile->GetLump(ii);
CheckLumpName(lump->Name);
if (lump->FullName != NULL)
if (lump->FullName.IsNotEmpty())
{
if (strnicmp(lump->FullName, "maps/", 5) == 0)
{
FString mapname(lump->FullName+5, strcspn(lump->FullName+5, "."));
FString mapname(&lump->FullName[5], strcspn(&lump->FullName[5], "."));
CheckLumpName(mapname);
}
}

View file

@ -1992,6 +1992,9 @@ static void D_DoomInit()
static void AddAutoloadFiles(const char *group, const char *autoname)
{
LumpFilterGroup = group;
LumpFilterIWAD = autoname;
if (!(gameinfo.flags & GI_SHAREWARE) && !Args->CheckParm("-noautoload"))
{
FString file;

View file

@ -69,3 +69,4 @@ int SinglePlayerClass[MAXPLAYERS];
bool ToggleFullscreen;
int BorderTopRefresh;
FString LumpFilterGroup, LumpFilterIWAD;

View file

@ -250,4 +250,7 @@ EXTERN_CVAR (Int, compatflags);
EXTERN_CVAR (Int, compatflags2);
extern int i_compatflags, i_compatflags2, ii_compatflags, ii_compatflags2, ib_compatflags;
// Filters from AddAutoloadFiles(). Used to filter files from archives.
extern FString LumpFilterGroup, LumpFilterIWAD;
#endif

View file

@ -179,7 +179,7 @@ struct F7ZLump : public FResourceLump
//==========================================================================
//
// Zip file
// 7-zip file
//
//==========================================================================
@ -190,8 +190,6 @@ class F7ZFile : public FResourceFile
F7ZLump *Lumps;
C7zArchive *Archive;
static int STACK_ARGS lumpcmp(const void * a, const void * b);
public:
F7ZFile(const char * filename, FileReader *filer);
bool Open(bool quiet);
@ -201,15 +199,6 @@ public:
int STACK_ARGS F7ZFile::lumpcmp(const void * a, const void * b)
{
F7ZLump * rec1 = (F7ZLump *)a;
F7ZLump * rec2 = (F7ZLump *)b;
return stricmp(rec1->FullName, rec2->FullName);
}
//==========================================================================
//
// 7Z file
@ -328,8 +317,7 @@ bool F7ZFile::Open(bool quiet)
if (!quiet) Printf(", %d lumps\n", NumLumps);
// Entries in archives are sorted alphabetically
qsort(&Lumps[0], NumLumps, sizeof(F7ZLump), lumpcmp);
PostProcessArchive(&Lumps[0], sizeof(F7ZLump));
return true;
}

View file

@ -86,8 +86,6 @@ class FDirectory : public FResourceFile
{
TArray<FDirectoryLump> Lumps;
static int STACK_ARGS lumpcmp(const void * a, const void * b);
int AddDirectory(const char *dirpath);
void AddEntry(const char *fullpath, int size);
@ -113,29 +111,18 @@ FDirectory::FDirectory(const char * directory)
#ifdef _WIN32
directory = _fullpath(NULL, directory, _MAX_PATH);
#else
// Todo for Linux: Resolve the path befire using it
// Todo for Linux: Resolve the path before using it
#endif
dirname = directory;
#ifdef _WIN32
free((void *)directory);
#endif
dirname.ReplaceChars('\\', '/');
if (dirname[dirname.Len()-1] != '/') dirname += '/';
Filename = copystring(dirname);
}
//==========================================================================
//
//
//
//==========================================================================
int STACK_ARGS FDirectory::lumpcmp(const void * a, const void * b)
{
FDirectoryLump * rec1 = (FDirectoryLump *)a;
FDirectoryLump * rec2 = (FDirectoryLump *)b;
return stricmp(rec1->FullName, rec2->FullName);
}
#ifdef _WIN32
//==========================================================================
//
@ -299,8 +286,7 @@ bool FDirectory::Open(bool quiet)
{
NumLumps = AddDirectory(Filename);
if (!quiet) Printf(", %d lumps\n", NumLumps);
// Entries in Zips are sorted alphabetically.
qsort(&Lumps[0], NumLumps, sizeof(FDirectoryLump), lumpcmp);
PostProcessArchive(&Lumps[0], sizeof(FDirectoryLump));
return true;
}

View file

@ -138,8 +138,6 @@ class FZipFile : public FResourceFile
{
FZipLump *Lumps;
static int STACK_ARGS lumpcmp(const void * a, const void * b);
public:
FZipFile(const char * filename, FileReader *file);
virtual ~FZipFile();
@ -148,16 +146,6 @@ public:
};
int STACK_ARGS FZipFile::lumpcmp(const void * a, const void * b)
{
FZipLump * rec1 = (FZipLump *)a;
FZipLump * rec2 = (FZipLump *)b;
return stricmp(rec1->FullName, rec2->FullName);
}
//==========================================================================
//
// Zip file
@ -274,8 +262,7 @@ bool FZipFile::Open(bool quiet)
if (!quiet) Printf(", %d lumps\n", NumLumps);
// Entries in Zips are sorted alphabetically.
qsort(Lumps, NumLumps, sizeof(FZipLump), lumpcmp);
PostProcessArchive(&Lumps[0], sizeof(FZipLump));
return true;
}

View file

@ -38,7 +38,8 @@
#include "cmdlib.h"
#include "w_wad.h"
#include "doomerrors.h"
#include "gi.h"
#include "doomstat.h"
//==========================================================================
@ -74,11 +75,6 @@ public:
FResourceLump::~FResourceLump()
{
if (FullName != NULL)
{
delete [] FullName;
FullName = NULL;
}
if (Cache != NULL && RefCount >= 0)
{
delete [] Cache;
@ -102,7 +98,7 @@ void FResourceLump::LumpNameSetup(const char *iname)
base = base.Left(base.LastIndexOf('.'));
uppercopy(Name, base);
Name[8] = 0;
FullName = copystring(iname);
FullName = iname;
// Map some directories to WAD namespaces.
// Note that some of these namespaces don't exist in WADS.
@ -321,6 +317,194 @@ FResourceFile::~FResourceFile()
delete Reader;
}
int STACK_ARGS lumpcmp(const void * a, const void * b)
{
FResourceLump * rec1 = (FResourceLump *)a;
FResourceLump * rec2 = (FResourceLump *)b;
return rec1->FullName.CompareNoCase(rec2->FullName);
}
//==========================================================================
//
// FResourceFile :: PostProcessArchive
//
// Sorts files by name.
// For files named "filter/<game>/*": Using the same filter rules as config
// autoloading, move them to the end and rename them without the "filter/"
// prefix. Filtered files that don't match are deleted.
//
//==========================================================================
void FResourceFile::PostProcessArchive(void *lumps, size_t lumpsize)
{
// Entries in archives are sorted alphabetically
qsort(lumps, NumLumps, lumpsize, lumpcmp);
// Filter out lumps using the same names as the Autoload.* sections
// in the ini file use. We reduce the maximum lump concidered after
// each one so that we don't risk refiltering already filtered lumps.
DWORD max = NumLumps;
max -= FilterLumps(gameinfo.ConfigName, lumps, lumpsize, max);
max -= FilterLumps(LumpFilterGroup, lumps, lumpsize, max);
max -= FilterLumps(LumpFilterIWAD, lumps, lumpsize, max);
JunkLeftoverFilters(lumps, lumpsize, max);
}
//==========================================================================
//
// FResourceFile :: FilterLumps
//
// Finds any lumps between [0,<max>) that match the pattern
// "filter/<filtername>/*" and moves them to the end of the lump list.
// Returns the number of lumps moved.
//
//==========================================================================
int FResourceFile::FilterLumps(FString filtername, void *lumps, size_t lumpsize, DWORD max)
{
FString filter;
DWORD start, end;
if (filtername.IsEmpty())
{
return 0;
}
filter << "filter/" << filtername << '/';
if (FindPrefixRange(filter, lumps, lumpsize, max, start, end))
{
void *from = (BYTE *)lumps + start * lumpsize;
// Remove filter prefix from every name
void *lump_p = from;
for (DWORD i = start; i < end; ++i, lump_p = (BYTE *)lump_p + lumpsize)
{
FResourceLump *lump = (FResourceLump *)lump_p;
assert(lump->FullName.CompareNoCase(filter, (int)filter.Len()) == 0);
lump->LumpNameSetup(&lump->FullName[filter.Len()]);
}
// Move filtered lumps to the end of the lump list.
size_t count = (end - start) * lumpsize;
void *to = (BYTE *)lumps + NumLumps * lumpsize - count;
assert (to >= from);
if (from != to)
{
// Copy filtered lumps to a temporary buffer.
BYTE *filteredlumps = new BYTE[count];
memcpy(filteredlumps, from, count);
// Shift lumps left to make room for the filtered ones at the end.
memmove(from, (BYTE *)from + count, (NumLumps - end) * lumpsize);
// Copy temporary buffer to newly freed space.
memcpy(to, filteredlumps, count);
delete[] filteredlumps;
}
}
return end - start;
}
//==========================================================================
//
// FResourceFile :: JunkLeftoverFilters
//
// Deletes any lumps beginning with "filter/" that were not matched.
//
//==========================================================================
void FResourceFile::JunkLeftoverFilters(void *lumps, size_t lumpsize, DWORD max)
{
DWORD start, end;
if (FindPrefixRange("filter/", lumps, lumpsize, max, start, end))
{
// Since the resource lumps may contain non-POD data besides the
// full name, we "delete" them by erasing their names so they
// can't be found.
void *stop = (BYTE *)lumps + end * lumpsize;
for (void *p = (BYTE *)lumps + start * lumpsize; p < stop; p = (BYTE *)p + lumpsize)
{
FResourceLump *lump = (FResourceLump *)p;
lump->FullName = 0;
lump->Name[0] = '\0';
lump->Namespace = ns_invalid;
}
}
}
//==========================================================================
//
// FResourceFile :: FindPrefixRange
//
// Finds a range of lumps that start with the prefix string. <start> is left
// indicating the first matching one. <end> is left at one plus the last
// matching one.
//
//==========================================================================
bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize, DWORD maxlump, DWORD &start, DWORD &end)
{
DWORD min, max, mid, inside;
FResourceLump *lump;
int cmp;
// Pretend that our range starts at 1 instead of 0 so that we can avoid
// unsigned overflow if the range starts at the first lump.
lumps = (BYTE *)lumps - lumpsize;
// Binary search to find any match at all.
min = 1, max = maxlump;
while (min <= max)
{
mid = min + (max - min) / 2;
lump = (FResourceLump *)((BYTE *)lumps + mid * lumpsize);
cmp = lump->FullName.CompareNoCase(filter, (int)filter.Len());
if (cmp == 0)
break;
else if (cmp < 0)
min = mid + 1;
else
max = mid - 1;
}
if (max < min)
{ // matched nothing
return false;
}
// Binary search to find first match.
inside = mid;
min = 1, max = mid;
while (min <= max)
{
mid = min + (max - min) / 2;
lump = (FResourceLump *)((BYTE *)lumps + mid * lumpsize);
cmp = lump->FullName.CompareNoCase(filter, (int)filter.Len());
// Go left on matches and right on misses.
if (cmp == 0)
max = mid - 1;
else
min = mid + 1;
}
start = mid + (cmp != 0) - 1;
// Binary search to find last match.
min = inside, max = maxlump;
while (min <= max)
{
mid = min + (max - min) / 2;
lump = (FResourceLump *)((BYTE *)lumps + mid * lumpsize);
cmp = lump->FullName.CompareNoCase(filter, (int)filter.Len());
// Go right on matches and left on misses.
if (cmp == 0)
min = mid + 1;
else
max = mid - 1;
}
end = mid - (cmp != 0);
return true;
}
//==========================================================================
//

View file

@ -13,7 +13,7 @@ struct FResourceLump
friend class FResourceFile;
int LumpSize;
char * FullName; // only valid for files loaded from a .zip file
FString FullName; // only valid for files loaded from a non-wad archive
union
{
char Name[9];
@ -30,7 +30,6 @@ struct FResourceLump
FResourceLump()
{
FullName = NULL;
Cache = NULL;
Owner = NULL;
Flags = 0;
@ -66,9 +65,16 @@ protected:
FResourceFile(const char *filename, FileReader *r);
// for archives that can contain directories
void PostProcessArchive(void *lumps, size_t lumpsize);
private:
DWORD FirstLump;
int FilterLumps(FString filtername, void *lumps, size_t lumpsize, DWORD max);
bool FindPrefixRange(FString filter, void *lumps, size_t lumpsize, DWORD max, DWORD &start, DWORD &end);
void JunkLeftoverFilters(void *lumps, size_t lumpsize, DWORD max);
public:
static FResourceFile *OpenResourceFile(const char *filename, FileReader *file, bool quiet = false);
static FResourceFile *OpenDirectory(const char *filename, bool quiet = false);

View file

@ -290,14 +290,9 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo)
FResourceLump *lump = resfile->GetLump(i);
if (lump->Flags & LUMPF_EMBEDDED)
{
char path[256];
mysnprintf(path, countof(path), "%s:", filename);
char *wadstr = path + strlen(path);
FString path;
path.Format("%s:%s", filename, lump->FullName.GetChars());
FileReader *embedded = lump->NewReader();
strcpy(wadstr, lump->FullName);
AddFile(path, embedded);
}
}
@ -345,7 +340,9 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo)
sprintf(cksumout + (j * 2), "%02X", cksum[j]);
}
fprintf(hashfile, "file: %s, lump: %s, hash: %s, size: %d\n", filename, lump->FullName ? lump->FullName : lump->Name, cksumout, lump->LumpSize);
fprintf(hashfile, "file: %s, lump: %s, hash: %s, size: %d\n", filename,
lump->FullName.IsNotEmpty() ? lump->FullName.GetChars() : lump->Name,
cksumout, lump->LumpSize);
delete reader;
}
@ -737,7 +734,7 @@ void FWadCollection::InitHashChains (void)
FirstLumpIndex[j] = i;
// Do the same for the full paths
if (LumpInfo[i].lump->FullName!=NULL)
if (LumpInfo[i].lump->FullName.IsNotEmpty())
{
j = MakeKey(LumpInfo[i].lump->FullName) % NumLumps;
NextLumpIndex_FullName[i] = FirstLumpIndex_FullName[j];
@ -1088,7 +1085,7 @@ const char *FWadCollection::GetLumpFullName (int lump) const
{
if ((size_t)lump >= NumLumps)
return NULL;
else if (LumpInfo[lump].lump->FullName != NULL)
else if (LumpInfo[lump].lump->FullName.IsNotEmpty())
return LumpInfo[lump].lump->FullName;
else
return LumpInfo[lump].lump->Name;
@ -1574,3 +1571,33 @@ static void PrintLastError ()
Printf (TEXTCOLOR_RED " %s\n", strerror(errno));
}
#endif
#ifdef _DEBUG
//==========================================================================
//
// CCMD LumpNum
//
//==========================================================================
CCMD(lumpnum)
{
for (int i = 1; i < argv.argc(); ++i)
{
Printf("%s: %d\n", argv[i], Wads.CheckNumForName(argv[i]));
}
}
//==========================================================================
//
// CCMD LumpNumFull
//
//==========================================================================
CCMD(lumpnumfull)
{
for (int i = 1; i < argv.argc(); ++i)
{
Printf("%s: %d\n", argv[i], Wads.CheckNumForFullName(argv[i]));
}
}
#endif

View file

@ -52,6 +52,8 @@ struct wadlump_t
// [RH] Namespaces from BOOM.
typedef enum {
ns_invalid = -1,
ns_global = 0,
ns_sprites,
ns_flats,