aboutsummaryrefslogtreecommitdiff
path: root/engines/saga
diff options
context:
space:
mode:
authorAndrew Kurushin2009-12-04 17:52:42 +0000
committerAndrew Kurushin2009-12-04 17:52:42 +0000
commitaa147a2f5af167048b3d57da558bc39a91c3a936 (patch)
treec0d76d59a96f4b415f5186f74dfcb73c27775fc6 /engines/saga
parent4fb779dbaf85d93c776549cdc4903c5a671013a4 (diff)
downloadscummvm-rg350-aa147a2f5af167048b3d57da558bc39a91c3a936.tar.gz
scummvm-rg350-aa147a2f5af167048b3d57da558bc39a91c3a936.tar.bz2
scummvm-rg350-aa147a2f5af167048b3d57da558bc39a91c3a936.zip
refactor resource module:
- struct ResourceContext => class ResourceContext - replace "*alloc","free" with array templates - simplify createContexts routines svn-id: r46254
Diffstat (limited to 'engines/saga')
-rw-r--r--engines/saga/actor.cpp2
-rw-r--r--engines/saga/font.cpp2
-rw-r--r--engines/saga/music.cpp4
-rw-r--r--engines/saga/resource.cpp458
-rw-r--r--engines/saga/resource.h201
-rw-r--r--engines/saga/resource_hrs.cpp50
-rw-r--r--engines/saga/resource_rsc.cpp166
-rw-r--r--engines/saga/saga.h2
-rw-r--r--engines/saga/scene.cpp8
-rw-r--r--engines/saga/script.cpp6
-rw-r--r--engines/saga/sndres.cpp47
-rw-r--r--engines/saga/sprite.cpp4
12 files changed, 440 insertions, 510 deletions
diff --git a/engines/saga/actor.cpp b/engines/saga/actor.cpp
index 0ffbe66314..c3f5fec83a 100644
--- a/engines/saga/actor.cpp
+++ b/engines/saga/actor.cpp
@@ -352,7 +352,7 @@ void Actor::loadFrameList(int frameListResourceId, ActorFrameSequence *&framesPo
memoryError("Actor::loadFrameList");
}
- MemoryReadStreamEndian readS(resourcePointer, resourceLength, _actorContext->isBigEndian);
+ MemoryReadStreamEndian readS(resourcePointer, resourceLength, _actorContext->isBigEndian());
for (int i = 0; i < framesCount; i++) {
debug(9, "frameType %d", i);
diff --git a/engines/saga/font.cpp b/engines/saga/font.cpp
index d414b903e6..3ffe27f783 100644
--- a/engines/saga/font.cpp
+++ b/engines/saga/font.cpp
@@ -90,7 +90,7 @@ void Font::loadFont(uint32 fontResourceId) {
error("Font::loadFont() Invalid font length (%i < %i)", (int)fontResourceLength, FONT_DESCSIZE);
}
- MemoryReadStreamEndian readS(fontResourcePointer, fontResourceLength, fontContext->isBigEndian);
+ MemoryReadStreamEndian readS(fontResourcePointer, fontResourceLength, fontContext->isBigEndian());
// Create new font structure
font = (FontData *)malloc(sizeof(*font));
diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp
index 31517f403e..aeca848719 100644
--- a/engines/saga/music.cpp
+++ b/engines/saga/music.cpp
@@ -296,12 +296,12 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
// Digital music
ResourceData *resData = _digitalMusicContext->getResourceData(resourceId - 9);
Common::File *musicFile = _digitalMusicContext->getFile(resData);
- int offs = (_digitalMusicContext->isCompressed) ? 9 : 0;
+ int offs = (_digitalMusicContext->isCompressed()) ? 9 : 0;
Common::SeekableSubReadStream *musicStream = new Common::SeekableSubReadStream(musicFile,
(uint32)resData->offset + offs, (uint32)resData->offset + resData->size - offs);
- if (!_digitalMusicContext->isCompressed) {
+ if (!_digitalMusicContext->isCompressed()) {
byte musicFlags = Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_STEREO |
Audio::Mixer::FLAG_16BITS | Audio::Mixer::FLAG_LITTLE_ENDIAN;
if (flags == MUSIC_LOOP)
diff --git a/engines/saga/resource.cpp b/engines/saga/resource.cpp
index 3bdd8e00db..bdff209704 100644
--- a/engines/saga/resource.cpp
+++ b/engines/saga/resource.cpp
@@ -39,21 +39,13 @@
namespace Saga {
-Resource::Resource(SagaEngine *vm): _vm(vm) {
- _contexts = NULL;
- _contextsCount = 0;
-}
-
-Resource::~Resource() {
- clearContexts();
-}
-
-bool Resource::loadResContext_v1(ResourceContext *context, uint32 contextOffset, uint32 contextSize) {
+bool ResourceContext::loadResV1(uint32 contextOffset, uint32 contextSize) {
size_t i;
bool result;
byte tableInfo[RSC_TABLEINFO_SIZE];
byte *tableBuffer;
size_t tableSize;
+ uint32 count;
uint32 resourceTableOffset;
ResourceData *resourceData;
@@ -61,41 +53,41 @@ bool Resource::loadResContext_v1(ResourceContext *context, uint32 contextOffset,
return false;
}
- context->file->seek(contextOffset + contextSize - RSC_TABLEINFO_SIZE);
+ _file.seek(contextOffset + contextSize - RSC_TABLEINFO_SIZE);
- if (context->file->read(tableInfo, RSC_TABLEINFO_SIZE) != RSC_TABLEINFO_SIZE) {
+ if (_file.read(tableInfo, RSC_TABLEINFO_SIZE) != RSC_TABLEINFO_SIZE) {
return false;
}
- MemoryReadStreamEndian readS(tableInfo, RSC_TABLEINFO_SIZE, context->isBigEndian);
+ MemoryReadStreamEndian readS(tableInfo, RSC_TABLEINFO_SIZE, _isBigEndian);
resourceTableOffset = readS.readUint32();
- context->count = readS.readUint32();
+ count = readS.readUint32();
// Check for sane table offset
- if (resourceTableOffset != contextSize - RSC_TABLEINFO_SIZE - RSC_TABLEENTRY_SIZE * context->count) {
+ if (resourceTableOffset != contextSize - RSC_TABLEINFO_SIZE - RSC_TABLEENTRY_SIZE * count) {
return false;
}
// Load resource table
- tableSize = RSC_TABLEENTRY_SIZE * context->count;
+ tableSize = RSC_TABLEENTRY_SIZE * count;
tableBuffer = (byte *)malloc(tableSize);
- context->file->seek(resourceTableOffset + contextOffset, SEEK_SET);
+ _file.seek(resourceTableOffset + contextOffset, SEEK_SET);
- result = (context->file->read(tableBuffer, tableSize) == tableSize);
+ result = (_file.read(tableBuffer, tableSize) == tableSize);
if (result) {
- context->table = (ResourceData *)calloc(context->count, sizeof(*context->table));
+ _table.resize(count);
- MemoryReadStreamEndian readS1(tableBuffer, tableSize, context->isBigEndian);
+ MemoryReadStreamEndian readS1(tableBuffer, tableSize, _isBigEndian);
- for (i = 0; i < context->count; i++) {
- resourceData = &context->table[i];
+ for (i = 0; i < count; i++) {
+ resourceData = &_table[i];
resourceData->offset = contextOffset + readS1.readUint32();
resourceData->size = readS1.readUint32();
//sanity check
- if ((resourceData->offset > (uint)context->fileSize) || (resourceData->size > contextSize)) {
+ if ((resourceData->offset > (uint)_fileSize) || (resourceData->size > contextSize)) {
result = false;
break;
}
@@ -106,7 +98,7 @@ bool Resource::loadResContext_v1(ResourceContext *context, uint32 contextOffset,
return result;
}
-bool Resource::loadContext(ResourceContext *context) {
+bool ResourceContext::load(SagaEngine *vm, Resource *resource) {
size_t i;
const GamePatchDescription *patchDescription;
ResourceData *resourceData;
@@ -119,45 +111,49 @@ bool Resource::loadContext(ResourceContext *context) {
size_t tableSize;
bool isMacBinary;
- if (!context->file->open(context->fileName)) {
+ if (_fileName == NULL) { // IHNM special case
+ return true;
+ }
+
+ if (!_file.open(_fileName)) {
return false;
}
- context->fileSize = context->file->size();
- context->isBigEndian = _vm->isBigEndian();
+ _fileSize = _file.size();
+ _isBigEndian = vm->isBigEndian();
- if (context->fileType & GAME_SWAPENDIAN)
- context->isBigEndian = !context->isBigEndian;
+ if (_fileType & GAME_SWAPENDIAN)
+ _isBigEndian = !_isBigEndian;
- isMacBinary = (context->fileType & GAME_MACBINARY) > 0;
- context->fileType &= ~GAME_MACBINARY;
+ isMacBinary = (_fileType & GAME_MACBINARY) > 0;
+ _fileType &= ~GAME_MACBINARY;
if (!isMacBinary) {
- if (!loadResContext(context, 0, context->fileSize)) {
+ if (!loadRes(0, _fileSize)) {
return false;
}
} else {
- if (!loadMacContext(context)) {
+ if (!loadMac()) {
return false;
}
}
//process internal patch files
- if (context->fileType & GAME_PATCHFILE) {
- subjectResourceType = ~GAME_PATCHFILE & context->fileType;
- subjectContext = getContext((GameFileTypes)subjectResourceType);
+ if (_fileType & GAME_PATCHFILE) {
+ subjectResourceType = ~GAME_PATCHFILE & _fileType;
+ subjectContext = resource->getContext((GameFileTypes)subjectResourceType);
if (subjectContext == NULL) {
- error("Resource::loadContext() Subject context not found");
+ error("ResourceContext::load() Subject context not found");
}
- loadResource(context, context->count - 1, tableBuffer, tableSize);
+ resource->loadResource(this, _table.size() - 1, tableBuffer, tableSize);
- MemoryReadStreamEndian readS2(tableBuffer, tableSize, context->isBigEndian);
+ MemoryReadStreamEndian readS2(tableBuffer, tableSize, _isBigEndian);
for (i = 0; i < tableSize / 8; i++) {
subjectResourceId = readS2.readUint32();
patchResourceId = readS2.readUint32();
subjectResourceData = subjectContext->getResourceData(subjectResourceId);
- resourceData = context->getResourceData(patchResourceId);
- subjectResourceData->patchData = new PatchData(context->file);
+ resourceData = getResourceData(patchResourceId);
+ subjectResourceData->patchData = new PatchData(&_file);
subjectResourceData->offset = resourceData->offset;
subjectResourceData->size = resourceData->size;
}
@@ -165,10 +161,10 @@ bool Resource::loadContext(ResourceContext *context) {
}
//process external patch files
- for (patchDescription = _vm->getPatchDescriptions(); patchDescription && patchDescription->fileName; ++patchDescription) {
- if ((patchDescription->fileType & context->fileType) != 0) {
- if (patchDescription->resourceId < context->count) {
- resourceData = &context->table[patchDescription->resourceId];
+ for (patchDescription = vm->getPatchDescriptions(); patchDescription && patchDescription->fileName; ++patchDescription) {
+ if ((patchDescription->fileType & _fileType) != 0) {
+ if (patchDescription->resourceId < _table.size()) {
+ resourceData = &_table[patchDescription->resourceId];
resourceData->patchData = new PatchData(patchDescription);
if (resourceData->patchData->_patchFile->open(patchDescription->fileName)) {
resourceData->offset = 0;
@@ -176,7 +172,7 @@ bool Resource::loadContext(ResourceContext *context) {
// ITE uses several patch files which are loaded and then not needed
// anymore (as they're in memory), so close them here. IHNM uses only
// 1 patch file, which is reused, so don't close it
- if (_vm->getGameId() == GID_ITE)
+ if (vm->getGameId() == GID_ITE)
resourceData->patchData->_patchFile->close();
} else {
delete resourceData->patchData;
@@ -189,221 +185,140 @@ bool Resource::loadContext(ResourceContext *context) {
// Close the file if it's part of a series of files
// This prevents having all voice files open in IHNM for no reason, as each chapter uses
// a different voice file
- if (context->serial > 0)
- context->file->close();
+ if (_serial > 0)
+ _file.close();
return true;
}
-bool Resource::createContexts() {
- int i;
+Resource::Resource(SagaEngine *vm): _vm(vm) {
+}
+
+Resource::~Resource() {
+ clearContexts();
+}
+
+void Resource::addContext(const char *fileName, uint16 fileType, bool isCompressed, int serial) {
ResourceContext *context;
- int soundFileIndex = 0;
- int voicesFileIndex = 0;
- bool digitalMusic = false;
+ context = createContext();
+ context->_fileName = fileName;
+ context->_fileType = fileType;
+ context->_isCompressed = isCompressed;
+ context->_serial = serial;
+ _contexts.push_back(context);
+}
+
+bool Resource::createContexts() {
bool soundFileInArray = false;
- bool multipleVoices = false;
- bool censoredVersion = false;
- bool compressedSounds = false;
- bool compressedMusic = false;
- uint16 voiceFileType = GAME_VOICEFILE;
- bool fileFound = false;
- int maxFile = 0;
_vm->_voiceFilesExist = true;
struct SoundFileInfo {
+ int gameId;
char fileName[40];
bool isCompressed;
+ uint16 voiceFileAddType;
};
- SoundFileInfo *curSoundfiles = 0;
// If the Wyrmkeep credits file is found, set the Wyrmkeep version flag to true
if (Common::File::exists("graphics/credit3n.dlt")) {
_vm->_gf_wyrmkeep = true;
}
- _contextsCount = 0;
- for (i = 0; _vm->getFilesDescriptions()[i].fileName; i++) {
- _contextsCount++;
- if (_vm->getFilesDescriptions()[i].fileType == GAME_SOUNDFILE)
+ for (const ADGameFileDescription *gameFileDescription = _vm->getFilesDescriptions();
+ gameFileDescription->fileName; gameFileDescription++) {
+ addContext(gameFileDescription->fileName, gameFileDescription->fileType);
+ if (gameFileDescription->fileType == GAME_SOUNDFILE) {
soundFileInArray = true;
+ }
}
//// Detect and add SFX files ////////////////////////////////////////////////
- SoundFileInfo sfxFilesITE[] = {
- { "sounds.rsc", false },
- { "sounds.cmp", true },
- { "soundsd.rsc", false },
- { "soundsd.cmp", true }
- };
-
+ SoundFileInfo sfxFiles[] = {
+ { GID_ITE, "sounds.rsc", false },
+ { GID_ITE, "sounds.cmp", true },
+ { GID_ITE, "soundsd.rsc", false },
+ { GID_ITE, "soundsd.cmp", true },
#ifdef ENABLE_IHNM
- SoundFileInfo sfxFilesIHNM[] = {
- { "sfx.res", false },
- { "sfx.cmp", true }
- };
+ { GID_IHNM, "sfx.res", false },
+ { GID_IHNM, "sfx.cmp", true },
#endif
-
#ifdef ENABLE_SAGA2
- SoundFileInfo sfxFilesFTA2[] = {
- { "ftasound.hrs", false }
- };
-
- SoundFileInfo sfxFilesDino[] = {
- { "dinosnd.hrs", false },
- };
+ { GID_FTA2, "ftasound.hrs", false },
+ { GID_DINO, "dinosnd.hrs", false },
#endif
+ { -1, NULL, false }
+ };
+ _soundFileName[0] = 0;
if (!soundFileInArray) {
- // If the sound file is not specified in the detector table, add it here
- fileFound = false;
-
- switch (_vm->getGameId()) {
- case GID_ITE:
- curSoundfiles = sfxFilesITE;
- maxFile = 4;
- break;
-#ifdef ENABLE_IHNM
- case GID_IHNM:
- curSoundfiles = sfxFilesIHNM;
- maxFile = 2;
- break;
-#endif
-#ifdef ENABLE_SAGA2
- case GID_DINO:
- curSoundfiles = sfxFilesDino;
- maxFile = 1;
- break;
- case GID_FTA2:
- curSoundfiles = sfxFilesFTA2;
- maxFile = 1;
- break;
-#endif
- }
-
- for (i = 0; i < maxFile; i++) {
- if (Common::File::exists(curSoundfiles[i].fileName)) {
- _contextsCount++;
- soundFileIndex = _contextsCount - 1;
- strcpy(_soundFileName, curSoundfiles[i].fileName);
- compressedSounds = curSoundfiles[i].isCompressed;
- fileFound = true;
- break;
- }
- }
-
- if (!fileFound) {
- // No sound file found, don't add any file to the array
- soundFileInArray = true;
- if (_vm->getGameId() == GID_ITE) {
- // ITE floppy versions have both voices and sounds in voices.rsc
- voiceFileType = GAME_SOUNDFILE | GAME_VOICEFILE;
- }
+ for (SoundFileInfo *curSoundFile = sfxFiles; (curSoundFile->gameId != -1); curSoundFile++) {
+ if (curSoundFile->gameId != _vm->getGameId()) continue;
+ if (!Common::File::exists(curSoundFile->fileName)) continue;
+ strcpy(_soundFileName, curSoundFile->fileName);
+ addContext(_soundFileName, GAME_SOUNDFILE, curSoundFile->isCompressed);
+ break;
}
}
//// Detect and add voice files /////////////////////////////////////////////
- SoundFileInfo voiceFilesITE[] = {
- { "voices.rsc", false },
- { "voices.cmp", true },
- { "voicesd.rsc", false },
- { "voicesd.cmp", true },
- { "inherit the earth voices", false },
- { "inherit the earth voices.cmp", true },
- { "ite voices.bin", false }
- };
-
+ SoundFileInfo voiceFiles[] = {
+ { GID_ITE, "voices.rsc", false , (_soundFileName[0] == 0) ? GAME_SOUNDFILE : 0},
+ { GID_ITE, "voices.cmp", true , (_soundFileName[0] == 0) ? GAME_SOUNDFILE : 0},
+ { GID_ITE, "voicesd.rsc", false , (_soundFileName[0] == 0) ? GAME_SOUNDFILE : 0},
+ { GID_ITE, "voicesd.cmp", true , (_soundFileName[0] == 0) ? GAME_SOUNDFILE : 0},
+ // The resources in the Wyrmkeep combined Windows/Mac/Linux CD version are little endian, but
+ // the voice file is big endian. If we got such a version with mixed files, mark this voice file
+ // as big endian
+ { GID_ITE, "inherit the earth voices", false , _vm->isBigEndian() ? 0 : GAME_SWAPENDIAN},
+ { GID_ITE, "inherit the earth voices.cmp", true , _vm->isBigEndian() ? 0 : GAME_SWAPENDIAN},
+ { GID_ITE, "ite voices.bin", false , GAME_MACBINARY},
#ifdef ENABLE_IHNM
- SoundFileInfo voiceFilesIHNM[] = {
- { "voicess.res", false },
- { "voicess.cmp", true },
- { "voicesd.res", false },
- { "voicesd.cmp", true },
- };
+ { GID_IHNM, "voicess.res", false , 0},
+ { GID_IHNM, "voicess.cmp", true , 0},
+ { GID_IHNM, "voicesd.res", false , 0},
+ { GID_IHNM, "voicesd.cmp", true , 0},
#endif
-
#ifdef ENABLE_SAGA2
- SoundFileInfo voiceFilesFTA2[] = {
- { "ftavoice.hrs", false },
- };
+ { GID_FTA2, "ftavoice.hrs", false , 0},
#endif
+ { -1, NULL, false , 0}
+ };
// Detect and add voice files
- fileFound = false;
-
- switch (_vm->getGameId()) {
- case GID_ITE:
- curSoundfiles = voiceFilesITE;
- maxFile = 7;
- break;
-#ifdef ENABLE_IHNM
- case GID_IHNM:
- curSoundfiles = voiceFilesIHNM;
- maxFile = 4;
- break;
-#endif
-#ifdef ENABLE_SAGA2
- /*
- case GID_DINO:
- // TODO
- curSoundfiles = NULL;
- maxFile = 0;
- break;
- */
- case GID_FTA2:
- curSoundfiles = voiceFilesFTA2;
- maxFile = 1;
- break;
-#endif
- }
+ _voicesFileName[0][0] = 0;
+ for (SoundFileInfo *curSoundFile = voiceFiles; (curSoundFile->gameId != -1); curSoundFile++) {
+ if (curSoundFile->gameId != _vm->getGameId()) continue;
+ if (!Common::File::exists(curSoundFile->fileName)) continue;
- for (i = 0; i < maxFile; i++) {
- if (Common::File::exists(curSoundfiles[i].fileName)) {
- _contextsCount++;
- voicesFileIndex = _contextsCount - 1;
- strcpy(_voicesFileName[0], curSoundfiles[i].fileName);
- compressedSounds = curSoundfiles[i].isCompressed;
- fileFound = true;
-
- // Special cases
- if (!scumm_stricmp(curSoundfiles[i].fileName, "inherit the earth voices") ||
- !scumm_stricmp(curSoundfiles[i].fileName, "inherit the earth voices.cmp")) {
- // The resources in the Wyrmkeep combined Windows/Mac/Linux CD version are little endian, but
- // the voice file is big endian. If we got such a version with mixed files, mark this voice file
- // as big endian
- if (!_vm->isBigEndian())
- voiceFileType = GAME_VOICEFILE | GAME_SWAPENDIAN; // This file is big endian
- }
-
- if (!scumm_stricmp(curSoundfiles[i].fileName, "ite voices.bin")) {
- voiceFileType = GAME_VOICEFILE | GAME_MACBINARY;
- }
+ strcpy(_voicesFileName[0], curSoundFile->fileName);
+ addContext(_voicesFileName[0], GAME_VOICEFILE | curSoundFile->voiceFileAddType, curSoundFile->isCompressed);
- if (!scumm_stricmp(curSoundfiles[i].fileName, "voicess.res") ||
- !scumm_stricmp(curSoundfiles[i].fileName, "voicess.cmp")) {
+ // Special cases
+ if (!scumm_stricmp(curSoundFile->fileName, "voicess.res") ||
+ !scumm_stricmp(curSoundFile->fileName, "voicess.cmp")) {
// IHNM has multiple voice files
- multipleVoices = true;
- // Note: it is assumed that the voice files are always last in the list
- if (Common::File::exists("voices4.res") || Common::File::exists("voices4.cmp")) {
- _contextsCount += 6; // voices1-voices6
- } else {
- // The German and French versions of IHNM don't have Nimdok's chapter,
- // therefore the voices file for that chapter is missing
- _contextsCount += 5; // voices1-voices3, voices4-voices5
- censoredVersion = true;
+ for (size_t i = 1; i <= 6; i++) { // voices1-voices6
+ sprintf(_voicesFileName[i], "voices%i.%s", i, curSoundFile->isCompressed ? "cmp" : "res");
+ if (i == 4) {
+ // The German and French versions of IHNM don't have Nimdok's chapter,
+ // therefore the voices file for that chapter is missing
+ if (!Common::File::exists(_voicesFileName[i])) {
+ continue;
+ }
+ }
+ addContext(_voicesFileName[i], GAME_VOICEFILE, curSoundFile->isCompressed, i);
}
- }
-
- break;
}
+ break;
}
- if (!fileFound) {
+ if (_voicesFileName[0][0] == 0) {
if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) {
// The Macintosh version of IHNM has no voices.res, and it has all
// its voice files in subdirectories, so don't do anything here
+ _contexts.push_back(new VoiceResourceContext_RES());
} else {
warning("No voice file found, voices will be disabled");
_vm->_voicesEnabled = false;
@@ -412,83 +327,27 @@ bool Resource::createContexts() {
}
}
- //// Detect and add ITE music files /////////////////////////////////////////
- SoundFileInfo musicFilesITE[] = {
- { "music.rsc", false },
- { "music.cmp", true },
- { "musicd.rsc", false },
- { "musicd.cmp", true },
+ //// Detect and add music files /////////////////////////////////////////
+ SoundFileInfo musicFiles[] = {
+ { GID_ITE, "music.rsc", false },
+ { GID_ITE, "music.cmp", true },
+ { GID_ITE, "musicd.rsc", false },
+ { GID_ITE, "musicd.cmp", true },
+ { -1, NULL, false }
};
// Check for digital music in ITE
- if (_vm->getGameId() == GID_ITE) {
- fileFound = false;
-
- for (i = 0; i < 4; i++) {
- if (Common::File::exists(musicFilesITE[i].fileName)) {
- _contextsCount++;
- digitalMusic = true;
- compressedMusic = musicFilesITE[i].isCompressed;
- fileFound = true;
- strcpy(_musicFileName, musicFilesITE[i].fileName);
- break;
- }
- }
- if (!fileFound) {
- // No sound file found, don't add any file to the array
- digitalMusic = false;
- }
+ for (SoundFileInfo *curSoundFile = musicFiles; (curSoundFile->gameId != -1); curSoundFile++) {
+ if (curSoundFile->gameId != _vm->getGameId()) continue;
+ if (!Common::File::exists(curSoundFile->fileName)) continue;
+ strcpy(_musicFileName, curSoundFile->fileName);
+ addContext(_musicFileName, GAME_DIGITALMUSICFILE, curSoundFile->isCompressed);
+ break;
}
- _contexts = (ResourceContext*)calloc(_contextsCount, sizeof(*_contexts));
-
- for (i = 0; i < _contextsCount; i++) {
- context = &_contexts[i];
- context->file = new Common::File();
- context->serial = 0;
-
- // For ITE, add the digital music file and sfx file information here
- if (_vm->getGameId() == GID_ITE && digitalMusic && i == _contextsCount - 1) {
- context->fileName = _musicFileName;
- context->fileType = GAME_DIGITALMUSICFILE;
- context->isCompressed = compressedMusic;
- } else if (!soundFileInArray && i == soundFileIndex) {
- context->fileName = _soundFileName;
- context->fileType = GAME_SOUNDFILE;
- context->isCompressed = compressedSounds;
- } else if (_vm->_voiceFilesExist && i == voicesFileIndex && !(_vm->getGameId() == GID_IHNM && _vm->isMacResources())) {
- context->fileName = _voicesFileName[0];
- // can be GAME_VOICEFILE or GAME_SOUNDFILE | GAME_VOICEFILE or GAME_VOICEFILE | GAME_SWAPENDIAN
- context->fileType = voiceFileType;
- context->isCompressed = compressedSounds;
- } else {
- if (!(_vm->_voiceFilesExist && multipleVoices && (i > voicesFileIndex))) {
- context->fileName = _vm->getFilesDescriptions()[i].fileName;
- context->fileType = _vm->getFilesDescriptions()[i].fileType;
- context->isCompressed = compressedSounds;
- } else {
- int token = (censoredVersion && (i - voicesFileIndex >= 4)) ? 1 : 0; // censored versions don't have voice4
-
- if (compressedSounds)
- sprintf(_voicesFileName[i - voicesFileIndex + token], "voices%i.cmp", i - voicesFileIndex + token);
- else
- sprintf(_voicesFileName[i - voicesFileIndex + token], "voices%i.res", i - voicesFileIndex + token);
-
- context->fileName = _voicesFileName[i - voicesFileIndex + token];
- context->fileType = GAME_VOICEFILE;
- context->isCompressed = compressedSounds;
-
- // IHNM has several different voice files, so we need to allow
- // multiple resource contexts of the same type. We tell them
- // apart by assigning each of the duplicates a unique serial
- // number. The default behaviour when requesting a context will
- // be to look for serial number 0.
- context->serial = i - voicesFileIndex + token;
- }
- }
-
- if (!loadContext(context)) {
+ for (ResourceContextList::iterator i = _contexts.begin(); i != _contexts.end(); ++i) {
+ if (!(*i)->load(_vm, this)) {
return false;
}
}
@@ -496,27 +355,12 @@ bool Resource::createContexts() {
}
void Resource::clearContexts() {
- int i;
- size_t j;
- ResourceContext *context;
- if (_contexts == NULL) {
- return;
- }
- for (i = 0; i < _contextsCount; i++) {
- context = &_contexts[i];
- delete context->file;
- if (context->table != NULL) {
- for (j = 0; j < context->count; j++) {
- delete context->table[j].patchData;
- }
- }
- if (_vm->isSaga2()) {
- free(context->categories);
- }
- free(context->table);
+ ResourceContextList::iterator i = _contexts.begin();
+ while (i != _contexts.end()) {
+ ResourceContext * context = *i;
+ i = _contexts.erase(i);
+ delete context;
}
- free(_contexts);
- _contexts = NULL;
}
void Resource::loadResource(ResourceContext *context, uint32 resourceId, byte*&resourceBuffer, size_t &resourceSize) {
@@ -548,4 +392,14 @@ void Resource::loadResource(ResourceContext *context, uint32 resourceId, byte*&r
file->close();
}
+ResourceContext *Resource::getContext(uint16 fileType, int serial) {
+ for (ResourceContextList::const_iterator i = _contexts.begin(); i != _contexts.end(); ++i) {
+ ResourceContext * context = *i;
+ if ((context->fileType() & fileType) && (context->serial() == serial)) {
+ return context;
+ }
+ }
+ return NULL;
+}
+
} // End of namespace Saga
diff --git a/engines/saga/resource.h b/engines/saga/resource.h
index c7d7eb9126..42b7a93404 100644
--- a/engines/saga/resource.h
+++ b/engines/saga/resource.h
@@ -62,53 +62,111 @@ struct ResourceData {
size_t size;
PatchData *patchData;
- bool isExternal() { return ((offset & (1L<<31)) != 0L); } // SAGA2
+ ResourceData() :
+ id(0), offset(0), size(0), patchData(NULL) {
+ }
+
+ ~ResourceData() {
+ if (patchData) {
+ delete patchData;
+ patchData = NULL;
+ }
+ }
+
+ bool isExternal() { // SAGA2
+ return ((offset & (1L<<31)) != 0L);
+ }
+};
+
+class ResourceDataArray : public Common::Array<ResourceData> {
};
-struct ResourceContext {
- const char *fileName;
- uint16 fileType;
- Common::File *file;
- int32 fileSize;
- int serial; // IHNM speech files
-
- bool isCompressed;
- bool isBigEndian;
- ResourceData *table;
- size_t count;
- ResourceData *categories; // SAGA2
-
- Common::File *getFile(ResourceData *resourceData) const {
- if (resourceData->patchData != NULL) {
- if (!resourceData->patchData->_patchFile->isOpen())
- resourceData->patchData->_patchFile->open(resourceData->patchData->_patchDescription->fileName);
- return resourceData->patchData->_patchFile;
+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():
+ _fileName(NULL), _fileType(0), _isCompressed(false), _serial(0),
+ _isBigEndian(false),
+ _fileSize(0) {
+ }
+
+ bool isCompressed() const {
+ return _isCompressed;
+ }
+
+ uint16 fileType() const {
+ return _fileType;
+ }
+
+ int serial() const {
+ return _serial;
+ }
+
+ bool isBigEndian() const {
+ return _isBigEndian;
+ }
+
+ const char * fileName() const {
+ return _fileName;
+ }
+
+ Common::File *getFile(ResourceData *resourceData) {
+ Common::File *file;
+ const char * fn;
+ if (resourceData && resourceData->patchData != NULL) {
+ file = resourceData->patchData->_patchFile;
+ fn = resourceData->patchData->_patchDescription->fileName;
} else {
- return file;
+ file = &_file;
+ fn = _fileName;
}
+ if (!file->isOpen())
+ file->open(fn);
+ return file;
}
bool validResourceId(uint32 resourceId) const {
- return (resourceId < count);
+ return (resourceId < _table.size());
}
- ResourceData *getResourceData(uint32 resourceId) const {
- if (resourceId >= count) {
+ ResourceData *getResourceData(uint32 resourceId) {
+ if (resourceId >= _table.size()) {
error("ResourceContext::getResourceData() wrong resourceId %d", resourceId);
}
- return &table[resourceId];
+ return &_table[resourceId];
}
// SAGA 2
int32 getEntryNum(uint32 id) {
- for (int32 i = 0; i < (int32)count; i++) {
- if (table[i].id == id) {
- return i;
+ int32 num = 0;
+ for (ResourceDataArray::const_iterator i = _table.begin(); i != _table.end(); ++i) {
+ if (i->id == id) {
+ return num;
}
+ num++;
}
return -1;
}
+};
+class ResourceContextList : public Common::List<ResourceContext*> {
};
struct MetaResource {
@@ -145,32 +203,29 @@ public:
virtual uint32 convertResourceId(uint32 resourceId) = 0;
virtual void loadGlobalResources(int chapter, int actorsEntrance) = 0;
- ResourceContext *getContext(uint16 fileType, int serial = 0) {
- for (int i = 0; i < _contextsCount; i++) {
- if ((_contexts[i].fileType & fileType) && _contexts[i].serial == serial) {
- return &_contexts[i];
- }
- }
- return NULL;
- }
-
+ ResourceContext *getContext(uint16 fileType, int serial = 0);
protected:
SagaEngine *_vm;
- ResourceContext *_contexts;
- int _contextsCount;
+ ResourceContextList _contexts;
char _voicesFileName[8][256];
char _musicFileName[256];
char _soundFileName[256];
- bool loadContext(ResourceContext *context);
- virtual bool loadMacContext(ResourceContext *context) = 0;
- virtual bool loadResContext(ResourceContext *context, uint32 contextOffset, uint32 contextSize) = 0;
- bool loadResContext_v1(ResourceContext *context, uint32 contextOffset, uint32 contextSize);
+ void addContext(const char *fileName, uint16 fileType, bool isCompressed = false, int serial = 0);
+ virtual ResourceContext *createContext() = 0;
public:
virtual MetaResource* getMetaResource() = 0;
};
// ITE
+class ResourceContext_RSC: public ResourceContext {
+protected:
+ virtual bool loadMac();
+ virtual bool loadRes(uint32 contextOffset, uint32 contextSize) {
+ return loadResV1(contextOffset, contextSize);
+ }
+};
+
class Resource_RSC : public Resource {
public:
Resource_RSC(SagaEngine *vm) : Resource(vm) {}
@@ -180,32 +235,70 @@ public:
MetaResource *dummy = 0;
return dummy;
}
-private:
- virtual bool loadMacContext(ResourceContext *context);
- virtual bool loadResContext(ResourceContext *context, uint32 contextOffset, uint32 contextSize) {
- return loadResContext_v1(context, contextOffset, contextSize);
+protected:
+ virtual ResourceContext *createContext() {
+ return new ResourceContext_RSC();
}
};
#ifdef ENABLE_IHNM
// IHNM
+class ResourceContext_RES: public ResourceContext {
+protected:
+ virtual bool loadMac() {
+ return false;
+ }
+ virtual bool loadRes(uint32 contextOffset, uint32 contextSize) {
+ return loadResV1(0, contextSize);
+ }
+};
+
+//TODO: move load routines from sndres
+class VoiceResourceContext_RES: public ResourceContext {
+protected:
+ virtual bool loadMac() {
+ return false;
+ }
+ virtual bool loadRes(uint32 contextOffset, uint32 contextSize) {
+ return false;
+ }
+public:
+ VoiceResourceContext_RES() : ResourceContext() {
+ _fileType = GAME_VOICEFILE;
+ _isBigEndian = true;
+ }
+};
+
class Resource_RES : public Resource {
public:
Resource_RES(SagaEngine *vm) : Resource(vm) {}
virtual uint32 convertResourceId(uint32 resourceId) { return resourceId; }
virtual void loadGlobalResources(int chapter, int actorsEntrance);
virtual MetaResource* getMetaResource() { return &_metaResource; };
-private:
- virtual bool loadMacContext(ResourceContext *context) { return false; }
- virtual bool loadResContext(ResourceContext *context, uint32 contextOffset, uint32 contextSize) {
- return loadResContext_v1(context, 0, contextSize);
+protected:
+ virtual ResourceContext *createContext() {
+ return new ResourceContext_RES();
}
+private:
MetaResource _metaResource;
};
#endif
#ifdef ENABLE_SAGA2
// DINO, FTA2
+class ResourceContext_HRS: public ResourceContext {
+protected:
+ ResourceDataArray _categories;
+
+ virtual bool loadMac() {
+ return false;
+ }
+ virtual bool loadRes(uint32 contextOffset, uint32 contextSize) {
+ return loadResV2(contextSize);
+ }
+ bool loadResV2(uint32 contextSize);
+};
+
class Resource_HRS : public Resource {
public:
Resource_HRS(SagaEngine *vm) : Resource(vm) {}
@@ -215,12 +308,10 @@ public:
MetaResource *dummy = 0;
return dummy;
}
-private:
- virtual bool loadMacContext(ResourceContext *context) { return false; }
- virtual bool loadResContext(ResourceContext *context, uint32 contextOffset, uint32 contextSize) {
- return loadResContext_v2(context, contextSize);
+protected:
+ virtual ResourceContext *createContext() {
+ return new ResourceContext_HRS();
}
- bool loadResContext_v2(ResourceContext *context, uint32 contextSize);
};
#endif
diff --git a/engines/saga/resource_hrs.cpp b/engines/saga/resource_hrs.cpp
index 9a7b593913..2ec2099c8d 100644
--- a/engines/saga/resource_hrs.cpp
+++ b/engines/saga/resource_hrs.cpp
@@ -42,64 +42,54 @@
namespace Saga {
-void readElement(Common::File *file, Saga::ResourceData *element) {
- element->id = file->readUint32BE();
- element->offset = file->readUint32LE();
- element->size = file->readUint32LE();
- debug(3, "Entry: id %u, offset %u, size %u", element->id, (uint)element->offset, (uint)element->size);
+void readElement(Common::File &file, Saga::ResourceData &element) {
+ element.id = file.readUint32BE();
+ element.offset = file.readUint32LE();
+ element.size = file.readUint32LE();
+ debug(3, "Entry: id %u, offset %u, size %u", element.id, (uint)element.offset, (uint)element.size);
}
-bool Resource_HRS::loadResContext_v2(ResourceContext *context, uint32 contextSize) {
- ResourceData *origin = new ResourceData();
+bool ResourceContext_HRS::loadResV2(uint32 contextSize) {
+ ResourceData origin;
uint32 firstEntryOffset;
uint32 tableSize;
int i, count;
const uint32 resourceSize = 4 + 4 + 4; // id, size, offset
- debug(3, "Context %s =====", context->fileName);
- context->file->seek(0, SEEK_SET);
+ debug(3, "Context %s =====", _fileName);
+ _file.seek(0, SEEK_SET);
- readElement(context->file, origin);
+ readElement(_file, origin);
// Check if the file is valid
- if (origin->id != MKID_BE('HRES')) { // header
- delete origin;
+ if (origin.id != MKID_BE('HRES')) { // header
return false;
}
// Read offset of first entry
- context->file->seek(origin->offset - sizeof(uint32), SEEK_SET);
- firstEntryOffset = context->file->readUint32LE();
+ _file.seek(origin.offset - sizeof(uint32), SEEK_SET);
+ firstEntryOffset = _file.readUint32LE();
// Allocate buffers for table, categories and data
- context->categories = (ResourceData *) calloc(origin->size / resourceSize, sizeof(*context->categories));
- tableSize = origin->offset - firstEntryOffset - sizeof(uint32);
- context->table = (ResourceData *) calloc(tableSize / resourceSize, sizeof(*context->table));
-
- if (context->categories == NULL || context->table == NULL) {
- delete origin;
- return false;
- }
+ _categories.resize(origin.size / resourceSize);
+ tableSize = origin.offset - firstEntryOffset - sizeof(uint32);
+ _table.resize(tableSize / resourceSize);
// Read categories
- count = origin->size / resourceSize;
+ count = origin.size / resourceSize;
debug(3, "Categories: %d =====", count);
for (i = 0; i < count; i++) {
- readElement(context->file, &context->categories[i]);
+ readElement(_file, _categories[i]);
}
- context->file->seek(firstEntryOffset, SEEK_SET);
+ _file.seek(firstEntryOffset, SEEK_SET);
// Read table entries
count = tableSize / resourceSize;
debug(3, "Entries: %d =====", count);
for (i = 0; i < count; i++) {
- readElement(context->file, &context->table[i]);
+ readElement(_file, _table[i]);
}
-
- context->count = tableSize / resourceSize;
-
- delete origin;
return true;
}
diff --git a/engines/saga/resource_rsc.cpp b/engines/saga/resource_rsc.cpp
index 035db7723a..7d5753ea07 100644
--- a/engines/saga/resource_rsc.cpp
+++ b/engines/saga/resource_rsc.cpp
@@ -52,6 +52,12 @@ struct MacResource {
byte attr;
int32 dataOffset;
byte name[255];
+ MacResource() : id(0), nameOffset(0), attr(0), dataOffset(0) {
+ name[0] = 0;
+ }
+};
+
+class MacResourceArray : public Common::Array<MacResource> {
};
struct MacResType {
@@ -59,27 +65,17 @@ struct MacResType {
int16 items;
int16 maxItemId;
int16 offset;
- MacResource *resources;
+ MacResourceArray resources;
+ MacResType() : id(0), items(0), maxItemId(0), offset(0) {
+ }
};
-#define ID_MIDI MKID_BE('Midi')
-
-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);
- }
- }
- }
+class MacResTypeArray : public Common::Array<MacResType> {
+};
- return resourceId;
-}
+#define ID_MIDI MKID_BE('Midi')
-bool Resource_RSC::loadMacContext(ResourceContext *context) {
+bool ResourceContext_RSC::loadMac() {
int32 macDataSize, macDataSizePad;
int32 macResSize, macResSizePad;
int32 macResOffset;
@@ -90,123 +86,127 @@ bool Resource_RSC::loadMacContext(ResourceContext *context) {
uint32 macDataOffset;
MacResMap macResMap;
- MacResType *macResTypes;
+ MacResTypeArray macResTypes;
- MacResType *macResType;
- MacResource *macResource;
- int i, j;
byte macNameLen;
bool notSagaContext = false;
- if (context->fileSize < RSC_MIN_FILESIZE + MAC_BINARY_HEADER_SIZE) {
+ if (_fileSize < RSC_MIN_FILESIZE + MAC_BINARY_HEADER_SIZE) {
return false;
}
- if (context->file->readByte() != 0) {
+ if (_file.readByte() != 0) {
return false;
}
- context->file->readByte(); //MAX Name Len
- context->file->seek(74);
- if (context->file->readByte() != 0) {
+ _file.readByte(); //MAX Name Len
+ _file.seek(74);
+ if (_file.readByte() != 0) {
return false;
}
- context->file->seek(82);
- if (context->file->readByte() != 0) {
+ _file.seek(82);
+ if (_file.readByte() != 0) {
return false;
}
- macDataSize = context->file->readSint32BE();
- macResSize = context->file->readSint32BE();
+ macDataSize = _file.readSint32BE();
+ macResSize = _file.readSint32BE();
macDataSizePad = (((macDataSize + 127) >> 7) << 7);
macResSizePad = (((macResSize + 127) >> 7) << 7);
macResOffset = MAC_BINARY_HEADER_SIZE + macDataSizePad;
- context->file->seek(macResOffset);
+ _file.seek(macResOffset);
- macDataOffset = context->file->readUint32BE() + macResOffset;
- macMapOffset = context->file->readUint32BE() + macResOffset;
- macDataLength = context->file->readUint32BE();
- macMapLength = context->file->readUint32BE();
+ macDataOffset = _file.readUint32BE() + macResOffset;
+ macMapOffset = _file.readUint32BE() + macResOffset;
+ macDataLength = _file.readUint32BE();
+ macMapLength = _file.readUint32BE();
- if (macDataOffset >= (uint)context->fileSize || macMapOffset >= (uint)context->fileSize ||
- macDataLength + macMapLength > (uint)context->fileSize) {
+ if (macDataOffset >= (uint)_fileSize || macMapOffset >= (uint)_fileSize ||
+ macDataLength + macMapLength > (uint)_fileSize) {
return false;
}
- context->file->seek(macMapOffset + 22);
+ _file.seek(macMapOffset + 22);
- macResMap.resAttr = context->file->readUint16BE();
- macResMap.typeOffset = context->file->readUint16BE();
- macResMap.nameOffset = context->file->readUint16BE();
- macResMap.numTypes = context->file->readUint16BE();
+ macResMap.resAttr = _file.readUint16BE();
+ macResMap.typeOffset = _file.readUint16BE();
+ macResMap.nameOffset = _file.readUint16BE();
+ macResMap.numTypes = _file.readUint16BE();
macResMap.numTypes++;
- context->file->seek(macMapOffset + macResMap.typeOffset + 2);
+ _file.seek(macMapOffset + macResMap.typeOffset + 2);
- macResTypes = (MacResType *)calloc(macResMap.numTypes, sizeof(*macResTypes));
+ macResTypes.resize(macResMap.numTypes);
- for (i = macResMap.numTypes, macResType = macResTypes; i > 0; i--, macResType++) {
- macResType->id = context->file->readUint32BE();
- macResType->items = context->file->readUint16BE();
- macResType->offset = context->file->readUint16BE();
- macResType->items++;
- macResType->resources = (MacResource*)calloc(macResType->items, sizeof(*macResType->resources));
+ for (MacResTypeArray::iterator k = macResTypes.begin(); k != macResTypes.end(); ++k) {
+ k->id = _file.readUint32BE();
+ k->items = _file.readUint16BE();
+ k->offset = _file.readUint16BE();
+ k->items++;
+ k->resources.resize(k->items);
}
- for (i = macResMap.numTypes, macResType = macResTypes; i > 0; i--, macResType++) {
- context->file->seek(macResType->offset + macMapOffset + macResMap.typeOffset);
+ for (MacResTypeArray::iterator k = macResTypes.begin(); k != macResTypes.end(); ++k) {
+ _file.seek(k->offset + macMapOffset + macResMap.typeOffset);
- for (j = macResType->items, macResource = macResType->resources; j > 0; j--, macResource++) {
- macResource->id = context->file->readUint16BE();
- macResource->nameOffset = context->file->readUint16BE();
- macResource->dataOffset = context->file->readUint32BE();
- macResSize = context->file->readUint32BE();
+ for (MacResourceArray::iterator j = k->resources.begin(); j != k->resources.end(); ++j) {
+ j->id = _file.readUint16BE();
+ j->nameOffset = _file.readUint16BE();
+ j->dataOffset = _file.readUint32BE();
+ macResSize = _file.readUint32BE();
- macResource->attr = macResource->dataOffset >> 24;
- macResource->dataOffset &= 0xFFFFFF;
- if (macResource->id > macResType->maxItemId) {
- macResType->maxItemId = macResource->id;
+ j->attr = j->dataOffset >> 24;
+ j->dataOffset &= 0xFFFFFF;
+ if (j->id > k->maxItemId) {
+ k->maxItemId = j->id;
}
}
- for (j = macResType->items, macResource = macResType->resources; j > 0; j--, macResource++) {
- if (macResource->nameOffset != -1) {
- context->file->seek(macResource->nameOffset + macMapOffset + macResMap.nameOffset);
- macNameLen = context->file->readByte();
- context->file->read(macResource->name, macNameLen);
+ for (MacResourceArray::iterator j = k->resources.begin(); j != k->resources.end(); ++j) {
+ if (j->nameOffset != -1) {
+ _file.seek(j->nameOffset + macMapOffset + macResMap.nameOffset);
+ macNameLen = _file.readByte();
+ _file.read(j->name, macNameLen);
}
}
}
-//
- for (i = macResMap.numTypes, macResType = macResTypes; i > 0; i--, macResType++) {
+ //
+ for (MacResTypeArray::iterator k = macResTypes.begin(); k != macResTypes.end(); ++k) {
//getting offsets & sizes of midi
- if (((context->fileType & GAME_MUSICFILE_GM) > 0) && (macResType->id == ID_MIDI)) {
-
- context->count = macResType->maxItemId + 1;
- context->table = (ResourceData *)calloc(context->count, sizeof(*context->table));
- for (j = macResType->items, macResource = macResType->resources; j > 0; j--, macResource++) {
- context->file->seek(macDataOffset + macResource->dataOffset);
- context->table[macResource->id].size = context->file->readUint32BE();
- context->table[macResource->id].offset = context->file->pos();
+ 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();
}
notSagaContext = true;
break;
}
}
-//free
- for (i = 0; i < macResMap.numTypes; i++) {
- free(macResTypes[i].resources);
- }
- free(macResTypes);
-
- if ((!notSagaContext) && (!loadResContext(context, MAC_BINARY_HEADER_SIZE, macDataSize))) {
+ 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
diff --git a/engines/saga/saga.h b/engines/saga/saga.h
index 2cf15946e7..674447a511 100644
--- a/engines/saga/saga.h
+++ b/engines/saga/saga.h
@@ -79,7 +79,7 @@ class PalAnim;
class Puzzle;
class Resource;
-struct ResourceContext;
+class ResourceContext;
struct StringList;
using Common::MemoryReadStream;
diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp
index f43db12d1a..5cb1890a2d 100644
--- a/engines/saga/scene.cpp
+++ b/engines/saga/scene.cpp
@@ -168,7 +168,7 @@ Scene::Scene(SagaEngine *vm) : _vm(vm) {
memoryError("Scene::Scene()");
}
- MemoryReadStreamEndian readS(sceneLUTPointer, sceneLUTLength, _sceneContext->isBigEndian);
+ MemoryReadStreamEndian readS(sceneLUTPointer, sceneLUTLength, _sceneContext->isBigEndian());
for (i = 0; i < _sceneCount; i++) {
_sceneLUT[i] = readS.readUint16();
@@ -929,7 +929,7 @@ void Scene::loadSceneDescriptor(uint32 resourceId) {
_vm->_resource->loadResource(_sceneContext, resourceId, sceneDescriptorData, sceneDescriptorDataLength);
if (sceneDescriptorDataLength == 16) {
- MemoryReadStreamEndian readS(sceneDescriptorData, sceneDescriptorDataLength, _sceneContext->isBigEndian);
+ MemoryReadStreamEndian readS(sceneDescriptorData, sceneDescriptorDataLength, _sceneContext->isBigEndian());
_sceneDescription.flags = readS.readSint16();
_sceneDescription.resourceListResourceId = readS.readSint16();
@@ -960,7 +960,7 @@ void Scene::loadSceneResourceList(uint32 resourceId) {
_vm->_resource->loadResource(_sceneContext, resourceId, resourceListData, resourceListDataLength);
if ((resourceListDataLength % SAGA_RESLIST_ENTRY_LEN) == 0) {
- MemoryReadStreamEndian readS(resourceListData, resourceListDataLength, _sceneContext->isBigEndian);
+ MemoryReadStreamEndian readS(resourceListData, resourceListDataLength, _sceneContext->isBigEndian());
// Allocate memory for scene resource list
_resourceListCount = resourceListDataLength / SAGA_RESLIST_ENTRY_LEN;
@@ -1302,7 +1302,7 @@ void Scene::loadSceneEntryList(const byte* resourcePointer, size_t resourceLengt
_entryList.entryListCount = resourceLength / 8;
- MemoryReadStreamEndian readS(resourcePointer, resourceLength, _sceneContext->isBigEndian);
+ MemoryReadStreamEndian readS(resourcePointer, resourceLength, _sceneContext->isBigEndian());
if (_entryList.entryList)
diff --git a/engines/saga/script.cpp b/engines/saga/script.cpp
index 8ddcc7d0bb..6f8810af40 100644
--- a/engines/saga/script.cpp
+++ b/engines/saga/script.cpp
@@ -109,7 +109,7 @@ SAGA1Script::SAGA1Script(SagaEngine *vm) : Script(vm) {
}
// Convert LUT resource to logical LUT
- MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, resourceContext->isBigEndian);
+ MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, resourceContext->isBigEndian());
for (i = 0; i < _modulesCount; i++) {
memset(&_modules[i], 0, sizeof(ModuleData));
@@ -1127,7 +1127,7 @@ void Script::loadModuleBase(ModuleData &module, const byte *resourcePointer, siz
memcpy(module.moduleBase, resourcePointer, resourceLength);
- MemoryReadStreamEndian scriptS(module.moduleBase, module.moduleBaseSize, _scriptContext->isBigEndian);
+ MemoryReadStreamEndian scriptS(module.moduleBase, module.moduleBaseSize, _scriptContext->isBigEndian());
module.entryPointsCount = scriptS.readUint16();
scriptS.readUint16(); //skip
@@ -1177,7 +1177,7 @@ void Script::loadVoiceLUT(VoiceLUT &voiceLUT, const byte *resourcePointer, size_
error("Script::loadVoiceLUT() not enough memory");
}
- MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, _scriptContext->isBigEndian);
+ MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, _scriptContext->isBigEndian());
for (i = 0; i < voiceLUT.voicesCount; i++) {
voiceLUT.voices[i] = scriptS.readUint16();
diff --git a/engines/saga/sndres.cpp b/engines/saga/sndres.cpp
index eddd35300e..05dd6219a1 100644
--- a/engines/saga/sndres.cpp
+++ b/engines/saga/sndres.cpp
@@ -48,15 +48,14 @@ namespace Saga {
#define RID_IHNM_SFX_LUT 265
#define RID_IHNMDEMO_SFX_LUT 222
-SndRes::SndRes(SagaEngine *vm) : _vm(vm) {
+SndRes::SndRes(SagaEngine *vm) : _vm(vm), _sfxContext(NULL), _voiceContext(NULL), _voiceSerial(-1) {
+
// Load sound module resource file contexts
_sfxContext = _vm->_resource->getContext(GAME_SOUNDFILE);
if (_sfxContext == NULL) {
error("SndRes::SndRes resource context not found");
}
- _voiceSerial = -1;
-
setVoiceBank(0);
if (_vm->getGameId() == GID_ITE) {
@@ -117,6 +116,7 @@ SndRes::~SndRes() {
}
void SndRes::setVoiceBank(int serial) {
+ Common::File *file;
if (_voiceSerial == serial)
return;
@@ -126,12 +126,7 @@ void SndRes::setVoiceBank(int serial) {
if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) {
_voiceSerial = serial;
// Set a dummy voice context
- _voiceContext = new ResourceContext();
- _voiceContext->fileType = GAME_VOICEFILE;
- _voiceContext->count = 0;
- _voiceContext->serial = 0;
- _voiceContext->isBigEndian = true;
- _voiceContext->isCompressed = false;
+ _voiceContext = new VoiceResourceContext_RES();
return;
}
#endif
@@ -141,16 +136,16 @@ void SndRes::setVoiceBank(int serial) {
return;
// Close previous voice bank file
- if (_voiceSerial >= 0 && _voiceContext->file->isOpen())
- _voiceContext->file->close();
+ if (_voiceContext != NULL) {
+ file = _voiceContext->getFile(NULL);
+ if (file->isOpen()) {
+ file->close();
+ }
+ }
_voiceSerial = serial;
_voiceContext = _vm->_resource->getContext(GAME_VOICEFILE, _voiceSerial);
-
- // Open new voice bank file
- if (!_voiceContext->file->isOpen())
- _voiceContext->file->open(_voiceContext->fileName);
}
void SndRes::playSound(uint32 resourceId, int volume, bool loop) {
@@ -199,11 +194,12 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
}
#ifdef ENABLE_IHNM
+ //TODO: move to resource_res so we can use normal "getResourceData" and "getFile" methods
if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) {
char soundFileName[40];
int dirIndex = resourceId / 64;
- if ((context->fileType & GAME_VOICEFILE) != 0) {
+ if ((context->fileType() & GAME_VOICEFILE) != 0) {
if (_voiceSerial == 0) {
sprintf(soundFileName, "Voices/VoicesS/Voices%d/VoicesS%03x", dirIndex, resourceId);
} else {
@@ -217,7 +213,6 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
file->open(soundFileName);
soundResourceLength = file->size();
- context->isBigEndian = true;
} else
#endif
{
@@ -249,14 +244,14 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
bool uncompressedSound = false;
// If patch data exists for sound resource 4 (used in ITE intro), don't treat this sound as compressed
// Patch data for this resource is in file p2_a.iaf or p2_a.voc
- if (_vm->getGameId() == GID_ITE && resourceId == 4 && context->table[resourceId].patchData != NULL)
+ if (_vm->getGameId() == GID_ITE && resourceId == 4 && context->getResourceData(resourceId)->patchData != NULL)
uncompressedSound = true;
// FIXME: Currently, the SFX.RES file in IHNM cannot be compressed
- if (_vm->getGameId() == GID_IHNM && (context->fileType & GAME_SOUNDFILE))
+ if (_vm->getGameId() == GID_IHNM && (context->fileType() & GAME_SOUNDFILE))
uncompressedSound = true;
- if (context->isCompressed && !uncompressedSound) {
+ if (context->isCompressed() && !uncompressedSound) {
if (header[0] == char(0)) {
resourceType = kSoundMP3;
} else if (header[0] == char(1)) {
@@ -269,7 +264,7 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
}
// Default sound type is 16-bit signed PCM, used in ITE by PCM and VOX files
- buffer.isCompressed = context->isCompressed;
+ buffer.isCompressed = context->isCompressed();
buffer.soundType = resourceType;
buffer.originalSize = 0;
// Set default flags and frequency for PCM, VOC and VOX files, which got no header
@@ -281,20 +276,20 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
buffer.flags &= ~Audio::Mixer::FLAG_16BITS;
} else {
// Voice files in newer ITE demo versions are OKI ADPCM (VOX) encoded
- if (!scumm_stricmp(context->fileName, "voicesd.rsc"))
+ if (!scumm_stricmp(context->fileName(), "voicesd.rsc"))
resourceType = kSoundVOX;
}
}
buffer.buffer = NULL;
// Check for LE sounds
- if (!context->isBigEndian)
+ if (!context->isBigEndian())
buffer.flags |= Audio::Mixer::FLAG_LITTLE_ENDIAN;
- if ((context->fileType & GAME_VOICEFILE) && (_vm->getFeatures() & GF_LE_VOICES))
+ if ((context->fileType() & GAME_VOICEFILE) && (_vm->getFeatures() & GF_LE_VOICES))
buffer.flags |= Audio::Mixer::FLAG_LITTLE_ENDIAN;
// Older Mac versions of ITE were Macbinary packed
- int soundOffset = (context->fileType & GAME_MACBINARY) ? 36 : 0;
+ int soundOffset = (context->fileType() & GAME_MACBINARY) ? 36 : 0;
switch (resourceType) {
case kSoundPCM:
@@ -404,7 +399,7 @@ int SndRes::getVoiceLength(uint32 resourceId) {
return -1;
}
- if (!_voiceContext->isCompressed || buffer.originalSize == 0)
+ if (!_voiceContext->isCompressed() || buffer.originalSize == 0)
msDouble = (double)buffer.size;
else
msDouble = (double)buffer.originalSize;
diff --git a/engines/saga/sprite.cpp b/engines/saga/sprite.cpp
index 7296637c2c..9e93efde4e 100644
--- a/engines/saga/sprite.cpp
+++ b/engines/saga/sprite.cpp
@@ -106,7 +106,7 @@ void Sprite::loadList(int resourceId, SpriteList &spriteList) {
return;
}
- MemoryReadStreamEndian readS(spriteListData, spriteListLength, _spriteContext->isBigEndian);
+ MemoryReadStreamEndian readS(spriteListData, spriteListLength, _spriteContext->isBigEndian());
spriteCount = readS.readUint16();
@@ -142,7 +142,7 @@ void Sprite::loadList(int resourceId, SpriteList &spriteList) {
spritePointer += offset;
if (bigHeader) {
- MemoryReadStreamEndian readS2(spritePointer, 8, _spriteContext->isBigEndian);
+ MemoryReadStreamEndian readS2(spritePointer, 8, _spriteContext->isBigEndian());
spriteInfo->xAlign = readS2.readSint16();
spriteInfo->yAlign = readS2.readSint16();