[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