From bc3702dcdb57814da4460469722c258ca10e6327 Mon Sep 17 00:00:00 2001 From: Greg Frieger Date: Tue, 3 Mar 2009 23:07:06 +0000 Subject: - ResourceManager uses HashMap to store and access resource info. - Changes and clean-ups in resource loading code. svn-id: r39098 --- engines/sci/scicore/resource.cpp | 240 +++++++++++++-------------------- engines/sci/scicore/resource.h | 98 ++++---------- engines/sci/scicore/resource_map.cpp | 210 +++++++---------------------- engines/sci/scicore/resource_patch.cpp | 22 ++- 4 files changed, 185 insertions(+), 385 deletions(-) diff --git a/engines/sci/scicore/resource.cpp b/engines/sci/scicore/resource.cpp index e7b9fc34c2..90ee1412a5 100644 --- a/engines/sci/scicore/resource.cpp +++ b/engines/sci/scicore/resource.cpp @@ -26,6 +26,7 @@ // Resource library #include "common/util.h" +#include "common/debug.h" #include "sci/tools.h" #include "sci/sci_memory.h" @@ -88,8 +89,6 @@ const char *getResourceTypeSuffix(ResourceType restype) { return resourceTypeSuffixes[restype]; } -int resourcecmp(const void *first, const void *second); - typedef int decomp_funct(Resource *result, Common::ReadStream &stream, int sci_version); typedef void patch_sprintf_funct(char *string, Resource *res); @@ -117,39 +116,32 @@ static patch_sprintf_funct *patch_sprintfers[] = { &sci1_sprintf_patch_file_name }; - -int resourcecmp(const void *first, const void *second) { - if (((Resource *)first)->type == - ((Resource *)second)->type) - return (((Resource *)first)->number < - ((Resource *)second)->number) ? -1 : - !(((Resource *)first)->number == - ((Resource *)second)->number); - else - return (((Resource *)first)->type < - ((Resource *)second)->type) ? -1 : 1; +//-- Resource main functions -- +Resource::Resource() { + data = NULL; + number = 0; + type = kResourceTypeInvalid; + id = 0; + size = 0; + file_offset = 0; + status = SCI_STATUS_NOMALLOC; + lockers = 0; + next = prev = NULL; + source = NULL; } - -//-- Resmgr helper functions -- - -void ResourceManager::addAltSource(Resource *res, ResourceSource *source, unsigned int file_offset) { - resource_altsource_t *rsrc = (resource_altsource_t *)sci_malloc(sizeof(resource_altsource_t)); - - rsrc->next = res->alt_sources; - rsrc->source = source; - rsrc->file_offset = file_offset; - res->alt_sources = rsrc; +Resource::~Resource() { + delete[] data; } -Resource *ResourceManager::findResourceUnsorted(Resource *res, int res_nr, ResourceType type, int number) { - int i; - for (i = 0; i < res_nr; i++) - if (res[i].number == number && res[i].type == type) - return res + i; - return NULL; +void Resource::unalloc() { + delete[] data; + data = NULL; + status = SCI_STATUS_NOMALLOC; } +//-- Resmgr helper functions -- + // Resource source list management ResourceSource *ResourceManager::addExternalMap(const char *file_name) { @@ -159,7 +151,7 @@ ResourceSource *ResourceManager::addExternalMap(const char *file_name) { newsrc->next = _sources; _sources = newsrc; - newsrc->source_type = RESSOURCE_TYPE_EXTERNAL_MAP; + newsrc->source_type = kSourceExtMap; newsrc->location_name = file_name; newsrc->scanned = false; newsrc->associated_map = NULL; @@ -174,7 +166,7 @@ ResourceSource *ResourceManager::addVolume(ResourceSource *map, const char *file newsrc->next = _sources; _sources = newsrc; - newsrc->source_type = RESSOURCE_TYPE_VOLUME; + newsrc->source_type = kSourceVolume; newsrc->scanned = false; newsrc->location_name = filename; newsrc->volume_number = number; @@ -190,7 +182,7 @@ ResourceSource *ResourceManager::addPatchDir(const char *dirname) { newsrc->next = _sources; _sources = newsrc; - newsrc->source_type = RESSOURCE_TYPE_DIRECTORY; + newsrc->source_type = kSourceDirectory; newsrc->scanned = false; newsrc->location_name = dirname; @@ -201,7 +193,7 @@ ResourceSource *ResourceManager::getVolume(ResourceSource *map, int volume_nr) { ResourceSource *seeker = _sources; while (seeker) { - if (seeker->source_type == RESSOURCE_TYPE_VOLUME && seeker->associated_map == map && + if (seeker->source_type == kSourceVolume && seeker->associated_map == map && seeker->volume_number == volume_nr) return seeker; seeker = seeker->next; @@ -212,79 +204,77 @@ ResourceSource *ResourceManager::getVolume(ResourceSource *map, int volume_nr) { // Resource manager constructors and operations -void ResourceManager::loadFromPatchFile(Common::File &file, Resource *res, char *filename) { - unsigned int really_read; +bool ResourceManager::loadFromPatchFile(Resource *res) { + Common::File file; + char filename[MAXPATHLEN]; + if (!patch_sprintfers[_sciVersion]) { + error("Resource manager's SCI version (%d) has no patch file name printers", _sciVersion); + } + // TODO: use only dir specified by res->source->location_dir_name + patch_sprintfers[_sciVersion](filename, res); + if (file.open(filename) == false) { + warning("Failed to open patch file %s", filename); + res->unalloc(); + return false; + } + res->data = new byte[res->size]; - res->data = (unsigned char *)sci_malloc(res->size); - really_read = file.read(res->data, res->size); + if (res->data == NULL) { + error("Can't allocate %d bytes needed for loading %s!", res->size, filename); + } - if (really_read < res->size) { + file.seek(res->file_offset, SEEK_SET); + unsigned int really_read = file.read(res->data, res->size); + if (really_read != res->size) { error("Read %d bytes from %s but expected %d!", really_read, filename, res->size); } - res->status = SCI_STATUS_ALLOCATED; + return true; } void ResourceManager::loadResource(Resource *res, bool protect) { + // TODO: check if protect is needed at all char filename[MAXPATHLEN]; Common::File file; Resource backup; memcpy(&backup, res, sizeof(Resource)); - // First try lower-case name - if (res->source->source_type == RESSOURCE_TYPE_DIRECTORY) { - if (!patch_sprintfers[_sciVersion]) { - error("Resource manager's SCI version (%d) has no patch file name printers", _sciVersion); - } - - // Get patch file name - patch_sprintfers[_sciVersion](filename, res); - - // FIXME: Instead of using SearchMan, maybe we should only search - // a single dir specified by this RESSOURCE_TYPE_DIRECTORY ResourceSource? - } else - strcpy(filename, res->source->location_name.c_str()); + if (res->source->source_type == kSourceDirectory && loadFromPatchFile(res)) + return; + // Either loading from volume or patch loading failed + strcpy(filename, res->source->location_name.c_str()); if (!file.open(filename)) { warning("Failed to open %s", filename); - res->data = NULL; - res->status = SCI_STATUS_NOMALLOC; - res->size = 0; + res->unalloc(); return; } - file.seek(res->file_offset, SEEK_SET); - if (res->source->source_type == RESSOURCE_TYPE_DIRECTORY) - loadFromPatchFile(file, res, filename); - else if (!decompressors[_sciVersion]) { - // Check whether we support this at all + // Check whether we support this at all + if (decompressors[_sciVersion] == NULL) error("Resource manager's SCI version (%d) is invalid", _sciVersion); - } else { - int error = // Decompress from regular resource file - decompressors[_sciVersion](res, file, _sciVersion); - - if (error) { - sciprintf("Error %d occured while reading %s.%03d from resource file: %s\n", - error, getResourceTypeName(res->type), res->number, sci_error_types[error]); + // Decompress from regular resource file + int error = decompressors[_sciVersion](res, file, _sciVersion); - if (protect) - memcpy(res, &backup, sizeof(Resource)); + if (error) { + warning("Error %d occured while reading %s.%03d from resource file: %s\n", + error, getResourceTypeName(res->type), res->number, sci_error_types[error]); - res->data = NULL; - res->status = SCI_STATUS_NOMALLOC; - res->size = 0; - } + if (protect) + memcpy(res, &backup, sizeof(Resource)); + res->unalloc(); } - } Resource *ResourceManager::testResource(ResourceType type, int number) { Resource binseeker; binseeker.type = type; binseeker.number = number; - return (Resource *)bsearch(&binseeker, _resources, _resourcesNr, sizeof(Resource), resourcecmp); + if (_resMap.contains(RESOURCE_HASH(type, number))) + return _resMap.getVal(RESOURCE_HASH(type, number)); + return NULL; } int sci0_get_compression_method(Common::ReadStream &stream); @@ -304,7 +294,7 @@ int sci_test_view_type(ResourceManager *mgr) { if (!res) continue; - if (res->source->source_type == RESSOURCE_TYPE_DIRECTORY) + if (res->source->source_type == kSourceDirectory) continue; strcpy(filename, res->source->location_name.c_str()); @@ -329,7 +319,7 @@ int sci_test_view_type(ResourceManager *mgr) { if (!res) continue; - if (res->source->source_type == RESSOURCE_TYPE_DIRECTORY) + if (res->source->source_type == kSourceDirectory) continue; strcpy(filename, res->source->location_name.c_str()); @@ -373,10 +363,12 @@ int ResourceManager::addAppropriateSources() { } int ResourceManager::scanNewSources(int *detected_version, ResourceSource *source) { + if (!source) + return SCI_ERROR_NO_RESOURCE_FILES_FOUND; + int preset_version = _sciVersion; int resource_error = 0; int dummy = _sciVersion; - //Resource **concat_ptr = &(mgr->_resources[mgr->_resourcesNr - 1].next); if (detected_version == NULL) detected_version = &dummy; @@ -388,13 +380,13 @@ int ResourceManager::scanNewSources(int *detected_version, ResourceSource *sourc if (!source->scanned) { source->scanned = true; switch (source->source_type) { - case RESSOURCE_TYPE_DIRECTORY: + case kSourceDirectory: if (_sciVersion <= SCI_VERSION_01) readResourcePatchesSCI0(source); else readResourcePatchesSCI1(source); break; - case RESSOURCE_TYPE_EXTERNAL_MAP: + case kSourceExtMap: if (preset_version <= SCI_VERSION_01_VGA_ODD /* || preset_version == SCI_VERSION_AUTODETECT -- subsumed by the above line */) { resource_error = readResourceMapSCI0(source, detected_version); #if 0 @@ -429,8 +421,7 @@ int ResourceManager::scanNewSources(int *detected_version, ResourceSource *sourc if (resource_error == SCI_ERROR_NO_RESOURCE_FILES_FOUND) { // Initialize empty resource manager - _resourcesNr = 0; - _resources = 0; // FIXME: Was = (Resource*)sci_malloc(1); + _resMap.clear(); resource_error = 0; } } @@ -440,7 +431,6 @@ int ResourceManager::scanNewSources(int *detected_version, ResourceSource *sourc default: break; } - qsort(_resources, _resourcesNr, sizeof(Resource), resourcecmp); // Sort resources } return resource_error; } @@ -461,8 +451,7 @@ ResourceManager::ResourceManager(int version, int maxMemory) { _memoryLocked = 0; _memoryLRU = 0; - _resources = NULL; - _resourcesNr = 0; + _resMap.clear(); _sources = NULL; _sciVersion = version; @@ -472,56 +461,43 @@ ResourceManager::ResourceManager(int version, int maxMemory) { addAppropriateSources(); scanNewSources(&resmap_version, _sources); - if (!_resources || !_resourcesNr) { - if (_resources) { - free(_resources); - _resources = NULL; - } - sciprintf("Resmgr: Could not retrieve a resource list!\n"); - freeResourceSources(_sources); - error("FIXME: Move this code to an init() method so that we can perform error handling"); -// return NULL; - } - - qsort(_resources, _resourcesNr, sizeof(Resource), resourcecmp); // Sort resources - if (version == SCI_VERSION_AUTODETECT) switch (resmap_version) { case SCI_VERSION_0: if (testResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_MAIN_VOCAB)) { version = sci_test_view_type(this); if (version == SCI_VERSION_01_VGA) { - sciprintf("Resmgr: Detected KQ5 or similar\n"); + debug("Resmgr: Detected KQ5 or similar\n"); } else { - sciprintf("Resmgr: Detected SCI0\n"); + debug("Resmgr: Detected SCI0\n"); version = SCI_VERSION_0; } } else if (testResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_MAIN_VOCAB)) { version = sci_test_view_type(this); if (version == SCI_VERSION_01_VGA) { - sciprintf("Resmgr: Detected KQ5 or similar\n"); + debug("Resmgr: Detected KQ5 or similar\n"); } else { if (testResource(kResourceTypeVocab, 912)) { - sciprintf("Resmgr: Running KQ1 or similar, using SCI0 resource encoding\n"); + debug("Resmgr: Running KQ1 or similar, using SCI0 resource encoding\n"); version = SCI_VERSION_0; } else { version = SCI_VERSION_01; - sciprintf("Resmgr: Detected SCI01\n"); + debug("Resmgr: Detected SCI01\n"); } } } else { version = sci_test_view_type(this); if (version == SCI_VERSION_01_VGA) { - sciprintf("Resmgr: Detected KQ5 or similar\n"); + debug("Resmgr: Detected KQ5 or similar\n"); } else { - sciprintf("Resmgr: Warning: Could not find vocabulary; assuming SCI0 w/o parser\n"); + debug("Resmgr: Warning: Could not find vocabulary; assuming SCI0 w/o parser\n"); version = SCI_VERSION_0; } } break; case SCI_VERSION_01_VGA_ODD: version = resmap_version; - sciprintf("Resmgr: Detected Jones/CD or similar\n"); + debug("Resmgr: Detected Jones/CD or similar\n"); break; case SCI_VERSION_1: { Resource *res = testResource(kResourceTypeScript, 0); @@ -529,58 +505,34 @@ ResourceManager::ResourceManager(int version, int maxMemory) { _sciVersion = version = SCI_VERSION_1_EARLY; loadResource(res, true); - if (res->status == SCI_STATUS_NOMALLOC) + if (res->status == SCI_STATUS_NOMALLOC) { _sciVersion = version = SCI_VERSION_1_LATE; + debug("Resmgr: Detected SCI1 Late"); + } else + debug("Resmgr: Detected SCI1 Early"); break; } case SCI_VERSION_1_1: // No need to handle SCI 1.1 here - it was done in resource_map.cpp version = SCI_VERSION_1_1; + debug("Resmgr: Detected SCI1.1"); break; default: - sciprintf("Resmgr: Warning: While autodetecting: Couldn't determine SCI version"); + debug("Resmgr: Warning: While autodetecting: Couldn't determine SCI version"); } - if (!resource_error) { - qsort(_resources, _resourcesNr, sizeof(Resource), resourcecmp); // Sort resources - } - _sciVersion = version; } -void ResourceManager::freeAltSources(resource_altsource_t *dynressrc) { - if (dynressrc) { - freeAltSources(dynressrc->next); - free(dynressrc); - } -} - -void ResourceManager::freeResources(Resource *resources, int resourcesNr) { - int i; - - for (i = 0; i < resourcesNr; i++) { - Resource *res = resources + i; - - // FIXME: alt_sources->next may point to an invalid memory location - freeAltSources(res->alt_sources); - - if (res->status != SCI_STATUS_NOMALLOC) - free(res->data); - } - - free(resources); -} - ResourceManager::~ResourceManager() { - freeResources(_resources, _resourcesNr); + // freeing resources + Common::HashMap::iterator itr = _resMap.begin(); + while (itr != _resMap.end()) { + delete itr->_value; + itr ++; + } freeResourceSources(_sources); - _resources = NULL; -} - -void ResourceManager::unalloc(Resource *res) { - free(res->data); - res->data = NULL; - res->status = SCI_STATUS_NOMALLOC; + _resMap.empty(); } void ResourceManager::removeFromLRU(Resource *res) { @@ -657,7 +609,7 @@ void ResourceManager::freeOldResources(int last_invulnerable) { } removeFromLRU(goner); - unalloc(goner); + goner->unalloc(); #ifdef SCI_VERBOSE_RESMGR sciprintf("Resmgr-debug: LRU: Freeing %s.%03d (%d bytes)\n", getResourceTypeName(goner->type), goner->number, goner->size); #endif diff --git a/engines/sci/scicore/resource.h b/engines/sci/scicore/resource.h index 8ae8b03f4b..83015c6f63 100644 --- a/engines/sci/scicore/resource.h +++ b/engines/sci/scicore/resource.h @@ -84,17 +84,19 @@ namespace Sci { #define SCI_VERSION_1 SCI_VERSION_1_EARLY enum ResSourceType { - RESSOURCE_TYPE_DIRECTORY = 0, - RESSOURCE_TYPE_VOLUME = 2, - RESSOURCE_TYPE_EXTERNAL_MAP = 3, - RESSOURCE_TYPE_INTERNAL_MAP = 4, - RESSOURCE_TYPE_MASK = 127 + kSourceDirectory = 0, + 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) + extern const char *sci_error_types[]; extern const char *sci_version_types[]; extern const int sci_max_resource_nr[]; /* Highest possible resource numbers */ @@ -150,31 +152,28 @@ struct ResourceSource { ResourceSource *next; }; -struct resource_altsource_t { - ResourceSource *source; - unsigned int file_offset; - resource_altsource_t *next; -}; - - -/** Struct for storing resources in memory */ +/** Class for storing resources in memory */ class Resource { public: + Resource::Resource(); + 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 - unsigned char *data; - unsigned short number; +public: + byte *data; + uint16 number; ResourceType type; uint16 id; /* contains number and type */ unsigned int size; unsigned int file_offset; /* Offset in file */ - unsigned char status; + byte status; unsigned short lockers; /* Number of places where this resource was locked */ Resource *next; /* Position marker for the LRU queue */ Resource *prev; ResourceSource *source; - resource_altsource_t *alt_sources; /* SLL of alternative resource data sources */ }; @@ -257,50 +256,21 @@ public: protected: int _maxMemory; /* Config option: Maximum total byte number allocated */ - int _resourcesNr; + //int _resourcesNr; ResourceSource *_sources; - Resource *_resources; + //Resource *_resources; int _memoryLocked; // Amount of resource bytes in locked memory int _memoryLRU; // Amount of resource bytes under LRU control Resource *lru_first, *lru_last; // Pointers to the first and last LRU queue entries // LRU queue: lru_first points to the most recent entry - - /* Frees a block of resources and associated data - ** Parameters: (Resource *) resources: The resources to free - ** (int) _resourcesNr: Number of resources in the block - ** Returns : (void) - */ - void freeResources(Resource *resources, int _resourcesNr); - - /* Finds a resource matching type.number in an unsorted Resource block - ** To be used during initial resource loading, when the resource list - ** may not have been sorted yet. - ** Parameters: (Resource *) res: Pointer to the block to search in - ** (int) res_nr: Number of Resource structs allocated and defined - ** in the block pointed to by res - ** (ResourceType) type: Type of the resource to look for - ** (int) number: Number of the resource to look for - ** Returns : (Resource) The matching resource entry, or NULL if not found - */ - Resource *findResourceUnsorted(Resource *res, int res_nr, ResourceType type, int number); - - /* Adds an alternative source to a resource - ** Parameters: (Resource *) res: The resource to add to - ** (ResourceSource *) source: The source of the resource - ** (unsigned int) file_offset: Offset in the file the resource - ** is stored at - ** Returns : (void) - */ - void addAltSource(Resource *res, ResourceSource *source, unsigned int file_offset); + Common::HashMap _resMap; int addAppropriateSources(); void freeResourceSources(ResourceSource *rss); - void freeAltSources(resource_altsource_t *dynressrc); void loadResource(Resource *res, bool protect); - void loadFromPatchFile(Common::File &file, Resource *res, char *filename); + bool loadFromPatchFile(Resource *res); void freeOldResources(int last_invulnerable); - void unalloc(Resource *res); /**--- Resource map decoding functions ---*/ @@ -326,28 +296,16 @@ protected: /**--- Patch management functions ---*/ - /* Reads SCI0 patch files from a local directory - ** Parameters: (char *) path: (unused) - ** (Resource **) resources: Pointer to a pointer - ** that will be set to the - ** location of the resources - ** (in one large chunk) - ** (int *) resource_nr_p: Pointer to an int the number of resources - ** read is stored in - ** Returns : (int) 0 on success, an SCI_ERROR_* code otherwise - */ + //! Reads SCI0 patch files from a local directory + /** @paramParameters: ResourceSource *source + * @return : (int) 0 on success, an SCI_ERROR_* code otherwise + */ int readResourcePatchesSCI0(ResourceSource *source); - /* Reads SCI1 patch files from a local directory - ** Parameters: (char *) path: (unused) - ** (Resource **) resources: Pointer to a pointer - ** that will be set to the - ** location of the resources - ** (in one large chunk) - ** (int *) resource_nr_p: Pointer to an int the number of resources - ** read is stored in - ** Returns : (int) 0 on success, an SCI_ERROR_* code otherwise - */ + //! Reads SCI1 patch files from a local directory + /** @paramParameters: ResourceSource *source + * @return : (int) 0 on success, an SCI_ERROR_* code otherwise + */ int readResourcePatchesSCI1(ResourceSource *source); void process_patch(ResourceSource *source, Common::ArchiveMember &member, diff --git a/engines/sci/scicore/resource_map.cpp b/engines/sci/scicore/resource_map.cpp index cb07c97d16..e50e24b257 100644 --- a/engines/sci/scicore/resource_map.cpp +++ b/engines/sci/scicore/resource_map.cpp @@ -200,13 +200,9 @@ int ResourceManager::parseHeaderSCI1(Common::ReadStream &stream, int *types, Res int ResourceManager::readResourceMapSCI0(ResourceSource *map, int *sci_version) { int fsize; Common::File file; - Resource *resources; - int resource_nr; - int resource_index = 0; + Resource *res, res1; int resources_total_read = 0; - int next_entry; - int max_resfile_nr = 0; - + bool bAdded = false; byte buf[SCI0_RESMAP_ENTRIES_SIZE]; if (!file.open(map->location_name)) @@ -255,86 +251,43 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map, int *sci_version) return SCI_ERROR_RESMAP_NOT_FOUND; } - resource_nr = fsize / SCI0_RESMAP_ENTRIES_SIZE; - - resources = (Resource *)sci_calloc(resource_nr, sizeof(Resource)); - // Sets valid default values for most entries + int resource_nr = fsize / SCI0_RESMAP_ENTRIES_SIZE; do { int read_ok = file.read(&buf, SCI0_RESMAP_ENTRIES_SIZE); - next_entry = 1; - if (read_ok < 0) { + if (read_ok != SCI0_RESMAP_ENTRIES_SIZE) { sciprintf("Error while reading %s: ", map->location_name.c_str()); perror(""); - next_entry = 0; - } else if (read_ok != SCI0_RESMAP_ENTRIES_SIZE) { - next_entry = 0; - } else if (buf[5] == 0xff) // Most significant offset byte - next_entry = 0; - - if (next_entry) { - int fresh = 1; - int addto = resource_index; - int i; - - if (resReadEntry(map, buf, resources + resource_index, *sci_version)) { - free(resources); - return SCI_ERROR_RESMAP_NOT_FOUND; - } - - for (i = 0; i < resource_index; i++) - if (resources[resource_index].id == resources[i].id) { - addto = i; - fresh = 0; - } - - addAltSource(resources + addto, resources[resource_index].source, resources[resource_index].file_offset); - - if (fresh) - ++resource_index; - - if (++resources_total_read >= resource_nr) { - warning("After %d entries, resource.map is not terminated", resource_index); - next_entry = 0; - } - + break; } + if(buf[5] == 0xff) + break; - } while (next_entry); - - file.close(); - - if (!resource_index) { - sciprintf("resource.map was empty!\n"); - freeResources(resources, resource_nr); - return SCI_ERROR_RESMAP_NOT_FOUND; - } - - if (max_resfile_nr > 999) { - freeResources(resources, resource_nr); - return SCI_ERROR_INVALID_RESMAP_ENTRY; - } else { -#if 0 - // Check disabled, Mac SQ3 thinks it has resource.004 but doesn't need it -- CR - // Check whether the highest resfile used exists - char filename_buf[14]; - sprintf(filename_buf, "resource.%03d", max_resfile_nr); - - if (!file.open(filename_buf) { - _scir_free_resources(resources, resource_nr); - sciprintf("'%s' requested by resource.map, but not found\n", filename_buf); - return SCI_ERROR_INVALID_RESMAP_ENTRY; + if (resReadEntry(map, buf, &res1, *sci_version)) + return SCI_ERROR_RESMAP_NOT_FOUND; + uint32 resId = RESOURCE_HASH(res1.type, res1.number); + // adding a new resource + if (_resMap.contains(resId) == false) { + res = new Resource; + res->id = res1.id; + res->file_offset = res1.file_offset; + res->number = res1.number; + res->type = res1.type; + res->source = res1.source; + _resMap.setVal(resId, res); + bAdded = true; } -#endif - } - - if (resource_index < resource_nr) - resources = (Resource *)sci_realloc(resources, sizeof(Resource) * resource_index); - _resources = resources; - _resourcesNr = resource_index; + if (++resources_total_read >= resource_nr) { + warning("After %d entries, resource.map is not terminated", resources_total_read); + break; + } + } while (!file.eos()); + if (!bAdded) + return SCI_ERROR_RESMAP_NOT_FOUND; + file.close(); return 0; } @@ -374,7 +327,6 @@ int ResourceManager::isSCI10or11(int *types) { int ResourceManager::readResourceMapSCI1(ResourceSource *map, ResourceSource *vol, int *sci_version) { int fsize; Common::File file; - Resource *resources, *resource_start; int resource_nr; int resource_index = 0; int ofs, header_size; @@ -412,10 +364,6 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map, ResourceSource *vo } resource_nr = (fsize - types[0]) / entrysize; - resource_start = resources = (Resource*)sci_realloc(_resources, (_resourcesNr + resource_nr) * sizeof(Resource)); - memset(resource_start + sizeof(Resource) * _resourcesNr, 0, resource_nr * sizeof(Resource)); - resources += _resourcesNr; - i = 0; while (types[i] == 0) i++; @@ -424,94 +372,38 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map, ResourceSource *vo file.seek(ofs, SEEK_SET); for (i = 0; i < resource_nr; i++) { - int read_ok = file.read(&buf, entrysize); - int j; Resource *res; - int addto = resource_index; - int fresh = 1; - - if (read_ok < entrysize) { -#if 0 - if (!file.eof()) { - sciprintf("Error while reading %s: ", map->location_name.c_str()); - perror(""); - } else - read_ok = 1; - break; -#endif + int number; + ResourceType type; + uint32 resId; + + file.read(&buf, entrysize); + type = resTypeSCI1(ofs, types, lastrt); + number = SCI1_RESFILE_GET_NUMBER(buf); + resId = RESOURCE_HASH(type, number); + // adding new resource only if it does not exist + if (_resMap.contains(resId) == false) { + res = new Resource; + _resMap.setVal(resId, res); + res->type = type; + res->number = number; + res->id = res->number | (res->type << 16); + // only 1st source would be used when loading resource + if (entry_size_selector < SCI_VERSION_1_1) { + res->source = getVolume(map, SCI1_RESFILE_GET_FILE(buf)); + res->file_offset = SCI1_RESFILE_GET_OFFSET(buf); + } else { + res->source = vol; + res->file_offset = SCI11_RESFILE_GET_OFFSET(buf); + }; } - res = &(resources[resource_index]); - res->type = resTypeSCI1(ofs, types, lastrt); - res->number = SCI1_RESFILE_GET_NUMBER(buf); - res->status = SCI_STATUS_NOMALLOC; - - if (entry_size_selector < SCI_VERSION_1_1) { - res->source = getVolume(map, SCI1_RESFILE_GET_FILE(buf)); - res->file_offset = SCI1_RESFILE_GET_OFFSET(buf); - } else { - res->source = vol; - res->file_offset = SCI11_RESFILE_GET_OFFSET(buf); - }; - - res->id = res->number | (res->type << 16); - - for (j = 0; i < resource_index; i++) - if (resources[resource_index].id == resources[i].id) { - addto = i; - fresh = 0; - } - -#if 0 - fprintf(stderr, "Read [%04x] %6d.%s\tresource.%03d, %08x ==> %d\n", - res->id, res->number, - sci_resource_type_suffixes[res->type], - res->file, res->file_offset, addto); -#endif - - addAltSource(resources + addto, resources[resource_index].source, resources[resource_index].file_offset); - - if (fresh) - ++resource_index; - ofs += entrysize; } free(types); - _resources = resource_start; - _resourcesNr += resource_index; - return 0; - -} - -#ifdef TEST_RESOURCE_MAP -int main(int argc, char **argv) { - int resource_nr; - Resource *resources; - int notok = sci0_read_resource_map(".", &resources, &resource_nr); - - if (notok) { - fprintf(stderr, "Failed: Error code %d\n", notok); - return 1; - } - - if (resources) { - int i; - - printf("Found %d resources:\n", resource_nr); - - for (i = 0; i < resource_nr; i++) { - Resource *res = resources + i; - - printf("#%04d:\tRESOURCE.%03d:%8d\t%s.%03d\n", i, res->file, res->file_offset, - sci_resource_types[res->type], res->number); - } - } else - fprintf(stderr, "Found no resources.\n"); - return 0; } -#endif } // End of namespace Sci diff --git a/engines/sci/scicore/resource_patch.cpp b/engines/sci/scicore/resource_patch.cpp index 2cbeb2b52c..695f33fb01 100644 --- a/engines/sci/scicore/resource_patch.cpp +++ b/engines/sci/scicore/resource_patch.cpp @@ -51,14 +51,15 @@ void ResourceManager::process_patch(ResourceSource *source, if (!file.open(member.createReadStream(), member.getName())) perror("""__FILE__"": (""__LINE__""): failed to open"); else { - uint8 filehdr[2]; - Resource *newrsc = findResourceUnsorted(_resources, _resourcesNr, restype, resnumber); + byte filehdr[2]; int fsize = file.size(); if (fsize < 3) { printf("File too small\n"); return; } - + + uint32 resId = RESOURCE_HASH(restype, resnumber); + Resource *newrsc; int patch_data_offset; file.read(filehdr, 2); @@ -74,23 +75,20 @@ void ResourceManager::process_patch(ResourceSource *source, fsize -= patch_data_offset; // Prepare destination, if neccessary - if (!newrsc) { - // Completely new resource! - _resourcesNr++; - _resources = (Resource *)sci_realloc(_resources, _resourcesNr * sizeof(Resource)); - newrsc = (_resources - 1) + _resourcesNr; - newrsc->alt_sources = NULL; - } + if (_resMap.contains(resId) == false) { + newrsc = new Resource; + _resMap.setVal(resId, newrsc); + } else + newrsc = _resMap.getVal(resId); // Overwrite everything, because we're patching newrsc->size = fsize - 2; - newrsc->id = restype << 11 | resnumber; + newrsc->id = resId; newrsc->number = resnumber; newrsc->status = SCI_STATUS_NOMALLOC; newrsc->type = restype; newrsc->source = source; newrsc->file_offset = 2 + patch_data_offset; - addAltSource(newrsc, source, 2); printf("OK\n"); } } -- cgit v1.2.3