diff options
| -rw-r--r-- | engines/sci/console.cpp | 128 | ||||
| -rw-r--r-- | engines/sci/console.h | 3 | 
2 files changed, 131 insertions, 0 deletions
| diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index a2b065ab6c..4d8ff17c10 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -117,6 +117,7 @@ Console::Console(SciEngine *engine) : GUI::Debugger(),  	registerCmd("alloc_list",				WRAP_METHOD(Console, cmdAllocList));  	registerCmd("hexgrep",			WRAP_METHOD(Console, cmdHexgrep));  	registerCmd("verify_scripts",		WRAP_METHOD(Console, cmdVerifyScripts)); +	registerCmd("integrity_dump",	WRAP_METHOD(Console, cmdResourceIntegrityDump));  	// Game  	registerCmd("save_game",			WRAP_METHOD(Console, cmdSaveGame));  	registerCmd("restore_game",		WRAP_METHOD(Console, cmdRestoreGame)); @@ -373,6 +374,7 @@ bool Console::cmdHelp(int argc, const char **argv) {  	debugPrintf(" alloc_list - Lists all allocated resources\n");  	debugPrintf(" hexgrep - Searches some resources for a particular sequence of bytes, represented as hexadecimal numbers\n");  	debugPrintf(" verify_scripts - Performs sanity checks on SCI1.1-SCI2.1 game scripts (e.g. if they're up to 64KB in total)\n"); +	debugPrintf(" integrity_dump - Dumps integrity data about resources in the current game to disk\n");  	debugPrintf("\n");  	debugPrintf("Game:\n");  	debugPrintf(" save_game - Saves the current game state to the hard disk\n"); @@ -919,6 +921,113 @@ bool Console::cmdList(int argc, const char **argv) {  	return true;  } +bool Console::cmdResourceIntegrityDump(int argc, const char **argv) { +	if (argc < 2) { +		debugPrintf("Dumps integrity data about resources in the current game to disk.\n"); +		debugPrintf("Usage: %s <filename> [<skip video file hashing>] [<skip video files altogether>]\n", argv[0]); +		return true; +	} + +	Common::DumpFile outFile; +	if (!outFile.open(argv[1])) { +		debugPrintf("Failed to open output file %s.\n", argv[1]); +		return true; +	} + +	const bool hashVideoFiles = argc < 3; +	const bool videoFiles = argc < 4; + +	for (int i = 0; i < kResourceTypeInvalid; ++i) { +		const ResourceType resType = (ResourceType)i; + +		// This will list video resources inside of resource bundles even if +		// video files are skipped, but this seems fine since those files are +		// small because they were intended to load into memory. (This happens +		// with VMDs in GK2.) +		Common::List<ResourceId> resources = _engine->getResMan()->listResources(resType); + +		const char *extension; +		if (videoFiles) { +			switch (resType) { +			case kResourceTypeRobot: +			case kResourceTypeVMD: +			case kResourceTypeDuck: +			case kResourceTypeClut: { +				extension = getResourceTypeExtension(resType); +				assert(*extension != '\0'); + +				const Common::String filesGlob = Common::String::format("*.%s", extension).c_str(); +				Common::ArchiveMemberList files; +				const int numMatches = SearchMan.listMatchingMembers(files, filesGlob); +				if (numMatches > 0) { +					Common::ArchiveMemberList::const_iterator it; +					for (it = files.begin(); it != files.end(); ++it) { +						const uint resNo = atoi((*it)->getName().c_str()); +						resources.push_back(ResourceId(resType, resNo)); +					} +				} + +				break; +			} +			default: +				extension = ""; +			} +		} + +		if (resources.size()) { +			Common::sort(resources.begin(), resources.end()); +			Common::List<ResourceId>::const_iterator it; +			debugPrintf("%s: ", getResourceTypeName(resType)); +			for (it = resources.begin(); it != resources.end(); ++it) { +				Common::String statusName; +				if (resType == kResourceTypeAudio36 || resType == kResourceTypeSync36) { +					statusName = it->toPatchNameBase36(); +				} else { +					statusName = Common::String::format("%d", it->getNumber()); +				} + +				const Common::String resourceName = it->toString(); + +				Resource *resource = _engine->getResMan()->findResource(*it, false); +				if (resource) { +					Common::MemoryReadStream stream = resource->toStream(); +					writeIntegrityDumpLine(statusName, resourceName, outFile, &stream, resource->size(), true); +				} else if (videoFiles && *extension != '\0') { +					const Common::String fileName = Common::String::format("%u.%s", it->getNumber(), extension); +					Common::File file; +					Common::ReadStream *stream = nullptr; +					if (file.open(fileName)) { +						stream = &file; +					} +					writeIntegrityDumpLine(statusName, resourceName, outFile, stream, file.size(), hashVideoFiles); +				} +			} + +			debugPrintf("\n"); +		} +	} + +	const char *otherVideoFiles[] = { "avi", "seq" }; +	for (uint i = 0; i < ARRAYSIZE(otherVideoFiles); ++i) { +		const char *extension = otherVideoFiles[i]; + +		Common::ArchiveMemberList files; +		if (SearchMan.listMatchingMembers(files, Common::String::format("*.%s", extension).c_str()) > 0) { +			debugPrintf("%s: ", extension); +			Common::sort(files.begin(), files.end(), Common::ArchiveMemberListComparator()); +			Common::ArchiveMemberList::const_iterator it; +			for (it = files.begin(); it != files.end(); ++it) { +				const Common::ArchiveMember &file = **it; +				Common::ScopedPtr<Common::SeekableReadStream> stream(file.createReadStream()); +				writeIntegrityDumpLine(file.getName(), file.getName(), outFile, stream.get(), stream->size(), hashVideoFiles); +			} +			debugPrintf("\n"); +		} +	} + +	return true; +} +  bool Console::cmdAllocList(int argc, const char **argv) {  	ResourceManager *resMan = _engine->getResMan(); @@ -4907,6 +5016,25 @@ void Console::printBitmap(reg_t reg) {  #endif +void Console::writeIntegrityDumpLine(const Common::String &statusName, const Common::String &resourceName, Common::WriteStream &out, Common::ReadStream *const data, const int size, const bool writeHash) { +	debugPrintf("%s", statusName.c_str()); + +	out.writeString(resourceName); +	if (!data) { +		out.writeString(" ERROR\n"); +		debugPrintf("[ERR] "); +	} else { +		out.writeString(Common::String::format(" %d ", size)); +		if (writeHash) { +			out.writeString(Common::computeStreamMD5AsString(*data)); +		} else { +			out.writeString("disabled"); +		} +		out.writeString("\n"); +		debugPrintf("[OK] "); +	} +} +  static void printChar(byte c) {  	if (c < 32 || c >= 127)  		c = '.'; diff --git a/engines/sci/console.h b/engines/sci/console.h index c467b863cd..3cc19ad254 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -71,6 +71,7 @@ private:  	bool cmdResourceInfo(int argc, const char **argv);  	bool cmdResourceTypes(int argc, const char **argv);  	bool cmdList(int argc, const char **argv); +	bool cmdResourceIntegrityDump(int argc, const char **argv);  	bool cmdAllocList(int argc, const char **argv);  	bool cmdHexgrep(int argc, const char **argv);  	bool cmdVerifyScripts(int argc, const char **argv); @@ -192,6 +193,8 @@ private:  	void printBitmap(reg_t reg);  #endif +	void writeIntegrityDumpLine(const Common::String &statusName, const Common::String &resourceName, Common::WriteStream &out, Common::ReadStream *const data, const int size, const bool writeHash); +  	SciEngine *_engine;  	DebugState &_debugState;  	Common::String _videoFile; | 
