Example #1
0
bool Debugger_EoB::cmd_saveOriginal(int argc, const char **argv) {
	if (!_vm->_runFlag) {
		DebugPrintf("This command doesn't work during intro or outro sequences,\nfrom the main menu or from the character generation.\n");
		return true;
	}

	Common::String dir = ConfMan.get("savepath");
	if (dir == "None")
		dir.clear();

	Common::FSNode nd(dir);
	if (!nd.isDirectory())
		return false;

	if (_vm->game() == GI_EOB1) {
		if (argc == 1) {
			if (_vm->saveAsOriginalSaveFile()) {
				Common::FSNode nf = nd.getChild(Common::String::format("EOBDATA.SAV"));
				if (nf.isReadable())
					DebugPrintf("Saved to file: %s\n\n", nf.getPath().c_str());
				else
					DebugPrintf("Failure.\n");
			} else {
				DebugPrintf("Failure.\n");
			}
		} else {
			DebugPrintf("Syntax:   save_original\n          (Saves game in original file format to a file which can be used with the orginal game executable.)\n\n");
		}
		return true;

	} else if (argc == 2) {
		int slot = atoi(argv[1]);
		if (slot < 0 || slot > 5) {
			DebugPrintf("Slot must be between (including) 0 and 5.\n");
		} else if (_vm->saveAsOriginalSaveFile(slot)) {
			Common::FSNode nf = nd.getChild(Common::String::format("EOBDATA%d.SAV", slot));
			if (nf.isReadable())
				DebugPrintf("Saved to file: %s\n\n", nf.getPath().c_str());
			else
				DebugPrintf("Failure.\n");
		} else {
			DebugPrintf("Failure.\n");
		}
		return true;
	}

	DebugPrintf("Syntax:   save_original <slot>\n          (Saves game in original file format to a file which can be used with the orginal game executable.\n          A save slot between 0 and 5 must be specified.)\n\n");
	return true;
}
Example #2
0
bool ThemeEngine::themeConfigUsable(const Common::FSNode &node, Common::String &themeName) {
	Common::File stream;
	bool foundHeader = false;

	if (node.getName().matchString("*.zip", true) && !node.isDirectory()) {
		Common::Archive *zipArchive = Common::makeZipArchive(node);
		if (zipArchive && zipArchive->hasFile("THEMERC")) {
			// Open THEMERC from the ZIP file.
			stream.open("THEMERC", *zipArchive);
		}
		// Delete the ZIP archive again. Note: This only works because
		// stream.open() only uses ZipArchive::createReadStreamForMember,
		// and that in turn happens to read all the data for a given
		// archive member into a memory block. So there will be no dangling
		// reference to zipArchive anywhere. This could change if we
		// ever modify ZipArchive::createReadStreamForMember.
		delete zipArchive;
	} else if (node.isDirectory()) {
		Common::FSNode headerfile = node.getChild("THEMERC");
		if (!headerfile.exists() || !headerfile.isReadable() || headerfile.isDirectory())
			return false;
		stream.open(headerfile);
	}

	if (stream.isOpen()) {
		Common::String stxHeader = stream.readLine();
		foundHeader = themeConfigParseHeader(stxHeader, themeName);
	}

	return foundHeader;
}
Example #3
0
void ThemeEngine::listUsableThemes(const Common::FSNode &node, Common::List<ThemeDescriptor> &list, int depth) {
	if (!node.exists() || !node.isReadable() || !node.isDirectory())
		return;

	ThemeDescriptor td;

	// Check whether we point to a valid theme directory.
	if (themeConfigUsable(node, td.name)) {
		td.filename = node.getPath();
		td.id = node.getName();

		list.push_back(td);

		// A theme directory should never contain any other themes
		// thus we just return to the caller here.
		return;
	}

	Common::FSList fileList;
	// Check all files. We need this to find all themes inside ZIP archives.
	if (!node.getChildren(fileList, Common::FSNode::kListFilesOnly))
		return;

	for (Common::FSList::iterator i = fileList.begin(); i != fileList.end(); ++i) {
		// We will only process zip files for now
		if (!i->getPath().matchString("*.zip", true))
			continue;

		td.name.clear();
		if (themeConfigUsable(*i, td.name)) {
			td.filename = i->getPath();
			td.id = i->getName();

			// If the name of the node object also contains
			// the ".zip" suffix, we will strip it.
			if (td.id.matchString("*.zip", true)) {
				for (int j = 0; j < 4; ++j)
					td.id.deleteLastChar();
			}

			list.push_back(td);
		}
	}

	fileList.clear();

	// Check if we exceeded the given recursion depth
	if (depth - 1 == -1)
		return;

	// As next step we will search all subdirectories
	if (!node.getChildren(fileList, Common::FSNode::kListDirectoriesOnly))
		return;

	for (Common::FSList::iterator i = fileList.begin(); i != fileList.end(); ++i)
		listUsableThemes(*i, list, depth == -1 ? - 1 : depth - 1);
}
Example #4
0
bool diskFileExists(const Common::String &filename) {
	// Try directly from SearchMan first
	Common::ArchiveMemberList files;
	SearchMan.listMatchingMembers(files, filename);

	for (Common::ArchiveMemberList::iterator it = files.begin(); it != files.end(); ++it) {
		if ((*it)->getName() == filename) {
			return true;
		}
	}
	// File wasn't found in SearchMan, try to parse the path as a relative path.
	Common::FSNode searchNode = getNodeForRelativePath(filename);
	if (searchNode.exists() && !searchNode.isDirectory() && searchNode.isReadable()) {
		return true;
	}
	return false;
}
Example #5
0
// Parse a relative path in the game-folder, and if it exists, return a FSNode to it.
static Common::FSNode getNodeForRelativePath(const Common::String &filename) {
	// The filename can be an explicit path, thus we need to chop it up, expecting the path the game
	// specifies to follow the Windows-convention of folder\subfolder\file (absolute paths should not happen)

	// Absolute path: These should have been handled in openDiskFile.
	if (filename.contains(':')) {
		// So just return an invalid node.
		return Common::FSNode();
	}

	// Relative path:
	if (filename.contains('\\')) {
		Common::StringTokenizer path(filename, "\\");

		// Start traversing relative to the game-data-dir
		const Common::FSNode gameDataDir(ConfMan.get("path"));
		Common::FSNode curNode = gameDataDir;

		// Parse all path-elements
		while (!path.empty()) {
			// Get the next path-component by slicing on '\\'
			Common::String pathPart = path.nextToken();
			// Get the next FSNode in the chain, if it exists as a child from the previous.
			curNode = curNode.getChild(pathPart);
			if (!curNode.isReadable()) {
				// Return an invalid FSNode.
				return Common::FSNode();
			}
			// Following the comments in common/fs.h, anything not a directory is a file.
			if (!curNode.isDirectory()) {
				if (!path.empty()) {
					error("Relative path %s reached a file before the end of the path", filename.c_str());
				}
				return curNode;
			}
		}
	}
	// Return an invalid FSNode to mark that we didn't find the requested file.
	return Common::FSNode();
}
Example #6
0
Common::SeekableReadStream *openDiskFile(const Common::String &filename) {
	uint32 prefixSize = 0;
	Common::SeekableReadStream *file = NULL;
	Common::String fixedFilename = filename;

	// Absolute path: TODO: Add specific fallbacks here.
	if (filename.contains(':')) {
		if (filename.hasPrefix("c:\\windows\\fonts\\")) { // East Side Story refers to "c:\windows\fonts\framd.ttf"
			fixedFilename = filename.c_str() + 17;
		} else {
			error("openDiskFile::Absolute path or invalid filename used in %s", filename.c_str());
		}
	}
	// Try directly from SearchMan first
	Common::ArchiveMemberList files;
	SearchMan.listMatchingMembers(files, fixedFilename);

	for (Common::ArchiveMemberList::iterator it = files.begin(); it != files.end(); ++it) {
		if ((*it)->getName() == filename) {
			file = (*it)->createReadStream();
			break;
		}
	}
	// File wasn't found in SearchMan, try to parse the path as a relative path.
	if (!file) {
		Common::FSNode searchNode = getNodeForRelativePath(filename);
		if (searchNode.exists() && !searchNode.isDirectory() && searchNode.isReadable()) {
			file = searchNode.createReadStream();
		}
	}
	if (file) {
		uint32 magic1, magic2;
		magic1 = file->readUint32LE();
		magic2 = file->readUint32LE();

		bool compressed = false;
		if (magic1 == DCGF_MAGIC && magic2 == COMPRESSED_FILE_MAGIC) {
			compressed = true;
		}

		if (compressed) {
			uint32 dataOffset, compSize, uncompSize;
			dataOffset = file->readUint32LE();
			compSize = file->readUint32LE();
			uncompSize = file->readUint32LE();

			byte *compBuffer = new byte[compSize];
			if (!compBuffer) {
				error("Error allocating memory for compressed file '%s'", filename.c_str());
				delete file;
				return NULL;
			}

			byte *data = new byte[uncompSize];
			if (!data) {
				error("Error allocating buffer for file '%s'", filename.c_str());
				delete[] compBuffer;
				delete file;
				return NULL;
			}
			file->seek(dataOffset + prefixSize, SEEK_SET);
			file->read(compBuffer, compSize);

			if (Common::uncompress(data, (unsigned long *)&uncompSize, compBuffer, compSize) != true) {
				error("Error uncompressing file '%s'", filename.c_str());
				delete[] compBuffer;
				delete file;
				return NULL;
			}

			delete[] compBuffer;
			delete file;
			return new Common::MemoryReadStream(data, uncompSize, DisposeAfterUse::YES);
		} else {
			file->seek(0, SEEK_SET);
			return file;
		}

		return file;

	}
	return NULL;
}