Changed file lookup order in .resources paks like in previous id Tech engines

This commit is contained in:
Robert Beckebans 2024-06-24 21:31:00 +02:00
parent b448fa839a
commit af0e94fee6
5 changed files with 240 additions and 156 deletions

View file

@ -840,6 +840,19 @@ void idConsoleLocal::Resize()
LOCALSAFE_BOTTOM = renderSystem->GetVirtualHeight() - LOCALSAFE_TOP;
LOCALSAFE_WIDTH = LOCALSAFE_RIGHT - LOCALSAFE_LEFT;
LOCALSAFE_HEIGHT = LOCALSAFE_BOTTOM - LOCALSAFE_TOP;
#if 0
LINE_WIDTH = ( ( LOCALSAFE_WIDTH / SMALLCHAR_WIDTH ) - 2 );
consoleField.Clear();
consoleField.SetWidthInChars( LINE_WIDTH );
for( int i = 0 ; i < COMMAND_HISTORY ; i++ )
{
historyEditLines[i].Clear();
historyEditLines[i].SetWidthInChars( LINE_WIDTH );
}
#endif
}
/*

View file

@ -3,7 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2012 Robert Beckebans
Copyright (C) 2012-2024 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -122,6 +122,9 @@ struct searchpath_t
{
idStr path; // c:\doom
idStr gamedir; // base
// RB: moved global resourcesFiles here
idList< idResourceContainer* > resourceFiles;
};
// search flags when opening a file
@ -177,18 +180,21 @@ public:
// RB end
virtual bool UsingResourceFiles()
{
return resourceFiles.Num() > 0;
// was return resourceFiles.Num() > 0;
/*
for( int sp = searchPaths.Num() - 1; sp >= 0; sp-- )
{
if( searchPaths[sp].resourceFiles.Num() > 0 )
{
return true;
}
}
*/
return resourceFilesFound;
}
virtual void UnloadMapResources( const char* name );
virtual void UnloadResourceContainer( const char* name );
idFile* GetResourceContainer( int idx )
{
if( idx >= 0 && idx < resourceFiles.Num() )
{
return resourceFiles[ idx ]->resourceFile;
}
return NULL;
}
virtual void StartPreload( const idStrList& _preload );
virtual void StopPreload();
@ -259,7 +265,7 @@ private:
idStrList fileManifest;
idPreloadManifest preloadList;
idList< idResourceContainer* > resourceFiles;
bool resourceFilesFound = false;
byte* resourceBufferPtr;
int resourceBufferSize;
int resourceBufferAvailable;
@ -287,11 +293,11 @@ private:
int GetFileListTree( const char* relativePath, const idStrList& extensions, idStrList& list, idHashIndex& hashIndex, bool allowSubdirsForResourcePaks = false, const char* gamedir = NULL );
void AddGameDirectory( const char* path, const char* dir );
int AddResourceFile( const char* resourceFileName );
idVec2i AddResourceFile( const char* resourceFileName );
void RemoveMapResourceFile( const char* resourceFileName );
void RemoveResourceFileByIndex( const int& idx );
void RemoveResourceFileByIndex( const idVec2i& idx );
void RemoveResourceFile( const char* resourceFileName );
int FindResourceFile( const char* resourceFileName );
idVec2i FindResourceFile( const char* resourceFileName );
void SetupGameDirectories( const char* gameName );
void Startup();
@ -428,7 +434,7 @@ int idFileSystemLocal::GetFileLength( const char* relativePath )
return -1;
}
if( resourceFiles.Num() > 0 )
if( UsingResourceFiles() )
{
idResourceCacheEntry rc;
if( GetResourceCacheEntry( relativePath, rc ) )
@ -675,7 +681,6 @@ idFileSystemLocal::BeginLevelLoad
*/
void idFileSystemLocal::BeginLevelLoad( const char* name, char* _blockBuffer, int _blockBufferSize )
{
if( name == NULL || *name == '\0' )
{
return;
@ -695,7 +700,7 @@ void idFileSystemLocal::BeginLevelLoad( const char* name, char* _blockBuffer, in
ReOpenCacheFiles();
manifestName.StripPath();
if( resourceFiles.Num() > 0 )
if( UsingResourceFiles() )
{
AddResourceFile( va( "%s.resources", manifestName.c_str() ) );
}
@ -1943,7 +1948,6 @@ timestamp can be NULL if not required
*/
int idFileSystemLocal::ReadFile( const char* relativePath, void** buffer, ID_TIME_T* timestamp )
{
idFile* f;
byte* buf;
int len;
@ -2017,7 +2021,7 @@ int idFileSystemLocal::ReadFile( const char* relativePath, void** buffer, ID_TIM
if( f == NULL )
{
// RB: moved here
if( buffer == NULL && timestamp != NULL && resourceFiles.Num() > 0 )
if( buffer == NULL && timestamp != NULL && UsingResourceFiles() )
{
static idResourceCacheEntry rc;
int size = 0;
@ -2252,83 +2256,87 @@ int idFileSystemLocal::GetFileList( const char* relativePath, const idStrList& e
}
idStrStatic< MAX_OSPATH > strippedName;
if( resourceFiles.Num() > 0 )
if( UsingResourceFiles() )
{
int idx = resourceFiles.Num() - 1;
while( idx >= 0 )
for( int sp = fileSystemLocal.searchPaths.Num() - 1; sp >= 0; sp-- )
{
for( int i = 0; i < resourceFiles[ idx ]->cacheTable.Num(); i++ )
const searchpath_t& searchpath = fileSystemLocal.searchPaths[sp];
int idx = searchpath.resourceFiles.Num() - 1;
while( idx >= 0 )
{
idResourceCacheEntry& rt = resourceFiles[ idx ]->cacheTable[ i ];
// if the name is not long anough to at least contain the path
if( rt.filename.Length() <= pathLength )
for( int i = 0; i < searchpath.resourceFiles[ idx ]->cacheTable.Num(); i++ )
{
continue;
}
idResourceCacheEntry& rt = searchpath.resourceFiles[ idx ]->cacheTable[ i ];
// if the name is not long anough to at least contain the path
// check for a path match without the trailing '/'
if( pathLength && idStr::Icmpn( rt.filename, relativePath, pathLength - 1 ) != 0 )
{
continue;
}
// ensure we have a path, and not just a filename containing the path
if( rt.filename[ pathLength ] == '\0' || ( pathLength && rt.filename[pathLength - 1] != '/' ) )
{
continue;
}
// make sure the file is not in a subdirectory
int j = pathLength;
// RB: expose this to an option for exportModelsToTrenchBroom
// so it doesn't break loading of sounds
if( !allowSubdirsForResourcePaks )
{
for( ; rt.filename[j + 1] != '\0'; j++ )
if( rt.filename.Length() <= pathLength )
{
if( rt.filename[ j ] == '/' )
continue;
}
// check for a path match without the trailing '/'
if( pathLength && idStr::Icmpn( rt.filename, relativePath, pathLength - 1 ) != 0 )
{
continue;
}
// ensure we have a path, and not just a filename containing the path
if( rt.filename[ pathLength ] == '\0' || ( pathLength && rt.filename[pathLength - 1] != '/' ) )
{
continue;
}
// make sure the file is not in a subdirectory
int j = pathLength;
// RB: expose this to an option for exportModelsToTrenchBroom
// so it doesn't break loading of sounds
if( !allowSubdirsForResourcePaks )
{
for( ; rt.filename[j + 1] != '\0'; j++ )
{
if( rt.filename[ j ] == '/' )
{
break;
}
}
if( rt.filename[ j + 1 ] )
{
continue;
}
}
// check for extension match
for( j = 0; j < extensions.Num(); j++ )
{
if( rt.filename.Length() >= extensions[j].Length() && extensions[j].Icmp( rt.filename.c_str() + rt.filename.Length() - extensions[j].Length() ) == 0 )
{
break;
}
}
if( rt.filename[ j + 1 ] )
if( j >= extensions.Num() )
{
continue;
}
}
// check for extension match
for( j = 0; j < extensions.Num(); j++ )
{
if( rt.filename.Length() >= extensions[j].Length() && extensions[j].Icmp( rt.filename.c_str() + rt.filename.Length() - extensions[j].Length() ) == 0 )
// unique the match
if( fullRelativePath )
{
break;
idStr work = relativePath;
work += "/";
work += rt.filename.c_str() + pathLength;
work.StripTrailing( '/' );
AddUnique( work, list, hashIndex );
}
else
{
idStr work = rt.filename.c_str() + pathLength;
work.StripTrailing( '/' );
AddUnique( work, list, hashIndex );
}
}
if( j >= extensions.Num() )
{
continue;
}
// unique the match
if( fullRelativePath )
{
idStr work = relativePath;
work += "/";
work += rt.filename.c_str() + pathLength;
work.StripTrailing( '/' );
AddUnique( work, list, hashIndex );
}
else
{
idStr work = rt.filename.c_str() + pathLength;
work.StripTrailing( '/' );
AddUnique( work, list, hashIndex );
}
idx--;
}
idx--;
}
}
@ -2695,14 +2703,17 @@ void idFileSystemLocal::Path_f( const idCmdArgs& args )
common->Printf( "Current search path:\n" );
for( int sp = fileSystemLocal.searchPaths.Num() - 1; sp >= 0; sp-- )
{
common->Printf( "%s/%s\n", fileSystemLocal.searchPaths[sp].path.c_str(), fileSystemLocal.searchPaths[sp].gamedir.c_str() );
}
const searchpath_t& search = fileSystemLocal.searchPaths[sp];
int idx = fileSystemLocal.resourceFiles.Num() - 1;
while( idx >= 0 )
{
common->Printf( "%s\n", fileSystemLocal.resourceFiles[idx]->GetFileName() );
idx--;
common->Printf( "%s/%s\n", search.path.c_str(), search.gamedir.c_str() );
int idx = search.resourceFiles.Num() - 1;
while( idx >= 0 )
{
common->Printf( "%s/%s/%s (%i files)\n", search.path.c_str(), search.gamedir.c_str(), search.resourceFiles[idx]->GetFileName(), search.resourceFiles[idx]->GetNumFileResources() );
//common->Printf( "%s (%i files)\n", search.resourceFiles[idx]->GetFileName(), search.resourceFiles[idx]->GetNumFileResources() );
idx--;
}
}
}
@ -2884,26 +2895,32 @@ void idFileSystemLocal::CreateCRCsForResourceFileList( const idFileList& list )
idFileSystemLocal::AddResourceFile
================
*/
int idFileSystemLocal::AddResourceFile( const char* resourceFileName )
idVec2i idFileSystemLocal::AddResourceFile( const char* resourceFileName )
{
// RB: check if it was already added
int idx = FindResourceFile( resourceFileName );
if( idx != -1 )
idVec2i idx = FindResourceFile( resourceFileName );
if( idx[0] != -1 && idx[1] != -1 )
{
return idx;
}
// RB end
idStrStatic< MAX_OSPATH > resourceFile = va( "maps/%s", resourceFileName );
idResourceContainer* rc = new idResourceContainer();
if( rc->Init( resourceFile, resourceFiles.Num() ) )
for( int sp = fileSystemLocal.searchPaths.Num() - 1; sp >= 0; sp-- )
{
resourceFiles.Append( rc );
common->Printf( "Loaded resource file %s\n", resourceFile.c_str() );
return resourceFiles.Num() - 1;
searchpath_t& search = fileSystemLocal.searchPaths[sp];
idStrStatic< MAX_OSPATH > resourceFile = va( "maps/%s", resourceFileName );
idResourceContainer* rc = new idResourceContainer();
if( rc->Init( resourceFile ) )
{
search.resourceFiles.Append( rc );
common->Printf( "Loaded resource file %s\n", resourceFile.c_str() );
return idVec2i( sp, search.resourceFiles.Num() - 1 );
}
delete rc;
}
delete rc;
return -1;
return idVec2i( -1, -1 );
}
/*
@ -2911,41 +2928,59 @@ int idFileSystemLocal::AddResourceFile( const char* resourceFileName )
idFileSystemLocal::FindResourceFile
================
*/
int idFileSystemLocal::FindResourceFile( const char* resourceFileName )
idVec2i idFileSystemLocal::FindResourceFile( const char* resourceFileName )
{
#if 0
// MadDeCoDeR: prevent vanilla .resource maps to be reloaded #447
const char* mapFileName = va( "maps/%s", resourceFileName );
for( int i = 0; i < resourceFiles.Num(); i++ )
for( int sp = fileSystemLocal.searchPaths.Num() - 1; sp >= 0; sp-- )
{
if( idStr::Icmp( resourceFileName, resourceFiles[ i ]->GetFileName() ) == 0 ||
idStr::Icmp( mapFileName, resourceFiles[i]->GetFileName() ) == 0 )
const searchpath_t& search = fileSystemLocal.searchPaths[sp];
for( int i = 0; i < search.resourceFiles.Num(); i++ )
{
return i;
if( idStr::Icmp( resourceFileName, search.resourceFiles[ i ]->GetFileName() ) == 0 ||
idStr::Icmp( mapFileName, search.resourceFiles[i]->GetFileName() ) == 0 )
{
return idVec2i( sp, i );
}
}
}
// MadDeCoDeR:end
return -1;
#else
// original behaviour
for( int sp = searchPaths.Num() - 1; sp >= 0; sp-- )
{
const searchpath_t& search = searchPaths[sp];
for( int i = 0; i < search.resourceFiles.Num(); i++ )
{
if( idStr::Icmp( resourceFileName, search.resourceFiles[ i ]->GetFileName() ) == 0 )
{
return idVec2i( sp, i );
}
}
}
#endif
return idVec2i( -1, -1 );
}
/*
================
idFileSystemLocal::RemoveResourceFileByIndex
================
*/
void idFileSystemLocal::RemoveResourceFileByIndex( const int& idx )
void idFileSystemLocal::RemoveResourceFileByIndex( const idVec2i& idx )
{
if( idx >= 0 && idx < resourceFiles.Num() )
if( idx.x >= 0 && idx.x < searchPaths.Num() )
{
if( idx >= 0 && idx < resourceFiles.Num() )
searchpath_t& search = searchPaths[idx.x];
if( idx.y >= 0 && idx.y < search.resourceFiles.Num() )
{
delete resourceFiles[ idx ];
resourceFiles.RemoveIndex( idx );
for( int i = 0; i < resourceFiles.Num(); i++ )
{
// fixup any container indexes
resourceFiles[ i ]->SetContainerIndex( i );
}
delete search.resourceFiles[ idx.y ];
search.resourceFiles.RemoveIndex( idx.y );
}
}
}
@ -2957,11 +2992,13 @@ idFileSystemLocal::RemoveMapResourceFile
*/
void idFileSystemLocal::RemoveMapResourceFile( const char* resourceFileName )
{
#if 0
int idx = FindResourceFile( va( "maps/%s", resourceFileName ) );
if( idx >= 0 )
{
RemoveResourceFileByIndex( idx );
}
#endif
}
/*
@ -2971,11 +3008,13 @@ idFileSystemLocal::RemoveResourceFile
*/
void idFileSystemLocal::RemoveResourceFile( const char* resourceFileName )
{
#if 0
int idx = FindResourceFile( resourceFileName );
if( idx >= 0 )
{
RemoveResourceFileByIndex( idx );
}
#endif
}
/*
@ -3035,11 +3074,13 @@ void idFileSystemLocal::AddGameDirectory( const char* path, const char* dir )
}
idResourceContainer* rc = new idResourceContainer();
if( rc->Init( pakfile, resourceFiles.Num() ) )
if( rc->Init( pakfile ) )
{
resourceFiles.Append( rc );
search.resourceFiles.Append( rc );
common->Printf( "Loaded resource file %s\n", pakfile.c_str() );
//com_productionMode.SetInteger( 2 );
resourceFilesFound = true;
}
}
}
@ -3220,10 +3261,12 @@ Frees all resources and closes all files
void idFileSystemLocal::Shutdown( bool reloading )
{
gameFolder.Clear();
searchPaths.Clear();
resourceFiles.DeleteContents();
for( int sp = fileSystemLocal.searchPaths.Num() - 1; sp >= 0; sp-- )
{
searchpath_t& search = fileSystemLocal.searchPaths[sp];
search.resourceFiles.DeleteContents();
}
cmdSystem->RemoveCommand( "path" );
cmdSystem->RemoveCommand( "dir" );
@ -3275,24 +3318,32 @@ bool idFileSystemLocal::GetResourceCacheEntry( const char* fileName, idResourceC
canonical.BackSlashesToSlashes();
canonical.ToLower();
int idx = resourceFiles.Num() - 1;
while( idx >= 0 )
for( int sp = fileSystemLocal.searchPaths.Num() - 1; sp >= 0; sp-- )
{
const int key = resourceFiles[ idx ]->cacheHash.GenerateKey( canonical, false );
for( int index = resourceFiles[ idx ]->cacheHash.GetFirst( key ); index != idHashIndex::NULL_INDEX; index = resourceFiles[ idx ]->cacheHash.GetNext( index ) )
const searchpath_t& search = fileSystemLocal.searchPaths[sp];
int idx = search.resourceFiles.Num() - 1;
while( idx >= 0 )
{
idResourceCacheEntry& rt = resourceFiles[ idx ]->cacheTable[ index ];
if( idStr::Icmp( rt.filename, canonical ) == 0 )
const int key = search.resourceFiles[ idx ]->cacheHash.GenerateKey( canonical, false );
for( int index = search.resourceFiles[ idx ]->cacheHash.GetFirst( key ); index != idHashIndex::NULL_INDEX; index = search.resourceFiles[ idx ]->cacheHash.GetNext( index ) )
{
rc.filename = rt.filename;
rc.length = rt.length;
rc.containerIndex = idx;
rc.offset = rt.offset;
return true;
idResourceCacheEntry& rt = search.resourceFiles[ idx ]->cacheTable[ index ];
if( idStr::Icmp( rt.filename, canonical ) == 0 )
{
rc.filename = rt.filename;
rc.length = rt.length;
rc.offset = rt.offset;
rc.owner = search.resourceFiles[idx];
return true;
}
}
idx--;
}
idx--;
}
return false;
}
@ -3306,8 +3357,7 @@ Returns NULL
idFile* idFileSystemLocal::GetResourceFile( const char* fileName, bool memFile )
{
if( resourceFiles.Num() == 0 )
if( !UsingResourceFiles() )
{
return NULL;
}
@ -3320,7 +3370,7 @@ idFile* idFileSystemLocal::GetResourceFile( const char* fileName, bool memFile )
idLib::Printf( "RES: loading file %s\n", rc.filename.c_str() );
}
idFile_InnerResource* file = new idFile_InnerResource( rc.filename, resourceFiles[ rc.containerIndex ]->resourceFile, rc.offset, rc.length );
idFile_InnerResource* file = new idFile_InnerResource( rc.filename, rc.owner->resourceFile, rc.offset, rc.length );
// DG: add parenthesis to make sure this block is only entered when file != NULL - bug found by clang.
if( file != NULL && ( ( memFile || rc.length <= resourceBufferAvailable ) || rc.length < 8 * 1024 * 1024 ) )
@ -3414,7 +3464,7 @@ idFile* idFileSystemLocal::OpenFileReadFlags( const char* relativePath, int sear
idLib::Printf( "FILE DEBUG: opening %s\n", relativePath );
}
if( resourceFiles.Num() > 0 && fs_resourceLoadPriority.GetInteger() == 1 )
if( UsingResourceFiles() && fs_resourceLoadPriority.GetInteger() == 1 )
{
idFile* rf = GetResourceFile( relativePath, ( searchFlags & FSFLAG_RETURN_FILE_MEM ) != 0 );
if( rf != NULL )
@ -3552,7 +3602,7 @@ idFile* idFileSystemLocal::OpenFileReadFlags( const char* relativePath, int sear
}
}
if( resourceFiles.Num() > 0 && fs_resourceLoadPriority.GetInteger() == 0 )
if( UsingResourceFiles() && fs_resourceLoadPriority.GetInteger() == 0 )
{
idFile* rf = GetResourceFile( relativePath, ( searchFlags & FSFLAG_RETURN_FILE_MEM ) != 0 );
if( rf != NULL )

View file

@ -57,9 +57,8 @@ void idResourceContainer::ReOpen()
idResourceContainer::Init
========================
*/
bool idResourceContainer::Init( const char* _fileName, uint8 containerIndex )
bool idResourceContainer::Init( const char* _fileName )
{
if( idStr::Icmp( _fileName, "_ordered.resources" ) == 0 )
{
resourceFile = fileSystem->OpenFileReadMemory( _fileName );
@ -103,7 +102,7 @@ bool idResourceContainer::Init( const char* _fileName, uint8 containerIndex )
rt.Read( &memFile );
rt.filename.BackSlashesToSlashes();
rt.filename.ToLower();
rt.containerIndex = containerIndex;
rt.owner = this;
const int key = cacheHash.GenerateKey( rt.filename, false );
bool found = false;
@ -315,20 +314,6 @@ void idResourceContainer::UpdateResourceFile( const char* _filename, const idStr
delete inFile;
}
/*
========================
idResourceContainer::ExtractResourceFile
========================
*/
void idResourceContainer::SetContainerIndex( const int& _idx )
{
for( int i = 0; i < cacheTable.Num(); i++ )
{
cacheTable[ i ].containerIndex = _idx;
}
}
/*
========================
idResourceContainer::ExtractResourceFile

View file

@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2024 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -36,6 +37,7 @@ If you have questions concerning this license or the applicable additional terms
==============================================================
*/
class idResourceContainer;
class idResourceCacheEntry
{
@ -47,10 +49,9 @@ public:
void Clear()
{
filename.Empty();
//filename = NULL;
offset = 0;
length = 0;
containerIndex = 0;
owner = NULL;
}
size_t Read( idFile* f )
{
@ -66,10 +67,14 @@ public:
sz += f->WriteBig( length );
return sz;
}
// part of .resources file format
idStrStatic< 256 > filename;
int offset; // into the resource file
int length;
uint8 containerIndex;
// helpers only in memory
idResourceContainer* owner;
};
static const uint32 RESOURCE_FILE_MAGIC = 0xD000000D;
@ -91,7 +96,7 @@ public:
delete resourceFile;
cacheTable.Clear();
}
bool Init( const char* fileName, uint8 containerIndex );
bool Init( const char* fileName );
static void WriteResourceFile( const char* fileName, const idStrList& manifest, const bool& _writeManifest );
static void WriteManifestFile( const char* name, const idStrList& list );
static int ReadManifestFile( const char* filename, idStrList& list );
@ -102,8 +107,12 @@ public:
{
return fileName.c_str();
}
void SetContainerIndex( const int& _idx );
void ReOpen();
int GetNumFileResources() const
{
return numFileResources;
}
private:
idStrStatic< 256 > fileName;
idFile* resourceFile; // open file handle

View file

@ -1,3 +1,30 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 2015 Daniel Gibson
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef NEO_IMGUI_IMGUI_HOOKS_H_
#define NEO_IMGUI_IMGUI_HOOKS_H_