Skip to content

Commit dd7987a

Browse files
committed
feat(filesystem): Recover 481 higher resolution textures in Zero Hour by re-prioritizing textures by size
1 parent 37f1631 commit dd7987a

File tree

3 files changed

+130
-48
lines changed

3 files changed

+130
-48
lines changed

Core/GameEngine/Include/Common/GameDefines.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@
6060
#define ENABLE_FILESYSTEM_EXISTENCE_CACHE (1)
6161
#endif
6262

63+
// Enable prioritization of textures by size. This will improve the texture quality of 481 textures in Zero Hour
64+
// by using the larger resolution textures from Generals. Content wise these textures are identical.
65+
#ifndef PRIORITIZE_TEXTURES_BY_SIZE
66+
#define PRIORITIZE_TEXTURES_BY_SIZE (1)
67+
#endif
68+
6369
// Enable obsolete code. This mainly refers to code that existed in Generals but was removed in GeneralsMD.
6470
// Disable and remove this when Generals and GeneralsMD are merged.
6571
#if RTS_GENERALS

GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DFileSystem.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#define __W3DFILESYSTEM_H_
4141

4242
#include "WWLib/ffactory.h"
43+
#include "Common/ArchiveFileSystem.h"
4344
#include "Common/file.h"
4445

4546
//-------------------------------------------------------------------------------------------------
@@ -93,6 +94,11 @@ class W3DFileSystem : public FileFactoryClass {
9394

9495
virtual FileClass * Get_File( char const *filename );
9596
virtual void Return_File( FileClass *file );
97+
98+
private:
99+
100+
static void reprioritizeTexturesBySize();
101+
static void reprioritizeTexturesBySize(ArchivedDirectoryInfo& dirInfo);
96102
};
97103

98104
extern W3DFileSystem *TheW3DFileSystem;

GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DFileSystem.cpp

Lines changed: 118 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,19 @@
4040
// for now we maintain old legacy files
4141
// #define MAINTAIN_LEGACY_FILES
4242

43+
#include "Common/ArchiveFile.h"
4344
#include "Common/Debug.h"
4445
#include "Common/file.h"
4546
#include "Common/FileSystem.h"
4647
#include "Common/GlobalData.h"
4748
#include "Common/MapObject.h"
4849
#include "Common/Registry.h"
4950
#include "W3DDevice/GameClient/W3DFileSystem.h"
50-
// DEFINES ////////////////////////////////////////////////////////////////////////////////////////
5151

5252
#include <io.h>
53+
#include <Utility/stdio_adapter.h>
54+
55+
// DEFINES ////////////////////////////////////////////////////////////////////////////////////////
5356

5457
//-------------------------------------------------------------------------------------------------
5558
/** Game file access. At present this allows us to access test assets, assets from
@@ -71,9 +74,9 @@ typedef enum
7174
GameFileClass::GameFileClass( char const *filename )
7275
{
7376

74-
m_fileExists = FALSE;
7577
m_theFile = NULL;
76-
m_filePath[ 0 ] = 0;
78+
m_fileExists = FALSE;
79+
m_filePath[0] = 0;
7780
m_filename[0] = 0;
7881

7982
if( filename )
@@ -119,6 +122,36 @@ inline static Bool isImageFileType( GameFileType fileType )
119122
return (fileType == FILE_TYPE_TGA || fileType == FILE_TYPE_DDS);
120123
}
121124

125+
//-------------------------------------------------------------------------------------------------
126+
//-------------------------------------------------------------------------------------------------
127+
static GameFileType getFileType( char const *filename )
128+
{
129+
const Int EXT_LEN = 32;
130+
char extension[EXT_LEN];
131+
extension[0] = 0;
132+
Int i = strlen(filename);
133+
i--;
134+
Int extLen = 1;
135+
while(i>0 && extLen < EXT_LEN) {
136+
if (filename[i] == '.') {
137+
strcpy(extension, filename+i);
138+
break;
139+
}
140+
i--;
141+
extLen++;
142+
}
143+
144+
// test the extension to recognize a few key file types
145+
if( stricmp( extension, ".w3d" ) == 0 )
146+
return FILE_TYPE_W3D;
147+
else if( stricmp( extension, ".tga" ) == 0 )
148+
return FILE_TYPE_TGA;
149+
else if( stricmp( extension, ".dds" ) == 0 )
150+
return FILE_TYPE_DDS;
151+
else
152+
return FILE_TYPE_COMPLETELY_UNKNOWN; // MBL FILE_TYPE_UNKNOWN change due to compile error
153+
}
154+
122155
//-------------------------------------------------------------------------------------------------
123156
/**
124157
Sets the file name, and finds the GDI asset if present.
@@ -146,43 +179,7 @@ char const * GameFileClass::Set_Name( char const *filename )
146179
// save the filename
147180
strncpy( m_filename, filename, _MAX_PATH );
148181

149-
char name[_MAX_PATH];
150-
const Int EXT_LEN = 32;
151-
char extension[EXT_LEN];
152-
extension[0] = 0;
153-
strcpy(name, filename);
154-
Int i = strlen(name);
155-
i--;
156-
Int extLen = 1;
157-
while(i>0 && extLen < EXT_LEN) {
158-
if (name[i] == '.') {
159-
strcpy(extension, name+i);
160-
name[i] = 0;
161-
break;
162-
}
163-
i--;
164-
extLen++;
165-
}
166-
Int j = 0;
167-
// Strip out spaces.
168-
for (i=0; name[i]; i++) {
169-
if (name[i] != ' ') {
170-
name[j] = name[i];
171-
j++;
172-
}
173-
}
174-
name[j] = 0;
175-
176-
// test the extension to recognize a few key file types
177-
GameFileType fileType = FILE_TYPE_COMPLETELY_UNKNOWN; // MBL FILE_TYPE_UNKNOWN change due to compile error
178-
if( stricmp( extension, ".w3d" ) == 0 )
179-
fileType = FILE_TYPE_W3D;
180-
else if( stricmp( extension, ".tga" ) == 0 )
181-
fileType = FILE_TYPE_TGA;
182-
else if( stricmp( extension, ".dds" ) == 0 )
183-
fileType = FILE_TYPE_DDS;
184-
185-
182+
GameFileType fileType = getFileType(filename);
186183

187184
// We need to be able to grab w3d's from a localization dir, since Germany hates exploding people units.
188185
if( fileType == FILE_TYPE_W3D )
@@ -192,9 +189,8 @@ char const * GameFileClass::Set_Name( char const *filename )
192189
strcat( m_filePath, filename );
193190

194191
} // end if
195-
196192
// We need to be able to grab images from a localization dir, because Art has a fetish for baked-in text. Munkee.
197-
if( isImageFileType(fileType) )
193+
else if( isImageFileType(fileType) )
198194
{
199195
static const char *localizedPathFormat = "Data/%s/Art/Textures/";
200196
sprintf(m_filePath,localizedPathFormat, GetRegistryLanguage().str());
@@ -298,7 +294,7 @@ char const * GameFileClass::Set_Name( char const *filename )
298294
strcat( m_filePath, filename );
299295

300296
} // end if
301-
if( isImageFileType(fileType) )
297+
else if( isImageFileType(fileType) )
302298
{
303299
sprintf(m_filePath,USER_TGA_DIR_PATH, TheGlobalData->getPath_UserData().str());
304300
//strcpy( m_filePath, USER_TGA_DIR_PATH );
@@ -312,10 +308,10 @@ char const * GameFileClass::Set_Name( char const *filename )
312308
} // end if
313309

314310

315-
// We Need to be able to "temporarily copy over the map preview for whichever directory it came from
311+
// We need to be able to temporarily copy over the map preview for whichever directory it came from
316312
if( m_fileExists == FALSE && TheGlobalData)
317313
{
318-
if( fileType == FILE_TYPE_TGA ) // just TGA, since we don't dds previews
314+
if( fileType == FILE_TYPE_TGA ) // just TGA, since we don't do dds previews
319315
{
320316
sprintf(m_filePath,MAP_PREVIEW_DIR_PATH, TheGlobalData->getPath_UserData().str());
321317
//strcpy( m_filePath, USER_TGA_DIR_PATH );
@@ -373,11 +369,9 @@ int GameFileClass::Open(int rights)
373369
return(false);
374370
}
375371

376-
// just open up the file in m_filePath
377372
m_theFile = TheFileSystem->openFile( m_filePath, File::READ | File::BINARY );
378373

379374
return (m_theFile != NULL);
380-
381375
}
382376

383377
//-------------------------------------------------------------------------------------------------
@@ -448,12 +442,16 @@ void GameFileClass::Close(void)
448442
extern W3DFileSystem *TheW3DFileSystem = NULL;
449443

450444
//-------------------------------------------------------------------------------------------------
451-
/** Constructor. Creating an instance of this class overrices the default
445+
/** Constructor. Creating an instance of this class overrides the default
452446
W3D file factory. */
453447
//-------------------------------------------------------------------------------------------------
454448
W3DFileSystem::W3DFileSystem(void)
455449
{
456450
_TheFileFactory = this; // override the w3d file factory.
451+
452+
#if PRIORITIZE_TEXTURES_BY_SIZE
453+
reprioritizeTexturesBySize();
454+
#endif
457455
}
458456

459457
//-------------------------------------------------------------------------------------------------
@@ -481,3 +479,75 @@ void W3DFileSystem::Return_File( FileClass *file )
481479
delete file;
482480
}
483481

482+
//-------------------------------------------------------------------------------------------------
483+
//-------------------------------------------------------------------------------------------------
484+
void W3DFileSystem::reprioritizeTexturesBySize()
485+
{
486+
{
487+
ArchivedDirectoryInfo* dirInfo = TheArchiveFileSystem->friend_getArchivedDirectoryInfo(TGA_DIR_PATH);
488+
if (dirInfo != NULL)
489+
reprioritizeTexturesBySize(*dirInfo);
490+
}
491+
492+
{
493+
char path[_MAX_PATH];
494+
snprintf(path, ARRAY_SIZE(path), "Data/%s/Art/Textures/", GetRegistryLanguage().str());
495+
ArchivedDirectoryInfo* dirInfo = TheArchiveFileSystem->friend_getArchivedDirectoryInfo(path);
496+
if (dirInfo != NULL)
497+
reprioritizeTexturesBySize(*dirInfo);
498+
}
499+
}
500+
501+
//-------------------------------------------------------------------------------------------------
502+
//-------------------------------------------------------------------------------------------------
503+
void W3DFileSystem::reprioritizeTexturesBySize(ArchivedDirectoryInfo& dirInfo)
504+
{
505+
ArchivedFileLocationMap::iterator it0;
506+
ArchivedFileLocationMap::iterator it1 = dirInfo.m_files.begin();
507+
ArchivedFileLocationMap::iterator end = dirInfo.m_files.end();
508+
509+
if (it1 != end)
510+
{
511+
it0 = it1;
512+
++it1;
513+
}
514+
515+
// This algorithm only prioritizes the first item in the multimap.
516+
for (; it1 != end; ++it1)
517+
{
518+
const AsciiString& file0 = it0->first;
519+
const AsciiString& file1 = it1->first;
520+
521+
if (file0 == file1)
522+
{
523+
GameFileType type = getFileType(file0.str());
524+
if (isImageFileType(type))
525+
{
526+
ArchiveFile* archive0 = it0->second;
527+
ArchiveFile* archive1 = it1->second;
528+
FileInfo info0;
529+
FileInfo info1;
530+
AsciiString filepath(dirInfo.m_path);
531+
filepath.concat(file0);
532+
533+
if (archive0->getFileInfo(filepath, &info0) && archive1->getFileInfo(filepath, &info1))
534+
{
535+
if (info0.size() < info1.size())
536+
{
537+
std::swap(it0->second, it1->second);
538+
539+
#if ENABLE_FILESYSTEM_LOGGING
540+
DEBUG_LOG(("W3DFileSystem::reprioritizeTexturesBySize - prioritize %s(%ukb) from %s over %s(%ukb) from %s",
541+
file1.str(), UnsignedInt(info1.size() / 1024), archive1->getName().str(),
542+
file0.str(), UnsignedInt(info0.size() / 1024), archive0->getName().str()));
543+
#endif
544+
}
545+
}
546+
}
547+
}
548+
else
549+
{
550+
it0 = it1;
551+
}
552+
}
553+
}

0 commit comments

Comments
 (0)