diff options
-rw-r--r-- | engines/sci/resource.cpp | 72 | ||||
-rw-r--r-- | engines/sci/resource.h | 3 | ||||
-rw-r--r-- | engines/sci/resource_audio.cpp | 63 | ||||
-rw-r--r-- | engines/sci/sound/audio.cpp | 24 |
4 files changed, 90 insertions, 72 deletions
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 307b4e888e..0b7badb8f7 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -481,6 +481,7 @@ int ResourceManager::addAppropriateSources() { addPatchDir("Robot Folder"); addPatchDir("Sound Folder"); addPatchDir("Voices Folder"); + addPatchDir("Voices"); //addPatchDir("VMD Folder"); // There can also be a "Patches" resource fork with patches @@ -620,11 +621,11 @@ void ResourceManager::scanNewSources() { switch (source->source_type) { case kSourceDirectory: readResourcePatches(source); -#ifdef ENABLE_SCI32 + // We can't use getSciVersion() at this point, thus using _volVersion if (_volVersion >= kResVersionSci11) // SCI1.1+ readResourcePatchesBase36(source); -#endif + readWaveAudioPatches(); break; case kSourceExtMap: @@ -1070,18 +1071,14 @@ ResourceManager::ResVersion ResourceManager::detectVolVersion() { // version-agnostic patch application void ResourceManager::processPatch(ResourceSource *source, ResourceType resourceType, uint16 resourceNr, uint32 tuple) { Common::SeekableReadStream *fileStream = 0; - Resource *newrsc; + Resource *newrsc = 0; ResourceId resId = ResourceId(resourceType, resourceNr, tuple); ResourceType checkForType = resourceType; - byte patchType, patchDataOffset; - int fsize; - uint32 audio36Header = 0; // base36 encoded patches (i.e. audio36 and sync36) have the same type as their non-base36 encoded counterparts if (checkForType == kResourceTypeAudio36) checkForType = kResourceTypeAudio; - - if (checkForType == kResourceTypeSync36) + else if (checkForType == kResourceTypeSync36) checkForType = kResourceTypeSync; if (source->resourceFile) { @@ -1094,18 +1091,15 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource } fileStream = file; } - fsize = fileStream->size(); + + int fsize = fileStream->size(); if (fsize < 3) { debug("Patching %s failed - file too small", source->location_name.c_str()); return; } - patchType = fileStream->readByte() & 0x7F; - patchDataOffset = fileStream->readByte(); - - if (resourceType == kResourceTypeAudio36) { - audio36Header = fileStream->readUint32BE(); - } + byte patchType = fileStream->readByte() & 0x7F; + byte patchDataOffset = fileStream->readByte(); delete fileStream; @@ -1114,13 +1108,6 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource return; } - if (resourceType == kResourceTypeAudio36) { - if (audio36Header != MKID_BE('SOL\x00')) { - debug("Patching %s failed - audio36 patch doesn't have SOL header", source->location_name.c_str()); - return; - } - } - // Fixes SQ5/German, patch file special case logic taken from SCI View disassembly if (patchDataOffset & 0x80) { switch (patchDataOffset & 0x7F) { @@ -1144,12 +1131,14 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource source->location_name.c_str(), patchDataOffset + 2, fsize); return; } + // Prepare destination, if neccessary if (_resMap.contains(resId) == false) { newrsc = new Resource; _resMap.setVal(resId, newrsc); } else newrsc = _resMap.getVal(resId); + // Overwrite everything, because we're patching newrsc->_id = resId; newrsc->_status = kResStatusNoMalloc; @@ -1160,8 +1149,6 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource debugC(1, kDebugLevelResMan, "Patching %s - OK", source->location_name.c_str()); } -#ifdef ENABLE_SCI32 - void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { // The base36 encoded audio36 and sync36 resources use a different naming scheme, because they // cannot be described with a single resource number, but are a result of a @@ -1192,19 +1179,20 @@ void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { name = (*x)->getName(); + inputName = (*x)->getName(); inputName.toUppercase(); - inputName.deleteChar(0); // delete the first character (type) inputName.deleteChar(7); // delete the dot // The base36 encoded resource contains the following: // uint16 resourceId, byte noun, byte verb, byte cond, byte seq - uint16 resourceNr = strtol(Common::String(inputName.c_str(), 3).c_str(), 0, 36); // 3 characters - uint16 noun = strtol(Common::String(inputName.c_str() + 3, 2).c_str(), 0, 36); // 2 characters - uint16 verb = strtol(Common::String(inputName.c_str() + 5, 2).c_str(), 0, 36); // 2 characters - uint16 cond = strtol(Common::String(inputName.c_str() + 7, 2).c_str(), 0, 36); // 2 characters - uint16 seq = strtol(Common::String(inputName.c_str() + 9, 1).c_str(), 0, 36); // 1 character + uint16 resourceNr = strtol(Common::String(inputName.c_str(), 3).c_str(), 0, 36); // 3 characters + uint16 noun = strtol(Common::String(inputName.c_str() + 3, 2).c_str(), 0, 36); // 2 characters + uint16 verb = strtol(Common::String(inputName.c_str() + 5, 2).c_str(), 0, 36); // 2 characters + uint16 cond = strtol(Common::String(inputName.c_str() + 7, 2).c_str(), 0, 36); // 2 characters + uint16 seq = strtol(Common::String(inputName.c_str() + 9, 1).c_str(), 0, 36); // 1 character + // Check, if we got valid results if ((noun <= 255) && (verb <= 255) && (cond <= 255) && (seq <= 255)) { ResourceId resource36((ResourceType)i, resourceNr, noun, verb, cond, seq); @@ -1216,6 +1204,28 @@ void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { debug("sync36 patch: %s => %s. tuple:%d, %s\n", name.c_str(), inputName.c_str(), resource36.tuple, resource36.toString().c_str()); */ + // Make sure that the audio patch is a valid resource + if (i == kResourceTypeAudio36) { + Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(name); + uint32 tag = stream->readUint32BE(); + + if (tag == MKID_BE('RIFF') || tag == MKID_BE('FORM')) { + delete stream; + processWavePatch(resource36, name); + continue; + } + + // Check for SOL as well + tag = (tag << 16) | stream->readUint16BE(); + + if (tag != MKID_BE('SOL\0')) { + delete stream; + continue; + } + + delete stream; + } + psrcPatch = new ResourceSource; psrcPatch->source_type = kSourcePatch; psrcPatch->location_name = name; @@ -1226,8 +1236,6 @@ void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { } } -#endif - void ResourceManager::readResourcePatches(ResourceSource *source) { // Note: since some SCI1 games(KQ5 floppy, SQ4) might use SCI0 naming scheme for patch files // this function tries to read patch file with any supported naming scheme, diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 533c81bdf5..66742f11f5 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -452,15 +452,14 @@ protected: * Reads patch files from a local directory. */ void readResourcePatches(ResourceSource *source); -#ifdef ENABLE_SCI32 void readResourcePatchesBase36(ResourceSource *source); -#endif void processPatch(ResourceSource *source, ResourceType resourceType, uint16 resourceNr, uint32 tuple = 0); /** * Process wave files as patches for Audio resources */ void readWaveAudioPatches(); + void processWavePatch(ResourceId resourceId, Common::String name); /** * Applies to all versions before 0.000.395 (i.e. KQ4 old, XMAS 1988 and LSL2). diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 2a5b56d4bc..861866edc0 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -162,6 +162,34 @@ void ResourceManager::addNewGMPatch(const Common::String &gameId) { } } +void ResourceManager::processWavePatch(ResourceId resourceId, Common::String name) { + ResourceSource *resSrc = new ResourceSource; + resSrc->source_type = kSourceWave; + resSrc->resourceFile = 0; + resSrc->location_name = name; + resSrc->volume_number = 0; + resSrc->audioCompressionType = 0; + + Resource *newRes = 0; + + if (_resMap.contains(resourceId)) { + newRes = _resMap.getVal(resourceId); + } else { + newRes = new Resource; + _resMap.setVal(resourceId, newRes); + } + + Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(name); + newRes->size = stream->size(); + delete stream; + + newRes->_id = resourceId; + newRes->_status = kResStatusNoMalloc; + newRes->_source = resSrc; + newRes->_headerSize = 0; + debugC(1, kDebugLevelResMan, "Patching %s - OK", name.c_str()); +} + void ResourceManager::readWaveAudioPatches() { // Here we do check for SCI1.1+ so we can patch wav files in as audio resources Common::ArchiveMemberList files; @@ -170,39 +198,8 @@ void ResourceManager::readWaveAudioPatches() { for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { Common::String name = (*x)->getName(); - if (isdigit(name[0])) { - int number = atoi(name.c_str()); - ResourceSource *psrcPatch = new ResourceSource; - psrcPatch->source_type = kSourceWave; - psrcPatch->resourceFile = 0; - psrcPatch->location_name = name; - psrcPatch->volume_number = 0; - psrcPatch->audioCompressionType = 0; - - ResourceId resId = ResourceId(kResourceTypeAudio, number); - - Resource *newrsc = NULL; - - // Prepare destination, if neccessary - if (_resMap.contains(resId) == false) { - newrsc = new Resource; - _resMap.setVal(resId, newrsc); - } else - newrsc = _resMap.getVal(resId); - - // Get the size of the file - Common::SeekableReadStream *stream = (*x)->createReadStream(); - uint32 fileSize = stream->size(); - delete stream; - - // Overwrite everything, because we're patching - newrsc->_id = resId; - newrsc->_status = kResStatusNoMalloc; - newrsc->_source = psrcPatch; - newrsc->size = fileSize; - newrsc->_headerSize = 0; - debugC(1, kDebugLevelResMan, "Patching %s - OK", psrcPatch->location_name.c_str()); - } + if (isdigit(name[0])) + processWavePatch(ResourceId(kResourceTypeAudio, atoi(name.c_str())), name); } } diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index 7748c0505b..f10cc5ed68 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -24,21 +24,22 @@ */ #include "sci/resource.h" -#include "sci/engine/selector.h" #include "sci/engine/kernel.h" +#include "sci/engine/selector.h" #include "sci/engine/seg_manager.h" #include "sci/sound/audio.h" -#include "common/system.h" #include "common/file.h" +#include "common/system.h" -#include "sound/audiostream.h" #include "sound/audiocd.h" -#include "sound/decoders/raw.h" -#include "sound/decoders/wave.h" +#include "sound/audiostream.h" +#include "sound/decoders/aiff.h" #include "sound/decoders/flac.h" #include "sound/decoders/mp3.h" +#include "sound/decoders/raw.h" #include "sound/decoders/vorbis.h" +#include "sound/decoders/wave.h" namespace Sci { @@ -287,6 +288,19 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 waveStream->seek(0, SEEK_SET); audioStream = Audio::makeWAVStream(waveStream, DisposeAfterUse::YES); + } else if (audioRes->size > 4 && READ_BE_UINT32(audioRes->data) == MKID_BE('FORM')) { + // AIFF detected + Common::MemoryReadStream *waveStream = new Common::MemoryReadStream(audioRes->data, audioRes->size, DisposeAfterUse::NO); + + // Calculate samplelen from AIFF header + int waveSize = 0, waveRate = 0; + byte waveFlags = 0; + Audio::loadAIFFFromStream(*waveStream, waveSize, waveRate, waveFlags); + *sampleLen = (waveFlags & Audio::FLAG_16BITS ? waveSize >> 1 : waveSize) * 60 / waveRate; + + waveStream->seek(0, SEEK_SET); + audioStream = Audio::makeAIFFStream(*waveStream); + delete waveStream; // makeAIFFStream doesn't handle this for us } else if (audioRes->size > 14 && READ_BE_UINT16(audioRes->data) == 1 && READ_BE_UINT16(audioRes->data + 2) == 1 && READ_BE_UINT16(audioRes->data + 4) == 5 && READ_BE_UINT32(audioRes->data + 10) == 0x00018051) { // Mac snd detected |