aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/detection.cpp8
-rw-r--r--engines/sci/detection_tables.h17
-rw-r--r--engines/sci/resource.cpp145
-rw-r--r--engines/sci/resource.h15
4 files changed, 172 insertions, 13 deletions
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index 3c526dd1cd..b574484319 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -223,7 +223,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl
Common::String filename = file->getName();
filename.toLowercase();
- if (filename.contains("resource.map") || filename.contains("resmap.00")) {
+ if (filename.contains("resource.map") || filename.contains("resmap.00") || filename.contains("Data1")) {
// HACK: resource.map is located in the same directory as the other resource files,
// therefore add the directory here, so that the game files can be opened later on
// We now add the parent directory temporary to our SearchMan so the engine code
@@ -259,6 +259,12 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl
|| filename.contains("ressci.000") || filename.contains("ressci.001"))
foundRes000 = true;
+ // Data1 contains both map and volume for SCI1.1+ Mac games
+ if (filename.contains("Data1")) {
+ foundResMap = foundRes000 = true;
+ s_fallbackDesc.platform = Common::kPlatformMacintosh;
+ }
+
// Determine the game platform
// The existence of any of these files indicates an Amiga game
if (filename.contains("9.pat") || filename.contains("spal") ||
diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index 4a67960875..dba4d879aa 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -1088,6 +1088,14 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{NULL, 0, NULL, 0}},
Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NONE },
+ // King's Quest 6 - English Macintosh Floppy
+ // VERSION file reports "1.0"
+ {"kq6", "", {
+ {"Data1", 0, "f3c38a33c94293b8ff0337c1090a4973", 3916479},
+ {"Data2", 0, "b255edf327d7b366dce816b7debf3b94", 15046256},
+ {NULL, 0, NULL, 0}},
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO_NOSPEECH },
+
#ifdef ENABLE_SCI32
@@ -2243,6 +2251,15 @@ static const struct ADGameDescription SciGameDescriptions[] = {
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH
},
+ // Quest for Glory 1 VGA Remake - English Macintosh Floppy
+ // VERSION file reports "2.0"
+ {"qfg1", "VGA Remake", {
+ {"Data1", 0, "14f26bc75f24bb1ecc94532df17b5371", 1768155},
+ {"Data2", 0, "a7aee8bd46fc9cef7fd3bea93ef173e0", 6586422},
+ {NULL, 0, NULL, 0}},
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO_NOSPEECH
+ },
+
// Quest for Glory 2 - English Amiga
// Executable scanning reports "1.003.004"
// SCI interpreter version 0.001.010
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp
index 20943c8f06..767dab8d66 100644
--- a/engines/sci/resource.cpp
+++ b/engines/sci/resource.cpp
@@ -26,6 +26,7 @@
// Resource library
#include "common/file.h"
+#include "common/macresman.h"
#include "sci/resource.h"
@@ -52,6 +53,7 @@ struct ResourceSource {
ResourceSource *associated_map;
uint32 audioCompressionType;
int32 *audioCompressionOffsetMapping;
+ Common::MacResManager macResMan;
};
//////////////////////////////////////////////////////////////////////
@@ -435,12 +437,29 @@ Common::File *ResourceManager::getVolumeFile(const char *filename) {
return NULL;
}
-void ResourceManager::loadResource(Resource *res) {
- Common::File *file;
+static const uint32 resTypeToMacTag(ResourceType type);
+void ResourceManager::loadResource(Resource *res) {
if (res->_source->source_type == kSourcePatch && loadFromPatchFile(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");
+
+ int error = decompress(res, stream);
+ if (error) {
+ warning("Error %d occured while reading %s from Mac resource file: %s",
+ error, res->_id.toString().c_str(), sci_error_types[error]);
+ res->unalloc();
+ }
+ return;
+ }
+
+ Common::File *file;
// Either loading from volume or patch loading failed
file = getVolumeFile(res->_source->location_name.c_str());
if (!file) {
@@ -549,11 +568,19 @@ int ResourceManager::addAppropriateSources() {
addSource(map, kSourceVolume, name.c_str(), number);
}
#ifdef ENABLE_SCI32
-
// GK1CD hires content
- if (Common::File::exists("ALT.MAP") && Common::File::exists("RESOURCE.ALT")) {
+ 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
+ SearchMan.listMatchingMembers(files, "Data?");
+
+ for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
+ Common::String filename = (*x)->getName();
+ addSource(0, kSourceMacResourceFork, filename.c_str(), atoi(filename.c_str() + 4));
}
+#ifdef ENABLE_SCI32
} else {
// SCI2.1-SCI3 file naming scheme
Common::ArchiveMemberList mapFiles;
@@ -712,6 +739,9 @@ void ResourceManager::scanNewSources() {
case kSourceIntMap:
readAudioMapSCI11(source);
break;
+ case kSourceMacResourceFork:
+ readMacResourceFork(source);
+ break;
default:
break;
}
@@ -720,8 +750,11 @@ void ResourceManager::scanNewSources() {
}
void ResourceManager::freeResourceSources() {
- for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it)
+ for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) {
+ if ((*it)->source_type == kSourceMacResourceFork)
+ (*it)->macResMan.close();
delete *it;
+ }
_sources.clear();
}
@@ -939,6 +972,8 @@ const char *ResourceManager::versionDescription(ResVersion version) const {
return "Late SCI1";
case kResVersionSci11:
return "SCI1.1";
+ case kResVersionSci11Mac:
+ return "Mac SCI1.1+";
case kResVersionSci32:
return "SCI32";
}
@@ -965,7 +1000,8 @@ ResourceManager::ResVersion ResourceManager::detectMapVersion() {
fileStream = file;
}
break;
- }
+ } else if (rsrc->source_type == kSourceMacResourceFork)
+ return kResVersionSci11Mac;
}
if (!fileStream)
@@ -1054,8 +1090,10 @@ ResourceManager::ResVersion ResourceManager::detectVolVersion() {
fileStream = file;
}
break;
- }
+ } else if (rsrc->source_type == kSourceMacResourceFork)
+ return kResVersionSci11Mac;
}
+
if (!fileStream) {
error("Failed to open volume file - if you got resource.p01/resource.p02/etc. files, merge them together into resource.000");
// resource.p01/resource.p02/etc. may be there when directly copying the files from the original floppies
@@ -1414,6 +1452,70 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
return 0;
}
+static const uint32 resourceTypeMacTags[] = {
+ 'V56 ', 'P56 ', 'SCR ', 'TEX ', 'SND ',
+ 0, 'VOC ', 'FON ', 0, 'Pat ', // 'CURS is a mac cursor, not sure if it goes in
+ 0, 'PAL ', 0, 0, 0,
+ 'MSG ', 0, 'HEP '
+};
+
+static const uint32 resTypeToMacTag(ResourceType type) {
+ if (type >= ARRAYSIZE(resourceTypeMacTags))
+ return 0;
+
+ return resourceTypeMacTags[type];
+}
+
+int ResourceManager::readMacResourceFork(ResourceSource *source) {
+ if (!source->macResMan.open(source->location_name.c_str()))
+ error("%s is not a valid Mac resource fork", source->location_name.c_str());
+
+ Common::MacResTagArray tagArray = source->macResMan.getResTagArray();
+
+ for (uint32 i = 0; i < tagArray.size(); i++) {
+ ResourceType type = kResourceTypeInvalid;
+
+ // Map the Mac tags to our ResourceType
+ for (uint32 j = 0; j < ARRAYSIZE(resourceTypeMacTags); j++)
+ if (tagArray[i] == resourceTypeMacTags[j]) {
+ type = (ResourceType)j;
+ break;
+ }
+
+ if (type == kResourceTypeInvalid)
+ continue;
+
+ Common::MacResIDArray idArray = source->macResMan.getResIDArray(tagArray[i]);
+
+ for (uint32 j = 0; j < idArray.size(); j++) {
+ ResourceId resId = ResourceId(type, idArray[j]);
+
+ Resource *newrsc = NULL;
+
+ // Prepare destination, if neccessary
+ if (!_resMap.contains(resId)) {
+ newrsc = new Resource;
+ _resMap.setVal(resId, newrsc);
+ } 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, because we're patching
+ newrsc->_id = resId;
+ newrsc->_status = kResStatusNoMalloc;
+ newrsc->_source = source;
+ newrsc->size = fileSize;
+ newrsc->_headerSize = 0;
+ }
+ }
+
+ return 0;
+}
+
void ResourceManager::addResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size) {
// Adding new resource only if it does not exist
if (_resMap.contains(resId) == false) {
@@ -1681,7 +1783,7 @@ int ResourceManager::getAudioLanguage() const {
return (_audioMapSCI1 ? _audioMapSCI1->volume_number : 0);
}
-int ResourceManager::readResourceInfo(Resource *res, Common::File *file,
+int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream *file,
uint32&szPacked, ResourceCompression &compression) {
// SCI0 volume format: {wResId wPacked+4 wUnpacked wCompression} = 8 bytes
// SCI1 volume format: {bResType wResNumber wPacked+4 wUnpacked wCompression} = 9 bytes
@@ -1715,6 +1817,15 @@ int ResourceManager::readResourceInfo(Resource *res, Common::File *file,
szUnpacked = file->readUint16LE();
wCompression = file->readUint16LE();
break;
+ case kResVersionSci11Mac:
+ // Doesn't store this data in the resource. Fortunately,
+ // we already have this data.
+ type = res->_id.type;
+ number = res->_id.number;
+ szPacked = file->size();
+ szUnpacked = file->size();
+ wCompression = 0;
+ break;
#ifdef ENABLE_SCI32
case kResVersionSci32:
type = (ResourceType)(file->readByte() & 0x7F);
@@ -1727,11 +1838,14 @@ int ResourceManager::readResourceInfo(Resource *res, Common::File *file,
default:
return SCI_ERROR_INVALID_RESMAP_ENTRY;
}
+
// check if there were errors while reading
if ((file->eos() || file->err()))
return SCI_ERROR_IO_ERROR;
+
res->_id = ResourceId(type, number);
res->size = szUnpacked;
+
// checking compression method
switch (wCompression) {
case 0:
@@ -1766,7 +1880,7 @@ int ResourceManager::readResourceInfo(Resource *res, Common::File *file,
return compression == kCompUnknown ? SCI_ERROR_UNKNOWN_COMPRESSION : 0;
}
-int ResourceManager::decompress(Resource *res, Common::File *file) {
+int ResourceManager::decompress(Resource *res, Common::SeekableReadStream *file) {
int error;
uint32 szPacked = 0;
ResourceCompression compression = kCompUnknown;
@@ -1775,6 +1889,7 @@ int ResourceManager::decompress(Resource *res, Common::File *file) {
error = readResourceInfo(res, file, szPacked, compression);
if (error)
return error;
+
// getting a decompressor
Decompressor *dec = NULL;
switch (compression) {
@@ -1930,6 +2045,7 @@ void ResourceManager::detectSciVersion() {
// Set view type
if (viewCompression == kCompDCL
|| _volVersion == kResVersionSci11 // pq4demo
+ || _volVersion == kResVersionSci11Mac // FIXME: Is this right?
#ifdef ENABLE_SCI32
|| viewCompression == kCompSTACpack
|| _volVersion == kResVersionSci32 // kq7
@@ -1941,6 +2057,17 @@ void ResourceManager::detectSciVersion() {
// Otherwise we detect it from a view
_viewType = detectViewType();
}
+
+ if (_volVersion == kResVersionSci11Mac) {
+ // SCI32 doesn't have the resource.cfg file, so we can figure out
+ // which of the games are SCI1.1.
+ // TODO: Decide between SCI2 and SCI2.1
+ if (Common::File::exists("resource.cfg"))
+ s_sciVersion = SCI_VERSION_1_1;
+ else
+ s_sciVersion = SCI_VERSION_2;
+ return;
+ }
// Handle SCI32 versions here
if (_volVersion == kResVersionSci32) {
diff --git a/engines/sci/resource.h b/engines/sci/resource.h
index 64e3cb4a12..1704336f2d 100644
--- a/engines/sci/resource.h
+++ b/engines/sci/resource.h
@@ -80,7 +80,8 @@ enum ResSourceType {
kSourceIntMap,
kSourceAudioVolume,
kSourceExtAudioMap,
- kSourceWave
+ kSourceWave,
+ kSourceMacResourceFork
};
enum ResourceType {
@@ -205,6 +206,7 @@ public:
kResVersionSci1Middle,
kResVersionSci1Late,
kResVersionSci11,
+ kResVersionSci11Mac,
kResVersionSci32
};
@@ -367,8 +369,8 @@ protected:
bool loadFromAudioVolumeSCI1(Resource *res, Common::File &file);
bool loadFromAudioVolumeSCI11(Resource *res, Common::File &file);
void freeOldResources();
- int decompress(Resource *res, Common::File *file);
- int readResourceInfo(Resource *res, Common::File *file, uint32&szPacked, ResourceCompression &compression);
+ int decompress(Resource *res, Common::SeekableReadStream *file);
+ int readResourceInfo(Resource *res, Common::SeekableReadStream *file, uint32&szPacked, ResourceCompression &compression);
void addResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size = 0);
void removeAudioResource(ResourceId resId);
@@ -389,6 +391,13 @@ protected:
* @return 0 on success, an SCI_ERROR_* code otherwise
*/
int readResourceMapSCI1(ResourceSource *map);
+
+ /**
+ * Reads the SCI1.1+ resource file from a Mac resource fork.
+ * @param source The source
+ * @return 0 on success, an SCI_ERROR_* code otherwise
+ */
+ int readMacResourceFork(ResourceSource *source);
/**
* Reads SCI1.1 audio map resources