NEVERHOOD: Add a patch system for broken resources in Russian versions

Some translated resources in Russian versions have incorrect unpacked
resource sizes. The original didn't perform checks for these, but we
do, thus we'll need to patch the unpacked resource sizes for each case
This commit is contained in:
Filippos Karapetis 2013-09-26 10:54:30 +03:00
parent dca513dc20
commit 9396958536
7 changed files with 50 additions and 11 deletions

View File

@ -252,7 +252,7 @@ bool Console::Cmd_DumpResource(int argc, const char **argv) {
if (!handle.isValid()) {
DebugPrintf("Invalid resource hash\n");
} else {
_vm->_res->loadResource(handle);
_vm->_res->loadResource(handle, _vm->applyResourceFixes());
Common::DumpFile outFile;
outFile.open(outFileName);
outFile.write(handle.data(), handle.size());

View File

@ -52,6 +52,10 @@ Common::Platform NeverhoodEngine::getPlatform() const {
return _gameDescription->desc.platform;
}
Common::Language NeverhoodEngine::getLanguage() const {
return _gameDescription->desc.language;
}
uint16 NeverhoodEngine::getVersion() const {
return _gameDescription->version;
}
@ -60,6 +64,10 @@ bool NeverhoodEngine::isDemo() const {
return _gameDescription->desc.flags & ADGF_DEMO;
}
bool NeverhoodEngine::applyResourceFixes() const {
return getLanguage() == Common::RU_RUS;
}
}
static const PlainGameDescriptor neverhoodGames[] = {

View File

@ -72,8 +72,10 @@ public:
uint32 getFeatures() const;
uint16 getVersion() const;
Common::Platform getPlatform() const;
Common::Language getLanguage() const;
bool hasFeature(EngineFeature f) const;
bool isDemo() const;
bool applyResourceFixes() const;
Common::String getTargetName() { return _targetName; };
Common::RandomSource *_rnd;

View File

@ -53,7 +53,7 @@ bool SpriteResource::load(uint32 fileHash, bool doLoadPosition) {
unload();
_vm->_res->queryResource(fileHash, _resourceHandle);
if (_resourceHandle.isValid() && _resourceHandle.type() == kResTypeBitmap) {
_vm->_res->loadResource(_resourceHandle);
_vm->_res->loadResource(_resourceHandle, _vm->applyResourceFixes());
const byte *spriteData = _resourceHandle.data();
NPoint *position = doLoadPosition ? &_position : NULL;
parseBitmapResource(spriteData, &_rle, &_dimensions, position, NULL, &_pixels);
@ -83,7 +83,7 @@ bool PaletteResource::load(uint32 fileHash) {
_vm->_res->queryResource(fileHash, _resourceHandle);
if (_resourceHandle.isValid() &&
(_resourceHandle.type() == kResTypeBitmap || _resourceHandle.type() == kResTypePalette)) {
_vm->_res->loadResource(_resourceHandle);
_vm->_res->loadResource(_resourceHandle, _vm->applyResourceFixes());
_palette = _resourceHandle.data();
// Check if the palette is stored in a bitmap
if (_resourceHandle.type() == kResTypeBitmap)
@ -144,7 +144,7 @@ bool AnimResource::load(uint32 fileHash) {
uint16 frameListStartOfs, frameCount;
uint32 spriteDataOfs, paletteDataOfs;
_vm->_res->loadResource(_resourceHandle);
_vm->_res->loadResource(_resourceHandle, _vm->applyResourceFixes());
resourceData = _resourceHandle.data();
animListCount = READ_LE_UINT16(resourceData);
@ -323,7 +323,7 @@ void TextResource::load(uint32 fileHash) {
unload();
_vm->_res->queryResource(fileHash, _resourceHandle);
if (_resourceHandle.isValid() && _resourceHandle.type() == kResTypeText) {
_vm->_res->loadResource(_resourceHandle);
_vm->_res->loadResource(_resourceHandle, _vm->applyResourceFixes());
_textData = _resourceHandle.data();
_count = READ_LE_UINT32(_textData);
}
@ -359,7 +359,7 @@ void DataResource::load(uint32 fileHash) {
unload();
_vm->_res->queryResource(fileHash, _resourceHandle);
if (_resourceHandle.isValid() && _resourceHandle.type() == kResTypeData) {
_vm->_res->loadResource(_resourceHandle);
_vm->_res->loadResource(_resourceHandle, _vm->applyResourceFixes());
data = _resourceHandle.data();
dataSize = _resourceHandle.size();
}

View File

@ -85,7 +85,25 @@ void ResourceMan::queryResource(uint32 fileHash, ResourceHandle &resourceHandle)
resourceHandle._extData = firstEntry ? firstEntry->archiveEntry->extData : NULL;
}
void ResourceMan::loadResource(ResourceHandle &resourceHandle) {
struct EntrySizeFix {
uint32 fileHash;
uint32 offset;
uint32 diskSize;
uint32 size;
uint32 fixedSize;
};
static const EntrySizeFix entrySizeFixes[] = {
// fileHash offset diskSize size fixedSize
// Fixes for the Russian "Dyadyushka Risech" version
// TODO
// Fixes for the Russian "Fargus" version
// TODO
//
{ 0, 0, 0, 0, 0 }
};
void ResourceMan::loadResource(ResourceHandle &resourceHandle, bool applyResourceFixes) {
resourceHandle._data = NULL;
if (resourceHandle.isValid()) {
const uint32 fileHash = resourceHandle.fileHash();
@ -97,8 +115,19 @@ void ResourceMan::loadResource(ResourceHandle &resourceHandle) {
if (resourceData->data != NULL) {
resourceData->dataRefCount++;
} else {
resourceData->data = new byte[resourceHandle._resourceFileEntry->archiveEntry->size];
resourceHandle._resourceFileEntry->archive->load(resourceHandle._resourceFileEntry->archiveEntry, resourceData->data, 0);
BlbArchiveEntry *entry = resourceHandle._resourceFileEntry->archiveEntry;
// Apply fixes for broken resources in Russian versions
if (applyResourceFixes) {
for (const EntrySizeFix *cur = entrySizeFixes; cur->fileHash > 0; ++cur) {
if (entry->fileHash == cur->fileHash && entry->offset == cur->offset &&
entry->diskSize == cur->diskSize && entry->size == cur->size)
entry->size = cur->fixedSize;
}
}
resourceData->data = new byte[entry->size];
resourceHandle._resourceFileEntry->archive->load(entry, resourceData->data, 0);
resourceData->dataRefCount = 1;
}
resourceHandle._data = resourceData->data;

View File

@ -78,7 +78,7 @@ public:
const ResourceFileEntry& getEntry(uint index) { return _entries[index]; }
uint getEntryCount() { return _entries.size(); }
void queryResource(uint32 fileHash, ResourceHandle &resourceHandle);
void loadResource(ResourceHandle &resourceHandle);
void loadResource(ResourceHandle &resourceHandle, bool applyResourceFixes);
void unloadResource(ResourceHandle &resourceHandle);
void purgeResources();
protected:

View File

@ -577,7 +577,7 @@ AudioResourceManSoundItem::AudioResourceManSoundItem(NeverhoodEngine *vm, uint32
void AudioResourceManSoundItem::loadSound() {
if (!_data && _resourceHandle.isValid() &&
(_resourceHandle.type() == kResTypeSound || _resourceHandle.type() == kResTypeMusic)) {
_vm->_res->loadResource(_resourceHandle);
_vm->_res->loadResource(_resourceHandle, _vm->applyResourceFixes());
_data = _resourceHandle.data();
}
}