From aa147a2f5af167048b3d57da558bc39a91c3a936 Mon Sep 17 00:00:00 2001 From: Andrew Kurushin Date: Fri, 4 Dec 2009 17:52:42 +0000 Subject: refactor resource module: - struct ResourceContext => class ResourceContext - replace "*alloc","free" with array templates - simplify createContexts routines svn-id: r46254 --- engines/saga/actor.cpp | 2 +- engines/saga/font.cpp | 2 +- engines/saga/music.cpp | 4 +- engines/saga/resource.cpp | 458 ++++++++++++++---------------------------- engines/saga/resource.h | 201 +++++++++++++----- engines/saga/resource_hrs.cpp | 50 ++--- engines/saga/resource_rsc.cpp | 166 +++++++-------- engines/saga/saga.h | 2 +- engines/saga/scene.cpp | 8 +- engines/saga/script.cpp | 6 +- engines/saga/sndres.cpp | 47 ++--- engines/saga/sprite.cpp | 4 +- 12 files changed, 440 insertions(+), 510 deletions(-) (limited to 'engines/saga') 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 { }; -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 { }; 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 { }; 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 { +}; - 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(); -- cgit v1.2.3