From fa53c0cf8350a873a3278c5debaee1562f51e15b Mon Sep 17 00:00:00 2001 From: johndoe123 Date: Sun, 14 Oct 2012 09:37:44 +0000 Subject: NEVERHOOD: Work on the resource system: - Remove unused stuff - Shuffle some stuff around --- engines/neverhood/blbarchive.cpp | 54 +++++++++++++------- engines/neverhood/blbarchive.h | 5 +- engines/neverhood/navigationscene.cpp | 4 ++ engines/neverhood/neverhood.cpp | 10 ++-- engines/neverhood/resourceman.cpp | 93 ++++++++++++----------------------- engines/neverhood/resourceman.h | 45 +++++++++++------ 6 files changed, 111 insertions(+), 100 deletions(-) diff --git a/engines/neverhood/blbarchive.cpp b/engines/neverhood/blbarchive.cpp index cb422a10e6..5551ff07f1 100644 --- a/engines/neverhood/blbarchive.cpp +++ b/engines/neverhood/blbarchive.cpp @@ -56,7 +56,8 @@ BlbArchive::~BlbArchive() { } void BlbArchive::open(const Common::String &filename) { - BlbHeader header; + BlbHeader header; + uint16 *extDataOffsets; _entries.clear(); @@ -72,7 +73,7 @@ void BlbArchive::open(const Common::String &filename) { if (header.id1 != 0x2004940 || header.id2 != 7 || header.fileSize != _fd.size()) error("BlbArchive::open() %s seems to be corrupt", filename.c_str()); - debug(2, "fileCount = %d", header.fileCount); + debug(2, "%s: fileCount = %d", filename.c_str(), header.fileCount); _entries.reserve(header.fileCount); @@ -83,63 +84,80 @@ void BlbArchive::open(const Common::String &filename) { _entries.push_back(entry); } + extDataOffsets = new uint16[header.fileCount]; + // Load file records for (uint i = 0; i < header.fileCount; i++) { BlbArchiveEntry &entry = _entries[i]; entry.type = _fd.readByte(); entry.comprType = _fd.readByte(); - entry.extDataOfs = _fd.readUint16LE(); + //entry.extDataOfs = _fd.readUint16LE(); + entry.extData = NULL; + extDataOffsets[i] = _fd.readUint16LE(); entry.timeStamp = _fd.readUint32LE(); entry.offset = _fd.readUint32LE(); entry.diskSize = _fd.readUint32LE(); entry.size = _fd.readUint32LE(); debug(2, "%08X: %03d, %02X, %04X, %08X, %08X, %08X, %08X", - entry.fileHash, entry.type, entry.comprType, entry.extDataOfs, entry.timeStamp, + entry.fileHash, entry.type, entry.comprType, extDataOffsets[i], entry.timeStamp, entry.offset, entry.diskSize, entry.size); } - + // Load ext data if (header.extDataSize > 0) { _extData = new byte[header.extDataSize]; _fd.read(_extData, header.extDataSize); + for (uint i = 0; i < header.fileCount; i++) + _entries[i].extData = extDataOffsets[i] > 0 ? _extData + extDataOffsets[i] - 1 : NULL; } + delete[] extDataOffsets; + } void BlbArchive::load(uint index, byte *buffer, uint32 size) { + load(&_entries[index], buffer, size); +} + +void BlbArchive::load(BlbArchiveEntry *entry, byte *buffer, uint32 size) { Common::StackLock lock(_mutex); - BlbArchiveEntry &entry = _entries[index]; + _fd.seek(entry->offset); - _fd.seek(entry.offset); - - switch (entry.comprType) { + switch (entry->comprType) { case 1: // Uncompressed if (size == 0) - size = entry.diskSize; + size = entry->diskSize; _fd.read(buffer, size); break; case 3: // DCL-compressed - if (!Common::decompressDCL(&_fd, buffer, entry.diskSize, entry.size)) { - debug("decompressDCL(diskSize: %d; size: %d)", entry.diskSize, entry.size); - debug("-> fileHash: %08X; type: %d; offset: %08X; endOffset: %08X", entry.fileHash, entry.type, entry.offset, entry.offset + entry.diskSize); + if (!Common::decompressDCL(&_fd, buffer, entry->diskSize, entry->size)) { + debug("decompressDCL(diskSize: %d; size: %d)", entry->diskSize, entry->size); + debug("-> fileHash: %08X; type: %d; offset: %08X; endOffset: %08X", entry->fileHash, entry->type, entry->offset, entry->offset + entry->diskSize); debug("-> fd.pos() = %08X", _fd.pos()); } break; default: - error("BlbArchive::load() Unknown compression type %d", entry.comprType); + error("BlbArchive::load() Unknown compression type %d", entry->comprType); } } byte *BlbArchive::getEntryExtData(uint index) { - BlbArchiveEntry &entry = _entries[index]; - return (_extData && entry.extDataOfs != 0) ? &_extData[entry.extDataOfs - 1] : NULL; + return getEntryExtData(&_entries[index]); +} + +byte *BlbArchive::getEntryExtData(BlbArchiveEntry *entry) { + //return (_extData && entry->extDataOfs != 0) ? &_extData[entry->extDataOfs - 1] : NULL; + return entry->extData; } Common::SeekableReadStream *BlbArchive::createStream(uint index) { - const BlbArchiveEntry &entry = _entries[index]; - return new SafeMutexedSeekableSubReadStream(&_fd, entry.offset, entry.offset + entry.diskSize, + return createStream(&_entries[index]); +} + +Common::SeekableReadStream *BlbArchive::createStream(BlbArchiveEntry *entry) { + return new SafeMutexedSeekableSubReadStream(&_fd, entry->offset, entry->offset + entry->diskSize, DisposeAfterUse::NO,_mutex); } diff --git a/engines/neverhood/blbarchive.h b/engines/neverhood/blbarchive.h index cd2fd117b7..620b12b8ac 100644 --- a/engines/neverhood/blbarchive.h +++ b/engines/neverhood/blbarchive.h @@ -44,7 +44,7 @@ struct BlbArchiveEntry { uint32 fileHash; byte type; byte comprType; - uint16 extDataOfs; + byte *extData; uint32 timeStamp; uint32 offset; uint32 diskSize; @@ -57,11 +57,14 @@ public: ~BlbArchive(); void open(const Common::String &filename); void load(uint index, byte *buffer, uint32 size); + void load(BlbArchiveEntry *entry, byte *buffer, uint32 size); byte *getEntryExtData(uint index); + byte *getEntryExtData(BlbArchiveEntry *entry); uint32 getSize(uint index) { return _entries[index].size; } BlbArchiveEntry *getEntry(uint index) { return &_entries[index]; } uint getCount() { return _entries.size(); } Common::SeekableReadStream *createStream(uint index); + Common::SeekableReadStream *createStream(BlbArchiveEntry *entry); private: Common::File _fd; Common::Mutex _mutex; diff --git a/engines/neverhood/navigationscene.cpp b/engines/neverhood/navigationscene.cpp index 5dc80c9322..bf3de5d812 100644 --- a/engines/neverhood/navigationscene.cpp +++ b/engines/neverhood/navigationscene.cpp @@ -80,6 +80,10 @@ void NavigationScene::update() { _vm->_screen->clear(); _vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder()); _smackerDone = false; + /* + if (!_interactive) + _smackerDone = true; + */ _smackerFileHash = 0; } else if (_smackerDone) { if (_leaveSceneAfter) { diff --git a/engines/neverhood/neverhood.cpp b/engines/neverhood/neverhood.cpp index cfeaf927d3..72fa3601ed 100644 --- a/engines/neverhood/neverhood.cpp +++ b/engines/neverhood/neverhood.cpp @@ -238,11 +238,11 @@ void NeverhoodEngine::dumpAllResources() { for (uint i = 0; i < entriesCount; i++) { const ResourceFileEntry &entry = _res->getEntry(i); - int type = _res->getResourceTypeByHash(entry.fileHash); - debug("hash: %08X; type: %d", entry.fileHash, type); + int type = _res->getResourceTypeByHash(entry.archiveEntry->fileHash); + debug("hash: %08X; type: %d", entry.archiveEntry->fileHash, type); if (type == 4) { AnimResource anim(this); - anim.load(entry.fileHash); + anim.load(entry.archiveEntry->fileHash); for (uint frameIndex = 0; frameIndex < anim.getFrameCount(); frameIndex++) { const AnimFrameInfo &frameInfo = anim.getFrameInfo(frameIndex); int16 width = (frameInfo.rect.width + 3) & 0xFFFC; @@ -251,8 +251,8 @@ void NeverhoodEngine::dumpAllResources() { anim.draw(frameIndex, pixels, width, false, false); Common::String filename = frameInfo.frameHash != 0 - ? Common::String::format("%08X_%03d_%08X.tga", entry.fileHash, frameIndex, frameInfo.frameHash) - : Common::String::format("%08X_%03d.tga", entry.fileHash, frameIndex); + ? Common::String::format("%08X_%03d_%08X.tga", entry.archiveEntry->fileHash, frameIndex, frameInfo.frameHash) + : Common::String::format("%08X_%03d.tga", entry.archiveEntry->fileHash, frameIndex); writeTga(filename.c_str(), pixels, vgaPalette, width, frameInfo.rect.height); delete[] pixels; } diff --git a/engines/neverhood/resourceman.cpp b/engines/neverhood/resourceman.cpp index 28cef366e1..eb6aa01533 100644 --- a/engines/neverhood/resourceman.cpp +++ b/engines/neverhood/resourceman.cpp @@ -32,49 +32,40 @@ ResourceMan::~ResourceMan() { void ResourceMan::addArchive(const Common::String &filename) { BlbArchive *archive = new BlbArchive(); - uint archiveIndex = _archives.size(); archive->open(filename); _archives.push_back(archive); debug(3, "ResourceMan::addArchive(%s) %d files", filename.c_str(), archive->getCount()); - _entries.reserve(_entries.size() + archive->getCount()); for (uint archiveEntryIndex = 0; archiveEntryIndex < archive->getCount(); archiveEntryIndex++) { BlbArchiveEntry *archiveEntry = archive->getEntry(archiveEntryIndex); ResourceFileEntry *entry = findEntrySimple(archiveEntry->fileHash); if (entry) { - if (archiveEntry->timeStamp > _archives[entry->archiveIndex]->getEntry(entry->entryIndex)->timeStamp) { - entry->archiveIndex = archiveIndex; - entry->entryIndex = archiveEntryIndex; + if (archiveEntry->timeStamp > entry->archiveEntry->timeStamp) { + entry->archive = archive; + entry->archiveEntry = archiveEntry; } } else { ResourceFileEntry newEntry; - newEntry.fileHash = archiveEntry->fileHash; newEntry.resourceHandle = -1; - newEntry.archiveIndex = archiveIndex; - newEntry.entryIndex = archiveEntryIndex; - _entries.push_back(newEntry); + newEntry.archive = archive; + newEntry.archiveEntry = archiveEntry; + _entries[archiveEntry->fileHash] = newEntry; } } + debug("_entries.size() = %d", _entries.size()); } ResourceFileEntry *ResourceMan::findEntrySimple(uint32 fileHash) { - for (uint i = 0; i < _entries.size(); i++) { - if (_entries[i].fileHash == fileHash) - return &_entries[i]; - } - return NULL; + EntriesMap::iterator p = _entries.find(fileHash); + return p != _entries.end() ? &(*p)._value : NULL; } ResourceFileEntry *ResourceMan::findEntry(uint32 fileHash) { ResourceFileEntry *entry = findEntrySimple(fileHash); - for (; entry && getArchiveEntry(entry)->comprType == 0x65; fileHash = getArchiveEntry(entry)->diskSize) + for (; entry && entry->archiveEntry->comprType == 0x65; fileHash = entry->archiveEntry->diskSize) entry = findEntrySimple(fileHash); return entry; } -BlbArchiveEntry *ResourceMan::getArchiveEntry(ResourceFileEntry *entry) const { - return _archives[entry->archiveIndex]->getEntry(entry->entryIndex); -} - int ResourceMan::useResource(uint32 fileHash) { ResourceFileEntry *entry = findEntry(fileHash); if (!entry) @@ -83,11 +74,7 @@ int ResourceMan::useResource(uint32 fileHash) { _resources[entry->resourceHandle]->useRefCount++; } else { Resource *resource = new Resource(); - resource->fileHash = entry->fileHash; - resource->archiveIndex = entry->archiveIndex; - resource->entryIndex = entry->entryIndex; - resource->data = NULL; - resource->dataRefCount = 0; + resource->entry = entry; resource->useRefCount = 1; entry->resourceHandle = (int)_resources.size(); _resources.push_back(resource); @@ -103,86 +90,68 @@ void ResourceMan::unuseResource(int resourceHandle) { resource->useRefCount--; } -void ResourceMan::unuseResourceByHash(uint32 fileHash) { - ResourceFileEntry *entry = findEntry(fileHash); - if (entry->resourceHandle != -1) - unuseResource(entry->resourceHandle); -} - -int ResourceMan::getResourceHandleByHash(uint32 fileHash) { - ResourceFileEntry *entry = findEntry(fileHash); - return entry->resourceHandle; -} - -bool ResourceMan::isResourceDataValid(int resourceHandle) const { - if (resourceHandle < 0) - return false; - return _resources[resourceHandle]->data != NULL; -} - uint32 ResourceMan::getResourceSize(int resourceHandle) const { if (resourceHandle < 0) return 0; Resource *resource = _resources[resourceHandle]; - return _archives[resource->archiveIndex]->getEntry(resource->entryIndex)->size; + return resource->entry->archiveEntry->size; } byte ResourceMan::getResourceType(int resourceHandle) { if (resourceHandle < 0) return 0; Resource *resource = _resources[resourceHandle]; - return _archives[resource->archiveIndex]->getEntry(resource->entryIndex)->type; + return resource->entry->archiveEntry->type; } byte ResourceMan::getResourceTypeByHash(uint32 fileHash) { ResourceFileEntry *entry = findEntry(fileHash); - return getArchiveEntry(entry)->type; + return entry->archiveEntry->type; } byte *ResourceMan::getResourceExtData(int resourceHandle) { if (resourceHandle < 0) return NULL; Resource *resource = _resources[resourceHandle]; - return _archives[resource->archiveIndex]->getEntryExtData(resource->entryIndex); + return resource->entry->archive->getEntryExtData(resource->entry->archiveEntry); } byte *ResourceMan::getResourceExtDataByHash(uint32 fileHash) { ResourceFileEntry *entry = findEntrySimple(fileHash); - return entry ? _archives[entry->archiveIndex]->getEntryExtData(entry->entryIndex) : NULL; + return entry ? entry->archive->getEntryExtData(entry->archiveEntry) : NULL; } byte *ResourceMan::loadResource(int resourceHandle, bool moveToFront) { if (resourceHandle < 0) return NULL; Resource *resource = _resources[resourceHandle]; - if (resource->data != NULL) { - resource->dataRefCount++; + ResourceData *resourceData = _data[resource->entry->archiveEntry->fileHash]; + if (!resourceData) { + resourceData = new ResourceData(); + _data[resource->entry->archiveEntry->fileHash] = resourceData; + } + if (resourceData->data != NULL) { + resourceData->dataRefCount++; } else { - BlbArchive *archive = _archives[resource->archiveIndex]; - BlbArchiveEntry *archiveEntry = archive->getEntry(resource->entryIndex); - resource->data = new byte[archiveEntry->size]; - archive->load(resource->entryIndex, resource->data, 0); - resource->dataRefCount = 1; + resourceData->data = new byte[resource->entry->archiveEntry->size]; + resource->entry->archive->load(resource->entry->archiveEntry, resourceData->data, 0); + resourceData->dataRefCount = 1; } - return resource->data; + return resourceData->data; } void ResourceMan::unloadResource(int resourceHandle) { if (resourceHandle < 0) return; Resource *resource = _resources[resourceHandle]; - if (resource->dataRefCount > 0) - resource->dataRefCount--; -} - -void ResourceMan::freeResource(Resource *resource) { - delete[] resource->data; - resource->data = NULL; + ResourceData *resourceData = _data[resource->entry->archiveEntry->fileHash]; + if (resourceData && resourceData->dataRefCount > 0) + resourceData->dataRefCount--; } Common::SeekableReadStream *ResourceMan::createStream(uint32 fileHash) { ResourceFileEntry *entry = findEntry(fileHash); - return _archives[entry->archiveIndex]->createStream(entry->entryIndex); + return entry->archive->createStream(entry->archiveEntry); } } // End of namespace Neverhood diff --git a/engines/neverhood/resourceman.h b/engines/neverhood/resourceman.h index ed5bffaf9b..5ca8fa2b04 100644 --- a/engines/neverhood/resourceman.h +++ b/engines/neverhood/resourceman.h @@ -25,26 +25,43 @@ #include "common/array.h" #include "common/file.h" +#include "common/hashmap.h" #include "neverhood/neverhood.h" #include "neverhood/blbarchive.h" namespace Neverhood { struct ResourceFileEntry { - uint32 fileHash; int resourceHandle; - uint archiveIndex; - uint entryIndex; + BlbArchive *archive; + BlbArchiveEntry *archiveEntry; }; struct Resource { - uint32 fileHash; - uint archiveIndex; - uint entryIndex; + ResourceFileEntry *entry; + int useRefCount; +}; + +struct ResourceData { byte *data; int dataRefCount; - int useRefCount; + ResourceData() : data(NULL), dataRefCount() {} +}; + +#if 0 +class ResourceMan; + +struct ResourceHandle { +public: + ResourceHandle(); + ~ResourceHandle(); + const byte *data(); + uint32 size() const { return _archiveEntry ? _archiveEntry->size : 0 }; +protected: + ResourceMan *_res; + ResourceFileEntry *_resourceFileEntry; }; +#endif class ResourceMan { public: @@ -53,12 +70,8 @@ public: void addArchive(const Common::String &filename); ResourceFileEntry *findEntrySimple(uint32 fileHash); ResourceFileEntry *findEntry(uint32 fileHash); - BlbArchiveEntry *getArchiveEntry(ResourceFileEntry *entry) const; int useResource(uint32 fileHash); void unuseResource(int resourceHandle); - void unuseResourceByHash(uint32 fileHash); - int getResourceHandleByHash(uint32 fileHash); - bool isResourceDataValid(int resourceHandle) const; uint32 getResourceSize(int resourceHandle) const; byte getResourceType(int resourceHandle); byte getResourceTypeByHash(uint32 fileHash); @@ -66,13 +79,17 @@ public: byte *getResourceExtDataByHash(uint32 fileHash); byte *loadResource(int resourceHandle, bool moveToFront = false); void unloadResource(int resourceHandle); - void freeResource(Resource *resource); Common::SeekableReadStream *createStream(uint32 fileHash); const ResourceFileEntry& getEntry(uint index) { return _entries[index]; } uint getEntryCount() { return _entries.size(); } -private: +#if 0 + ResourceHandle getResource(uint32 fileHash); +#endif +protected: + typedef Common::HashMap EntriesMap; Common::Array _archives; - Common::Array _entries; + EntriesMap _entries; + Common::HashMap _data; Common::Array _resources; }; -- cgit v1.2.3