/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program 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 2 * of the License, or (at your option) any later version. * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * $URL$ * $Id$ * */ #ifndef SCI_SCICORE_RESOURCE_H #define SCI_SCICORE_RESOURCE_H #include "common/str.h" #include "common/file.h" #include "common/archive.h" #include "sci/engine/vm.h" // for Object #include "sci/scicore/decompressor.h" namespace Common { class ReadStream; } namespace Sci { /** The maximum allowed size for a compressed or decompressed resource */ #define SCI_MAX_RESOURCE_SIZE 0x0400000 /*** RESOURCE STATUS TYPES ***/ enum ResourceStatus { kResStatusNoMalloc = 0, kResStatusAllocated, kResStatusEnqueued, /* In the LRU queue */ kResStatusLocked /* Allocated and in use */ }; /*** INITIALIZATION RESULT TYPES ***/ #define SCI_ERROR_IO_ERROR 1 #define SCI_ERROR_EMPTY_OBJECT 2 #define SCI_ERROR_INVALID_RESMAP_ENTRY 3 /* Invalid resource.map entry */ #define SCI_ERROR_RESMAP_NOT_FOUND 4 #define SCI_ERROR_NO_RESOURCE_FILES_FOUND 5 /* No resource at all was found */ #define SCI_ERROR_UNKNOWN_COMPRESSION 6 #define SCI_ERROR_DECOMPRESSION_OVERFLOW 7 /* decompression failed: Buffer overflow (wrong SCI version?) */ #define SCI_ERROR_DECOMPRESSION_INSANE 8 /* sanity checks failed during decompression */ #define SCI_ERROR_RESOURCE_TOO_BIG 9 /* Resource size exceeds SCI_MAX_RESOURCE_SIZE */ #define SCI_ERROR_UNSUPPORTED_VERSION 10 #define SCI_ERROR_INVALID_SCRIPT_VERSION 11 #define SCI_ERROR_CRITICAL SCI_ERROR_NO_RESOURCE_FILES_FOUND /* the first critical error number */ /*** SCI VERSION NUMBERS ***/ #define SCI_VERSION_AUTODETECT 0 #define SCI_VERSION_0 1 #define SCI_VERSION_01 2 #define SCI_VERSION_01_VGA 3 #define SCI_VERSION_01_VGA_ODD 4 #define SCI_VERSION_1_EARLY 5 #define SCI_VERSION_1_LATE 6 #define SCI_VERSION_1_1 7 #ifdef ENABLE_SCI32 #define SCI_VERSION_32 8 #endif #define SCI_VERSION_LAST SCI_VERSION_1_LATE /* The last supported SCI version */ #define SCI_VERSION_1 SCI_VERSION_1_EARLY #define MAX_OPENED_VOLUMES 5 // Max number of simultaneously opened volumes enum ResSourceType { kSourceDirectory = 0, kSourcePatch = 1, kSourceVolume = 2, kSourceExtMap = 3, kSourceIntMap = 4, kSourceMask = 127 }; #define RESSOURCE_ADDRESSING_BASIC 0 #define RESSOURCE_ADDRESSING_EXTENDED 128 #define RESSOURCE_ADDRESSING_MASK 128 #define RESOURCE_HASH(type, number) (uint32)((type<<16) | number) #define SCI0_RESMAP_ENTRIES_SIZE 6 #define SCI1_RESMAP_ENTRIES_SIZE 6 #define SCI11_RESMAP_ENTRIES_SIZE 5 extern const char *sci_error_types[]; extern const char *sci_version_types[]; extern const int sci_max_resource_nr[]; /* Highest possible resource numbers */ enum ResourceType { kResourceTypeView = 0, kResourceTypePic, kResourceTypeScript, kResourceTypeText, kResourceTypeSound, kResourceTypeMemory, kResourceTypeVocab, kResourceTypeFont, kResourceTypeCursor, kResourceTypePatch, kResourceTypeBitmap, kResourceTypePalette, kResourceTypeCdAudio, kResourceTypeAudio, kResourceTypeSync, kResourceTypeMessage, kResourceTypeMap, kResourceTypeHeap, kResourceTypeInvalid }; const char *getResourceTypeName(ResourceType restype); // Suffixes for SCI1 patch files const char *getResourceTypeSuffix(ResourceType restype); #define sci0_last_resource kResourceTypePatch #define sci1_last_resource kResourceTypeHeap /* Used for autodetection */ // resource type for SCI1 resource.map file struct resource_index_t { uint16 wOffset; uint16 wSize; }; struct ResourceSource { ResSourceType source_type; bool scanned; Common::String location_name; // FIXME: Replace by FSNode ? int volume_number; ResourceSource *associated_map; ResourceSource *next; }; /** Class for storing resources in memory */ class Resource { public: Resource(); ~Resource(); void unalloc(); // NOTE : Currently all member data has the same name and public visibility // to let the rest of the engine compile without changes public: byte *data; uint16 number; ResourceType type; uint32 id; // contains number and type. unsigned int size; unsigned int file_offset; /* Offset in file */ ResourceStatus status; unsigned short lockers; /* Number of places where this resource was locked */ ResourceSource *source; }; class ResourceManager { public: int _sciVersion; /* SCI resource version to use */ int _mapVersion; // RESOURCE.MAP version int _volVersion; // RESOURCE.0xx version /** * Creates a new SCI resource manager. * @param version The SCI version to look for; use SCI_VERSION_AUTODETECT * in the default case. * @param maxMemory Maximum number of bytes to allow allocated for resources * * @note maxMemory will not be interpreted as a hard limit, only as a restriction * for resources which are not explicitly locked. However, a warning will be * issued whenever this limit is exceeded. */ ResourceManager(int version, int maxMemory); ~ResourceManager(); //! Looks up a resource's data /** @param type: The resource type to look for * @param number: The resource number to search * @param lock: non-zero iff the resource should be locked * @return (Resource *): The resource, or NULL if it doesn't exist * @note Locked resources are guaranteed not to have their contents freed until * they are unlocked explicitly (by unlockResource). */ Resource *findResource(ResourceType type, int number, int lock); /* Unlocks a previously locked resource ** (Resource *) res: The resource to free ** (int) number: Number of the resource to check (ditto) ** (ResourceType) type: Type of the resource to check (for error checking) ** Returns : (void) */ void unlockResource(Resource *res, int restype, ResourceType resnum); /* Tests whether a resource exists ** (ResourceType) type: Type of the resource to check ** (int) number: Number of the resource to check ** Returns : (Resource *) non-NULL if the resource exists, NULL otherwise ** This function may often be much faster than finding the resource ** and should be preferred for simple tests. ** The resource object returned is, indeed, the resource in question, but ** it should be used with care, as it may be unallocated. ** Use scir_find_resource() if you want to use the data contained in the resource. */ Resource *testResource(ResourceType type, int number); protected: int _maxMemory; // Config option: Maximum total byte number allocated ResourceSource *_sources; int _memoryLocked; // Amount of resource bytes in locked memory int _memoryLRU; // Amount of resource bytes under LRU control Common::List _LRU; // Last Resource Used list Common::HashMap _resMap; Common::List _volumeFiles; // list of opened volume files /* Add a path to the resource manager's list of sources. ** Returns: A pointer to the added source structure, or NULL if an error occurred. */ ResourceSource *addPatchDir(const char *path); ResourceSource *getVolume(ResourceSource *map, int volume_nr); //! Add a volume to the resource manager's list of sources. /** @param map The map associated with this volume * @param filename The name of the volume to add * @param extended_addressing 1 if this volume uses extended addressing, * 0 otherwise. * @return A pointer to the added source structure, or NULL if an error occurred. */ ResourceSource *addVolume(ResourceSource *map, const char *filename, int number, int extended_addressing); //! Add an external (i.e. separate file) map resource to the resource manager's list of sources. /** @param file_name The name of the volume to add * @return A pointer to the added source structure, or NULL if an error occurred. */ ResourceSource *addExternalMap(const char *file_name); //! Scans newly registered resource sources for resources, earliest addition first. /** @param detected_version: Pointer to the detected version number, * used during startup. May be NULL. * @return One of SCI_ERROR_*. */ int scanNewSources(ResourceSource *source); int addAppropriateSources(); void freeResourceSources(ResourceSource *rss); Common::File *getVolumeFile(const char *filename); void loadResource(Resource *res); bool loadFromPatchFile(Resource *res); void freeOldResources(int last_invulnerable); int decompress(Resource *res, Common::File *file); int readResourceInfo(Resource *res, Common::File *file, uint32&szPacked, ResourceCompression &compression); /**--- Resource map decoding functions ---*/ int detectMapVersion(); int detectVolVersion(); /* Reads the SCI0 resource.map file from a local directory ** Returns : (int) 0 on success, an SCI_ERROR_* code otherwise */ int readResourceMapSCI0(ResourceSource *map); /* Reads the SCI1 resource.map file from a local directory ** Returns : (int) 0 on success, an SCI_ERROR_* code otherwise */ int readResourceMapSCI1(ResourceSource *map); /**--- Patch management functions ---*/ //! Reads patch files from a local directory /** @paramParameters: ResourceSource *source */ void readResourcePatches(ResourceSource *source); void processPatch(ResourceSource *source, ResourceType restype, int resnumber); void printLRU(); void addToLRU(Resource *res); void removeFromLRU(Resource *res); }; class ResourceSync : public Resource { public: ResourceSync() {} ~ResourceSync() {} void startSync(EngineState *s, reg_t obj); void nextSync(EngineState *s, reg_t obj); void stopSync(); protected: uint16 *_ptr; int16 _syncTime, _syncCue; //bool _syncStarted; // not used }; } // End of namespace Sci #endif // SCI_SCICORE_RESOURCE_H