2024-03-20 18:08:17 -06:00

328 lines
9.6 KiB
C++

//-----------------------------------------------------------------------------
// Torque Game Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _RESMANAGER_H_
#define _RESMANAGER_H_
#ifndef _PLATFORM_H_
#include "platform/platform.h"
#endif
#ifndef _TVECTOR_H_
#include "core/tVector.h"
#endif
#ifndef _STRINGTABLE_H_
#include "core/stringTable.h"
#endif
#ifndef _FILESTREAM_H_
#include "core/fileStream.h"
#endif
#ifndef _ZIPSUBSTREAM_H_
#include "core/zipSubStream.h"
#endif
#ifndef _ZIPAGGREGATE_H_
#include "core/zipAggregate.h"
#endif
#ifndef _ZIPHEADERS_H_
#include "core/zipHeaders.h"
#endif
#ifndef _CRC_H_
#include "core/crc.h"
#endif
#define RES_DEFAULT_TIMEOUT (5*60*1000) //5-minutes
class Stream;
class FileStream;
class ZipSubRStream;
class ResManager;
class FindMatch;
extern ResManager *ResourceManager;
//------------------------------------------------------------------------------
// Basic resource manager behavior
// -set the mod path
// ResManager scans directory tree under listed base directories
// Any .rpk (.zip) file in the root directory of a mod is added (scanned)
// for resources
// Any files currently in the resource manager become memory resources
// They can be "reattached" to the first file that matches the file name
//
//------------------------------------------------------------------------------
// all classes which wish to be handled by the resource manager
// need to be
// 1) derrived from ResourceInstance
// 2) register a creation function and file extension with the manager
class ResourceInstance
{
private:
public:
virtual ~ResourceInstance() {}
};
typedef ResourceInstance* (*RESOURCE_CREATE_FN)(Stream &stream);
//------------------------------------------------------------------------------
#define InvalidCRC 0xFFFFFFFF
class ResourceObject
{
friend class ResDictionary;
friend class ResManager;
ResourceObject *prev, *next; // timeout list
ResourceObject *nextEntry; // objects are inserted by id or name
ResourceObject *nextResource; // in linked list of all resources
ResourceObject *prevResource;
public:
enum
{
VolumeBlock = 1 << 0,
File = 1 << 1,
Added = 1 << 2,
};
S32 flags;
StringTableEntry path; // resource path
StringTableEntry name; // resource name
StringTableEntry zipPath; // path/name of file of volume if in Zip Volume
StringTableEntry zipName;
S32 fileOffset; // offset on disk in fileName file of resource
S32 fileSize; // size on disk of resource block
S32 compressedFileSize; // Actual size of resource data.
ResourceInstance *mInstance; // ptr ot actual object instance
S32 lockCount;
U32 crc;
ResourceObject();
~ResourceObject() { unlink(); }
void destruct();
ResourceObject* getNext() const { return next; }
void unlink();
void linkAfter(ResourceObject* res);
void getFileTimes(FileTime *createTime, FileTime *modifyTime);
};
inline void ResourceObject::unlink()
{
if (next)
next->prev = prev;
if (prev)
prev->next = next;
next = prev = 0;
}
inline void ResourceObject::linkAfter(ResourceObject* res)
{
unlink();
prev = res;
if ((next = res->next) != 0)
next->prev = this;
res->next = this;
}
//------------------------------------------------------------------------------
template <class T> class Resource
{
private:
ResourceObject *obj;
// ***WARNING***
// Using a faster lock that bypasses the resource manger.
// void _lock() { if (obj) obj->rm->lockResource( obj ); }
void _lock();
void _unlock();
public:
// If assigned a ResourceObject, it's assumed to already have
// been locked, lock count is incremented only for copies or
// assignment from another Resource.
Resource() : obj(NULL) { ; }
Resource(ResourceObject *p) : obj(p) { ; }
Resource(const Resource &res) : obj(res.obj) { _lock(); }
~Resource() { unlock(); }
const char *getFilePath() const { return (obj ? obj->path : NULL); }
const char *getFileName() const { return (obj ? obj->name : NULL); }
Resource& operator= (ResourceObject *p) { _unlock(); obj = p; return *this; }
Resource& operator= (const Resource &r) { _unlock(); obj = r.obj; _lock(); return *this; }
U32 getCRC() { return (obj ? obj->crc : 0); }
bool isNull() const { return ((obj == NULL) || (obj->mInstance == NULL)); }
operator bool() const { return ((obj != NULL) && (obj->mInstance != NULL)); }
T* operator->() { return (T*)obj->mInstance; }
T& operator*() { return *((T*)obj->mInstance); }
operator T*() { return (obj) ? (T*)obj->mInstance : (T*)NULL; }
const T* operator->() const { return (const T*)obj->mInstance; }
const T& operator*() const { return *((const T*)obj->mInstance); }
operator const T*() const { return (obj) ? (const T*)obj->mInstance : (const T*)NULL; }
void unlock();
void purge();
};
template<class T> inline void Resource<T>::unlock()
{
if (obj) {
ResourceManager->unlock( obj );
obj=NULL;
}
}
template<class T> inline void Resource<T>::purge()
{
if (obj) {
ResourceManager->unlock( obj );
if (obj->lockCount == 0)
ResourceManager->purge(obj);
obj = NULL;
}
}
template <class T> inline void Resource<T>::_lock()
{
if (obj)
obj->lockCount++;
}
template <class T> inline void Resource<T>::_unlock()
{
if (obj)
ResourceManager->unlock( obj );
}
#define INVALID_ID ((U32)(~0))
//----------------------------------------------------------------------------
// Map of Names and Object IDs to objects
// Provides fast lookup for name->object, id->object and
// for fast removal of an object given object*
//
class ResDictionary
{
enum { DefaultTableSize = 1029 };
ResourceObject **hashTable;
S32 entryCount;
S32 hashTableSize;
DataChunker memPool;
S32 hash(StringTableEntry path, StringTableEntry name);
S32 hash(ResourceObject *obj) { return hash(obj->path, obj->name); }
public:
ResDictionary();
~ResDictionary();
void insert(ResourceObject *obj, StringTableEntry path, StringTableEntry file);
ResourceObject* find(StringTableEntry path, StringTableEntry file);
ResourceObject* find(StringTableEntry path, StringTableEntry file, StringTableEntry filePath, StringTableEntry fileName);
ResourceObject* find(StringTableEntry path, StringTableEntry file, U32 flags);
void pushBehind(ResourceObject *obj, S32 mask);
void remove(ResourceObject *obj);
};
//------------------------------------------------------------------------------
class ResManager
{
private:
char writeablePath[1024];
char primaryPath[1024];
char* pathList;
ResourceObject timeoutList;
ResourceObject resourceList;
ResDictionary dictionary;
bool echoFileNames;
bool scanZip(ResourceObject *zipObject);
ResourceObject* createResource(StringTableEntry path, StringTableEntry file);
ResourceObject* createZipResource(StringTableEntry path, StringTableEntry file, StringTableEntry zipPath, StringTableEntry zipFle);
void searchPath(const char *pathStart);
struct RegisteredExtension
{
StringTableEntry mExtension;
RESOURCE_CREATE_FN mCreateFn;
RegisteredExtension *next;
};
RegisteredExtension *registeredList;
ResManager();
public:
//Added for displaying dts files
ResourceObject* createResource(const char *);
RESOURCE_CREATE_FN getCreateFunction( const char *name );
~ResManager();
static void create();
static void destroy();
void setFileNameEcho(bool on);
void setModPaths(U32 numPaths, const char **dirs);
const char* getModPaths();
void registerExtension(const char *extension, RESOURCE_CREATE_FN create_fn);
S32 getSize(const char* filename);
const char* getFullPath(const char * filename, char * path, U32 pathLen);
const char* getModPathOf(const char* fileName);
const char* getPathOf(const char * filename);
const char* getBasePath();
ResourceObject* load(const char * fileName, bool computeCRC = false);
Stream* openStream(const char * fileName);
Stream* openStream(ResourceObject *object);
void closeStream(Stream *stream);
void unlock( ResourceObject* );
bool add(const char* name, ResourceInstance *addInstance, bool extraLock = false);
ResourceObject* find(const char * fileName);
ResourceInstance* loadInstance(const char *fileName, bool computeCRC = false);
ResourceInstance* loadInstance(ResourceObject *object, bool computeCRC = false);
ResourceObject* find(const char * fileName, U32 flags);
ResourceObject* findMatch(const char *expression, const char **fn, ResourceObject *start = NULL);
void purge();
void purge( ResourceObject *obj );
void freeResource(ResourceObject *resObject);
void serialize(VectorPtr<const char *> &filenames);
S32 findMatches( FindMatch *pFM );
bool findFile( const char *name );
bool getCrc(const char * fileName, U32 & crcVal, const U32 crcInitialVal = INITIAL_CRC_VALUE );
void setWriteablePath(const char *path);
bool isValidWriteFileName(const char *fn);
bool openFileForWrite(FileStream &fs, const char *fileName, U32 accessMode = 1);
#ifdef DEBUG
void dumpLoadedResources();
#endif
};
#endif //_RESMANAGER_H_