From c874ff15a8e95acb85940ba5de0243b93077cc9d Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 23 May 2010 10:28:03 +0000 Subject: Cleaned up the game ID code: - The game ID is now obtained from ScummVM ID directly, not by converting Sierra's internal ID - Moved the code which reads the internal Sierra ID inside the resource manager - Moved the code which converts the internal Sierra ID to ScummVM's IDs together with the rest of the detection code svn-id: r49152 --- engines/sci/resource.cpp | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 4888dbd4cb..aa3b8019de 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -2329,6 +2329,41 @@ bool ResourceManager::hasSci1Voc900() { return offset == res->size; } +#define READ_UINT16(ptr) (!isSci11Mac() ? READ_LE_UINT16(ptr) : READ_BE_UINT16(ptr)) + +Common::String ResourceManager::findSierraGameId() { + Resource *script = findResource(ResourceId(kResourceTypeScript, 0), false); + // In SCI0-SCI1, the heap is embedded in the script. In SCI1.1+, it's separated + Resource *heap = 0; + byte *seeker = 0; + + // Seek to the name selector of the first export + if (getSciVersion() < SCI_VERSION_1_1) { + const int nameSelector = 3; + int extraSci0EarlyBytes = (getSciVersion() == SCI_VERSION_0_EARLY) ? 2 : 0; + byte *exportPtr = script->data + extraSci0EarlyBytes + 4 + 2; + seeker = script->data + READ_UINT16(script->data + READ_UINT16(exportPtr) + nameSelector * 2); + } else { + const int nameSelector = 5 + 3; + heap = findResource(ResourceId(kResourceTypeHeap, 0), false); + byte *exportPtr = script->data + 4 + 2 + 2; + seeker = heap->data + READ_UINT16(heap->data + READ_UINT16(exportPtr) + nameSelector * 2); + } + + char sierraId[20]; + int i = 0; + byte curChar = 0; + + do { + curChar = *(seeker + i); + sierraId[i++] = curChar; + } while (curChar != 0); + + return sierraId; +} + +#undef READ_UINT16 + SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersion soundVersion) : _resMan(resMan), _soundVersion(soundVersion) { Resource *resource = _resMan->findResource(ResourceId(kResourceTypeSound, resNumber), true); int trackNr, channelNr; -- cgit v1.2.3 From d49fb8f42db7b9776f1dc426ebe2c6d806ad4720 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Mon, 24 May 2010 17:21:11 +0000 Subject: Add support for showing the icon bar in SCI1.1 Mac. svn-id: r49196 --- engines/sci/resource.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index aa3b8019de..428e66ebe2 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -445,11 +445,10 @@ void ResourceManager::loadResource(Resource *res) { return; if (res->_source->source_type == kSourceMacResourceFork) { - //error("ResourceManager::loadResource(): TODO: Mac resource fork ;)"); Common::SeekableReadStream *stream = res->_source->macResMan.getResource(resTypeToMacTag(res->_id.type), res->_id.number); if (!stream) - error("Could not get Mac resource fork resource"); + error("Could not get Mac resource fork resource: %d %d", res->_id.type, res->_id.number); int error = decompress(res, stream); if (error) { @@ -1476,7 +1475,10 @@ struct { { MKID_BE('PAL '), kResourceTypePalette }, { MKID_BE('snd '), kResourceTypeAudio }, { MKID_BE('MSG '), kResourceTypeMessage }, - { MKID_BE('HEP '), kResourceTypeHeap } + { MKID_BE('HEP '), kResourceTypeHeap }, + { MKID_BE('IBIN'), kResourceTypeMacIconBarPictN }, + { MKID_BE('IBIS'), kResourceTypeMacIconBarPictS }, + { MKID_BE('PICT'), kResourceTypeMacPict } }; static uint32 resTypeToMacTag(ResourceType type) { @@ -1509,6 +1511,16 @@ int ResourceManager::readMacResourceFork(ResourceSource *source) { Common::MacResIDArray idArray = source->macResMan.getResIDArray(tagArray[i]); for (uint32 j = 0; j < idArray.size(); j++) { + // Get the size of the file + Common::SeekableReadStream *stream = source->macResMan.getResource(tagArray[i], idArray[j]); + + // Some IBIS resources have a size of 0, so we skip them + if (!stream) + continue; + + uint32 fileSize = stream->size(); + delete stream; + ResourceId resId = ResourceId(type, idArray[j]); Resource *newrsc = NULL; @@ -1520,11 +1532,6 @@ int ResourceManager::readMacResourceFork(ResourceSource *source) { } else newrsc = _resMap.getVal(resId); - // Get the size of the file - Common::SeekableReadStream *stream = source->macResMan.getResource(tagArray[i], idArray[j]); - uint32 fileSize = stream->size(); - delete stream; - // Overwrite everything newrsc->_id = resId; newrsc->_status = kResStatusNoMalloc; -- cgit v1.2.3 From 60dd3106885b9784af15cb96122d28a5f0bf33f1 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 26 May 2010 06:53:08 +0000 Subject: Cleanup svn-id: r49227 --- engines/sci/resource.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 428e66ebe2..57a4fbc751 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -2343,6 +2343,7 @@ Common::String ResourceManager::findSierraGameId() { // In SCI0-SCI1, the heap is embedded in the script. In SCI1.1+, it's separated Resource *heap = 0; byte *seeker = 0; + Common::String sierraId; // Seek to the name selector of the first export if (getSciVersion() < SCI_VERSION_1_1) { @@ -2357,14 +2358,12 @@ Common::String ResourceManager::findSierraGameId() { seeker = heap->data + READ_UINT16(heap->data + READ_UINT16(exportPtr) + nameSelector * 2); } - char sierraId[20]; - int i = 0; - byte curChar = 0; + char c = 0; do { - curChar = *(seeker + i); - sierraId[i++] = curChar; - } while (curChar != 0); + c = *(seeker++); + sierraId += c; + } while (c); return sierraId; } -- cgit v1.2.3 From 3187149cca9ab48a391e09c7af6430c2187cd4c6 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 26 May 2010 11:02:50 +0000 Subject: Avoid adding a null char in the sierraId Common::String svn-id: r49234 --- engines/sci/resource.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 57a4fbc751..af0f08b17a 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -2358,12 +2358,9 @@ Common::String ResourceManager::findSierraGameId() { seeker = heap->data + READ_UINT16(heap->data + READ_UINT16(exportPtr) + nameSelector * 2); } - char c = 0; - do { - c = *(seeker++); - sierraId += c; - } while (c); + sierraId += *(seeker++); + } while (*seeker); return sierraId; } -- cgit v1.2.3 From 7b8837cda7b3c44d5e283ef8bb9ebe6e943ebb27 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 26 May 2010 15:41:50 +0000 Subject: SCI: Simplify appending string 'seeker' to sierraId svn-id: r49244 --- engines/sci/resource.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index af0f08b17a..3535e36f77 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -2358,9 +2358,7 @@ Common::String ResourceManager::findSierraGameId() { seeker = heap->data + READ_UINT16(heap->data + READ_UINT16(exportPtr) + nameSelector * 2); } - do { - sierraId += *(seeker++); - } while (*seeker); + sierraId += (const char *)seeker; return sierraId; } -- cgit v1.2.3 From 99fc5cbfca3403b07ab023c857b7b997cc9389b4 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 27 May 2010 03:15:24 +0000 Subject: Add the Mac sync resource type and allow for more than 9 Mac SCI1.1+ data files. svn-id: r49255 --- engines/sci/resource.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 3535e36f77..4bffdd3068 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -574,7 +574,7 @@ int ResourceManager::addAppropriateSources() { #endif } else if (Common::File::exists("Data1")) { // Mac SCI1.1+ file naming scheme - SearchMan.listMatchingMembers(files, "Data?"); + SearchMan.listMatchingMembers(files, "Data?*"); for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { Common::String filename = (*x)->getName(); @@ -1478,7 +1478,8 @@ struct { { MKID_BE('HEP '), kResourceTypeHeap }, { MKID_BE('IBIN'), kResourceTypeMacIconBarPictN }, { MKID_BE('IBIS'), kResourceTypeMacIconBarPictS }, - { MKID_BE('PICT'), kResourceTypeMacPict } + { MKID_BE('PICT'), kResourceTypeMacPict }, + { MKID_BE('SYN '), kResourceTypeSync } }; static uint32 resTypeToMacTag(ResourceType type) { -- cgit v1.2.3 From 739f551852b428115f2cd2bca4f7a0a1054b79a8 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 27 May 2010 07:50:23 +0000 Subject: Slight formatting, and added a note that audio36 and sync36 resource patches were introduced in SCI2, and didn't exist in SCI0-SCI1.1 svn-id: r49259 --- engines/sci/resource.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 4bffdd3068..0b985ea67c 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1242,9 +1242,9 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType restype, 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, -// regardless of s_sciVersion value + // 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, + // regardless of s_sciVersion value Common::String mask, name; Common::ArchiveMemberList files; @@ -1254,6 +1254,7 @@ void ResourceManager::readResourcePatches(ResourceSource *source) { for (int i = kResourceTypeView; i <= kResourceTypeRobot; ++i) { // TODO: add support for audio36 and sync36 files + // Such patches were introduced in SCI2, and didn't exist in SCI0-SCI1.1 if (i == kResourceTypeAudio36 || i == kResourceTypeSync36) continue; -- cgit v1.2.3 From e5eaf3ee5578367cc74c3155a68a904e6ce77b9b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 27 May 2010 08:09:32 +0000 Subject: Split all of the audio-related functions of the resource manager in a separate file svn-id: r49260 --- engines/sci/resource.cpp | 679 ----------------------------------------------- 1 file changed, 679 deletions(-) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 0b985ea67c..89b7a5b7e2 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -26,7 +26,6 @@ // Resource library #include "common/file.h" -#include "common/macresman.h" #include "sci/resource.h" #include "sci/util.h" @@ -45,18 +44,6 @@ struct resource_index_t { uint16 wSize; }; -struct ResourceSource { - ResSourceType source_type; - bool scanned; - Common::String location_name; // FIXME: Replace by FSNode ? - const Common::FSNode *resourceFile; - int volume_number; - ResourceSource *associated_map; - uint32 audioCompressionType; - int32 *audioCompressionOffsetMapping; - Common::MacResManager macResMan; -}; - ////////////////////////////////////////////////////////////////////// static SciVersion s_sciVersion = SCI_VERSION_NONE; // FIXME: Move this inside a suitable class, e.g. SciEngine @@ -270,36 +257,6 @@ ResourceSource *ResourceManager::getVolume(ResourceSource *map, int volume_nr) { // Resource manager constructors and operations -void ResourceManager::checkIfAudioVolumeIsCompressed(ResourceSource *source) { - Common::File *file = getVolumeFile(source->location_name.c_str()); - if (!file) { - warning("Failed to open %s", source->location_name.c_str()); - return; - } - file->seek(0, SEEK_SET); - uint32 compressionType = file->readUint32BE(); - switch (compressionType) { - case MKID_BE('MP3 '): - case MKID_BE('OGG '): - case MKID_BE('FLAC'): - // Detected a compressed audio volume - source->audioCompressionType = compressionType; - // Now read the whole offset mapping table for later usage - int32 recordCount = file->readUint32LE(); - if (!recordCount) - error("compressed audio volume doesn't contain any entries!"); - int32 *offsetMapping = new int32[(recordCount + 1) * 2]; - source->audioCompressionOffsetMapping = offsetMapping; - for (int recordNo = 0; recordNo < recordCount; recordNo++) { - *offsetMapping++ = file->readUint32LE(); - *offsetMapping++ = file->readUint32LE(); - } - // Put ending zero - *offsetMapping++ = 0; - *offsetMapping++ = file->size(); - } -} - bool ResourceManager::loadPatch(Resource *res, Common::File &file) { // We assume that the resource type matches res->type // We also assume that the current file position is right at the actual data (behind resourceid/headersize byte) @@ -341,70 +298,6 @@ bool ResourceManager::loadFromPatchFile(Resource *res) { return loadPatch(res, file); } -bool ResourceManager::loadFromWaveFile(Resource *res, Common::File &file) { - res->data = new byte[res->size]; - - uint32 really_read = file.read(res->data, res->size); - if (really_read != res->size) - error("Read %d bytes from %s but expected %d", really_read, res->_id.toString().c_str(), res->size); - - res->_status = kResStatusAllocated; - return true; -} - -bool ResourceManager::loadFromAudioVolumeSCI11(Resource *res, Common::File &file) { - // Check for WAVE files here - uint32 riffTag = file.readUint32BE(); - if (riffTag == MKID_BE('RIFF')) { - res->_headerSize = 0; - res->size = file.readUint32LE(); - file.seek(-8, SEEK_CUR); - return loadFromWaveFile(res, file); - } - file.seek(-4, SEEK_CUR); - - ResourceType type = (ResourceType)(file.readByte() & 0x7f); - if (((res->_id.type == kResourceTypeAudio || res->_id.type == kResourceTypeAudio36) && (type != kResourceTypeAudio)) - || ((res->_id.type == kResourceTypeSync || res->_id.type == kResourceTypeSync36) && (type != kResourceTypeSync))) { - warning("Resource type mismatch loading %s from %s", res->_id.toString().c_str(), file.getName()); - res->unalloc(); - return false; - } - - res->_headerSize = file.readByte(); - - if (type == kResourceTypeAudio) { - if (res->_headerSize != 11 && res->_headerSize != 12) { - warning("Unsupported audio header"); - res->unalloc(); - return false; - } - - // Load sample size - file.seek(7, SEEK_CUR); - res->size = file.readUint32LE(); - // Adjust offset to point at the header data again - file.seek(-11, SEEK_CUR); - } - - return loadPatch(res, file); -} - -bool ResourceManager::loadFromAudioVolumeSCI1(Resource *res, Common::File &file) { - res->data = new byte[res->size]; - - if (res->data == NULL) { - error("Can't allocate %d bytes needed for loading %s", res->size, res->_id.toString().c_str()); - } - - unsigned int really_read = file.read(res->data, res->size); - if (really_read != res->size) - warning("Read %d bytes from %s but expected %d", really_read, res->_id.toString().c_str(), res->size); - - res->_status = kResStatusAllocated; - return true; -} - Common::File *ResourceManager::getVolumeFile(const char *filename) { Common::List::iterator it = _volumeFiles.begin(); Common::File *file; @@ -695,36 +588,6 @@ int ResourceManager::addInternalSources() { return 1; } -void ResourceManager::addNewGMPatch(const Common::String &gameId) { - Common::String gmPatchFile; - - if (gameId == "ecoquest") - gmPatchFile = "ECO1GM.PAT"; - else if (gameId == "hoyle3") - gmPatchFile = "HOY3GM.PAT"; - else if (gameId == "hoyle3") - gmPatchFile = "HOY3GM.PAT"; - else if (gameId == "lsl1sci") - gmPatchFile = "LL1_GM.PAT"; - else if (gameId == "lsl5") - gmPatchFile = "LL5_GM.PAT"; - else if (gameId == "longbow") - gmPatchFile = "ROBNGM.PAT"; - else if (gameId == "sq1sci") - gmPatchFile = "SQ1_GM.PAT"; - else if (gameId == "sq4") - gmPatchFile = "SQ4_GM.PAT"; - else if (gameId == "fairytales") - gmPatchFile = "TALEGM.PAT"; - - if (!gmPatchFile.empty() && Common::File::exists(gmPatchFile)) { - ResourceSource *psrcPatch = new ResourceSource; - psrcPatch->source_type = kSourcePatch; - psrcPatch->location_name = gmPatchFile; - processPatch(psrcPatch, kResourceTypePatch, 4); - } -} - void ResourceManager::scanNewSources() { for (Common::List::iterator it = _sources.begin(); it != _sources.end(); ++it) { ResourceSource *source = *it; @@ -1295,49 +1158,6 @@ void ResourceManager::readResourcePatches(ResourceSource *source) { } } -void ResourceManager::readWaveAudioPatches() { - // Here we do check for SCI1.1+ so we can patch wav files in as audio resources - Common::ArchiveMemberList files; - SearchMan.listMatchingMembers(files, "*.wav"); - - 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->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()); - } - } -} - int ResourceManager::readResourceMapSCI0(ResourceSource *map) { Common::File file; Resource *res; @@ -1558,261 +1378,6 @@ void ResourceManager::addResource(ResourceId resId, ResourceSource *src, uint32 } } -void ResourceManager::removeAudioResource(ResourceId resId) { - // Remove resource, unless it was loaded from a patch - if (_resMap.contains(resId)) { - Resource *res = _resMap.getVal(resId); - - if (res->_source->source_type == kSourceAudioVolume) { - if (res->_status == kResStatusLocked) { - warning("Failed to remove resource %s (still in use)", resId.toString().c_str()); - } else { - if (res->_status == kResStatusEnqueued) - removeFromLRU(res); - - _resMap.erase(resId); - delete res; - } - } - } -} - -// Early SCI1.1 65535.MAP structure (uses RESOURCE.AUD): -// ========= -// 6-byte entries: -// w nEntry -// dw offset - -// Late SCI1.1 65535.MAP structure (uses RESOURCE.SFX): -// ========= -// 5-byte entries: -// w nEntry -// tb offset (cumulative) - -// Early SCI1.1 MAP structure: -// =============== -// 10-byte entries: -// b noun -// b verb -// b cond -// b seq -// dw offset -// w syncSize + syncAscSize - -// Late SCI1.1 MAP structure: -// =============== -// Header: -// dw baseOffset -// Followed by 7 or 11-byte entries: -// b noun -// b verb -// b cond -// b seq -// tb cOffset (cumulative offset) -// w syncSize (iff seq has bit 7 set) -// w syncAscSize (iff seq has bit 6 set) - -int ResourceManager::readAudioMapSCI11(ResourceSource *map) { - bool isEarly = true; - uint32 offset = 0; - Resource *mapRes = findResource(ResourceId(kResourceTypeMap, map->volume_number), false); - - if (!mapRes) { - warning("Failed to open %i.MAP", map->volume_number); - return SCI_ERROR_RESMAP_NOT_FOUND; - } - - ResourceSource *src = getVolume(map, 0); - - if (!src) - return SCI_ERROR_NO_RESOURCE_FILES_FOUND; - - byte *ptr = mapRes->data; - - if (map->volume_number == 65535) { - // Heuristic to detect late SCI1.1 map format - if ((mapRes->size >= 6) && (ptr[mapRes->size - 6] != 0xff)) - isEarly = false; - - while (ptr < mapRes->data + mapRes->size) { - uint16 n = READ_LE_UINT16(ptr); - ptr += 2; - - if (n == 0xffff) - break; - - if (isEarly) { - offset = READ_LE_UINT32(ptr); - ptr += 4; - } else { - offset += READ_LE_UINT24(ptr); - ptr += 3; - } - - addResource(ResourceId(kResourceTypeAudio, n), src, offset); - } - } else { - // Heuristic to detect late SCI1.1 map format - if ((mapRes->size >= 11) && (ptr[mapRes->size - 11] == 0xff)) - isEarly = false; - - if (!isEarly) { - offset = READ_LE_UINT32(ptr); - ptr += 4; - } - - while (ptr < mapRes->data + mapRes->size) { - uint32 n = READ_BE_UINT32(ptr); - int syncSize = 0; - ptr += 4; - - if (n == 0xffffffff) - break; - - if (isEarly) { - offset = READ_LE_UINT32(ptr); - ptr += 4; - } else { - offset += READ_LE_UINT24(ptr); - ptr += 3; - } - - if (isEarly || (n & 0x80)) { - syncSize = READ_LE_UINT16(ptr); - ptr += 2; - - if (syncSize > 0) - addResource(ResourceId(kResourceTypeSync36, map->volume_number, n & 0xffffff3f), src, offset, syncSize); - } - - if (n & 0x40) { - syncSize += READ_LE_UINT16(ptr); - ptr += 2; - } - - addResource(ResourceId(kResourceTypeAudio36, map->volume_number, n & 0xffffff3f), src, offset + syncSize); - } - } - - return 0; -} - -// AUDIOnnn.MAP contains 10-byte entries: -// Early format: -// w 5 bits resource type and 11 bits resource number -// dw 7 bits volume number and 25 bits offset -// dw size -// Later format: -// w nEntry -// dw offset+volume (as in resource.map) -// dw size -// ending with 10 0xFFs -int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) { - Common::File file; - - if (!file.open(map->location_name)) - return SCI_ERROR_RESMAP_NOT_FOUND; - - bool oldFormat = (file.readUint16LE() >> 11) == kResourceTypeAudio; - file.seek(0); - - while (1) { - uint16 n = file.readUint16LE(); - uint32 offset = file.readUint32LE(); - uint32 size = file.readUint32LE(); - - if (file.eos() || file.err()) { - warning("Error while reading %s", map->location_name.c_str()); - return SCI_ERROR_RESMAP_NOT_FOUND; - } - - if (n == 0xffff) - break; - - byte volume_nr; - - if (oldFormat) { - n &= 0x07ff; // Mask out resource type - volume_nr = offset >> 25; // most significant 7 bits - offset &= 0x01ffffff; // least significant 25 bits - } else { - volume_nr = offset >> 28; // most significant 4 bits - offset &= 0x0fffffff; // least significant 28 bits - } - - ResourceSource *src = getVolume(map, volume_nr); - - if (src) { - if (unload) - removeAudioResource(ResourceId(kResourceTypeAudio, n)); - else - addResource(ResourceId(kResourceTypeAudio, n), src, offset, size); - } else { - warning("Failed to find audio volume %i", volume_nr); - } - } - - return 0; -} - -void ResourceManager::setAudioLanguage(int language) { - if (_audioMapSCI1) { - if (_audioMapSCI1->volume_number == language) { - // This language is already loaded - return; - } - - // We already have a map loaded, so we unload it first - readAudioMapSCI1(_audioMapSCI1, true); - - // Remove all volumes that use this map from the source list - Common::List::iterator it = _sources.begin(); - while (it != _sources.end()) { - ResourceSource *src = *it; - if (src->associated_map == _audioMapSCI1) { - it = _sources.erase(it); - delete src; - } else { - ++it; - } - } - - // Remove the map itself from the source list - _sources.remove(_audioMapSCI1); - delete _audioMapSCI1; - - _audioMapSCI1 = NULL; - } - - char filename[9]; - snprintf(filename, 9, "AUDIO%03d", language); - - Common::String fullname = Common::String(filename) + ".MAP"; - if (!Common::File::exists(fullname)) { - warning("No audio map found for language %i", language); - return; - } - - _audioMapSCI1 = addSource(NULL, kSourceExtAudioMap, fullname.c_str(), language); - - // Search for audio volumes for this language and add them to the source list - Common::ArchiveMemberList files; - SearchMan.listMatchingMembers(files, Common::String(filename) + ".0??"); - for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { - const Common::String name = (*x)->getName(); - const char *dot = strrchr(name.c_str(), '.'); - int number = atoi(dot + 1); - - addSource(_audioMapSCI1, kSourceAudioVolume, name.c_str(), number); - } - - scanNewSources(); -} - -int ResourceManager::getAudioLanguage() const { - return (_audioMapSCI1 ? _audioMapSCI1->volume_number : 0); -} - int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream *file, uint32&szPacked, ResourceCompression &compression) { // SCI0 volume format: {wResId wPacked+4 wUnpacked wCompression} = 8 bytes @@ -2367,248 +1932,4 @@ Common::String ResourceManager::findSierraGameId() { #undef READ_UINT16 -SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersion soundVersion) : _resMan(resMan), _soundVersion(soundVersion) { - Resource *resource = _resMan->findResource(ResourceId(kResourceTypeSound, resNumber), true); - int trackNr, channelNr; - if (!resource) - return; - - _innerResource = resource; - - byte *data, *data2; - byte *dataEnd; - Channel *channel, *sampleChannel; - - switch (_soundVersion) { - case SCI_VERSION_0_EARLY: - case SCI_VERSION_0_LATE: - // SCI0 only has a header of 0x11/0x21 byte length and the actual midi track follows afterwards - _trackCount = 1; - _tracks = new Track[_trackCount]; - _tracks->digitalChannelNr = -1; - _tracks->type = 0; // Not used for SCI0 - _tracks->channelCount = 1; - // Digital sample data included? -> Add an additional channel - if (resource->data[0] == 2) - _tracks->channelCount++; - _tracks->channels = new Channel[_tracks->channelCount]; - memset(_tracks->channels, 0, sizeof(Channel) * _tracks->channelCount); - channel = &_tracks->channels[0]; - if (_soundVersion == SCI_VERSION_0_EARLY) { - channel->data = resource->data + 0x11; - channel->size = resource->size - 0x11; - } else { - channel->data = resource->data + 0x21; - channel->size = resource->size - 0x21; - } - if (_tracks->channelCount == 2) { - // Digital sample data included - _tracks->digitalChannelNr = 1; - sampleChannel = &_tracks->channels[1]; - // we need to find 0xFC (channel terminator) within the data - data = channel->data; - dataEnd = channel->data + channel->size; - while ((data < dataEnd) && (*data != 0xfc)) - data++; - // Skip any following 0xFCs as well - while ((data < dataEnd) && (*data == 0xfc)) - data++; - // Now adjust channels accordingly - sampleChannel->data = data; - sampleChannel->size = channel->size - (data - channel->data); - channel->size = data - channel->data; - // Read sample header information - //Offset 14 in the header contains the frequency as a short integer. Offset 32 contains the sample length, also as a short integer. - _tracks->digitalSampleRate = READ_LE_UINT16(sampleChannel->data + 14); - _tracks->digitalSampleSize = READ_LE_UINT16(sampleChannel->data + 32); - _tracks->digitalSampleStart = 0; - _tracks->digitalSampleEnd = 0; - sampleChannel->data += 44; // Skip over header - sampleChannel->size -= 44; - } - break; - - case SCI_VERSION_1_EARLY: - case SCI_VERSION_1_LATE: - data = resource->data; - // Count # of tracks - _trackCount = 0; - while ((*data++) != 0xFF) { - _trackCount++; - while (*data != 0xFF) - data += 6; - data++; - } - _tracks = new Track[_trackCount]; - data = resource->data; - for (trackNr = 0; trackNr < _trackCount; trackNr++) { - // Track info starts with track type:BYTE - // Then the channel information gets appended Unknown:WORD, ChannelOffset:WORD, ChannelSize:WORD - // 0xFF:BYTE as terminator to end that track and begin with another track type - // Track type 0xFF is the marker signifying the end of the tracks - - _tracks[trackNr].type = *data++; - // Counting # of channels used - data2 = data; - _tracks[trackNr].channelCount = 0; - while (*data2 != 0xFF) { - data2 += 6; - _tracks[trackNr].channelCount++; - } - _tracks[trackNr].channels = new Channel[_tracks[trackNr].channelCount]; - _tracks[trackNr].digitalChannelNr = -1; // No digital sound associated - _tracks[trackNr].digitalSampleRate = 0; - _tracks[trackNr].digitalSampleSize = 0; - _tracks[trackNr].digitalSampleStart = 0; - _tracks[trackNr].digitalSampleEnd = 0; - if (_tracks[trackNr].type != 0xF0) { // Digital track marker - not supported currently - for (channelNr = 0; channelNr < _tracks[trackNr].channelCount; channelNr++) { - channel = &_tracks[trackNr].channels[channelNr]; - channel->prio = READ_LE_UINT16(data); - channel->data = resource->data + READ_LE_UINT16(data + 2) + 2; - channel->size = READ_LE_UINT16(data + 4) - 2; // Not counting channel header - channel->number = *(channel->data - 2); - channel->poly = *(channel->data - 1); - channel->time = channel->prev = 0; - if (channel->number == 0xFE) { // Digital channel - _tracks[trackNr].digitalChannelNr = channelNr; - _tracks[trackNr].digitalSampleRate = READ_LE_UINT16(channel->data); - _tracks[trackNr].digitalSampleSize = READ_LE_UINT16(channel->data + 2); - _tracks[trackNr].digitalSampleStart = READ_LE_UINT16(channel->data + 4); - _tracks[trackNr].digitalSampleEnd = READ_LE_UINT16(channel->data + 6); - channel->data += 8; // Skip over header - channel->size -= 8; - } - data += 6; - } - } else { - // Skip over digital track - data += 6; - } - data++; // Skipping 0xFF that closes channels list - } - break; - - default: - error("SoundResource: SCI version %d is unsupported", _soundVersion); - } -} - -SoundResource::~SoundResource() { - for (int trackNr = 0; trackNr < _trackCount; trackNr++) - delete[] _tracks[trackNr].channels; - delete[] _tracks; - - _resMan->unlockResource(_innerResource); -} - -#if 0 -SoundResource::Track* SoundResource::getTrackByNumber(uint16 number) { - if (_soundVersion <= SCI_VERSION_0_LATE) - return &_tracks[0]; - - if (/*number >= 0 &&*/number < _trackCount) - return &_tracks[number]; - return NULL; -} -#endif - -SoundResource::Track *SoundResource::getTrackByType(byte type) { - if (_soundVersion <= SCI_VERSION_0_LATE) - return &_tracks[0]; - - for (int trackNr = 0; trackNr < _trackCount; trackNr++) { - if (_tracks[trackNr].type == type) - return &_tracks[trackNr]; - } - return NULL; -} - -SoundResource::Track *SoundResource::getDigitalTrack() { - for (int trackNr = 0; trackNr < _trackCount; trackNr++) { - if (_tracks[trackNr].digitalChannelNr != -1) - return &_tracks[trackNr]; - } - return NULL; -} - -// Gets the filter mask for SCI0 sound resources -int SoundResource::getChannelFilterMask(int hardwareMask, bool wantsRhythm) { - byte *data = _innerResource->data; - int channelMask = 0; - - if (_soundVersion > SCI_VERSION_0_LATE) - return 0; - - data++; // Skip over digital sample flag - - for (int channelNr = 0; channelNr < 16; channelNr++) { - channelMask = channelMask >> 1; - - byte flags; - - if (_soundVersion == SCI_VERSION_0_EARLY) { - // Each channel is specified by a single byte - // Upper 4 bits of the byte is a voices count - // Lower 4 bits -> bit 0 set: use for AdLib - // bit 1 set: use for PCjr - // bit 2 set: use for PC speaker - // bit 3 set and bit 0 clear: control channel (15) - // bit 3 set and bit 0 set: rhythm channel (9) - // Note: control channel is dynamically assigned inside the drivers, - // but seems to be fixed at 15 in the song data. - flags = *data++; - - // Get device bits - flags &= 0x7; - } else { - // Each channel is specified by 2 bytes - // 1st byte is voices count - // 2nd byte is play mask, which specifies if the channel is supposed to be played - // by the corresponding hardware - - // Skip voice count - data++; - - flags = *data++; - } - - bool play; - switch (channelNr) { - case 15: - // Always play control channel - play = true; - break; - case 9: - // Play rhythm channel when requested - play = wantsRhythm; - break; - default: - // Otherwise check for flag - play = flags & hardwareMask; - } - - if (play) { - // This Channel is supposed to be played by the hardware - channelMask |= 0x8000; - } - } - - return channelMask; -} - -byte SoundResource::getInitialVoiceCount(byte channel) { - byte *data = _innerResource->data; - - if (_soundVersion > SCI_VERSION_0_LATE) - return 0; // TODO - - data++; // Skip over digital sample flag - - if (_soundVersion == SCI_VERSION_0_EARLY) - return data[channel] >> 4; - else - return data[channel * 2]; -} - } // End of namespace Sci -- cgit v1.2.3 From 5f5dcbad47c3f120541c59a141e84bb8aed5184d Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 27 May 2010 12:00:20 +0000 Subject: Added an explanation for audio36 and sync36 external patches svn-id: r49262 --- engines/sci/resource.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 89b7a5b7e2..cc3a2b0d1a 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1109,6 +1109,14 @@ void ResourceManager::readResourcePatches(ResourceSource *source) { // this function tries to read patch file with any supported naming scheme, // regardless of s_sciVersion value + // Note that audio36 and sync36 use a different naming scheme, because they cannot be described + // with a single resource number, but are a result of a tuple. + // Please don't be confused with the normal audio patches (*.aud) and normal sync patches (*.syn). + // audio36 patches can be seen for example in the AUD folder of GK1CD, and are like this file: + // @0CS0M00.0X1. GK1CD is the first game where these have been observed. The actual audio36 and + // sync36 resources exist in SCI1.1 as well, but the first game where external patch files for + // them have been found is GK1CD + Common::String mask, name; Common::ArchiveMemberList files; int number = -1; -- cgit v1.2.3 From 6f056c6c98e6c32c1e18a731ca6296b9ee4b130a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 29 May 2010 14:03:08 +0000 Subject: Added a method to the resource manager, to limit the places where script exports are accessed, since for SCI11 and newer exports can be functions and objects (first step in removing scriptRelocateExportsSci11(), which is a gross hack and it fails in QFG1VGA) svn-id: r49308 --- engines/sci/resource.cpp | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index cc3a2b0d1a..d336cbab38 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1913,26 +1913,37 @@ bool ResourceManager::hasSci1Voc900() { #define READ_UINT16(ptr) (!isSci11Mac() ? READ_LE_UINT16(ptr) : READ_BE_UINT16(ptr)) -Common::String ResourceManager::findSierraGameId() { +reg_t ResourceManager::findGameObject(bool addSci11ScriptOffset) { Resource *script = findResource(ResourceId(kResourceTypeScript, 0), false); + int extraBytes = 0; + if (getSciVersion() == SCI_VERSION_0_EARLY || getSciVersion() >= SCI_VERSION_1_1) + extraBytes = 2; + + int16 offset = READ_UINT16(script->data + extraBytes + 4 + 2); + + // In SCI1.1 and newer, the heap is appended at the end of the script, + // so adjust the offset accordingly + if (getSciVersion() >= SCI_VERSION_1_1 && addSci11ScriptOffset) + offset += script->size; + + return make_reg(1, offset); +} + +Common::String ResourceManager::findSierraGameId() { // In SCI0-SCI1, the heap is embedded in the script. In SCI1.1+, it's separated Resource *heap = 0; - byte *seeker = 0; - Common::String sierraId; + int nameSelector = 3; - // Seek to the name selector of the first export if (getSciVersion() < SCI_VERSION_1_1) { - const int nameSelector = 3; - int extraSci0EarlyBytes = (getSciVersion() == SCI_VERSION_0_EARLY) ? 2 : 0; - byte *exportPtr = script->data + extraSci0EarlyBytes + 4 + 2; - seeker = script->data + READ_UINT16(script->data + READ_UINT16(exportPtr) + nameSelector * 2); + heap = findResource(ResourceId(kResourceTypeScript, 0), false); } else { - const int nameSelector = 5 + 3; heap = findResource(ResourceId(kResourceTypeHeap, 0), false); - byte *exportPtr = script->data + 4 + 2 + 2; - seeker = heap->data + READ_UINT16(heap->data + READ_UINT16(exportPtr) + nameSelector * 2); + nameSelector += 5; } + // Seek to the name selector of the first export + byte *seeker = heap->data + READ_UINT16(heap->data + findGameObject(false).offset + nameSelector * 2); + Common::String sierraId; sierraId += (const char *)seeker; return sierraId; -- cgit v1.2.3 From 708b37898c17ca520e8b3ae92a2e458665c7bd81 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 29 May 2010 15:01:33 +0000 Subject: Fixed regression in SCI2-SCI21 games from commit 49308 svn-id: r49309 --- engines/sci/resource.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index d336cbab38..ab46fa3abd 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1926,6 +1926,10 @@ reg_t ResourceManager::findGameObject(bool addSci11ScriptOffset) { if (getSciVersion() >= SCI_VERSION_1_1 && addSci11ScriptOffset) offset += script->size; + // TODO: Investigate why this is needed for SCI2+ games + if (getSciVersion() >= SCI_VERSION_2) + offset += 1; + return make_reg(1, offset); } @@ -1941,8 +1945,14 @@ Common::String ResourceManager::findSierraGameId() { nameSelector += 5; } + int16 gameObjectOffset = findGameObject(false).offset; + + // Compensate for the odd offsets of SCI2+ games + if (getSciVersion() >= SCI_VERSION_2) + gameObjectOffset -= 1; + // Seek to the name selector of the first export - byte *seeker = heap->data + READ_UINT16(heap->data + findGameObject(false).offset + nameSelector * 2); + byte *seeker = heap->data + READ_UINT16(heap->data + gameObjectOffset + nameSelector * 2); Common::String sierraId; sierraId += (const char *)seeker; -- cgit v1.2.3 From 3d09af03773d353e73b61197befa63031e99d096 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 29 May 2010 15:27:27 +0000 Subject: Removed the hack inside findGameObject(), and replaced it with code from the segment manager, till we find out why the segment is sometimes off by 1 (note that findGameObject() works fine for finding the game ID itself) svn-id: r49310 --- engines/sci/resource.cpp | 8 -------- 1 file changed, 8 deletions(-) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index ab46fa3abd..56ff24389e 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1926,10 +1926,6 @@ reg_t ResourceManager::findGameObject(bool addSci11ScriptOffset) { if (getSciVersion() >= SCI_VERSION_1_1 && addSci11ScriptOffset) offset += script->size; - // TODO: Investigate why this is needed for SCI2+ games - if (getSciVersion() >= SCI_VERSION_2) - offset += 1; - return make_reg(1, offset); } @@ -1947,10 +1943,6 @@ Common::String ResourceManager::findSierraGameId() { int16 gameObjectOffset = findGameObject(false).offset; - // Compensate for the odd offsets of SCI2+ games - if (getSciVersion() >= SCI_VERSION_2) - gameObjectOffset -= 1; - // Seek to the name selector of the first export byte *seeker = heap->data + READ_UINT16(heap->data + gameObjectOffset + nameSelector * 2); Common::String sierraId; -- cgit v1.2.3 From 0276ec835ef3c77a4dbf772ea54cc6d5292452f2 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 30 May 2010 15:17:29 +0000 Subject: Fixed findGameObject() for SCI11 games svn-id: r49326 --- engines/sci/resource.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 56ff24389e..ba5689dcf0 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1923,9 +1923,13 @@ reg_t ResourceManager::findGameObject(bool addSci11ScriptOffset) { // In SCI1.1 and newer, the heap is appended at the end of the script, // so adjust the offset accordingly - if (getSciVersion() >= SCI_VERSION_1_1 && addSci11ScriptOffset) + if (getSciVersion() >= SCI_VERSION_1_1 && addSci11ScriptOffset) { offset += script->size; + if (script->size & 2) + offset++; + } + return make_reg(1, offset); } -- cgit v1.2.3 From 016862ac3a4928529d9eaedf6edf3e916c89155c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 30 May 2010 18:45:07 +0000 Subject: Moved setScriptSize() inside Script::init(), and removed a FIXME - the SCI1.1 word-align is done inside Script::init() svn-id: r49330 --- engines/sci/resource.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index ba5689dcf0..c36feb57c6 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1926,6 +1926,7 @@ reg_t ResourceManager::findGameObject(bool addSci11ScriptOffset) { if (getSciVersion() >= SCI_VERSION_1_1 && addSci11ScriptOffset) { offset += script->size; + // Ensure that the start of the heap is word-aligned - same as in Script::init() if (script->size & 2) offset++; } -- cgit v1.2.3 From 95001e3676c98b5d13dee3340efcc20e6f4d9f77 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 1 Jun 2010 20:37:55 +0000 Subject: Add support for SCI2.1 resource patches to the fallback detector svn-id: r49380 --- engines/sci/resource.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index c36feb57c6..96bef504f7 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -537,8 +537,6 @@ int ResourceManager::addAppropriateSources(const Common::FSList &fslist) { Common::String filename = file->getName(); filename.toLowercase(); - // TODO: Load the SCI2.1+ maps (resmap.*) in concurrence with the volumes to - // get the proper volume numbers from the maps. if (filename.contains("resource.map") || filename.contains("resmap.000")) { map = addExternalMap(file); break; @@ -564,6 +562,14 @@ int ResourceManager::addAppropriateSources(const Common::FSList &fslist) { } } +#ifdef ENABLE_SCI32 + // SCI2.1 resource patches + if (Common::File::exists("RESMAP.PAT") && Common::File::exists("RESSCI.PAT")) { + // We add this resource with a map which surely won't exist + addSource(addExternalMap("RESMAP.PAT", 100), kSourceVolume, "RESSCI.PAT", 100); + } +#endif + // This function is only called by the advanced detector, and we don't really need // to add a patch directory or message.map here -- cgit v1.2.3 From a6efbf8880d56680e5503bcf1f68fdf2c9ef9156 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 1 Jun 2010 22:06:52 +0000 Subject: Fixed the detection of SCI2.1 games in the fallback detector svn-id: r49382 --- engines/sci/resource.cpp | 60 +++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 24 deletions(-) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 96bef504f7..b07b76f9c9 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -183,7 +183,7 @@ ResourceSource *ResourceManager::addExternalMap(const char *file_name, int volum return newsrc; } -ResourceSource *ResourceManager::addExternalMap(const Common::FSNode *mapFile) { +ResourceSource *ResourceManager::addExternalMap(const Common::FSNode *mapFile, int volume_nr) { ResourceSource *newsrc = new ResourceSource(); newsrc->source_type = kSourceExtMap; @@ -191,7 +191,7 @@ ResourceSource *ResourceManager::addExternalMap(const Common::FSNode *mapFile) { newsrc->resourceFile = mapFile; newsrc->scanned = false; newsrc->associated_map = NULL; - newsrc->volume_number = 0; + newsrc->volume_number = volume_nr; _sources.push_back(newsrc); return newsrc; @@ -447,11 +447,11 @@ int sci0_get_compression_method(Common::ReadStream &stream) { int ResourceManager::addAppropriateSources() { Common::ArchiveMemberList files; - if (Common::File::exists("RESOURCE.MAP")) { + if (Common::File::exists("resource.map")) { // SCI0-SCI2 file naming scheme - ResourceSource *map = addExternalMap("RESOURCE.MAP"); + ResourceSource *map = addExternalMap("resource.map"); - SearchMan.listMatchingMembers(files, "RESOURCE.0??"); + SearchMan.listMatchingMembers(files, "resource.0??"); for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { const Common::String name = (*x)->getName(); @@ -462,8 +462,8 @@ int ResourceManager::addAppropriateSources() { } #ifdef ENABLE_SCI32 // GK1CD hires content - if (Common::File::exists("ALT.MAP") && Common::File::exists("RESOURCE.ALT")) - addSource(addExternalMap("ALT.MAP", 10), kSourceVolume, "RESOURCE.ALT", 10); + if (Common::File::exists("alt.map") && Common::File::exists("resource.alt")) + addSource(addExternalMap("alt.map", 10), kSourceVolume, "resource.alt", 10); #endif } else if (Common::File::exists("Data1")) { // Mac SCI1.1+ file naming scheme @@ -486,8 +486,8 @@ int ResourceManager::addAppropriateSources() { } else { // SCI2.1-SCI3 file naming scheme Common::ArchiveMemberList mapFiles; - SearchMan.listMatchingMembers(mapFiles, "RESMAP.0??"); - SearchMan.listMatchingMembers(files, "RESSCI.0??"); + SearchMan.listMatchingMembers(mapFiles, "resmap.0??"); + SearchMan.listMatchingMembers(files, "ressci.0??"); // We need to have the same number of maps as resource archives if (mapFiles.empty() || files.empty() || mapFiles.size() != files.size()) @@ -509,9 +509,9 @@ int ResourceManager::addAppropriateSources() { } // SCI2.1 resource patches - if (Common::File::exists("RESMAP.PAT") && Common::File::exists("RESSCI.PAT")) { + if (Common::File::exists("resmap.pat") && Common::File::exists("ressci.pat")) { // We add this resource with a map which surely won't exist - addSource(addExternalMap("RESMAP.PAT", 100), kSourceVolume, "RESSCI.PAT", 100); + addSource(addExternalMap("resmap.pat", 100), kSourceVolume, "ressci.pat", 100); } } #else @@ -520,14 +520,16 @@ int ResourceManager::addAppropriateSources() { #endif addPatchDir("."); - if (Common::File::exists("MESSAGE.MAP")) - addSource(addExternalMap("MESSAGE.MAP"), kSourceVolume, "RESOURCE.MSG", 0); + if (Common::File::exists("message.map")) + addSource(addExternalMap("message.map"), kSourceVolume, "resource.msg", 0); return 1; } int ResourceManager::addAppropriateSources(const Common::FSList &fslist) { ResourceSource *map = 0; + ResourceSource *sci21PatchMap = 0; + const Common::FSNode *sci21PatchRes = 0; // First, find resource.map for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { @@ -537,15 +539,33 @@ int ResourceManager::addAppropriateSources(const Common::FSList &fslist) { Common::String filename = file->getName(); filename.toLowercase(); - if (filename.contains("resource.map") || filename.contains("resmap.000")) { + if (filename.contains("resource.map")) map = addExternalMap(file); - break; + + if (filename.contains("resmap.0")) { + const char *dot = strrchr(file->getName().c_str(), '.'); + int number = atoi(dot + 1); + map = addExternalMap(file, number); } + +#ifdef ENABLE_SCI32 + // SCI2.1 resource patches + if (filename.contains("resmap.pat")) + sci21PatchMap = addExternalMap(file, 100); + + if (filename.contains("ressci.pat")) + sci21PatchRes = file; +#endif } if (!map) return 0; +#ifdef ENABLE_SCI32 + if (sci21PatchMap && sci21PatchRes) + addSource(sci21PatchMap, kSourceVolume, sci21PatchRes, 100); +#endif + // Now find all the resource.0?? files for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { if (file->isDirectory()) @@ -562,14 +582,6 @@ int ResourceManager::addAppropriateSources(const Common::FSList &fslist) { } } -#ifdef ENABLE_SCI32 - // SCI2.1 resource patches - if (Common::File::exists("RESMAP.PAT") && Common::File::exists("RESSCI.PAT")) { - // We add this resource with a map which surely won't exist - addSource(addExternalMap("RESMAP.PAT", 100), kSourceVolume, "RESSCI.PAT", 100); - } -#endif - // This function is only called by the advanced detector, and we don't really need // to add a patch directory or message.map here @@ -1282,7 +1294,7 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) { res->_id = resId; // NOTE: We add the map's volume number here to the specified volume number - // for SCI2.1 and SCI3 maps that are not RESMAP.000. The RESMAP.* files' numbers + // for SCI2.1 and SCI3 maps that are not resmap.000. The resmap.* files' numbers // need to be used in concurrence with the volume specified in the map to get // the actual resource file. res->_source = getVolume(map, volume_nr + map->volume_number); -- cgit v1.2.3 From 24673b9ee91f6d80ae1b32f239fbe25489c519a0 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 2 Jun 2010 00:20:52 +0000 Subject: Fix warning svn-id: r49386 --- engines/sci/resource.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index b07b76f9c9..8f4fd64d90 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -528,8 +528,10 @@ int ResourceManager::addAppropriateSources() { int ResourceManager::addAppropriateSources(const Common::FSList &fslist) { ResourceSource *map = 0; +#ifdef ENABLE_SCI32 ResourceSource *sci21PatchMap = 0; const Common::FSNode *sci21PatchRes = 0; +#endif // First, find resource.map for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { -- cgit v1.2.3 From 4493080220a98d596ee578bddc8a64c0d3955eac Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Wed, 2 Jun 2010 02:55:55 +0000 Subject: If we can't find the game object or game ID in fallback detection, break out instead of assuming the script is there. Fixes a segfault when detecting an LSCI game. svn-id: r49389 --- engines/sci/resource.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 8f4fd64d90..11d9492ad5 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1935,6 +1935,10 @@ bool ResourceManager::hasSci1Voc900() { reg_t ResourceManager::findGameObject(bool addSci11ScriptOffset) { Resource *script = findResource(ResourceId(kResourceTypeScript, 0), false); + + if (!script) + return NULL_REG; + int extraBytes = 0; if (getSciVersion() == SCI_VERSION_0_EARLY || getSciVersion() >= SCI_VERSION_1_1) extraBytes = 2; @@ -1966,8 +1970,14 @@ Common::String ResourceManager::findSierraGameId() { nameSelector += 5; } + if (!heap) + return ""; + int16 gameObjectOffset = findGameObject(false).offset; + if (!gameObjectOffset) + return ""; + // Seek to the name selector of the first export byte *seeker = heap->data + READ_UINT16(heap->data + gameObjectOffset + nameSelector * 2); Common::String sierraId; -- cgit v1.2.3 From af3fec8c26d92005b507dca65d1d50f820feb0e7 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 2 Jun 2010 13:17:36 +0000 Subject: - Fixed findGameObject() to properly handle SCI0-SCI1 games where the first block of script 0 isn't the exports block - Changed many places where Common::File is used directly to use Common::SeekableReadStream instead (in order to ultimately remove the SCI_detection hack in the fallback detector) svn-id: r49391 --- engines/sci/resource.cpp | 125 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 90 insertions(+), 35 deletions(-) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 11d9492ad5..449effd737 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -237,6 +237,7 @@ ResourceSource *ResourceManager::addPatchDir(const char *dirname) { ResourceSource *newsrc = new ResourceSource(); newsrc->source_type = kSourceDirectory; + newsrc->resourceFile = 0; newsrc->scanned = false; newsrc->location_name = dirname; @@ -257,7 +258,7 @@ ResourceSource *ResourceManager::getVolume(ResourceSource *map, int volume_nr) { // Resource manager constructors and operations -bool ResourceManager::loadPatch(Resource *res, Common::File &file) { +bool ResourceManager::loadPatch(Resource *res, Common::SeekableReadStream *file) { // We assume that the resource type matches res->type // We also assume that the current file position is right at the actual data (behind resourceid/headersize byte) @@ -272,12 +273,12 @@ bool ResourceManager::loadPatch(Resource *res, Common::File &file) { unsigned int really_read; if (res->_headerSize > 0) { - really_read = file.read(res->_header, res->_headerSize); + really_read = file->read(res->_header, res->_headerSize); if (really_read != res->_headerSize) error("Read %d bytes from %s but expected %d", really_read, res->_id.toString().c_str(), res->_headerSize); } - really_read = file.read(res->data, res->size); + really_read = file->read(res->data, res->size); if (really_read != res->size) error("Read %d bytes from %s but expected %d", really_read, res->_id.toString().c_str(), res->size); @@ -295,7 +296,7 @@ bool ResourceManager::loadFromPatchFile(Resource *res) { } // Skip resourceid and header size byte file.seek(2, SEEK_SET); - return loadPatch(res, file); + return loadPatch(res, &file); } Common::File *ResourceManager::getVolumeFile(const char *filename) { @@ -352,10 +353,15 @@ void ResourceManager::loadResource(Resource *res) { return; } - Common::File *file; + Common::SeekableReadStream *fileStream; + // Either loading from volume or patch loading failed - file = getVolumeFile(res->_source->location_name.c_str()); - if (!file) { + if (res->_source->resourceFile) + fileStream = res->_source->resourceFile->createReadStream(); + else + fileStream = getVolumeFile(res->_source->location_name.c_str()); + + if (!fileStream) { warning("Failed to open %s", res->_source->location_name.c_str()); res->unalloc(); return; @@ -363,8 +369,8 @@ void ResourceManager::loadResource(Resource *res) { switch(res->_source->source_type) { case kSourceWave: - file->seek(res->_fileOffset, SEEK_SET); - loadFromWaveFile(res, *file); + fileStream->seek(res->_fileOffset, SEEK_SET); + loadFromWaveFile(res, fileStream); return; case kSourceAudioVolume: @@ -395,30 +401,30 @@ void ResourceManager::loadResource(Resource *res) { if (!compressedOffset) error("could not translate offset to compressed offset in audio volume"); - file->seek(compressedOffset, SEEK_SET); + fileStream->seek(compressedOffset, SEEK_SET); switch (res->_id.type) { case kResourceTypeAudio: case kResourceTypeAudio36: // Directly read the stream, compressed audio wont have resource type id and header size for SCI1.1 - loadFromAudioVolumeSCI1(res, *file); + loadFromAudioVolumeSCI1(res, fileStream); return; default: break; } } else { // original file, directly seek to given offset and get SCI1/SCI1.1 audio resource - file->seek(res->_fileOffset, SEEK_SET); + fileStream->seek(res->_fileOffset, SEEK_SET); } if (getSciVersion() < SCI_VERSION_1_1) - loadFromAudioVolumeSCI1(res, *file); + loadFromAudioVolumeSCI1(res, fileStream); else - loadFromAudioVolumeSCI11(res, *file); + loadFromAudioVolumeSCI11(res, fileStream); return; default: - file->seek(res->_fileOffset, SEEK_SET); - int error = decompress(res, file); + fileStream->seek(res->_fileOffset, SEEK_SET); + int error = decompress(res, fileStream); if (error) { warning("Error %d occured while reading %s from resource file: %s", error, res->_id.toString().c_str(), sci_error_types[error]); @@ -872,7 +878,6 @@ const char *ResourceManager::versionDescription(ResVersion version) const { ResourceManager::ResVersion ResourceManager::detectMapVersion() { Common::SeekableReadStream *fileStream = 0; - Common::File *file = 0; byte buff[6]; ResourceSource *rsrc= 0; @@ -883,7 +888,7 @@ ResourceManager::ResVersion ResourceManager::detectMapVersion() { if (rsrc->resourceFile) { fileStream = rsrc->resourceFile->createReadStream(); } else { - file = new Common::File(); + Common::File *file = new Common::File(); file->open(rsrc->location_name); if (file->isOpen()) fileStream = file; @@ -963,7 +968,6 @@ ResourceManager::ResVersion ResourceManager::detectMapVersion() { ResourceManager::ResVersion ResourceManager::detectVolVersion() { Common::SeekableReadStream *fileStream = 0; - Common::File *file = 0; ResourceSource *rsrc; for (Common::List::iterator it = _sources.begin(); it != _sources.end(); ++it) { @@ -973,7 +977,7 @@ ResourceManager::ResVersion ResourceManager::detectVolVersion() { if (rsrc->resourceFile) { fileStream = rsrc->resourceFile->createReadStream(); } else { - file = new Common::File(); + Common::File *file = new Common::File(); file->open(rsrc->location_name); if (file->isOpen()) fileStream = file; @@ -1063,7 +1067,7 @@ ResourceManager::ResVersion ResourceManager::detectVolVersion() { // version-agnostic patch application void ResourceManager::processPatch(ResourceSource *source, ResourceType restype, int resnumber) { - Common::File file; + Common::SeekableReadStream *fileStream = 0; Resource *newrsc; ResourceId resId = ResourceId(restype, resnumber); byte patchtype, patch_data_offset; @@ -1071,18 +1075,27 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType restype, if (resnumber == -1) return; - if (!file.open(source->location_name)) { - warning("ResourceManager::processPatch(): failed to open %s", source->location_name.c_str()); - return; + + if (source->resourceFile) { + fileStream = source->resourceFile->createReadStream(); + } else { + Common::File *file = new Common::File(); + if (!file->open(source->location_name)) { + warning("ResourceManager::processPatch(): failed to open %s", source->location_name.c_str()); + return; + } + fileStream = file; } - fsize = file.size(); + fsize = fileStream->size(); if (fsize < 3) { debug("Patching %s failed - file too small", source->location_name.c_str()); return; } - patchtype = file.readByte() & 0x7F; - patch_data_offset = file.readByte(); + patchtype = fileStream->readByte() & 0x7F; + patch_data_offset = fileStream->readByte(); + + delete fileStream; if (patchtype != restype) { debug("Patching %s failed - resource type mismatch", source->location_name.c_str()); @@ -1097,8 +1110,12 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType restype, case 1: patch_data_offset = 2; break; + case 4: + patch_data_offset = 8; + break; default: - warning("Resource patch unsupported special case %X", patch_data_offset); + warning("Resource patch unsupported special case %X", patch_data_offset & 0x7F); + return; } } @@ -1180,6 +1197,7 @@ void ResourceManager::readResourcePatches(ResourceSource *source) { psrcPatch = new ResourceSource; psrcPatch->source_type = kSourcePatch; psrcPatch->location_name = name; + psrcPatch->resourceFile = 0; processPatch(psrcPatch, (ResourceType)i, number); } } @@ -1931,7 +1949,31 @@ bool ResourceManager::hasSci1Voc900() { return offset == res->size; } -#define READ_UINT16(ptr) (!isSci11Mac() ? READ_LE_UINT16(ptr) : READ_BE_UINT16(ptr)) +// Same function as Script::findBlock(). Slight code +// duplication here, but this has been done to keep the resource +// manager independent from the rest of the engine +static byte *findSci0ExportsBlock(byte *buffer) { + byte *buf = buffer; + bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); + + if (oldScriptHeader) + buf += 2; + + do { + int seekerType = READ_LE_UINT16(buf); + + if (seekerType == 0) + break; + if (seekerType == 7) // exports + return buf; + + int seekerSize = READ_LE_UINT16(buf + 2); + assert(seekerSize > 0); + buf += seekerSize; + } while (1); + + return NULL; +} reg_t ResourceManager::findGameObject(bool addSci11ScriptOffset) { Resource *script = findResource(ResourceId(kResourceTypeScript, 0), false); @@ -1939,11 +1981,26 @@ reg_t ResourceManager::findGameObject(bool addSci11ScriptOffset) { if (!script) return NULL_REG; - int extraBytes = 0; - if (getSciVersion() == SCI_VERSION_0_EARLY || getSciVersion() >= SCI_VERSION_1_1) - extraBytes = 2; + byte *offsetPtr = 0; + + if (getSciVersion() < SCI_VERSION_1_1) { + byte *buf = (getSciVersion() == SCI_VERSION_0_EARLY) ? script->data + 2 : script->data; + + // Check if the first block is the exports block (in most cases, it is) + bool exportsIsFirst = (READ_LE_UINT16(buf + 4) == 7); + if (exportsIsFirst) { + offsetPtr = buf + 4 + 2; + } else { + offsetPtr = findSci0ExportsBlock(script->data); + if (!offsetPtr) + error("Unable to find exports block from script 0"); + offsetPtr += 4 + 2; + } + } else { + offsetPtr = script->data + 4 + 2 + 2; + } - int16 offset = READ_UINT16(script->data + extraBytes + 4 + 2); + int16 offset = !isSci11Mac() ? READ_LE_UINT16(offsetPtr) : READ_BE_UINT16(offsetPtr); // In SCI1.1 and newer, the heap is appended at the end of the script, // so adjust the offset accordingly @@ -1986,6 +2043,4 @@ Common::String ResourceManager::findSierraGameId() { return sierraId; } -#undef READ_UINT16 - } // End of namespace Sci -- cgit v1.2.3 From e9f35fbf4ce36b2a7cbdada429c5e7a2d49cbab8 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 5 Jun 2010 14:09:52 +0000 Subject: Rewrote the remaining parts of the ResourceManager class to work with file streams, thus removing the SCI_detection hack in the fallback detector svn-id: r49438 --- engines/sci/resource.cpp | 105 ++++++++++++++++++++++++++++++----------------- 1 file changed, 68 insertions(+), 37 deletions(-) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 449effd737..b17117a1cd 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -371,6 +371,8 @@ void ResourceManager::loadResource(Resource *res) { case kSourceWave: fileStream->seek(res->_fileOffset, SEEK_SET); loadFromWaveFile(res, fileStream); + if (res->_source->resourceFile) + delete fileStream; return; case kSourceAudioVolume: @@ -408,6 +410,8 @@ void ResourceManager::loadResource(Resource *res) { case kResourceTypeAudio36: // Directly read the stream, compressed audio wont have resource type id and header size for SCI1.1 loadFromAudioVolumeSCI1(res, fileStream); + if (res->_source->resourceFile) + delete fileStream; return; default: break; @@ -420,11 +424,18 @@ void ResourceManager::loadResource(Resource *res) { loadFromAudioVolumeSCI1(res, fileStream); else loadFromAudioVolumeSCI11(res, fileStream); + + if (res->_source->resourceFile) + delete fileStream; return; default: fileStream->seek(res->_fileOffset, SEEK_SET); int error = decompress(res, fileStream); + + if (res->_source->resourceFile) + delete fileStream; + if (error) { warning("Error %d occured while reading %s from resource file: %s", error, res->_id.toString().c_str(), sci_error_types[error]); @@ -437,19 +448,6 @@ Resource *ResourceManager::testResource(ResourceId id) { return _resMap.getVal(id, NULL); } -int sci0_get_compression_method(Common::ReadStream &stream) { - uint16 compressionMethod; - - stream.readUint16LE(); - stream.readUint16LE(); - stream.readUint16LE(); - compressionMethod = stream.readUint16LE(); - if (stream.err()) - return SCI_ERROR_IO_ERROR; - - return compressionMethod; -} - int ResourceManager::addAppropriateSources() { Common::ArchiveMemberList files; @@ -1205,25 +1203,34 @@ void ResourceManager::readResourcePatches(ResourceSource *source) { } int ResourceManager::readResourceMapSCI0(ResourceSource *map) { - Common::File file; + Common::SeekableReadStream *fileStream = 0; Resource *res; ResourceType type; uint16 number, id; uint32 offset; - if (!file.open(map->location_name)) - return SCI_ERROR_RESMAP_NOT_FOUND; + if (map->resourceFile) { + fileStream = map->resourceFile->createReadStream(); + if (!fileStream) + return SCI_ERROR_RESMAP_NOT_FOUND; + } else { + Common::File *file = new Common::File(); + if (!file->open(map->location_name)) + return SCI_ERROR_RESMAP_NOT_FOUND; + fileStream = file; + } - file.seek(0, SEEK_SET); + fileStream->seek(0, SEEK_SET); byte bMask = (_mapVersion == kResVersionSci1Middle) ? 0xF0 : 0xFC; byte bShift = (_mapVersion == kResVersionSci1Middle) ? 28 : 26; do { - id = file.readUint16LE(); - offset = file.readUint32LE(); + id = fileStream->readUint16LE(); + offset = fileStream->readUint32LE(); - if (file.eos() || file.err()) { + if (fileStream->eos() || fileStream->err()) { + delete fileStream; warning("Error while reading %s", map->location_name.c_str()); return SCI_ERROR_RESMAP_NOT_FOUND; } @@ -1252,15 +1259,26 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) { res->_id = resId; _resMap.setVal(resId, res); } - } while (!file.eos()); + } while (!fileStream->eos()); + + delete fileStream; return 0; } int ResourceManager::readResourceMapSCI1(ResourceSource *map) { - Common::File file; + Common::SeekableReadStream *fileStream = 0; Resource *res; - if (!file.open(map->location_name)) - return SCI_ERROR_RESMAP_NOT_FOUND; + + if (map->resourceFile) { + fileStream = map->resourceFile->createReadStream(); + if (!fileStream) + return SCI_ERROR_RESMAP_NOT_FOUND; + } else { + Common::File *file = new Common::File(); + if (!file->open(map->location_name)) + return SCI_ERROR_RESMAP_NOT_FOUND; + fileStream = file; + } resource_index_t resMap[32]; memset(resMap, 0, sizeof(resource_index_t) * 32); @@ -1271,8 +1289,8 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) { // Read resource type and offsets to resource offsets block from .MAP file // The last entry has type=0xFF (0x1F) and offset equals to map file length do { - type = file.readByte() & 0x1F; - resMap[type].wOffset = file.readUint16LE(); + type = fileStream->readByte() & 0x1F; + resMap[type].wOffset = fileStream->readUint16LE(); resMap[prevtype].wSize = (resMap[type].wOffset - resMap[prevtype].wOffset) / nEntrySize; prevtype = type; @@ -1283,18 +1301,18 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) { for (type = 0; type < 32; type++) { if (resMap[type].wOffset == 0) // this resource does not exist in map continue; - file.seek(resMap[type].wOffset); + fileStream->seek(resMap[type].wOffset); for (int i = 0; i < resMap[type].wSize; i++) { - uint16 number = file.readUint16LE(); + uint16 number = fileStream->readUint16LE(); int volume_nr = 0; if (_mapVersion == kResVersionSci11) { // offset stored in 3 bytes - off = file.readUint16LE(); - off |= file.readByte() << 16; + off = fileStream->readUint16LE(); + off |= fileStream->readByte() << 16; off <<= 1; } else { // offset/volume stored in 4 bytes - off = file.readUint32LE(); + off = fileStream->readUint32LE(); if (_mapVersion < kResVersionSci11) { volume_nr = off >> 28; // most significant 4 bits off &= 0x0FFFFFFF; // least significant 28 bits @@ -1302,7 +1320,8 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) { // in SCI32 it's a plain offset } } - if (file.eos() || file.err()) { + if (fileStream->eos() || fileStream->err()) { + delete fileStream; warning("Error while reading %s", map->location_name.c_str()); return SCI_ERROR_RESMAP_NOT_FOUND; } @@ -1322,6 +1341,8 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) { } } } + + delete fileStream; return 0; } @@ -1574,7 +1595,7 @@ ResourceCompression ResourceManager::getViewCompression() { // Test 10 views to see if any are compressed for (int i = 0; i < 1000; i++) { - Common::File *file; + Common::SeekableReadStream *fileStream = 0; Resource *res = testResource(ResourceId(kResourceTypeView, i)); if (!res) @@ -1583,16 +1604,26 @@ ResourceCompression ResourceManager::getViewCompression() { if (res->_source->source_type != kSourceVolume) continue; - file = getVolumeFile(res->_source->location_name.c_str()); - if (!file) + if (res->_source->resourceFile) + fileStream = res->_source->resourceFile->createReadStream(); + else + fileStream = getVolumeFile(res->_source->location_name.c_str()); + + if (!fileStream) continue; - file->seek(res->_fileOffset, SEEK_SET); + fileStream->seek(res->_fileOffset, SEEK_SET); uint32 szPacked; ResourceCompression compression; - if (readResourceInfo(res, file, szPacked, compression)) + if (readResourceInfo(res, fileStream, szPacked, compression)) { + if (res->_source->resourceFile) + delete fileStream; continue; + } + + if (res->_source->resourceFile) + delete fileStream; if (compression != kCompNone) return compression; -- cgit v1.2.3 From 43c353d9308515e0ce4d73773e50810f9e89ae47 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 6 Jun 2010 13:04:24 +0000 Subject: Now opening all files via getVolumeFile() svn-id: r49451 --- engines/sci/resource.cpp | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index b17117a1cd..f22c4d75fe 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -299,10 +299,15 @@ bool ResourceManager::loadFromPatchFile(Resource *res) { return loadPatch(res, &file); } -Common::File *ResourceManager::getVolumeFile(const char *filename) { +Common::SeekableReadStream *ResourceManager::getVolumeFile(ResourceSource *source) { Common::List::iterator it = _volumeFiles.begin(); Common::File *file; + if (source->resourceFile) + return source->resourceFile->createReadStream(); + + const char *filename = source->location_name.c_str(); + // check if file is already opened while (it != _volumeFiles.end()) { file = *it; @@ -353,13 +358,7 @@ void ResourceManager::loadResource(Resource *res) { return; } - Common::SeekableReadStream *fileStream; - - // Either loading from volume or patch loading failed - if (res->_source->resourceFile) - fileStream = res->_source->resourceFile->createReadStream(); - else - fileStream = getVolumeFile(res->_source->location_name.c_str()); + Common::SeekableReadStream *fileStream = getVolumeFile(res->_source); if (!fileStream) { warning("Failed to open %s", res->_source->location_name.c_str()); @@ -1604,10 +1603,7 @@ ResourceCompression ResourceManager::getViewCompression() { if (res->_source->source_type != kSourceVolume) continue; - if (res->_source->resourceFile) - fileStream = res->_source->resourceFile->createReadStream(); - else - fileStream = getVolumeFile(res->_source->location_name.c_str()); + fileStream = getVolumeFile(res->_source); if (!fileStream) continue; -- cgit v1.2.3 From 43ec405ffe08cef3168c9618be6169e6d81290f8 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 7 Jun 2010 09:10:22 +0000 Subject: Some initial code for audio36 and sync36 patch support svn-id: r49477 --- engines/sci/resource.cpp | 77 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 16 deletions(-) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index f22c4d75fe..5d60438f7f 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -620,6 +620,9 @@ void ResourceManager::scanNewSources() { switch (source->source_type) { case kSourceDirectory: readResourcePatches(source); +#ifdef ENABLE_SCI32 + readResourcePatchesBase36(source); +#endif readWaveAudioPatches(); break; case kSourceExtMap: @@ -1063,10 +1066,10 @@ ResourceManager::ResVersion ResourceManager::detectVolVersion() { } // version-agnostic patch application -void ResourceManager::processPatch(ResourceSource *source, ResourceType restype, int resnumber) { +void ResourceManager::processPatch(ResourceSource *source, ResourceType restype, uint16 resnumber, uint32 tuple) { Common::SeekableReadStream *fileStream = 0; Resource *newrsc; - ResourceId resId = ResourceId(restype, resnumber); + ResourceId resId = ResourceId(restype, resnumber, tuple); byte patchtype, patch_data_offset; int fsize; @@ -1137,32 +1140,73 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType restype, 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 + // tuple. Please don't be confused with the normal audio patches + // (*.aud) and normal sync patches (*.syn). audio36 patches can be seen for example in the AUD + // folder of GK1CD, and are like this file: @0CS0M00.0X1. GK1CD is the first game where these + // have been observed. The actual audio36 and sync36 resources exist in SCI1.1 as well, but the + // first game where external patch files for them have been found is GK1CD. The names of these + // files are base36 encoded, and we handle their decoding here. audio36 files start with a "@", + // whereas sync36 start with a "#" + + Common::String mask, name, inputName; + Common::ArchiveMemberList files; + //ResourceSource *psrcPatch; + + for (int i = kResourceTypeAudio36; i <= kResourceTypeSync36; ++i) { + // audio36 resources start with a @ + // sync36 resources start with a # + mask = (i == kResourceTypeAudio36) ? "@*.*" : "#*.*"; + SearchMan.listMatchingMembers(files, mask); + + 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 number, byte noun, byte verb, byte cond, byte seq + // TODO: this is still not right (especially the tuple part, seems to be overflowing?) + uint16 number = strtol(Common::String(inputName.c_str(), 2).c_str(), 0, 36); + uint32 tuple = strtol(inputName.c_str() + 2, 0, 36); + ResourceId resource36((ResourceType)i, number, tuple); + + if (i == kResourceTypeAudio36) + debug("audio36 patch: %s => %s. tuple:%d, %s\n", name.c_str(), inputName.c_str(), tuple, resource36.toString().c_str()); + else + debug("sync36 patch: %s => %s. tuple:%d, %s\n", name.c_str(), inputName.c_str(), tuple, resource36.toString().c_str()); + + /* + psrcPatch = new ResourceSource; + psrcPatch->source_type = kSourcePatch; + psrcPatch->location_name = name; + psrcPatch->resourceFile = 0; + processPatch(psrcPatch, (ResourceType)i, number, tuple); + */ + } + } +} + +#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, // regardless of s_sciVersion value - // Note that audio36 and sync36 use a different naming scheme, because they cannot be described - // with a single resource number, but are a result of a tuple. - // Please don't be confused with the normal audio patches (*.aud) and normal sync patches (*.syn). - // audio36 patches can be seen for example in the AUD folder of GK1CD, and are like this file: - // @0CS0M00.0X1. GK1CD is the first game where these have been observed. The actual audio36 and - // sync36 resources exist in SCI1.1 as well, but the first game where external patch files for - // them have been found is GK1CD - Common::String mask, name; Common::ArchiveMemberList files; int number = -1; const char *szResType; ResourceSource *psrcPatch; - for (int i = kResourceTypeView; i <= kResourceTypeRobot; ++i) { - // TODO: add support for audio36 and sync36 files - // Such patches were introduced in SCI2, and didn't exist in SCI0-SCI1.1 - if (i == kResourceTypeAudio36 || i == kResourceTypeSync36) - continue; - + for (int i = kResourceTypeView; i <= kResourceTypeHeap; ++i) { files.clear(); szResType = getResourceTypeName((ResourceType)i); // SCI0 naming - type.nnn @@ -1173,6 +1217,7 @@ void ResourceManager::readResourcePatches(ResourceSource *source) { mask = "*."; mask += resourceTypeSuffixes[i]; SearchMan.listMatchingMembers(files, mask); + for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { bool bAdd = false; name = (*x)->getName(); -- cgit v1.2.3 From d5b5a8dbaeac596d02ad6063a61f566c6c092de0 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Mon, 7 Jun 2010 11:44:52 +0000 Subject: Allow for the other audio36 patch naming schemes (Mac and some Torin ones). svn-id: r49482 --- engines/sci/resource.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 5d60438f7f..d700513817 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1150,18 +1150,23 @@ void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { // folder of GK1CD, and are like this file: @0CS0M00.0X1. GK1CD is the first game where these // have been observed. The actual audio36 and sync36 resources exist in SCI1.1 as well, but the // first game where external patch files for them have been found is GK1CD. The names of these - // files are base36 encoded, and we handle their decoding here. audio36 files start with a "@", - // whereas sync36 start with a "#" + // files are base36 encoded, and we handle their decoding here. audio36 files start with a '@', + // whereas sync36 start with a '#'. Mac versions begin with 'A' (probably meaning AIFF). Torin + // has several that begin with 'B'. - Common::String mask, name, inputName; + Common::String name, inputName; Common::ArchiveMemberList files; //ResourceSource *psrcPatch; for (int i = kResourceTypeAudio36; i <= kResourceTypeSync36; ++i) { - // audio36 resources start with a @ + // audio36 resources start with a @, A, or B // sync36 resources start with a # - mask = (i == kResourceTypeAudio36) ? "@*.*" : "#*.*"; - SearchMan.listMatchingMembers(files, mask); + if (i == kResourceTypeAudio36) { + SearchMan.listMatchingMembers(files, "@???????.???"); + SearchMan.listMatchingMembers(files, "A???????.???"); + SearchMan.listMatchingMembers(files, "B???????.???"); + } else + SearchMan.listMatchingMembers(files, "#???????.???"); for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { name = (*x)->getName(); -- cgit v1.2.3 From 8ef5d55edb5b463abca1adf0ed1f359ce94bd391 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 7 Jun 2010 13:47:14 +0000 Subject: Fix gcc warning about an comparison which is always false due to data type range. svn-id: r49484 --- engines/sci/resource.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci/resource.cpp') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index d700513817..4818428663 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1073,7 +1073,7 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType restype, byte patchtype, patch_data_offset; int fsize; - if (resnumber == -1) + if (resnumber == 0xFFFF) return; if (source->resourceFile) { -- cgit v1.2.3