//----------------------------------------------------------------------------- // 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 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 inline void Resource::unlock() { if (obj) { ResourceManager->unlock( obj ); obj=NULL; } } template inline void Resource::purge() { if (obj) { ResourceManager->unlock( obj ); if (obj->lockCount == 0) ResourceManager->purge(obj); obj = NULL; } } template inline void Resource::_lock() { if (obj) obj->lockCount++; } template inline void Resource::_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 &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_