[Scummvm-cvs-logs] SF.net SVN: scummvm:[48998] scummvm/trunk/engines/sci

mthreepwood at users.sourceforge.net mthreepwood at users.sourceforge.net
Mon May 10 20:29:13 CEST 2010


Revision: 48998
          http://scummvm.svn.sourceforge.net/scummvm/?rev=48998&view=rev
Author:   mthreepwood
Date:     2010-05-10 18:29:13 +0000 (Mon, 10 May 2010)

Log Message:
-----------
Add support for loading SCI games from Mac resource forks. The games themselves do not work yet as some (not all) of the data is in BE order instead of LE. They currently error out because it thinks the relocation block is outside of the script.

Modified Paths:
--------------
    scummvm/trunk/engines/sci/detection.cpp
    scummvm/trunk/engines/sci/detection_tables.h
    scummvm/trunk/engines/sci/resource.cpp
    scummvm/trunk/engines/sci/resource.h

Modified: scummvm/trunk/engines/sci/detection.cpp
===================================================================
--- scummvm/trunk/engines/sci/detection.cpp	2010-05-10 18:23:54 UTC (rev 48997)
+++ scummvm/trunk/engines/sci/detection.cpp	2010-05-10 18:29:13 UTC (rev 48998)
@@ -223,7 +223,7 @@
 		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 @@
 			|| 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") ||

Modified: scummvm/trunk/engines/sci/detection_tables.h
===================================================================
--- scummvm/trunk/engines/sci/detection_tables.h	2010-05-10 18:23:54 UTC (rev 48997)
+++ scummvm/trunk/engines/sci/detection_tables.h	2010-05-10 18:29:13 UTC (rev 48998)
@@ -1088,6 +1088,14 @@
 		{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 @@
 		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

Modified: scummvm/trunk/engines/sci/resource.cpp
===================================================================
--- scummvm/trunk/engines/sci/resource.cpp	2010-05-10 18:23:54 UTC (rev 48997)
+++ scummvm/trunk/engines/sci/resource.cpp	2010-05-10 18:29:13 UTC (rev 48998)
@@ -26,6 +26,7 @@
 // Resource library
 
 #include "common/file.h"
+#include "common/macresman.h"
 
 #include "sci/resource.h"
 
@@ -52,6 +53,7 @@
 	ResourceSource *associated_map;
 	uint32 audioCompressionType;
 	int32 *audioCompressionOffsetMapping;
+	Common::MacResManager macResMan;
 };
 
 //////////////////////////////////////////////////////////////////////
@@ -435,12 +437,29 @@
 	return NULL;
 }
 
+static const uint32 resTypeToMacTag(ResourceType type);
+
 void ResourceManager::loadResource(Resource *res) {
-	Common::File *file;
-
 	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 @@
 			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 @@
 			case kSourceIntMap:
 				readAudioMapSCI11(source);
 				break;
+			case kSourceMacResourceFork:
+				readMacResourceFork(source);
+				break;
 			default:
 				break;
 			}
@@ -720,8 +750,11 @@
 }
 
 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 @@
 		return "Late SCI1";
 	case kResVersionSci11:
 		return "SCI1.1";
+	case kResVersionSci11Mac:
+		return "Mac SCI1.1+";
 	case kResVersionSci32:
 		return "SCI32";
 	}
@@ -965,7 +1000,8 @@
 					fileStream = file;
 			}
 			break;
-		}
+		} else if (rsrc->source_type == kSourceMacResourceFork)
+			return kResVersionSci11Mac;
 	}
 
 	if (!fileStream)
@@ -1054,8 +1090,10 @@
 					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 @@
 	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 @@
 	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 @@
 		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 @@
 	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 @@
 	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 @@
 	error = readResourceInfo(res, file, szPacked, compression);
 	if (error)
 		return error;
+
 	// getting a decompressor
 	Decompressor *dec = NULL;
 	switch (compression) {
@@ -1930,6 +2045,7 @@
 	// 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 @@
 		// 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) {

Modified: scummvm/trunk/engines/sci/resource.h
===================================================================
--- scummvm/trunk/engines/sci/resource.h	2010-05-10 18:23:54 UTC (rev 48997)
+++ scummvm/trunk/engines/sci/resource.h	2010-05-10 18:29:13 UTC (rev 48998)
@@ -80,7 +80,8 @@
 	kSourceIntMap,
 	kSourceAudioVolume,
 	kSourceExtAudioMap,
-	kSourceWave
+	kSourceWave,
+	kSourceMacResourceFork
 };
 
 enum ResourceType {
@@ -205,6 +206,7 @@
 		kResVersionSci1Middle,
 		kResVersionSci1Late,
 		kResVersionSci11,
+		kResVersionSci11Mac,
 		kResVersionSci32
 	};
 
@@ -367,8 +369,8 @@
 	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 @@
 	 * @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


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list