From e88d6265d8ea3d1133661073a5484e0ed372458e Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 20 Jul 2014 21:19:20 +0300 Subject: SAGA: Add support for MIDI music in SAGA2 games --- engines/saga/interface.cpp | 5 +++++ engines/saga/introproc_saga2.cpp | 6 ------ engines/saga/music.cpp | 12 ++++++++--- engines/saga/resource.h | 16 +++++++++++--- engines/saga/resource_hrs.cpp | 45 ++++++++++++++++++++++++++++++++-------- 5 files changed, 63 insertions(+), 21 deletions(-) diff --git a/engines/saga/interface.cpp b/engines/saga/interface.cpp index 680b2274f5..44581f26fc 100644 --- a/engines/saga/interface.cpp +++ b/engines/saga/interface.cpp @@ -710,6 +710,11 @@ bool Interface::processAscii(Common::KeyState keystate) { } void Interface::setStatusText(const char *text, int statusColor) { + if (_vm->getGameId() == GID_FTA2 || _vm->getGameId() == GID_DINO) { + warning("setStatusText not implemented for SAGA2"); + return; + } + if (_vm->getGameId() == GID_IHNM) { // Don't show the status text for the IHNM chapter selection screens (chapter 8), or // scene 0 (IHNM demo introduction) diff --git a/engines/saga/introproc_saga2.cpp b/engines/saga/introproc_saga2.cpp index 710236b0c4..0b773b03f0 100644 --- a/engines/saga/introproc_saga2.cpp +++ b/engines/saga/introproc_saga2.cpp @@ -43,9 +43,6 @@ int Scene::DinoStartProc() { playMovie("testvid.smk"); - // HACK: Forcibly quit here - _vm->quitGame(); - return SUCCESS; } @@ -55,9 +52,6 @@ int Scene::FTA2StartProc() { playMovie("trimark.smk"); playMovie("intro.smk"); - // HACK: Forcibly quit here - _vm->quitGame(); - return SUCCESS; } diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp index 6e36f51dee..d20882ca26 100644 --- a/engines/saga/music.cpp +++ b/engines/saga/music.cpp @@ -147,7 +147,7 @@ Music::Music(SagaEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) { if (!_musicContext) { if (_vm->getGameId() == GID_ITE) { _musicContext = _vm->_resource->getContext(GAME_RESOURCEFILE); - } else { + } else if (_vm->getGameId() == GID_IHNM) { // I've listened to music from both the FM and the GM // file, and I've tentatively reached the conclusion // that they are both General MIDI. My guess is that @@ -173,6 +173,8 @@ Music::Music(SagaEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) { // Note that the IHNM demo has only got one music file // (music.rsc). It is assumed that it contains FM music _musicContext = _vm->_resource->getContext(GAME_MUSICFILE_FM); + } else if (_vm->getGameId() == GID_DINO || _vm->getGameId() == GID_FTA2) { + _musicContext = _vm->_resource->getContext(GAME_SOUNDFILE); } } @@ -255,14 +257,18 @@ void Music::play(uint32 resourceId, MusicFlags flags) { _mixer->stopHandle(_musicHandle); _player->stop(); - int realTrackNumber; + int realTrackNumber = 0; if (_vm->getGameId() == GID_ITE) { if (flags == MUSIC_NORMAL && (resourceId == 13 || resourceId == 19)) flags = MUSIC_LOOP; realTrackNumber = resourceId - 8; - } else { + } else if (_vm->getGameId() == GID_IHNM) { + realTrackNumber = resourceId + 1; + } else if (_vm->getGameId() == GID_DINO || _vm->getGameId() == GID_FTA2) { realTrackNumber = resourceId + 1; + uint32 musicTrackTag = MKTAG('X','M','I', (byte)(resourceId + 1)); + resourceId = _musicContext->getEntryNum(musicTrackTag); } // Try to open standalone digital track diff --git a/engines/saga/resource.h b/engines/saga/resource.h index 252e92c967..2a1aaf3103 100644 --- a/engines/saga/resource.h +++ b/engines/saga/resource.h @@ -60,12 +60,13 @@ struct PatchData { struct ResourceData { uint32 id; // SAGA2 + uint32 category; // SAGA2 size_t offset; size_t size; PatchData *patchData; ResourceData() : - id(0), offset(0), size(0), patchData(NULL) { + id(0), category(0), offset(0), size(0), patchData(NULL) { } ~ResourceData() { @@ -130,10 +131,15 @@ public: // SAGA 2 int32 getEntryNum(uint32 id) { int32 num = 0; + uint32 miloCategory = MKTAG('M', 'I', 'L', 'O'); + for (ResourceDataArray::const_iterator i = _table.begin(); i != _table.end(); ++i) { - if (i->id == id) { + //uint32 c = i->category; + //debug("%c%c%c%c, offset: %d, size: %d", (c >> 24), (c >> 16) & 0xFF, (c >> 8) & 0xFF, c & 0xFF, i->offset, i->size); + // Ignore low quality music resources (MILO) + if (i->id == id && i->category != miloCategory) return num; - } + num++; } return -1; @@ -282,6 +288,10 @@ protected: return loadResV2(contextSize); } bool loadResV2(uint32 contextSize); + + void readCategory(ResourceData &element); + void readEntry(ResourceData &element); + uint32 getCategory(uint32 resourceOffset); }; class Resource_HRS : public Resource { diff --git a/engines/saga/resource_hrs.cpp b/engines/saga/resource_hrs.cpp index 09da9cf0bb..ba58830269 100644 --- a/engines/saga/resource_hrs.cpp +++ b/engines/saga/resource_hrs.cpp @@ -39,13 +39,35 @@ namespace Saga { -void readElement(Common::File &file, Saga::ResourceData &element) { - element.id = file.readUint32BE(); - element.offset = file.readUint32LE(); - element.size = file.readUint32LE(); +void ResourceContext_HRS::readCategory(ResourceData &element) { + element.id = _file.readUint32BE(); + element.offset = _file.readUint32LE(); + element.size = _file.readUint32LE(); + element.category = 0; + debug(3, "Category: id %u, offset %u, size %u", element.id, (uint)element.offset, (uint)element.size); +} + +void ResourceContext_HRS::readEntry(ResourceData &element) { + element.id = _file.readUint32BE(); + element.offset = _file.readUint32LE(); + element.size = _file.readUint32LE(); + element.category = getCategory(_file.pos()); debug(3, "Entry: id %u, offset %u, size %u", element.id, (uint)element.offset, (uint)element.size); } +uint32 ResourceContext_HRS::getCategory(uint32 resourceOffset) { + for (int i = _categories.size() - 1; i >= 0; --i) { + if (resourceOffset >= _categories[i].offset) + return _categories[i].id; + } + + error("Unknown category for offset %d", resourceOffset); +} + +static bool categorySortHelper(const ResourceData &r1, const ResourceData &r2) { + return r1.offset < r2.offset; +} + bool ResourceContext_HRS::loadResV2(uint32 contextSize) { ResourceData origin; uint32 firstEntryOffset; @@ -56,7 +78,7 @@ bool ResourceContext_HRS::loadResV2(uint32 contextSize) { debug(3, "Context %s =====", _fileName); _file.seek(0, SEEK_SET); - readElement(_file, origin); + readCategory(origin); // Check if the file is valid if (origin.id != MKTAG('H','R','E','S')) { // header @@ -74,18 +96,23 @@ bool ResourceContext_HRS::loadResV2(uint32 contextSize) { // Read categories count = origin.size / resourceSize; - debug(3, "Categories: %d =====", count); + debug(3, "File: %s, categories: %d =====", _file.getName(), count); for (i = 0; i < count; i++) { - readElement(_file, _categories[i]); + readCategory(_categories[i]); + //uint32 id = _categories[i].id; + //debug("%i: %c%c%c%c, offset: %d, size: %d", i, (id >> 24), (id >> 16) & 0xFF, (id >> 8) & 0xFF, id & 0xFF, _categories[i].offset, _categories[i].size); } + Common::sort(_categories.begin(), _categories.end(), categorySortHelper); + _file.seek(firstEntryOffset, SEEK_SET); // Read table entries count = tableSize / resourceSize; - debug(3, "Entries: %d =====", count); + debug(3, "File: %s, entries: %d =====", _file.getName(), count); for (i = 0; i < count; i++) { - readElement(_file, _table[i]); + readEntry(_table[i]); + //debug("%i: offset: %d, size: %d", i, _table[i].offset, _table[i].size); } return true; } -- cgit v1.2.3