Skip to content

Commit

Permalink
NEVERHOOD: Work on the resource system:
Browse files Browse the repository at this point in the history
- Remove unused stuff
- Shuffle some stuff around
  • Loading branch information
johndoe123 authored and wjp committed May 8, 2013
1 parent a80ec8c commit fa53c0c
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 100 deletions.
54 changes: 36 additions & 18 deletions engines/neverhood/blbarchive.cpp
Expand Up @@ -56,7 +56,8 @@ BlbArchive::~BlbArchive() {
}

void BlbArchive::open(const Common::String &filename) {
BlbHeader header;
BlbHeader header;
uint16 *extDataOffsets;

_entries.clear();

Expand All @@ -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);

Expand All @@ -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);
}

Expand Down
5 changes: 4 additions & 1 deletion engines/neverhood/blbarchive.h
Expand Up @@ -44,7 +44,7 @@ struct BlbArchiveEntry {
uint32 fileHash;
byte type;
byte comprType;
uint16 extDataOfs;
byte *extData;
uint32 timeStamp;
uint32 offset;
uint32 diskSize;
Expand All @@ -57,11 +57,14 @@ class BlbArchive {
~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;
Expand Down
4 changes: 4 additions & 0 deletions engines/neverhood/navigationscene.cpp
Expand Up @@ -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) {
Expand Down
10 changes: 5 additions & 5 deletions engines/neverhood/neverhood.cpp
Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down
93 changes: 31 additions & 62 deletions engines/neverhood/resourceman.cpp
Expand Up @@ -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)
Expand All @@ -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);
Expand All @@ -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

0 comments on commit fa53c0c

Please sign in to comment.