diff options
author | Filippos Karapetis | 2011-01-31 10:46:52 +0000 |
---|---|---|
committer | Filippos Karapetis | 2011-01-31 10:46:52 +0000 |
commit | 90d58cf487c8d2f63a6aeff952b02b410e320b19 (patch) | |
tree | 7848430e08761cab953c69a4d4b5a9f0719289c7 | |
parent | a256b74e0aa870cee4342826d6cc80183647cc7b (diff) | |
download | scummvm-rg350-90d58cf487c8d2f63a6aeff952b02b410e320b19.tar.gz scummvm-rg350-90d58cf487c8d2f63a6aeff952b02b410e320b19.tar.bz2 scummvm-rg350-90d58cf487c8d2f63a6aeff952b02b410e320b19.zip |
SAGA: Rewrote the MacBinary resource loading code
This simplifies the overall code and makes it easier to understand. Also, a bug with the
speech in the MacBinary packed version has been corrected, so there are no more clicking
sounds before each sample.
The Common::MacResMan code isn't really useful here, since it doesn't expose the offsets
and sizes of the actual files, which is what is needed in SAGA.
svn-id: r55674
-rw-r--r-- | engines/saga/resource.cpp | 38 | ||||
-rw-r--r-- | engines/saga/resource.h | 52 | ||||
-rw-r--r-- | engines/saga/resource_rsc.cpp | 142 |
3 files changed, 75 insertions, 157 deletions
diff --git a/engines/saga/resource.cpp b/engines/saga/resource.cpp index 169c901950..0ef0d438d9 100644 --- a/engines/saga/resource.cpp +++ b/engines/saga/resource.cpp @@ -83,7 +83,7 @@ bool ResourceContext::loadResV1(uint32 contextOffset, uint32 contextSize) { resourceData = &_table[i]; resourceData->offset = contextOffset + readS1.readUint32(); resourceData->size = readS1.readUint32(); - //sanity check + // Sanity check if ((resourceData->offset > (uint)_fileSize) || (resourceData->size > contextSize)) { result = false; break; @@ -103,15 +103,12 @@ bool ResourceContext::load(SagaEngine *vm, Resource *resource) { uint32 subjectResourceId; uint32 patchResourceId; ResourceData *subjectResourceData; - bool isMacBinary; - if (_fileName == NULL) { // IHNM special case + if (_fileName == NULL) // IHNM special case return true; - } - if (!_file.open(_fileName)) { + if (!_file.open(_fileName)) return false; - } _fileSize = _file.size(); _isBigEndian = vm->isBigEndian(); @@ -119,20 +116,25 @@ bool ResourceContext::load(SagaEngine *vm, Resource *resource) { if (_fileType & GAME_SWAPENDIAN) _isBigEndian = !_isBigEndian; - isMacBinary = (_fileType & GAME_MACBINARY) > 0; - _fileType &= ~GAME_MACBINARY; - - if (!isMacBinary) { - if (!loadRes(0, _fileSize)) { - return false; - } - } else { - if (!loadMac()) { - return false; + if (_fileType & GAME_MACBINARY) { + // Special case for the MacBinary packed files in the old Mac ITE + // release. There are no patch files in this case. + if (!(_fileType & GAME_MUSICFILE_GM)) { + // Find the actual size, as there may be padded data in the end. + _file.seek(83); + uint32 macDataSize = _file.readSint32BE(); + // Skip the MacBinary headers, and read the resource data. + return loadRes(MAC_BINARY_HEADER_SIZE, macDataSize); + } else { + // Unpack MacBinady packed MIDI files + return loadMacMIDI(); } } - //process internal patch files + if (!loadRes(0, _fileSize)) + return false; + + // Process internal patch files if (_fileType & GAME_PATCHFILE) { subjectResourceType = ~GAME_PATCHFILE & _fileType; subjectContext = resource->getContext((GameFileTypes)subjectResourceType); @@ -155,7 +157,7 @@ bool ResourceContext::load(SagaEngine *vm, Resource *resource) { } } - //process external patch files + // Process external patch files for (patchDescription = vm->getPatchDescriptions(); patchDescription && patchDescription->fileName; ++patchDescription) { if ((patchDescription->fileType & _fileType) != 0) { if (patchDescription->resourceId < _table.size()) { diff --git a/engines/saga/resource.h b/engines/saga/resource.h index 5009c862f4..048ed3933d 100644 --- a/engines/saga/resource.h +++ b/engines/saga/resource.h @@ -84,22 +84,6 @@ class ResourceDataArray : public Common::Array<ResourceData> { class ResourceContext { friend class Resource; -protected: - const char *_fileName; - uint16 _fileType; - bool _isCompressed; - int _serial; // IHNM speech files - - bool _isBigEndian; - ResourceDataArray _table; - Common::File _file; - int32 _fileSize; - - bool load(SagaEngine *_vm, Resource *resource); - bool loadResV1(uint32 contextOffset, uint32 contextSize); - - virtual bool loadMac() = 0; - virtual bool loadRes(uint32 contextOffset, uint32 contextSize) = 0; public: ResourceContext(): @@ -172,6 +156,22 @@ public: } return -1; } +protected: + const char *_fileName; + uint16 _fileType; + bool _isCompressed; + int _serial; // IHNM speech files + + bool _isBigEndian; + ResourceDataArray _table; + Common::File _file; + int32 _fileSize; + + bool load(SagaEngine *_vm, Resource *resource); + bool loadResV1(uint32 contextOffset, uint32 contextSize); + + virtual bool loadMacMIDI() = 0; + virtual bool loadRes(uint32 contextOffset, uint32 contextSize) = 0; }; class ResourceContextList : public Common::List<ResourceContext*> { @@ -228,7 +228,7 @@ public: // ITE class ResourceContext_RSC: public ResourceContext { protected: - virtual bool loadMac(); + virtual bool loadMacMIDI(); virtual bool loadRes(uint32 contextOffset, uint32 contextSize) { return loadResV1(contextOffset, contextSize); } @@ -237,7 +237,9 @@ protected: class Resource_RSC : public Resource { public: Resource_RSC(SagaEngine *vm) : Resource(vm) {} - virtual uint32 convertResourceId(uint32 resourceId); + virtual uint32 convertResourceId(uint32 resourceId) { + return _vm->isMacResources() ? resourceId - 2 : resourceId; + } virtual void loadGlobalResources(int chapter, int actorsEntrance) {} virtual MetaResource* getMetaResource() { MetaResource *dummy = 0; @@ -253,20 +255,16 @@ protected: // IHNM class ResourceContext_RES: public ResourceContext { protected: - virtual bool loadMac() { - return false; - } + virtual bool loadMacMIDI() { return false; } virtual bool loadRes(uint32 contextOffset, uint32 contextSize) { return loadResV1(0, contextSize); } }; -//TODO: move load routines from sndres +// TODO: move load routines from sndres class VoiceResourceContext_RES: public ResourceContext { protected: - virtual bool loadMac() { - return false; - } + virtual bool loadMacMIDI() { return false; } virtual bool loadRes(uint32 contextOffset, uint32 contextSize) { return false; } @@ -298,9 +296,7 @@ class ResourceContext_HRS: public ResourceContext { protected: ResourceDataArray _categories; - virtual bool loadMac() { - return false; - } + virtual bool loadMacMIDI() { return false; } virtual bool loadRes(uint32 contextOffset, uint32 contextSize) { return loadResV2(contextSize); } diff --git a/engines/saga/resource_rsc.cpp b/engines/saga/resource_rsc.cpp index b07741436b..6d9ef70bfe 100644 --- a/engines/saga/resource_rsc.cpp +++ b/engines/saga/resource_rsc.cpp @@ -26,142 +26,62 @@ // RSC Resource file management module (SAGA 1, used in ITE) #include "saga/saga.h" - -#include "saga/actor.h" -#include "saga/animation.h" -#include "saga/interface.h" -#include "saga/music.h" #include "saga/resource.h" -#include "saga/scene.h" -#include "saga/sndres.h" - -#include "engines/advancedDetector.h" namespace Saga { -struct MacResource { - int16 id; - int32 dataOffset; - MacResource() : id(0), dataOffset(0) {} -}; - -class MacResourceArray : public Common::Array<MacResource> { -}; - -struct MacResType { - uint32 id; - int16 maxItemId; - int16 offset; - MacResourceArray resources; - MacResType() : id(0), maxItemId(0), offset(0) { - } -}; - -class MacResTypeArray : public Common::Array<MacResType> { -}; - #define ID_MIDI MKID_BE('Midi') -bool ResourceContext_RSC::loadMac() { - int32 macDataSize, macResSizePad, macResOffset; - uint32 macMapOffset, macDataOffset; - - MacResTypeArray macResTypes; - - bool notSagaContext = false; - +bool ResourceContext_RSC::loadMacMIDI() { // Sanity check if (_fileSize < RSC_MIN_FILESIZE + MAC_BINARY_HEADER_SIZE) return false; - _file.seek(82); - if (_file.readByte() != 0) - return false; - - macDataSize = _file.readSint32BE(); - macResOffset = MAC_BINARY_HEADER_SIZE + (((macDataSize + 127) >> 7) << 7); + _file.seek(83); + int macDataSize = _file.readSint32BE(); + int macResOffset = MAC_BINARY_HEADER_SIZE + (((macDataSize + 127) >> 7) << 7); - macResSizePad = (((_file.readSint32BE() + 127) >> 7) << 7); _file.seek(macResOffset); - - macDataOffset = _file.readUint32BE() + macResOffset; - macMapOffset = _file.readUint32BE() + macResOffset; - // Used for sanity checks - uint32 macDataLength = _file.readUint32BE(); - uint32 macMapLength = _file.readUint32BE(); - - if (macDataOffset >= (uint)_fileSize || macMapOffset >= (uint)_fileSize || - macDataLength + macMapLength > (uint)_fileSize) - return false; + uint32 macDataOffset = _file.readUint32BE() + macResOffset; + uint32 macMapOffset = _file.readUint32BE() + macResOffset; _file.seek(macMapOffset + 22); - _file.readUint16BE(); // resAttr int16 typeOffset = _file.readUint16BE(); _file.readUint16BE(); // nameOffset - int16 numTypes = _file.readUint16BE() + 1; - macResTypes.resize(numTypes); + uint16 numTypes = _file.readUint16BE() + 1; _file.seek(macMapOffset + typeOffset + 2); - for (MacResTypeArray::iterator k = macResTypes.begin(); k != macResTypes.end(); ++k) { - k->id = _file.readUint32BE(); - int16 items = _file.readUint16BE() + 1; - k->resources.resize(items); - k->offset = _file.readUint16BE(); - } - - for (MacResTypeArray::iterator k = macResTypes.begin(); k != macResTypes.end(); ++k) { - _file.seek(k->offset + macMapOffset + typeOffset); - - for (MacResourceArray::iterator j = k->resources.begin(); j != k->resources.end(); ++j) { - j->id = _file.readUint16BE(); - _file.readUint16BE(); // nameOffset - j->dataOffset = _file.readUint32BE(); - _file.readUint32BE(); // macResSize - - j->dataOffset &= 0xFFFFFF; - if (j->id > k->maxItemId) - k->maxItemId = j->id; - } - } - - // - for (MacResTypeArray::iterator k = macResTypes.begin(); k != macResTypes.end(); ++k) { - //getting offsets & sizes of midi - if (((_fileType & GAME_MUSICFILE_GM) > 0) && (k->id == ID_MIDI)) { - - _table.resize(k->maxItemId + 1); - for (MacResourceArray::iterator j = k->resources.begin(); j != k->resources.end(); ++j) { - _file.seek(macDataOffset + j->dataOffset); - _table[j->id].size = _file.readUint32BE(); - _table[j->id].offset = _file.pos(); + // Find the MIDI files + for (uint16 i = 0; i < numTypes; i++) { + uint32 id = _file.readUint32BE(); + uint16 items = _file.readUint16BE() + 1; + uint16 offset = _file.readUint16BE(); + + if (id == ID_MIDI) { + for (uint16 curMidi = 0; curMidi < items; curMidi++) { + // Jump to the header of the entry and read its fields + _file.seek(offset + macMapOffset + typeOffset + curMidi * 12); + uint16 midiID = _file.readUint16BE(); + _file.readUint16BE(); // nameOffset + uint32 midiOffset = _file.readUint32BE() & 0xFFFFFF; + _file.readUint32BE(); // macResSize + + // Jump to the actual data and read the file size + _file.seek(macDataOffset + midiOffset); + uint32 midiSize = _file.readUint32BE(); + + // Add the entry + if (_table.size() <= midiID) + _table.resize(midiID + 1); + _table[midiID].offset = macDataOffset + midiOffset + 4; + _table[midiID].size = midiSize; } - notSagaContext = true; - break; } } - if ((!notSagaContext) && (!loadRes(MAC_BINARY_HEADER_SIZE, macDataSize))) { - return false; - } - return true; } -uint32 Resource_RSC::convertResourceId(uint32 resourceId) { - - if (_vm->isMacResources()) { - if (resourceId > 1537) { - return resourceId - 2; - } else { - if (resourceId == 1535 || resourceId == 1536) { - error("Wrong resource number %d for Mac ITE", resourceId); - } - } - } - - return resourceId; -} - } // End of namespace Saga |