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

mthreepwood at users.sourceforge.net mthreepwood at users.sourceforge.net
Tue Aug 3 16:58:57 CEST 2010


Revision: 51696
          http://scummvm.svn.sourceforge.net/scummvm/?rev=51696&view=rev
Author:   mthreepwood
Date:     2010-08-03 14:58:57 +0000 (Tue, 03 Aug 2010)

Log Message:
-----------
SCI: Add support for SCI2.1 chunk resources

And if no scripts are present, but chunk 0 is present, load resources from there. This fixes the Lighthouse SCI2.1 demo.

Modified Paths:
--------------
    scummvm/trunk/engines/sci/resource.cpp
    scummvm/trunk/engines/sci/resource.h
    scummvm/trunk/engines/sci/resource_audio.cpp
    scummvm/trunk/engines/sci/resource_intern.h

Modified: scummvm/trunk/engines/sci/resource.cpp
===================================================================
--- scummvm/trunk/engines/sci/resource.cpp	2010-08-03 14:58:01 UTC (rev 51695)
+++ scummvm/trunk/engines/sci/resource.cpp	2010-08-03 14:58:57 UTC (rev 51696)
@@ -182,7 +182,7 @@
 }
 
 //-- Resource main functions --
-Resource::Resource(ResourceId id) : _id(id) {
+Resource::Resource(ResourceManager *resMan, ResourceId id) : _resMan(resMan), _id(id) {
 	data = NULL;
 	size = 0;
 	_fileOffset = 0;
@@ -705,7 +705,87 @@
 	resMan->readAudioMapSCI11(this);
 }
 
+#ifdef ENABLE_SCI32
 
+// Chunk resources are resources that hold other resources. They are normally called
+// when using the kLoadChunk SCI2.1 kernel function. However, for example, the Lighthouse
+// SCI2.1 demo has a chunk but no scripts outside of the chunk.
+
+// A chunk resource is pretty straightforward in terms of layout
+// It begins with 11-byte entries in the header:
+// =========
+// b resType
+// w nEntry
+// dw offset
+// dw length
+
+ChunkResourceSource::ChunkResourceSource(const Common::String &name, uint16 number)
+	: ResourceSource(kSourceChunk, name) {
+
+	_number = 0;
+}
+
+void ChunkResourceSource::scanSource(ResourceManager *resMan) {
+	Resource *chunk = resMan->findResource(ResourceId(kResourceTypeChunk, _number), false);
+
+	if (!chunk)
+		error("Trying to load non-existent chunk");
+
+	byte *ptr = chunk->data;
+	uint32 firstOffset = 0;
+	
+	for (;;) {
+		ResourceType type = resMan->convertResType(*ptr);
+		uint16 number = READ_LE_UINT16(ptr + 1);
+		ResourceId id(type, number);
+
+		ResourceEntry entry;
+		entry.offset = READ_LE_UINT32(ptr + 3);
+		entry.length = READ_LE_UINT32(ptr + 7);
+
+		_resMap[id] = entry;
+		ptr += 11;
+
+		debugC(kDebugLevelResMan, 2, "Found %s in chunk %d", id.toString().c_str(), _number);
+
+		resMan->updateResource(id, this, entry.length);
+
+		// There's no end marker to the data table, but the first resource
+		// begins directly after the entry table. So, when we hit the first
+		// resource, we're at the end of the entry table.
+		
+		if (!firstOffset)
+			firstOffset = entry.offset;
+
+		if ((ptr - chunk->data) >= firstOffset)
+			break;
+	}
+}
+
+void ChunkResourceSource::loadResource(ResourceManager *resMan, Resource *res) {
+	Resource *chunk = resMan->findResource(ResourceId(kResourceTypeChunk, _number), false);
+
+	if (!_resMap.contains(res->_id))
+		error("Trying to load non-existent resource from chunk %d: %s %d", _number, getResourceTypeName(res->_id.getType()), res->_id.getNumber());
+
+	ResourceEntry entry = _resMap[res->_id];
+	res->data = new byte[entry.length];
+	res->size = entry.length;
+	res->_header = 0;
+	res->_headerSize = 0;
+	res->_status = kResStatusAllocated;
+
+	// Copy the resource data over
+	memcpy(res->data, chunk->data + entry.offset, entry.length);
+}
+
+void ResourceManager::addResourcesFromChunk(uint16 id) {
+	addSource(new ChunkResourceSource(Common::String::printf("Chunk %d", id), id));
+	scanNewSources();
+}
+
+#endif
+
 void ResourceManager::freeResourceSources() {
 	for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it)
 		delete *it;
@@ -770,6 +850,21 @@
 	default:
 		error("resMan: Couldn't determine view type");
 	}
+
+#ifdef ENABLE_SCI32
+	if (getSciVersion() >= SCI_VERSION_2_1) {
+		// If we have no scripts, but chunk 0 is present, open up the chunk
+		// to try to get to any scripts in there. The Lighthouse SCI2.1 demo
+		// does exactly this.
+
+		Common::List<ResourceId> *scriptList = listResources(kResourceTypeScript);
+
+		if (scriptList->empty() && testResource(ResourceId(kResourceTypeChunk, 0)))
+			addResourcesFromChunk(0);
+
+		delete scriptList;
+	}
+#endif
 }
 
 ResourceManager::~ResourceManager() {
@@ -1544,7 +1639,7 @@
 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) {
-		Resource *res = new Resource(resId);
+		Resource *res = new Resource(this, resId);
 		_resMap.setVal(resId, res);
 		res->_source = src;
 		res->_fileOffset = offset;
@@ -1559,7 +1654,7 @@
 	if (_resMap.contains(resId)) {
 		res = _resMap.getVal(resId);
 	} else {
-		res = new Resource(resId);
+		res = new Resource(this, resId);
 		_resMap.setVal(resId, res);
 	}
 
@@ -1585,21 +1680,21 @@
 	case kResVersionSci0Sci1Early:
 	case kResVersionSci1Middle:
 		w = file->readUint16LE();
-		type = (ResourceType)(w >> 11);
+		type = _resMan->convertResType(w >> 11);
 		number = w & 0x7FF;
 		szPacked = file->readUint16LE() - 4;
 		szUnpacked = file->readUint16LE();
 		wCompression = file->readUint16LE();
 		break;
 	case kResVersionSci1Late:
-		type = (ResourceType)(file->readByte() & 0x7F);
+		type = _resMan->convertResType(file->readByte());
 		number = file->readUint16LE();
 		szPacked = file->readUint16LE() - 4;
 		szUnpacked = file->readUint16LE();
 		wCompression = file->readUint16LE();
 		break;
 	case kResVersionSci11:
-		type = (ResourceType)(file->readByte() & 0x7F);
+		type = _resMan->convertResType(file->readByte());
 		number = file->readUint16LE();
 		szPacked = file->readUint16LE();
 		szUnpacked = file->readUint16LE();
@@ -1616,7 +1711,7 @@
 		break;
 #ifdef ENABLE_SCI32
 	case kResVersionSci32:
-		type = (ResourceType)(file->readByte() & 0x7F);
+		type = _resMan->convertResType(file->readByte());
 		number = file->readUint16LE();
 		szPacked = file->readUint32LE();
 		szUnpacked = file->readUint32LE();

Modified: scummvm/trunk/engines/sci/resource.h
===================================================================
--- scummvm/trunk/engines/sci/resource.h	2010-08-03 14:58:01 UTC (rev 51695)
+++ scummvm/trunk/engines/sci/resource.h	2010-08-03 14:58:57 UTC (rev 51696)
@@ -193,6 +193,9 @@
 	friend class WaveResourceSource;
 	friend class AudioVolumeResourceSource;
 	friend class MacResourceForkResourceSource;
+#ifdef ENABLE_SCI32
+	friend class ChunkResourceSource;
+#endif
 
 // NOTE : Currently most member variables lack the underscore prefix and have
 // public visibility to let the rest of the engine compile without changes.
@@ -203,7 +206,7 @@
 	uint32 _headerSize;
 
 public:
-	Resource(ResourceId id);
+	Resource(ResourceManager *resMan, ResourceId id);
 	~Resource();
 	void unalloc();
 
@@ -227,6 +230,7 @@
 	ResourceStatus _status;
 	uint16 _lockers; /**< Number of places where this resource was locked */
 	ResourceSource *_source;
+	ResourceManager *_resMan;
 
 	bool loadPatch(Common::SeekableReadStream *file);
 	bool loadFromPatchFile();
@@ -251,6 +255,9 @@
 	friend class ExtAudioMapResourceSource;
 	friend class WaveResourceSource;
 	friend class MacResourceForkResourceSource;
+#ifdef ENABLE_SCI32
+	friend class ChunkResourceSource;
+#endif
 
 public:
 	/**
@@ -324,6 +331,14 @@
 	 */
 	void addNewGMPatch(SciGameId gameId);
 
+#ifdef ENABLE_SCI32
+	/**
+	 * Parses all resources from a SCI2.1 chunk resource and adds them to the
+	 * resource manager.
+	 */
+	void addResourcesFromChunk(uint16 id);
+#endif
+
 	bool detectHires();
 	// Detects, if standard font of current game includes extended characters (>0x80)
 	bool detectFontExtended();

Modified: scummvm/trunk/engines/sci/resource_audio.cpp
===================================================================
--- scummvm/trunk/engines/sci/resource_audio.cpp	2010-08-03 14:58:01 UTC (rev 51695)
+++ scummvm/trunk/engines/sci/resource_audio.cpp	2010-08-03 14:58:57 UTC (rev 51696)
@@ -99,7 +99,7 @@
 	}
 	file->seek(-4, SEEK_CUR);
 
-	ResourceType type = (ResourceType)(file->readByte() & 0x7f);
+	ResourceType type = _resMan->convertResType(file->readByte());
 	if (((getType() == kResourceTypeAudio || getType() == kResourceTypeAudio36) && (type != kResourceTypeAudio))
 		|| ((getType() == kResourceTypeSync || getType() == kResourceTypeSync36) && (type != kResourceTypeSync))) {
 		warning("Resource type mismatch loading %s", _id.toString().c_str());

Modified: scummvm/trunk/engines/sci/resource_intern.h
===================================================================
--- scummvm/trunk/engines/sci/resource_intern.h	2010-08-03 14:58:01 UTC (rev 51695)
+++ scummvm/trunk/engines/sci/resource_intern.h	2010-08-03 14:58:57 UTC (rev 51696)
@@ -43,7 +43,8 @@
 	kSourceAudioVolume,
 	kSourceExtAudioMap,
 	kSourceWave,
-	kSourceMacResourceFork
+	kSourceMacResourceFork,
+	kSourceChunk
 };
 
 
@@ -188,6 +189,31 @@
 	virtual void loadResource(ResourceManager *resMan, Resource *res);
 };
 
+#ifdef ENABLE_SCI32
+
+/**
+ * Reads resources from SCI2.1+ chunk resources
+ */
+class ChunkResourceSource : public ResourceSource {
+public:
+	ChunkResourceSource(const Common::String &name, uint16 number);
+
+	virtual void scanSource(ResourceManager *resMan);
+	virtual void loadResource(ResourceManager *resMan, Resource *res);
+
+protected:
+	uint16 _number;
+
+	struct ResourceEntry {
+		uint32 offset;
+		uint32 length;
+	};
+
+	Common::HashMap<ResourceId, ResourceEntry, ResourceIdHash> _resMap;
+};
+
+#endif
+
 } // End of namespace Sci
 
 #endif // SCI_RESOURCE_INTERN_H


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