瀏覽代碼

* Implementation of the new filesystem API (msvc project files needs to be updated)

beegee1 13 年之前
父節點
當前提交
1ed91077f7

+ 1 - 0
Global.h

@@ -35,6 +35,7 @@
 #include <vector>
 #include <string>
 #include <map>
+#include <unordered_map>
 #include <queue>
 #include <set>
 #include <utility>

+ 134 - 0
lib/Filesystem/CBinaryReader.cpp

@@ -0,0 +1,134 @@
+#include "StdInc.h"
+#include "CBinaryReader.h"
+#include <SDL_endian.h>
+#include "CInputStream.h"
+
+CBinaryReader::CBinaryReader() : stream(nullptr)
+{
+
+}
+
+CBinaryReader::CBinaryReader(CInputStream & stream) : stream(&stream)
+{
+
+}
+
+CInputStream * CBinaryReader::getStream()
+{
+	return stream;
+}
+
+void CBinaryReader::setStream(CInputStream & stream)
+{
+	this->stream = &stream;
+}
+
+si64 CBinaryReader::read(ui8 * data, si64 size)
+{
+	return stream->read(data, size);
+}
+
+ui8 CBinaryReader::readUInt8()
+{
+	ui8 val;
+	si64 b = stream->read(&val, 1);
+	if(b < 1)
+	{
+		throw std::runtime_error(getEndOfStreamExceptionMsg(1));
+	}
+
+	return val;
+}
+
+si8 CBinaryReader::readInt8()
+{
+	si8 val;
+	si64 b = stream->read(reinterpret_cast<ui8 *>(&val), 1);
+	if(b < 1)
+	{
+		throw std::runtime_error(getEndOfStreamExceptionMsg(1));
+	}
+
+	return val;
+}
+
+ui16 CBinaryReader::readUInt16()
+{
+	ui16 val;
+	si64 b = stream->read(reinterpret_cast<ui8 *>(&val), 2);
+	if(b < 2)
+	{
+		throw std::runtime_error(getEndOfStreamExceptionMsg(2));
+	}
+
+	return SDL_SwapLE16(val);
+}
+
+si16 CBinaryReader::readInt16()
+{
+	si16 val;
+	si64 b = stream->read(reinterpret_cast<ui8 *>(&val), 2);
+	if(b < 2)
+	{
+		throw std::runtime_error(getEndOfStreamExceptionMsg(2));
+	}
+
+	return SDL_SwapLE16(val);
+}
+
+ui32 CBinaryReader::readUInt32()
+{
+	ui32 val;
+	si64 b = stream->read(reinterpret_cast<ui8 *>(&val), 4);
+	if(b < 4)
+	{
+		throw std::runtime_error(getEndOfStreamExceptionMsg(4));
+	}
+
+	return SDL_SwapLE32(val);
+}
+
+si32 CBinaryReader::readInt32()
+{
+	si32 val;
+	si64 b = stream->read(reinterpret_cast<ui8 *>(&val), 4);
+	if(b < 4)
+	{
+		throw std::runtime_error(getEndOfStreamExceptionMsg(4));
+	}
+
+	return SDL_SwapLE32(val);
+}
+
+ui64 CBinaryReader::readUInt64()
+{
+	ui64 val;
+	si64 b = stream->read(reinterpret_cast<ui8 *>(&val), 8);
+	if(b < 8)
+	{
+		throw std::runtime_error(getEndOfStreamExceptionMsg(8));
+	}
+
+	return SDL_SwapLE64(val);
+}
+
+si64 CBinaryReader::readInt64()
+{
+	si64 val;
+	si64 b = stream->read(reinterpret_cast<ui8 *>(&val), 8);
+	if(b < 8)
+	{
+		throw std::runtime_error(getEndOfStreamExceptionMsg(8));
+	}
+
+	return SDL_SwapLE64(val);
+}
+
+std::string CBinaryReader::getEndOfStreamExceptionMsg(long bytesToRead) const
+{
+	std::stringstream ss;
+	ss << "The end of the stream was reached unexpectedly. The stream has a length of " << stream->getSize() << " and the current reading position is "
+				<< stream->tell() << ". The client wanted to read " << bytesToRead << " bytes.";
+
+	return ss.str();
+}

+ 143 - 0
lib/Filesystem/CBinaryReader.h

@@ -0,0 +1,143 @@
+
+/*
+ * CBinaryReader.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#pragma once
+
+class CInputStream;
+
+/**
+ * Reads primitive binary values from a underlying stream.
+ *
+ * The integers which are read are supposed to be little-endian values permanently. They will be
+ * converted to big-endian values on big-endian machines.
+ */
+class DLL_LINKAGE CBinaryReader : public boost::noncopyable
+{
+public:
+	/**
+	 * Default c-tor.
+	 */
+	CBinaryReader();
+
+	/**
+	 * C-tor.
+	 *
+	 * @param stream The base stream object which serves as the reading input.
+	 */
+	CBinaryReader(CInputStream & stream);
+
+	/**
+	 * Gets the underlying stream.
+	 *
+	 * @return the base stream.
+	 */
+	CInputStream * getStream();
+
+	/**
+	 * Sets the underlying stream.
+	 *
+	 * @param stream The base stream to set
+	 */
+	void setStream(CInputStream & stream);
+
+	/**
+	 * Reads n bytes from the stream into the data buffer.
+	 *
+	 * @param data A pointer to the destination data array.
+	 * @param size The number of bytes to read.
+	 * @return the number of bytes read actually.
+	 */
+	si64 read(ui8 * data, si64 size);
+
+	/**
+	 * Reads a unsigned 8 bit integer. Advances the read pointer by one byte.
+	 *
+	 * @return a unsigned 8 bit integer.
+	 *
+	 * @throws std::runtime_error if the end of the stream was reached unexpectedly
+	 */
+	ui8 readUInt8();
+
+	/**
+	 * Reads a signed 8 bit integer. Advances the read pointer by one byte.
+	 *
+	 * @return a signed 8 bit integer.
+	 *
+	 * @throws std::runtime_error if the end of the stream was reached unexpectedly
+	 */
+	si8 readInt8();
+
+	/**
+	 * Reads a unsigned 16 bit integer. Advances the read pointer by two bytes.
+	 *
+	 * @return a unsigned 16 bit integer.
+	 *
+	 * @throws std::runtime_error if the end of the stream was reached unexpectedly
+	 */
+	ui16 readUInt16();
+
+	/**
+	 * Reads a signed 16 bit integer. Advances the read pointer by two bytes.
+	 *
+	 * @return a signed 16 bit integer.
+	 *
+	 * @throws std::runtime_error if the end of the stream was reached unexpectedly
+	 */
+	si16 readInt16();
+
+	/**
+	 * Reads a unsigned 32 bit integer. Advances the read pointer by four bytes.
+	 *
+	 * @return a unsigned 32 bit integer.
+	 *
+	 * @throws std::runtime_error if the end of the stream was reached unexpectedly
+	 */
+	ui32 readUInt32();
+
+	/**
+	 * Reads a signed 32 bit integer. Advances the read pointer by four bytes.
+	 *
+	 * @return a signed 32 bit integer.
+	 *
+	 * @throws std::runtime_error if the end of the stream was reached unexpectedly
+	 */
+	si32 readInt32();
+
+	/**
+	 * Reads a unsigned 64 bit integer. Advances the read pointer by eight bytes.
+	 *
+	 * @return a unsigned 64 bit integer.
+	 *
+	 * @throws std::runtime_error if the end of the stream was reached unexpectedly
+	 */
+	ui64 readUInt64();
+
+	/**
+	 * Reads a signed 64 bit integer. Advances the read pointer by eight bytes.
+	 *
+	 * @return a signed 64 bit integer.
+	 *
+	 * @throws std::runtime_error if the end of the stream was reached unexpectedly
+	 */
+	si64 readInt64();
+
+private:
+	/**
+	 * Gets a end of stream exception message.
+	 *
+	 * @param bytesToRead The number of bytes which should be read.
+	 * @return the exception message text
+	 */
+	std::string getEndOfStreamExceptionMsg(long bytesToRead) const;
+
+	/** The underlying base stream */
+	CInputStream * stream;
+};

+ 105 - 0
lib/Filesystem/CFileInfo.cpp

@@ -0,0 +1,105 @@
+#include "StdInc.h"
+#include "CFileInfo.h"
+
+CFileInfo::CFileInfo() : name("")
+{
+
+}
+
+CFileInfo::CFileInfo(const std::string & name)
+	: name(name)
+{
+
+}
+
+bool CFileInfo::exists() const
+{
+	return boost::filesystem::exists(name);
+}
+
+bool CFileInfo::isDirectory() const
+{
+	return boost::filesystem::is_directory(name);
+}
+
+void CFileInfo::setName(const std::string & name)
+{
+	this->name = name;
+}
+
+std::string CFileInfo::getName() const
+{
+	return name;
+}
+
+std::string CFileInfo::getPath() const
+{
+	size_t found = name.find_last_of("/\\");
+	return name.substr(0, found);
+}
+
+std::string CFileInfo::getExtension() const
+{
+	// Get position of file extension dot
+	size_t dotPos = name.find_last_of("/.");
+
+	if(dotPos != std::string::npos && name[dotPos] == '.')
+		return name.substr(dotPos);
+	else
+		return "";
+}
+
+std::string CFileInfo::getFilename() const
+{
+	size_t found = name.find_last_of("/\\");
+	return name.substr(found + 1);
+}
+
+std::string CFileInfo::getStem() const
+{
+	std::string rslt = name;
+
+	// Remove file extension
+	size_t dotPos = name.find_last_of("/.");
+
+	if(dotPos != std::string::npos && name[dotPos] == '.')
+		rslt.erase(dotPos);
+
+	// Remove path
+	size_t found = rslt.find_last_of("/\\");
+	return rslt.substr(found + 1);
+}
+
+EResType CFileInfo::getType() const
+{
+	return EResTypeHelper::getTypeFromExtension(getExtension());
+}
+
+std::time_t CFileInfo::getDate() const
+{
+	return boost::filesystem::last_write_time(name);
+}
+
+std::unique_ptr<std::list<CFileInfo> > CFileInfo::listFiles(const std::string & extensionFilter /*= ""*/) const
+{
+	std::unique_ptr<std::list<CFileInfo> > fileListPtr;
+
+	if(exists() && isDirectory())
+	{
+		std::list<CFileInfo> * fileList = new std::list<CFileInfo>;
+
+		boost::filesystem::directory_iterator enddir;
+		for(boost::filesystem::directory_iterator it(name); it != enddir; ++it)
+		{
+			if(extensionFilter == "" || it->path().extension() == extensionFilter)
+			{
+				CFileInfo file(it->path().string());
+				fileList->push_back(file);
+			}
+		}
+
+		fileListPtr.reset(fileList);
+	}
+
+	return fileListPtr;
+}

+ 119 - 0
lib/Filesystem/CFileInfo.h

@@ -0,0 +1,119 @@
+
+/*
+ * CFileInfo.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#pragma once
+
+#include "CResourceLoader.h"
+
+/**
+ * A class which holds information about a file.
+ */
+class DLL_LINKAGE CFileInfo
+{
+public:
+	/**
+	 * Default ctor.
+	 */
+	CFileInfo();
+
+	/**
+	 * Ctor.
+	 *
+	 * @param name The path and name of the file.
+	 */
+	explicit CFileInfo(const std::string & name);
+
+	/**
+	 * Checks if the file exists.
+	 *
+	 * @return true if the file exists, false if not.
+	 */
+	bool exists() const;
+
+	/**
+	 * Checks if the file is a directory.
+	 *
+	 * @return true if the file is a directory, false if not.
+	 */
+	bool isDirectory() const;
+
+	/**
+	 * Sets the name.
+	 *
+	 * @param name The name of the file
+	 */
+	void setName(const std::string & name);
+
+	/**
+	 * Gets the name of the file.
+	 *
+	 * @return the path and name of the file. E.g. ./dir/file.ext
+	 */
+	std::string getName() const;
+
+	/**
+	 * Gets the path to the file only.
+	 *
+	 * @return the path to the file only. E.g. ./dir/
+	 */
+	std::string getPath() const;
+
+	/**
+	 * Gets the file extension.
+	 *
+	 * @return the file extension. E.g. .ext
+	 */
+	std::string getExtension() const;
+
+	/**
+	 * Returns the name of the file.
+	 *
+	 * @return the name of the file. E.g. foo.txt
+	 */
+	std::string getFilename() const;
+
+	/**
+	 * Gets the file name exclusive the extension of the file.
+	 *
+	 * @return the file name exclusive the extension of the file. E.g. foo
+	 */
+	std::string getStem() const;
+
+	/**
+	 * Gets the extension type as a EResType enumeration.
+	 *
+	 * @return the extension type as a EResType enumeration.
+	 */
+	EResType getType() const;
+
+	/**
+	 * Gets the timestamp of the file.
+	 *
+	 * @return the timestamp of the file, 0 if no timestamp was set
+	 */
+	std::time_t getDate() const;
+
+	/**
+	 * Returns a list of pathnames denoting the files in the directory denoted by this pathname.
+	 *
+	 * If the pathname of this directory is absolute, then the file info pathnames are absolute as well. If the pathname of this directory is relative
+	 * then the file info pathnames are relative to the basedir as well.
+	 *
+	 * @param extensionFilter Filters files by the given extension. Optional. Empty string if all files and directories in the directory should be listed.
+	 * @return a list of pathnames denoting the files and directories in the directory denoted by this pathname as a unique ptr.
+	 * The array will be empty if the directory is empty. Ptr is null if the directory doesn't exist or if it isn't a directory.
+	 */
+	std::unique_ptr<std::list<CFileInfo> > listFiles(const std::string & extensionFilter = "") const;
+
+private:
+	/** Contains the original URI(not modified) e.g. ./dir/foo.txt */
+	std::string name;
+};

+ 80 - 0
lib/Filesystem/CFileInputStream.cpp

@@ -0,0 +1,80 @@
+#include "StdInc.h"
+#include "CFileInputStream.h"
+#include "CFileInfo.h"
+
+CFileInputStream::CFileInputStream()
+{
+
+}
+
+CFileInputStream::CFileInputStream(const std::string & file)
+{
+	open(file);
+}
+
+CFileInputStream::CFileInputStream(const CFileInfo & file)
+{
+	open(file);
+}
+
+CFileInputStream::~CFileInputStream()
+{
+	close();
+}
+
+void CFileInputStream::open(const std::string & file)
+{
+	close();
+
+	fileStream.open(file.c_str(), std::ios::in | std::ios::binary);
+	if (fileStream.fail())
+	{
+		throw std::runtime_error("File " + file + " isn't available.");
+	}
+}
+
+void CFileInputStream::open(const CFileInfo & file)
+{
+	open(file.getName());
+}
+
+si64 CFileInputStream::read(ui8 * data, si64 size)
+{
+	fileStream.read(reinterpret_cast<char *>(data), size);
+	return fileStream.gcount();
+}
+
+si64 CFileInputStream::seek(si64 position)
+{
+	si64 diff = tell();
+	fileStream.seekg(position);
+
+	return tell() - diff;
+}
+
+si64 CFileInputStream::tell()
+{
+	return fileStream.tellg();
+}
+
+si64 CFileInputStream::skip(si64 delta)
+{
+	si64 diff = tell();
+	fileStream.seekg(delta, std::ios::cur);
+
+	return tell() - diff;
+}
+
+si64 CFileInputStream::getSize()
+{
+	fileStream.seekg(0, std::ios::end);
+	return fileStream.tellg();
+}
+
+void CFileInputStream::close()
+{
+	if (fileStream.is_open())
+	{
+		fileStream.close();
+	}
+}

+ 117 - 0
lib/Filesystem/CFileInputStream.h

@@ -0,0 +1,117 @@
+
+/*
+ * CFileInputStream.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#pragma once
+
+#include "CInputStream.h"
+
+class CFileInfo;
+
+/**
+ * A class which provides method definitions for reading a file from the filesystem.
+ */
+class DLL_LINKAGE CFileInputStream : public CInputStream
+{
+public:
+	/**
+	 * Standard c-tor.
+	 */
+	CFileInputStream();
+
+	/**
+	 * C-tor. Opens the specified file.
+	 *
+	 * @param file Path to the file.
+	 *
+	 * @throws std::runtime_error if file wasn't found
+	 */
+	CFileInputStream(const std::string & file);
+
+	/**
+	 * C-tor. Opens the specified file.
+	 *
+	 * @param file A file info object, pointing to a location in the file system
+	 *
+	 * @throws std::runtime_error if file wasn't found
+	 */
+	CFileInputStream(const CFileInfo & file);
+
+	/**
+	 * D-tor. Calls the close method implicitely, if the file is still opened.
+	 */
+	~CFileInputStream();
+
+	/**
+	 * Opens a file. If a file is currently opened, it will be closed.
+	 *
+	 * @param file Path to the file.
+	 *
+	 * @throws std::runtime_error if file wasn't found
+	 */
+	void open(const std::string & file);
+
+	/**
+	 * Opens a file.
+	 *
+	 * @param file A file info object, pointing to a location in the file system
+	 *
+	 * @throws std::runtime_error if file wasn't found
+	 */
+	void open(const CFileInfo & file);
+
+	/**
+	 * Reads n bytes from the stream into the data buffer.
+	 *
+	 * @param data A pointer to the destination data array.
+	 * @param size The number of bytes to read.
+	 * @return the number of bytes read actually.
+	 */
+	si64 read(ui8 * data, si64 size);
+
+	/**
+	 * Seeks the internal read pointer to the specified position.
+	 *
+	 * @param position The read position from the beginning.
+	 * @return the position actually moved to, -1 on error.
+	 */
+	si64 seek(si64 position);
+
+	/**
+	 * Gets the current read position in the stream.
+	 *
+	 * @return the read position. -1 on failure or if the read pointer isn't in the valid range.
+	 */
+	si64 tell();
+
+	/**
+	 * Skips delta numbers of bytes.
+	 *
+	 * @param delta The count of bytes to skip.
+	 * @return the count of bytes skipped actually.
+	 */
+	si64 skip(si64 delta);
+
+	/**
+	 * Gets the length in bytes of the stream.
+	 *
+	 * @return the length in bytes of the stream.
+	 */
+	si64 getSize();
+
+	/**
+	 * Closes the stream and releases any system resources associated with the stream explicitely.
+	 */
+	void close();
+
+private:
+	/** Native c++ input file stream object. */
+	std::ifstream fileStream;
+};

+ 70 - 0
lib/Filesystem/CFilesystemLoader.cpp

@@ -0,0 +1,70 @@
+#include "StdInc.h"
+#include "CFilesystemLoader.h"
+
+#include "CFileInfo.h"
+#include "CFileInputStream.h"
+
+CFilesystemLoader::CFilesystemLoader()
+{
+
+}
+
+CFilesystemLoader::CFilesystemLoader(const std::string & baseDirectory)
+{
+	open(baseDirectory);
+}
+
+CFilesystemLoader::CFilesystemLoader(const CFileInfo & baseDirectory)
+{
+	open(baseDirectory);
+}
+
+void CFilesystemLoader::open(const std::string & baseDirectory)
+{
+	// Indexes all files in the directory and store them
+	this->baseDirectory = baseDirectory;
+	CFileInfo directory(baseDirectory);
+	std::unique_ptr<std::list<CFileInfo> > fileList = directory.listFiles();
+	if(fileList == nullptr)
+	{
+		throw std::runtime_error("Directory " + baseDirectory + " not available.");
+	}
+
+	this->fileList = std::move(*fileList);
+}
+
+void CFilesystemLoader::open(const CFileInfo & baseDirectory)
+{
+	open(baseDirectory.getName());
+}
+
+std::unique_ptr<CInputStream> CFilesystemLoader::load(const std::string & resourceName) const
+{
+	std::unique_ptr<CInputStream> stream(new CFileInputStream(resourceName));
+	return stream;
+}
+
+bool CFilesystemLoader::existsEntry(const std::string & resourceName) const
+{
+	for(auto it = fileList.begin(); it != fileList.end(); ++it)
+	{
+		if((*it).getName() == resourceName)
+		{
+			return true;
+		}
+	}
+
+	return false;
+}
+
+std::list<std::string> CFilesystemLoader::getEntries() const
+{
+	std::list<std::string> retList;
+
+	for(auto it = fileList.begin(); it != fileList.end(); ++it)
+	{
+		retList.push_back(it->getName());
+	}
+
+	return std::move(retList);
+}

+ 94 - 0
lib/Filesystem/CFilesystemLoader.h

@@ -0,0 +1,94 @@
+
+/*
+ * CFilesystemLoader.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#pragma once
+
+#include "ISimpleResourceLoader.h"
+
+class CFileInfo;
+class CInputStream;
+
+/**
+ * A class which can scan and load files of directories.
+ */
+class DLL_LINKAGE CFilesystemLoader : public ISimpleResourceLoader
+{
+public:
+	/**
+	 * Default c-tor.
+	 */
+	CFilesystemLoader();
+
+	/**
+	 * Ctor.
+	 *
+	 * @param baseDirectory Specifies the base directory and their sub-directories which should be indexed.
+	 *
+	 * @throws std::runtime_error if the base directory is not a directory or if it is not available
+	 */
+	explicit CFilesystemLoader(const std::string & baseDirectory);
+
+	/**
+	 * Ctor.
+	 *
+	 * @param baseDirectory Specifies the base directory and their sub-directories which should be indexed.
+	 *
+	 * @throws std::runtime_error if the base directory is not a directory or if it is not available
+	 */
+	explicit CFilesystemLoader(const CFileInfo & baseDirectory);
+
+	/**
+	 * Opens a base directory to be read and indexed.
+	 *
+	 * @param baseDirectory Specifies the base directory and their sub-directories which should be indexed.
+	 *
+	 * @throws std::runtime_error if the base directory is not a directory or if it is not available
+	 */
+	void open(const std::string & baseDirectory);
+
+	/**
+	 * Opens a base directory to be read and indexed.
+	 *
+	 * @param baseDirectory Specifies the base directory and their sub-directories which should be indexed.
+	 *
+	 * @throws std::runtime_error if the base directory is not a directory or if it is not available
+	 */
+	void open(const CFileInfo & baseDirectory);
+
+	/**
+	 * Loads a resource with the given resource name.
+	 *
+	 * @param resourceName The unqiue resource name in space of the filesystem.
+	 * @return a input stream object, not null
+	 */
+	std::unique_ptr<CInputStream> load(const std::string & resourceName) const;
+
+	/**
+	 * Checks if the file entry exists.
+	 *
+	 * @return true if the entry exists, false if not.
+	 */
+	bool existsEntry(const std::string & resourceName) const;
+
+	/**
+	 * Gets all entries in the filesystem.
+	 *
+	 * @return a list of all entries in the filesystem.
+	 */
+	std::list<std::string> getEntries() const;
+
+private:
+	/** The base directory which is scanned and indexed. */
+	std::string baseDirectory;
+
+	/** A list of files in the directory */
+	std::list<CFileInfo> fileList;
+};

+ 68 - 0
lib/Filesystem/CInputStream.h

@@ -0,0 +1,68 @@
+
+/*
+ * CInputStream.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#pragma once
+
+/**
+ * Abstract class which provides method definitions for reading from a stream.
+ */
+class DLL_LINKAGE CInputStream : public boost::noncopyable
+{
+public:
+	/**
+	 * D-tor.
+	 */
+	virtual ~CInputStream() {}
+
+	/**
+	 * Reads n bytes from the stream into the data buffer.
+	 *
+	 * @param data A pointer to the destination data array.
+	 * @param size The number of bytes to read.
+	 * @return the number of bytes read actually.
+	 */
+	virtual si64 read(ui8 * data, si64 size) = 0;
+
+	/**
+	 * Seeks the internal read pointer to the specified position.
+	 *
+	 * @param position The read position from the beginning.
+	 * @return the position actually moved to, -1 on error.
+	 */
+	virtual si64 seek(si64 position) = 0;
+
+	/**
+	 * Gets the current read position in the stream.
+	 *
+	 * @return the read position.
+	 */
+	virtual si64 tell() = 0;
+
+	/**
+	 * Skips delta numbers of bytes.
+	 *
+	 * @param delta The count of bytes to skip.
+	 * @return the count of bytes skipped actually.
+	 */
+	virtual si64 skip(si64 delta) = 0;
+
+	/**
+	 * Gets the length in bytes of the stream.
+	 *
+	 * @return the length in bytes of the stream.
+	 */
+	virtual si64 getSize() = 0;
+
+	/**
+	 * Closes the stream and releases any system resources associated with the stream explicitely.
+	 */
+	virtual void close() = 0;
+};

+ 236 - 0
lib/Filesystem/CLodArchiveLoader.cpp

@@ -0,0 +1,236 @@
+#include "StdInc.h"
+#include "CLodArchiveLoader.h"
+#include "CInputStream.h"
+#include "CFileInputStream.h"
+#include "CLodStream.h"
+#include "CBinaryReader.h"
+#include "CFileInfo.h"
+#include <SDL_endian.h>
+
+ArchiveEntry::ArchiveEntry()
+	: offset(0), realSize(0), size(0)
+{
+
+}
+
+CLodArchiveLoader::CLodArchiveLoader()
+{
+
+}
+
+CLodArchiveLoader::CLodArchiveLoader(const std::string & archive)
+{
+	open(archive);
+}
+
+CLodArchiveLoader::CLodArchiveLoader(const CFileInfo & archive)
+{
+	open(archive);
+}
+
+void CLodArchiveLoader::open(const std::string & archive)
+{
+	// Open archive file(.snd, .vid, .lod)
+	this->archive = archive;
+	CFileInputStream fileStream(archive);
+
+	// Retrieve file extension of archive in uppercase
+	CFileInfo fileInfo(archive);
+	std::string ext = fileInfo.getExtension();
+	boost::to_upper(ext);
+
+	// Init the specific lod container format
+	if(ext == ".LOD")
+	{
+		initLODArchive(fileStream);
+	}
+	else if(ext == ".VID")
+	{
+		initVIDArchive(fileStream);
+	}
+	else if(ext == ".SND")
+	{
+		initSNDArchive(fileStream);
+	}
+	else
+	{
+		throw std::runtime_error("LOD archive format unknown. Cannot deal with " + archive);
+	}
+}
+
+void CLodArchiveLoader::open(const CFileInfo & archive)
+{
+	open(archive.getName());
+}
+
+void CLodArchiveLoader::initLODArchive(CFileInputStream & fileStream)
+{
+	// Define LodEntryBlock struct
+	struct LodEntryBlock
+	{
+		char filename[16];
+		ui32 offset;
+		ui32 uncompressedSize;
+		ui32 unused;
+		ui32 size;
+	};
+
+	// Read count of total files
+	CBinaryReader reader(fileStream);
+	fileStream.seek(8);
+	ui32 totalFiles = reader.readUInt32();
+
+	// Get all entries from file
+	fileStream.seek(0x5c);
+	struct LodEntryBlock * lodEntries = new struct LodEntryBlock[totalFiles];
+	fileStream.read(reinterpret_cast<ui8 *>(lodEntries), sizeof(struct LodEntryBlock) * totalFiles);
+
+	// Insert entries to list
+	for(ui32 i = 0; i < totalFiles; i++)
+	{
+		// Create archive entry
+		ArchiveEntry entry;
+		entry.name = lodEntries[i].filename;
+		entry.offset= SDL_SwapLE32(lodEntries[i].offset);
+		entry.realSize = SDL_SwapLE32(lodEntries[i].uncompressedSize);
+		entry.size = SDL_SwapLE32(lodEntries[i].size);
+
+		// Add lod entry to local entries map
+		entries[entry.name] = entry;
+	}
+
+	// Delete lod entries array
+	delete[] lodEntries;
+}
+
+void CLodArchiveLoader::initVIDArchive(CFileInputStream & fileStream)
+{
+	// Define VideoEntryBlock struct
+	struct VideoEntryBlock
+	{
+		char filename[40];
+		ui32 offset;
+	};
+
+	// Read count of total files
+	CBinaryReader reader(fileStream);
+	fileStream.seek(0);
+	ui32 totalFiles = reader.readUInt32();
+
+	// Get all entries from file
+	fileStream.seek(4);
+	struct VideoEntryBlock * vidEntries = new struct VideoEntryBlock[totalFiles];
+	fileStream.read(reinterpret_cast<ui8 *>(vidEntries), sizeof(struct VideoEntryBlock) * totalFiles);
+
+	// Insert entries to list
+	for(ui32 i = 0; i < totalFiles; i++)
+	{
+		VideoEntryBlock vidEntry = vidEntries[i];
+		ArchiveEntry entry;
+
+		entry.name = vidEntry.filename;
+		entry.offset = SDL_SwapLE32(vidEntry.offset);
+
+		// There is no size, so check where the next file is
+		if (i == totalFiles - 1)
+		{
+			entry.size = fileStream.getSize() - entry.offset;
+		}
+		else
+		{
+			VideoEntryBlock nextVidEntry = vidEntries[i + 1];
+			entry.size = SDL_SwapLE32(nextVidEntry.offset) - entry.offset;
+		}
+
+		entries[entry.name] = entry;
+	}
+
+	// Delete vid entries array
+	delete[] vidEntries;
+}
+
+void CLodArchiveLoader::initSNDArchive(CFileInputStream & fileStream)
+{
+	// Define SoundEntryBlock struct
+	struct SoundEntryBlock
+	{
+		char filename[40];
+		ui32 offset;
+		ui32 size;
+	};
+
+	// Read count of total files
+	CBinaryReader reader(fileStream);
+	fileStream.seek(0);
+	ui32 totalFiles = reader.readUInt32();
+
+	// Get all entries from file
+	fileStream.seek(4);
+	struct SoundEntryBlock * sndEntries = new struct SoundEntryBlock[totalFiles];
+	fileStream.read(reinterpret_cast<ui8 *>(sndEntries), sizeof(struct SoundEntryBlock) * totalFiles);
+
+	// Insert entries to list
+	for(ui8 i = 0; i < totalFiles; i++)
+	{
+		SoundEntryBlock sndEntry = sndEntries[i];
+		ArchiveEntry entry;
+
+		entry.name = sndEntry.filename;
+		entry.offset = SDL_SwapLE32(sndEntry.offset);
+		entry.size = SDL_SwapLE32(sndEntry.size);
+
+		entries[entry.name] = entry;
+	}
+
+	// Delete snd entries array
+	delete[] sndEntries;
+}
+
+std::unique_ptr<CInputStream> CLodArchiveLoader::load(const std::string & resourceName) const
+{
+	std::unique_ptr<CInputStream> stream(new CLodStream(this, resourceName));
+	return stream;
+}
+
+std::list<std::string> CLodArchiveLoader::getEntries() const
+{
+	std::list<std::string> retList;
+
+	for(auto it = entries.begin(); it != entries.end(); ++it)
+	{
+		const ArchiveEntry & entry = it->second;
+		retList.push_back(entry.name);
+	}
+
+	return std::move(retList);
+}
+
+const ArchiveEntry * CLodArchiveLoader::getArchiveEntry(const std::string & resourceName) const
+{
+	auto it = entries.find(resourceName);
+
+	if(it != entries.end())
+	{
+		return &(it->second);
+	}
+
+	return nullptr;
+}
+
+bool CLodArchiveLoader::existsEntry(const std::string & resourceName) const
+{
+	auto it = entries.find(resourceName);
+	if(it != entries.end())
+	{
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+std::string CLodArchiveLoader::getOrigin() const
+{
+	return archive;
+}

+ 167 - 0
lib/Filesystem/CLodArchiveLoader.h

@@ -0,0 +1,167 @@
+
+/*
+ * CLodArchiveLoader.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#pragma once
+
+#include "ISimpleResourceLoader.h"
+
+class CFileInfo;
+class CFileInputStream;
+
+/**
+ * A struct which holds information about the archive entry e.g. where it is located in space of the archive container.
+ */
+struct ArchiveEntry
+{
+	/**
+	 * Default c-tor.
+	 */
+	ArchiveEntry();
+
+	/** Entry name **/
+	std::string name;
+
+	/** Distance in bytes from beginning **/
+	int offset;
+
+	/** Size without compression in bytes **/
+	int realSize;
+
+	/** Size within compression in bytes **/
+	int size;
+};
+
+/**
+ * A class which can scan and load files of a LOD archive.
+ */
+class DLL_LINKAGE CLodArchiveLoader : public ISimpleResourceLoader
+{
+public:
+	/**
+	 * Default c-tor.
+	 */
+	CLodArchiveLoader();
+
+	/**
+	 * Ctor.
+	 *
+	 * The file extension of the param archive determines the type of the Lod file.
+	 * These are valid extensions: .LOD, .SND, .VID
+	 *
+	 * @param archive Specifies the file path to the archive which should be indexed and loaded.
+	 *
+	 * @throws std::runtime_error if the archive wasn't found or if the archive isn't supported
+	 */
+	explicit CLodArchiveLoader(const std::string & archive);
+
+	/**
+	 * Ctor.
+	 *
+	 * The file extension of the param archive determines the type of the Lod file.
+	 * These are valid extensions: .LOD, .SND, .VID
+	 *
+	 * @param archive Specifies the file path to the archive which should be indexed and loaded.
+	 *
+	 * @throws std::runtime_error if the archive wasn't found or if the archive isn't supported
+	 */
+	explicit CLodArchiveLoader(const CFileInfo & archive);
+
+	/**
+	 * Opens an LOD archive.
+	 *
+	 * The file extension of the param archive determines the type of the Lod file.
+	 * These are valid extensions: .LOD, .SND, .VID
+	 *
+	 * @param archive Specifies the file path to the archive which should be indexed and loaded.
+	 *
+	 * @throws std::runtime_error if the archive wasn't found or if the archive isn't supported
+	 */
+	void open(const std::string & archive);
+
+	/**
+	 * Opens an LOD archive.
+	 *
+	 * The file extension of the param archive determines the type of the Lod file.
+	 * These are valid extensions: .LOD, .SND, .VID
+	 *
+	 * @param archive Specifies the file path to the archive which should be indexed and loaded.
+	 *
+	 * @throws std::runtime_error if the archive wasn't found or if the archive isn't supported
+	 */
+	void open(const CFileInfo & archive);
+
+	/**
+	 * Loads a resource with the given resource name.
+	 *
+	 * @param resourceName The unqiue resource name in space of the archive.
+	 * @return a input stream object, not null.
+	 *
+	 * @throws std::runtime_error if the archive entry wasn't found
+	 */
+	std::unique_ptr<CInputStream> load(const std::string & resourceName) const;
+
+	/**
+	 * Gets all entries in the archive.
+	 *
+	 * @return a list of all entries in the archive.
+	 */
+	std::list<std::string> getEntries() const;
+
+	/**
+	 * Gets the archive entry for the requested resource
+	 *
+	 * @param resourceName The unqiue resource name in space of the archive.
+	 * @return the archive entry for the requested resource or a null ptr if the archive wasn't found
+	 */
+	const ArchiveEntry * getArchiveEntry(const std::string & resourceName) const;
+
+	/**
+	 * Checks if the archive entry exists.
+	 *
+	 * @return true if the entry exists, false if not.
+	 */
+	bool existsEntry(const std::string & resourceName) const;
+
+	/**
+	 * Gets the origin of the archive loader.
+	 *
+	 * @return the file path to the archive which is scanned and indexed.
+	 */
+	std::string getOrigin() const;
+
+private:
+	/**
+	 * Initializes a LOD archive.
+	 *
+	 * @param fileStream File stream to the .lod archive
+	 */
+	void initLODArchive(CFileInputStream & fileStream);
+
+	/**
+	 * Initializes a VID archive.
+	 *
+	 * @param fileStream File stream to the .vid archive
+	 */
+	void initVIDArchive(CFileInputStream & fileStream);
+
+	/**
+	 * Initializes a SND archive.
+	 *
+	 * @param fileStream File stream to the .snd archive
+	 */
+	void initSNDArchive(CFileInputStream & fileStream);
+
+	/** The file path to the archive which is scanned and indexed. */
+	std::string archive;
+
+	/** Holds all entries of the archive file. An entry can be accessed via the entry name. **/
+	std::unordered_map<std::string, ArchiveEntry> entries;
+};

+ 155 - 0
lib/Filesystem/CLodStream.cpp

@@ -0,0 +1,155 @@
+#include "StdInc.h"
+#include "CLodStream.h"
+
+#include "CLodArchiveLoader.h"
+#include "CFileInputStream.h"
+#include <zlib.h>
+
+CLodStream::CLodStream()
+{
+
+}
+
+CLodStream::CLodStream(const CLodArchiveLoader * loader, const std::string & resourceName)
+{
+	open(loader, resourceName);
+}
+
+void CLodStream::open(const CLodArchiveLoader * loader, const std::string & resourceName)
+{
+	close();
+
+	const ArchiveEntry * archiveEntry = loader->getArchiveEntry(resourceName);
+	if(archiveEntry == nullptr)
+	{
+		throw std::runtime_error("Archive entry " + resourceName + " wasn't found in the archive " + loader->getOrigin());
+	}
+	this->archiveEntry = archiveEntry;
+
+	// Open the archive and set the read pointer to the correct position
+	fileStream.open(loader->getOrigin());
+	fileStream.seek(this->archiveEntry->offset);
+}
+
+si64 CLodStream::read(ui8 * data, si64 size)
+{
+	// Test whether the file has to be decompressed
+	if(archiveEntry->size == 0)
+	{
+		// No decompression
+		return fileStream.read(data, size);
+	}
+	else
+	{
+		// Decompress file
+
+		// We can't decompress partially, so the size of the output buffer has to be minimum the
+		// size of the decompressed lod entry. If this isn't the case, it is a programming fault.
+		assert(size >= archiveEntry->realSize);
+
+		// Read the compressed data into a buffer
+		ui8 * comp = new ui8[archiveEntry->size];
+		fileStream.read(comp, archiveEntry->size);
+
+		// Decompress the file
+		if(!decompressFile(comp, archiveEntry->size, archiveEntry->realSize, data))
+		{
+			throw std::runtime_error("File decompression wasn't successful. Resource name: " + archiveEntry->name);
+		}
+		delete[] comp;
+
+		// We're reading the total size always
+		return archiveEntry->realSize;
+	}
+}
+
+bool CLodStream::decompressFile(ui8 * in, int size, int realSize, ui8 * out)
+{
+	const int WBITS = 15;
+	const int FCHUNK = 50000;
+
+	int ret;
+	unsigned have;
+	z_stream strm;
+	int latPosOut = 0;
+
+	// Allocate inflate state
+	strm.zalloc = Z_NULL;
+	strm.zfree = Z_NULL;
+	strm.opaque = Z_NULL;
+	strm.avail_in = 0;
+	strm.next_in = Z_NULL;
+	ret = inflateInit2(&strm, WBITS);
+	if (ret != Z_OK)
+		return false;
+
+	int chunkNumber = 0;
+	do
+	{
+		if(size < chunkNumber * FCHUNK)
+			break;
+		strm.avail_in = std::min(FCHUNK, size - chunkNumber * FCHUNK);
+		if (strm.avail_in == 0)
+			break;
+		strm.next_in = in + chunkNumber * FCHUNK;
+
+		// Run inflate() on input until output buffer not full
+		do
+		{
+			strm.avail_out = realSize - latPosOut;
+			strm.next_out = out + latPosOut;
+			ret = inflate(&strm, Z_NO_FLUSH);
+
+			bool breakLoop = false;
+			switch (ret)
+			{
+			case Z_STREAM_END:
+				breakLoop = true;
+				break;
+			case Z_NEED_DICT:
+				ret = Z_DATA_ERROR;
+			case Z_DATA_ERROR:
+			case Z_MEM_ERROR:
+				(void)inflateEnd(&strm);
+				return false;
+			}
+
+			if(breakLoop)
+				break;
+
+			have = realSize - latPosOut - strm.avail_out;
+			latPosOut += have;
+		} while (strm.avail_out == 0);
+
+		++chunkNumber;
+	} while (ret != Z_STREAM_END);
+
+	// Clean up and return
+	(void)inflateEnd(&strm);
+	return ret == Z_STREAM_END ? true : false;
+}
+
+si64 CLodStream::seek(si64 position)
+{
+	return fileStream.seek(archiveEntry->offset + position);
+}
+
+si64 CLodStream::tell()
+{
+	return fileStream.tell() - archiveEntry->offset;
+}
+
+si64 CLodStream::skip(si64 delta)
+{
+	return fileStream.skip(delta);
+}
+
+si64 CLodStream::getSize()
+{
+	return archiveEntry->realSize;
+}
+
+void CLodStream::close()
+{
+	fileStream.close();
+}

+ 114 - 0
lib/Filesystem/CLodStream.h

@@ -0,0 +1,114 @@
+
+/*
+ * CLodStream.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#pragma once
+
+#include "CInputStream.h"
+#include "CFileInputStream.h"
+#include "CLodArchiveLoader.h"
+
+/**
+ * A class which provides method definitions for reading a file from a LOD archive.
+ */
+class DLL_LINKAGE CLodStream : public CInputStream
+{
+public:
+	/**
+	 * Default c-tor.
+	 */
+	CLodStream();
+
+	/**
+	 * C-tor.
+	 *
+	 * @param loader The archive loader object which knows about the structure of the archive format.
+	 * @param resourceName The resource name which says what resource should be loaded.
+	 *
+	 * @throws std::runtime_error if the archive entry wasn't found
+	 */
+	CLodStream(const CLodArchiveLoader * loader, const std::string & resourceName);
+
+	/**
+	 * Opens a lod stream. It will close any currently opened file stream.
+	 *
+	 * @param loader The archive loader object which knows about the structure of the archive format.
+	 * @param resourceName The resource name which says what resource should be loaded.
+	 *
+	 * @throws std::runtime_error if the archive entry wasn't found
+	 */
+	void open(const CLodArchiveLoader * loader, const std::string & resourceName);
+
+	/**
+	 * Reads n bytes from the stream into the data buffer.
+	 *
+	 * Warning: You can't read just a part of the archive entry if it's a decompressed one. So reading the total size always is
+	 * recommended unless you really know what you're doing e.g. reading from a video stream.
+	 *
+	 * @param data A pointer to the destination data array.
+	 * @param size The number of bytes to read.
+	 * @return the number of bytes read actually.
+	 *
+	 * @throws std::runtime_error if the file decompression was not successful
+	 */
+	si64 read(ui8 * data, si64 size);
+
+	/**
+	 * Seeks the internal read pointer to the specified position.
+	 *
+	 * @param position The read position from the beginning.
+	 * @return the position actually moved to, -1 on error.
+	 */
+	si64 seek(si64 position);
+
+	/**
+	 * Gets the current read position in the stream.
+	 *
+	 * @return the read position.
+	 */
+	si64 tell();
+
+	/**
+	 * Skips delta numbers of bytes.
+	 *
+	 * @param delta The count of bytes to skip.
+	 * @return the count of bytes skipped actually.
+	 */
+	si64 skip(si64 delta);
+
+	/**
+	 * Gets the length in bytes of the stream.
+	 *
+	 * @return the length in bytes of the stream.
+	 */
+	si64 getSize();
+
+	/**
+	 * Closes the stream and releases any system resources associated with the stream explicitely.
+	 */
+	void close();
+
+private:
+	/**
+	 * Decompresses an archive entry.
+	 *
+	 * @param in A pointer to the compressed data array
+	 * @param size The size of the compressed data array
+	 * @param realSize The size of the decompressed real size of the entry
+	 * @param out
+	 */
+	bool decompressFile(ui8 * in, int size, int realSize, ui8 * out);
+
+	/** The file stream for reading from the LOD archive. */
+	CFileInputStream fileStream;
+
+	/** The archive entry which specifies the length, offset,... of the entry. */
+	const ArchiveEntry * archiveEntry;
+};

+ 65 - 0
lib/Filesystem/CMemoryStream.cpp

@@ -0,0 +1,65 @@
+#include "StdInc.h"
+#include "CMemoryStream.h"
+
+CMemoryStream::CMemoryStream() : data(nullptr), size(0), position(0), freeData(false)
+{
+
+}
+
+CMemoryStream::CMemoryStream(const ui8 * data, si64 size, bool freeData /*= false*/) : data(data), size(size), position(0), freeData(freeData)
+{
+
+}
+
+CMemoryStream::~CMemoryStream()
+{
+	close();
+}
+
+void CMemoryStream::open(const ui8 * data, si64 size, bool freeData /*= false*/)
+{
+	close();
+
+	this->size = size;
+	this->data = data;
+	this->freeData = freeData;
+	this->position = 0;
+}
+
+si64 CMemoryStream::read(ui8 * data, si64 size)
+{
+	std::copy(this->data + position, this->data + position + size, data);
+	position += size;
+	return size;
+}
+
+si64 CMemoryStream::seek(si64 position)
+{
+	si64 diff = this->position;
+	this->position = position;
+	return position - diff;
+}
+
+si64 CMemoryStream::tell()
+{
+	return this->position;
+}
+
+si64 CMemoryStream::skip(si64 delta)
+{
+	this->position += delta;
+	return delta;
+}
+
+si64 CMemoryStream::getSize()
+{
+	return size;
+}
+
+void CMemoryStream::close()
+{
+	if(freeData)
+	{
+		delete[] data;
+	}
+}

+ 107 - 0
lib/Filesystem/CMemoryStream.h

@@ -0,0 +1,107 @@
+
+/*
+ * CMemoryStream.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#pragma once
+
+#include "CInputStream.h"
+
+/**
+ * A class which provides method definitions for reading from memory.
+ */
+class DLL_LINKAGE CMemoryStream : public CInputStream
+{
+public:
+	/**
+	 * Default c-tor.
+	 */
+	CMemoryStream();
+
+	/**
+	 * C-tor. The data buffer will be freed by the stream's destructor.
+	 *
+	 * @param data A pointer to the data array.
+	 * @param size The size in bytes of the array.
+	 * @param freeData Flag which specifies if the data array should be freed in the memory stream's destructor.
+	 */
+	CMemoryStream(const ui8 * data, si64 size, bool freeData = false);
+
+	/**
+	 * D-tor. Frees the data array if the freeData flag was set to true.
+	 */
+	~CMemoryStream();
+
+	/**
+	 * Opens the stream with the given data array. If a stream is currently loaded, it will be freed
+	 * if neccessary.
+	 *
+	 * @param data A pointer to the data array.
+	 * @param size The size in bytes of the array.
+	 * @param freeData Flag which specifies if the data array should be freed in the memory stream's destructor.
+	 */
+	void open(const ui8 * data, si64 size, bool freeData = false);
+
+	/**
+	 * Reads n bytes from the stream into the data buffer.
+	 *
+	 * @param data A pointer to the destination data array.
+	 * @param size The number of bytes to read.
+	 * @return the number of bytes read actually.
+	 */
+	si64 read(ui8 * data, si64 size);
+
+	/**
+	 * Seeks the internal read pointer to the specified position.
+	 *
+	 * @param position The read position from the beginning.
+	 * @return the position actually moved to, -1 on error.
+	 */
+	si64 seek(si64 position);
+
+	/**
+	 * Gets the current read position in the stream.
+	 *
+	 * @return the read position.
+	 */
+	si64 tell();
+
+	/**
+	 * Skips delta numbers of bytes.
+	 *
+	 * @param delta The count of bytes to skip.
+	 * @return the count of bytes skipped actually.
+	 */
+	si64 skip(si64 delta);
+
+	/**
+	 * Gets the length in bytes of the stream.
+	 *
+	 * @return the length in bytes of the stream.
+	 */
+	si64 getSize();
+
+	/**
+	 * Closes the stream and releases any system resources associated with the stream explicitely.
+	 */
+	void close();
+
+private:
+	/** A pointer to the data array. */
+	const ui8 * data;
+
+	/** The size in bytes of the array. */
+	si64 size;
+
+	/** Current reading position of the stream. */
+	si64 position;
+
+	/** Flag which specifies if the data array should be freed in the memory stream's destructor. */
+	bool freeData;
+};

+ 254 - 0
lib/Filesystem/CResourceLoader.cpp

@@ -0,0 +1,254 @@
+#include "StdInc.h"
+#include "CResourceLoader.h"
+#include "CFileInfo.h"
+#include "CLodArchiveLoader.h"
+
+CResourceLoader * CResourceLoaderFactory::resourceLoader = nullptr;
+
+ResourceIdentifier::ResourceIdentifier() : type(EResType::OTHER)
+{
+
+}
+
+ResourceIdentifier::ResourceIdentifier(const std::string & name, EResType type) : name(name), type(type)
+{
+	boost::to_upper(this->name);
+}
+
+std::string ResourceIdentifier::getName() const
+{
+	return name;
+}
+
+EResType ResourceIdentifier::getType() const
+{
+	return type;
+}
+
+void ResourceIdentifier::setName(const std::string & name)
+{
+	this->name = name;
+	boost::to_upper(this->name);
+}
+
+void ResourceIdentifier::setType(EResType type)
+{
+	this->type = type;
+}
+
+CResourceLoader::CResourceLoader()
+{
+
+}
+
+CResourceLoader::~CResourceLoader()
+{
+	// Delete all loader objects
+	for(auto it = loaders.begin(); it != loaders.end(); ++it)
+	{
+		delete *it;
+	}
+}
+
+std::unique_ptr<CInputStream> CResourceLoader::load(const ResourceIdentifier & resourceIdent) const
+{
+	if(!existsResource(resourceIdent))
+	{
+		throw std::runtime_error("Resource with name " + resourceIdent.getName() + " and type "
+			+ EResTypeHelper::getEResTypeAsString(resourceIdent.getType()) + " wasn't found.");
+	}
+
+	// get the last added resource(most overriden)
+	const ResourceLocator & locator = resources.at(resourceIdent).back();
+
+	// load the resource and return it
+	return locator.getLoader()->load(locator.getResourceName());
+}
+
+bool CResourceLoader::existsResource(const ResourceIdentifier & resourceIdent) const
+{
+	// Check if resource is registered
+	if(resources.find(resourceIdent) != resources.end())
+	{
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+void CResourceLoader::addLoader(ISimpleResourceLoader * loader)
+{
+	loaders.push_back(loader);
+
+	// Get entries and add them to the resources list
+	const std::list<std::string> & entries = loader->getEntries();
+
+	for(auto it = entries.begin(); it != entries.end(); ++it)
+	{
+		std::string entry = *it;
+		CFileInfo file(entry);
+
+		// Create identifier and locator and add them to the resources list
+		ResourceIdentifier ident(file.getStem(), file.getType());
+		ResourceLocator locator(loader, entry);
+		resources[ident].push_back(locator);
+	}
+}
+
+CResourceLoader * CResourceLoaderFactory::getInstance()
+{
+	if(resourceLoader != nullptr)
+	{
+		return resourceLoader;
+	}
+	else
+	{
+		std::stringstream string;
+		string << "Error: Resource loader wasn't initialized. "
+			   << "Make sure that you set one via CResourceLoaderFactory::setInstance";
+		throw std::runtime_error(string.str());
+	}
+}
+
+void CResourceLoaderFactory::setInstance(CResourceLoader * resourceLoader)
+{
+	CResourceLoaderFactory::resourceLoader = resourceLoader;
+}
+
+ResourceLocator::ResourceLocator(ISimpleResourceLoader * loader, const std::string & resourceName)
+			: loader(loader), resourceName(resourceName)
+{
+
+}
+
+ISimpleResourceLoader * ResourceLocator::getLoader() const
+{
+	return loader;
+}
+
+std::string ResourceLocator::getResourceName() const
+{
+	return resourceName;
+}
+
+EResType EResTypeHelper::getTypeFromExtension(std::string extension)
+{
+	boost::to_upper(extension);
+
+	if(extension == ".TXT" || extension == ".JSON")
+	{
+		return EResType::TEXT;
+	}
+	else if(extension == ".DEF" || extension == ".JSON")
+	{
+		return EResType::ANIMATION;
+	}
+	else if(extension == ".MSK" || extension == ".MSG")
+	{
+		return EResType::MASK;
+	}
+	else if(extension == ".H3C")
+	{
+		return EResType::CAMPAIGN;
+	}
+	else if(extension == ".H3M")
+	{
+		return EResType::MAP;
+	}
+	else if(extension == ".FNT")
+	{
+		return EResType::FONT;
+	}
+	else if(extension == ".BMP" || extension == ".JPG" || extension == ".PCX" || extension == ".PNG" || extension == ".TGA")
+	{
+		return EResType::IMAGE;
+	}
+	else if(extension == ".WAV")
+	{
+		return EResType::SOUND;
+	}
+	else if(extension == ".SMK" || extension == ".BIK")
+	{
+		return EResType::VIDEO;
+	}
+	else if(extension == ".MP3" || extension == ".OGG")
+	{
+		return EResType::MUSIC;
+	}
+	else if(extension == ".ZIP" || extension == ".TAR.GZ" || extension == ".LOD" || extension == ".VID" || extension == ".SND")
+	{
+		return EResType::ARCHIVE;
+	}
+	else if(extension == ".VLGM1")
+	{
+		return EResType::SAVEGAME;
+	}
+	else
+	{
+		return EResType::OTHER;
+	}
+}
+
+std::string EResTypeHelper::getEResTypeAsString(EResType type)
+{
+	if(type == EResType::ANIMATION)
+	{
+		return "ANIMATION";
+	}
+	else if(type == EResType::ANY)
+	{
+		return "ANY";
+	}
+	else if(type == EResType::ARCHIVE)
+	{
+		return "ARCHIVE";
+	}
+	else if(type == EResType::CAMPAIGN)
+	{
+		return "CAMPAIGN";
+	}
+	else if(type == EResType::FONT)
+	{
+		return "FONT";
+	}
+	else if(type == EResType::IMAGE)
+	{
+		return "IMAGE";
+	}
+	else if(type == EResType::MAP)
+	{
+		return "MAP";
+	}
+	else if(type == EResType::MASK)
+	{
+		return "MASK";
+	}
+	else if(type == EResType::MUSIC)
+	{
+		return "MUSIC";
+	}
+	else if(type == EResType::OTHER)
+	{
+		return "OTHER";
+	}
+	else if(type == EResType::SAVEGAME)
+	{
+		return "SAVEGAME";
+	}
+	else if(type == EResType::SOUND)
+	{
+		return "SOUND";
+	}
+	else if(type == EResType::TEXT)
+	{
+		return "TEXT";
+	}
+	else if(type == EResType::VIDEO)
+	{
+		return "VIDEO";
+	}
+
+	return "";
+}

+ 294 - 0
lib/Filesystem/CResourceLoader.h

@@ -0,0 +1,294 @@
+
+/*
+ * CResourceLoader.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#pragma once
+
+#include "CInputStream.h"
+
+class ResourceLocator;
+class ISimpleResourceLoader;
+
+/**
+ * Specifies the resource type.
+ *
+ * Supported file extensions:
+ *
+ * Text: .json
+ * Animation: .def
+ * Mask: .msk
+ * Campaign: .h3c
+ * Map: .h3m
+ * Font: .fnt
+ * Image: .bmp, .jpg, .pcx, .png, .tga
+ * Sound: .wav
+ * Video: .smk, .bik
+ * Music: .mp3, .ogg
+ * Archive: .lod, .snd, .vid, .zip, .tar.gz
+ * Savegame: .vlgm1
+ */
+enum class EResType
+{
+	ANY,
+	TEXT,
+	ANIMATION,
+	MASK,
+	CAMPAIGN,
+	MAP,
+	FONT,
+	IMAGE,
+	VIDEO,
+	SOUND,
+	MUSIC,
+	ARCHIVE,
+	SAVEGAME,
+	OTHER
+};
+
+/**
+ * A struct which identifies a resource clearly.
+ */
+class DLL_LINKAGE ResourceIdentifier
+{
+public:
+	/**
+	 * Default c-tor.
+	 */
+	ResourceIdentifier();
+
+	/**
+	 * Ctor.
+	 *
+	 * @param name The resource name.
+	 * @param type The resource type. A constant from the enumeration EResType.
+	 */
+	ResourceIdentifier(const std::string & name, EResType type);
+
+	/**
+	 * Compares this object with a another resource identifier.
+	 *
+	 * @param other The other resource identifier.
+	 * @return Returns true if both are equally, false if not.
+	 */
+	inline bool operator==(ResourceIdentifier const & other) const
+	{
+		return name == other.name && type == other.type;
+	}
+
+	/**
+	 * Gets the name of the identifier.
+	 *
+	 * @return the name of the identifier
+	 */
+	std::string getName() const;
+
+	/**
+	 * Gets the type of the identifier.
+	 *
+	 * @return the type of the identifier
+	 */
+	EResType getType() const;
+
+	/**
+	 * Sets the name of the identifier.
+	 *
+	 * @param name the name of the identifier. No extension, will be converted to uppercase.
+	 */
+	void setName(const std::string & name);
+
+	/**
+	 * Sets the type of the identifier.
+	 *
+	 * @param type the type of the identifier.
+	 */
+	void setType(EResType type);
+
+private:
+	/** Specifies the resource name. No extension so .pcx and .png can override each other, always in upper case. **/
+	std::string name;
+
+	/**
+	 * Specifies the resource type. EResType::OTHER if not initialized.
+	 * Required to prevent conflicts if files with different types (e.g. text and image) have the same name.
+	 */
+	EResType type;
+};
+
+namespace std
+{
+	/**
+	 * Template specialization for std::hash.
+	 */
+    template <>
+    class hash<ResourceIdentifier>
+    {
+public:
+    	/**
+    	 * Generates a hash value for the resource identifier object.
+    	 *
+    	 * @param resourceIdent The object from which a hash value should be generated.
+    	 * @return the generated hash value
+    	 */
+		size_t operator()(const ResourceIdentifier & resourceIdent) const
+		{
+			return hash<string>()(resourceIdent.getName()) ^ hash<int>()(static_cast<int>(resourceIdent.getType()));
+		}
+    };
+};
+
+/**
+ * This class manages the loading of resources whether standard
+ * or derived from several container formats and the file system.
+ */
+class DLL_LINKAGE CResourceLoader : public boost::noncopyable
+{
+public:
+	CResourceLoader();
+
+	/**
+	 * D-tor.
+	 */
+	virtual ~CResourceLoader();
+
+	/**
+	 * Loads the resource specified by the resource identifier.
+	 *
+	 * @param resourceIdent This parameter identifies the resource to load.
+	 * @return a pointer to the input stream, not null
+	 *
+	 * @throws std::runtime_error if the resource doesn't exists
+	 */
+	std::unique_ptr<CInputStream> load(const ResourceIdentifier & resourceIdent) const;
+
+	/**
+	 * Tests whether the specified resource exists.
+	 *
+	 * @param resourceIdent the resource which should be checked
+	 * @return true if the resource exists, false if not
+	 */
+	bool existsResource(const ResourceIdentifier & resourceIdent) const;
+
+	/**
+	 * Adds a simple resource loader to the loaders list and its entries to the resources list.
+	 *
+	 * The loader object will be destructed when this resource loader is destructed.
+	 * Don't delete it manually.
+	 *
+	 * @param loader The simple resource loader object to add
+	 */
+	void addLoader(ISimpleResourceLoader * loader);
+
+private:
+
+	/**
+	 * Contains lists of same resources which can be accessed uniquely by an
+	 * resource identifier.
+	 */
+	std::unordered_map<ResourceIdentifier, std::list<ResourceLocator> > resources;
+
+	/** A list of resource loader objects */
+	std::list<ISimpleResourceLoader *> loaders;
+};
+
+/**
+ * This class has static methods for a global resource loader access.
+ *
+ * Note: Compared to the singleton pattern it has the advantage that the class CResourceLoader
+ * and classes which use it can be tested separately. CResourceLoader can be sub-classes as well.
+ * Compared to a global variable the factory pattern can throw an exception if the resource loader wasn't
+ * initialized.
+ *
+ * This class is not thread-safe. Make sure nobody is calling getInstance while somebody else is calling setInstance.
+ */
+class DLL_LINKAGE CResourceLoaderFactory
+{
+public:
+	/**
+	 * Gets an instance of resource loader.
+	 *
+	 * Make sure that you've set an instance before using it. It'll throw an exception if no instance was set.
+	 *
+	 * @return Returns an instance of resource loader.
+	 */
+	static CResourceLoader * getInstance();
+
+	/**
+	 * Sets an instance of resource loader.
+	 *
+	 * @param resourceLoader An instance of resource loader.
+	 */
+	static void setInstance(CResourceLoader * resourceLoader);
+
+private:
+	/** Instance of resource loader */
+	static CResourceLoader * resourceLoader;
+};
+
+/**
+ * A struct which describes the exact position of a resource.
+ */
+class DLL_LINKAGE ResourceLocator
+{
+public:
+	/**
+	 * Ctor.
+	 *
+	 * @param archive A pointer to the resource archive object.
+	 * @param resourceName Unique resource name in the space of the given resource archive.
+	 */
+	ResourceLocator(ISimpleResourceLoader * loader, const std::string & resourceName);
+
+	/**
+	 * Gets a pointer to the resource loader object.
+	 *
+	 * @return a pointer to the resource loader object
+	 */
+	ISimpleResourceLoader * getLoader() const;
+
+	/**
+	 * Gets the resource name.
+	 *
+	 * @return the resource name.
+	 */
+	std::string getResourceName() const;
+
+private:
+	/**
+	 * A pointer to the loader which knows where and how to construct a stream object
+	 * which does the loading process actually.
+	 */
+	ISimpleResourceLoader * loader;
+
+	/** A unique name of the resource in space of the loader. */
+	std::string resourceName;
+};
+
+/**
+ * A helper class which provides a functionality to convert extension strings to EResTypes.
+ */
+class DLL_LINKAGE EResTypeHelper
+{
+public:
+	/**
+	 * Converts a extension string to a EResType enum object.
+	 *
+	 * @param extension The extension string e.g. .BMP, .PNG
+	 * @return Returns a EResType enum object
+	 */
+	static EResType getTypeFromExtension(std::string extension);
+
+	/**
+	 * Gets the EResType as a string representation.
+	 *
+	 * @param type the EResType
+	 * @return the type as a string representation
+	 */
+	static std::string getEResTypeAsString(EResType type);
+};

+ 48 - 0
lib/Filesystem/ISimpleResourceLoader.h

@@ -0,0 +1,48 @@
+
+/*
+ * ISimpleResourceLoader.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#pragma once
+
+#include "CInputStream.h"
+
+/**
+ * A class which knows the files containing in the archive or system and how to load them.
+ */
+class DLL_LINKAGE ISimpleResourceLoader
+{
+public:
+	/**
+	 * Dtor.
+	 */
+	virtual ~ISimpleResourceLoader() { };
+
+	/**
+	 * Loads a resource with the given resource name.
+	 *
+	 * @param resourceName The unqiue resource name in space of the archive.
+	 * @return a input stream object
+	 */
+	virtual std::unique_ptr<CInputStream> load(const std::string & resourceName) const =0;
+
+	/**
+	 * Checks if the entry exists.
+	 *
+	 * @return Returns true if the entry exists, false if not.
+	 */
+	virtual bool existsEntry(const std::string & resourceName) const =0;
+
+	/**
+	 * Gets all entries in the archive or (file) system.
+	 *
+	 * @return Returns a list of all entries in the archive or (file) system.
+	 */
+	virtual std::list<std::string> getEntries() const =0;
+};

+ 8 - 0
lib/Makefile.am

@@ -7,6 +7,14 @@ libvcmi_la_LIBADD = @BOOST_SYSTEM_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_THREAD_LIB@
 libvcmi_la_CXXFLAGS = @SDL_CFLAGS@ -DVCMI_DLL
 libvcmi_la_SOURCES = \
 	../Global.h \
+	Filesystem/CBinaryReader.cpp \
+	Filesystem/CFileInfo.cpp \
+	Filesystem/CFileInputStream.cpp \
+	Filesystem/CFilesystemLoader.cpp \
+	Filesystem/CLodArchiveLoader.cpp \
+	Filesystem/CLodStream.cpp \
+	Filesystem/CMemoryStream.cpp \
+	Filesystem/CResourceLoader.cpp \
 	BattleAction.cpp \
 	BattleAction.h \
 	BattleState.cpp \

+ 93 - 16
lib/Makefile.in

@@ -85,22 +85,27 @@ am__uninstall_files_from_dir = { \
 am__installdirs = "$(DESTDIR)$(pkglibdir)"
 LTLIBRARIES = $(pkglib_LTLIBRARIES)
 libvcmi_la_DEPENDENCIES =
-am_libvcmi_la_OBJECTS = libvcmi_la-BattleAction.lo \
-	libvcmi_la-BattleState.lo libvcmi_la-CArtHandler.lo \
-	libvcmi_la-CBuildingHandler.lo libvcmi_la-CCampaignHandler.lo \
-	libvcmi_la-CConsoleHandler.lo libvcmi_la-CCreatureHandler.lo \
-	libvcmi_la-CCreatureSet.lo libvcmi_la-CDefObjInfoHandler.lo \
-	libvcmi_la-CFileUtility.lo libvcmi_la-CGameInterface.lo \
-	libvcmi_la-CGameState.lo libvcmi_la-CGeneralTextHandler.lo \
-	libvcmi_la-CHeroHandler.lo libvcmi_la-CLodHandler.lo \
-	libvcmi_la-CLogger.lo libvcmi_la-CMapInfo.lo \
-	libvcmi_la-CObjectHandler.lo libvcmi_la-CObstacleInstance.lo \
-	libvcmi_la-CSpellHandler.lo libvcmi_la-CTownHandler.lo \
-	libvcmi_la-CThreadHelper.lo libvcmi_la-Connection.lo \
-	libvcmi_la-HeroBonus.lo libvcmi_la-IGameCallback.lo \
-	libvcmi_la-JsonNode.lo libvcmi_la-NetPacksLib.lo \
-	libvcmi_la-ResourceSet.lo libvcmi_la-BattleHex.lo \
-	libvcmi_la-VCMI_Lib.lo libvcmi_la-map.lo
+am_libvcmi_la_OBJECTS = libvcmi_la-CBinaryReader.lo \
+	libvcmi_la-CFileInfo.lo libvcmi_la-CFileInputStream.lo \
+	libvcmi_la-CFilesystemLoader.lo \
+	libvcmi_la-CLodArchiveLoader.lo libvcmi_la-CLodStream.lo \
+	libvcmi_la-CMemoryStream.lo libvcmi_la-CResourceLoader.lo \
+	libvcmi_la-BattleAction.lo libvcmi_la-BattleState.lo \
+	libvcmi_la-CArtHandler.lo libvcmi_la-CBuildingHandler.lo \
+	libvcmi_la-CCampaignHandler.lo libvcmi_la-CConsoleHandler.lo \
+	libvcmi_la-CCreatureHandler.lo libvcmi_la-CCreatureSet.lo \
+	libvcmi_la-CDefObjInfoHandler.lo libvcmi_la-CFileUtility.lo \
+	libvcmi_la-CGameInterface.lo libvcmi_la-CGameState.lo \
+	libvcmi_la-CGeneralTextHandler.lo libvcmi_la-CHeroHandler.lo \
+	libvcmi_la-CLodHandler.lo libvcmi_la-CLogger.lo \
+	libvcmi_la-CMapInfo.lo libvcmi_la-CObjectHandler.lo \
+	libvcmi_la-CObstacleInstance.lo libvcmi_la-CSpellHandler.lo \
+	libvcmi_la-CTownHandler.lo libvcmi_la-CThreadHelper.lo \
+	libvcmi_la-Connection.lo libvcmi_la-HeroBonus.lo \
+	libvcmi_la-IGameCallback.lo libvcmi_la-JsonNode.lo \
+	libvcmi_la-NetPacksLib.lo libvcmi_la-ResourceSet.lo \
+	libvcmi_la-BattleHex.lo libvcmi_la-VCMI_Lib.lo \
+	libvcmi_la-map.lo
 libvcmi_la_OBJECTS = $(am_libvcmi_la_OBJECTS)
 AM_V_lt = $(am__v_lt_@AM_V@)
 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -295,6 +300,14 @@ libvcmi_la_LIBADD = @BOOST_SYSTEM_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_THREAD_LIB@
 libvcmi_la_CXXFLAGS = @SDL_CFLAGS@ -DVCMI_DLL
 libvcmi_la_SOURCES = \
 	../Global.h \
+	Filesystem/CBinaryReader.cpp \
+	Filesystem/CFileInfo.cpp \
+	Filesystem/CFileInputStream.cpp \
+	Filesystem/CFilesystemLoader.cpp \
+	Filesystem/CLodArchiveLoader.cpp \
+	Filesystem/CLodStream.cpp \
+	Filesystem/CMemoryStream.cpp \
+	Filesystem/CResourceLoader.cpp \
 	BattleAction.cpp \
 	BattleAction.h \
 	BattleState.cpp \
@@ -444,22 +457,30 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-BattleHex.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-BattleState.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CArtHandler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CBinaryReader.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CBuildingHandler.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CCampaignHandler.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CConsoleHandler.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CCreatureHandler.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CCreatureSet.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CDefObjInfoHandler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CFileInfo.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CFileInputStream.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CFileUtility.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CFilesystemLoader.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CGameInterface.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CGameState.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CGeneralTextHandler.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CHeroHandler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CLodArchiveLoader.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CLodHandler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CLodStream.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CLogger.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CMapInfo.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CMemoryStream.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CObjectHandler.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CObstacleInstance.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CResourceLoader.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CSpellHandler.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CThreadHelper.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CTownHandler.Plo@am__quote@
@@ -493,6 +514,62 @@ distclean-compile:
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
 
+libvcmi_la-CBinaryReader.lo: Filesystem/CBinaryReader.cpp
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -MT libvcmi_la-CBinaryReader.lo -MD -MP -MF $(DEPDIR)/libvcmi_la-CBinaryReader.Tpo -c -o libvcmi_la-CBinaryReader.lo `test -f 'Filesystem/CBinaryReader.cpp' || echo '$(srcdir)/'`Filesystem/CBinaryReader.cpp
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libvcmi_la-CBinaryReader.Tpo $(DEPDIR)/libvcmi_la-CBinaryReader.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='Filesystem/CBinaryReader.cpp' object='libvcmi_la-CBinaryReader.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -c -o libvcmi_la-CBinaryReader.lo `test -f 'Filesystem/CBinaryReader.cpp' || echo '$(srcdir)/'`Filesystem/CBinaryReader.cpp
+
+libvcmi_la-CFileInfo.lo: Filesystem/CFileInfo.cpp
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -MT libvcmi_la-CFileInfo.lo -MD -MP -MF $(DEPDIR)/libvcmi_la-CFileInfo.Tpo -c -o libvcmi_la-CFileInfo.lo `test -f 'Filesystem/CFileInfo.cpp' || echo '$(srcdir)/'`Filesystem/CFileInfo.cpp
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libvcmi_la-CFileInfo.Tpo $(DEPDIR)/libvcmi_la-CFileInfo.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='Filesystem/CFileInfo.cpp' object='libvcmi_la-CFileInfo.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -c -o libvcmi_la-CFileInfo.lo `test -f 'Filesystem/CFileInfo.cpp' || echo '$(srcdir)/'`Filesystem/CFileInfo.cpp
+
+libvcmi_la-CFileInputStream.lo: Filesystem/CFileInputStream.cpp
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -MT libvcmi_la-CFileInputStream.lo -MD -MP -MF $(DEPDIR)/libvcmi_la-CFileInputStream.Tpo -c -o libvcmi_la-CFileInputStream.lo `test -f 'Filesystem/CFileInputStream.cpp' || echo '$(srcdir)/'`Filesystem/CFileInputStream.cpp
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libvcmi_la-CFileInputStream.Tpo $(DEPDIR)/libvcmi_la-CFileInputStream.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='Filesystem/CFileInputStream.cpp' object='libvcmi_la-CFileInputStream.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -c -o libvcmi_la-CFileInputStream.lo `test -f 'Filesystem/CFileInputStream.cpp' || echo '$(srcdir)/'`Filesystem/CFileInputStream.cpp
+
+libvcmi_la-CFilesystemLoader.lo: Filesystem/CFilesystemLoader.cpp
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -MT libvcmi_la-CFilesystemLoader.lo -MD -MP -MF $(DEPDIR)/libvcmi_la-CFilesystemLoader.Tpo -c -o libvcmi_la-CFilesystemLoader.lo `test -f 'Filesystem/CFilesystemLoader.cpp' || echo '$(srcdir)/'`Filesystem/CFilesystemLoader.cpp
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libvcmi_la-CFilesystemLoader.Tpo $(DEPDIR)/libvcmi_la-CFilesystemLoader.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='Filesystem/CFilesystemLoader.cpp' object='libvcmi_la-CFilesystemLoader.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -c -o libvcmi_la-CFilesystemLoader.lo `test -f 'Filesystem/CFilesystemLoader.cpp' || echo '$(srcdir)/'`Filesystem/CFilesystemLoader.cpp
+
+libvcmi_la-CLodArchiveLoader.lo: Filesystem/CLodArchiveLoader.cpp
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -MT libvcmi_la-CLodArchiveLoader.lo -MD -MP -MF $(DEPDIR)/libvcmi_la-CLodArchiveLoader.Tpo -c -o libvcmi_la-CLodArchiveLoader.lo `test -f 'Filesystem/CLodArchiveLoader.cpp' || echo '$(srcdir)/'`Filesystem/CLodArchiveLoader.cpp
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libvcmi_la-CLodArchiveLoader.Tpo $(DEPDIR)/libvcmi_la-CLodArchiveLoader.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='Filesystem/CLodArchiveLoader.cpp' object='libvcmi_la-CLodArchiveLoader.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -c -o libvcmi_la-CLodArchiveLoader.lo `test -f 'Filesystem/CLodArchiveLoader.cpp' || echo '$(srcdir)/'`Filesystem/CLodArchiveLoader.cpp
+
+libvcmi_la-CLodStream.lo: Filesystem/CLodStream.cpp
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -MT libvcmi_la-CLodStream.lo -MD -MP -MF $(DEPDIR)/libvcmi_la-CLodStream.Tpo -c -o libvcmi_la-CLodStream.lo `test -f 'Filesystem/CLodStream.cpp' || echo '$(srcdir)/'`Filesystem/CLodStream.cpp
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libvcmi_la-CLodStream.Tpo $(DEPDIR)/libvcmi_la-CLodStream.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='Filesystem/CLodStream.cpp' object='libvcmi_la-CLodStream.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -c -o libvcmi_la-CLodStream.lo `test -f 'Filesystem/CLodStream.cpp' || echo '$(srcdir)/'`Filesystem/CLodStream.cpp
+
+libvcmi_la-CMemoryStream.lo: Filesystem/CMemoryStream.cpp
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -MT libvcmi_la-CMemoryStream.lo -MD -MP -MF $(DEPDIR)/libvcmi_la-CMemoryStream.Tpo -c -o libvcmi_la-CMemoryStream.lo `test -f 'Filesystem/CMemoryStream.cpp' || echo '$(srcdir)/'`Filesystem/CMemoryStream.cpp
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libvcmi_la-CMemoryStream.Tpo $(DEPDIR)/libvcmi_la-CMemoryStream.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='Filesystem/CMemoryStream.cpp' object='libvcmi_la-CMemoryStream.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -c -o libvcmi_la-CMemoryStream.lo `test -f 'Filesystem/CMemoryStream.cpp' || echo '$(srcdir)/'`Filesystem/CMemoryStream.cpp
+
+libvcmi_la-CResourceLoader.lo: Filesystem/CResourceLoader.cpp
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -MT libvcmi_la-CResourceLoader.lo -MD -MP -MF $(DEPDIR)/libvcmi_la-CResourceLoader.Tpo -c -o libvcmi_la-CResourceLoader.lo `test -f 'Filesystem/CResourceLoader.cpp' || echo '$(srcdir)/'`Filesystem/CResourceLoader.cpp
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libvcmi_la-CResourceLoader.Tpo $(DEPDIR)/libvcmi_la-CResourceLoader.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='Filesystem/CResourceLoader.cpp' object='libvcmi_la-CResourceLoader.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -c -o libvcmi_la-CResourceLoader.lo `test -f 'Filesystem/CResourceLoader.cpp' || echo '$(srcdir)/'`Filesystem/CResourceLoader.cpp
+
 libvcmi_la-BattleAction.lo: BattleAction.cpp
 @am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -MT libvcmi_la-BattleAction.lo -MD -MP -MF $(DEPDIR)/libvcmi_la-BattleAction.Tpo -c -o libvcmi_la-BattleAction.lo `test -f 'BattleAction.cpp' || echo '$(srcdir)/'`BattleAction.cpp
 @am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libvcmi_la-BattleAction.Tpo $(DEPDIR)/libvcmi_la-BattleAction.Plo