mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-15 06:08:35 +00:00
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
This commit is contained in:
parent
a256b74e0a
commit
90d58cf487
@ -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()) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
_file.seek(83);
|
||||
int macDataSize = _file.readSint32BE();
|
||||
int macResOffset = MAC_BINARY_HEADER_SIZE + (((macDataSize + 127) >> 7) << 7);
|
||||
|
||||
macDataSize = _file.readSint32BE();
|
||||
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();
|
||||
}
|
||||
// Find the MIDI files
|
||||
for (uint16 i = 0; i < numTypes; i++) {
|
||||
uint32 id = _file.readUint32BE();
|
||||
uint16 items = _file.readUint16BE() + 1;
|
||||
uint16 offset = _file.readUint16BE();
|
||||
|
||||
for (MacResTypeArray::iterator k = macResTypes.begin(); k != macResTypes.end(); ++k) {
|
||||
_file.seek(k->offset + macMapOffset + typeOffset);
|
||||
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
|
||||
|
||||
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
|
||||
// Jump to the actual data and read the file size
|
||||
_file.seek(macDataOffset + midiOffset);
|
||||
uint32 midiSize = _file.readUint32BE();
|
||||
|
||||
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();
|
||||
// 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
|
||||
|
Loading…
Reference in New Issue
Block a user