aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippos Karapetis2011-01-31 10:46:52 +0000
committerFilippos Karapetis2011-01-31 10:46:52 +0000
commit90d58cf487c8d2f63a6aeff952b02b410e320b19 (patch)
tree7848430e08761cab953c69a4d4b5a9f0719289c7
parenta256b74e0aa870cee4342826d6cc80183647cc7b (diff)
downloadscummvm-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.cpp38
-rw-r--r--engines/saga/resource.h52
-rw-r--r--engines/saga/resource_rsc.cpp142
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