aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2010-07-31 13:02:58 +0000
committerEugene Sandulenko2010-10-12 22:15:42 +0000
commitea29e41b86dd6efad5b044220505ded798b2503e (patch)
tree461451b1ee2eb4c006bc95f130ff25b446a360c0
parentbed623b11ef007bb46b26f1f995b6073914383c5 (diff)
downloadscummvm-rg350-ea29e41b86dd6efad5b044220505ded798b2503e.tar.gz
scummvm-rg350-ea29e41b86dd6efad5b044220505ded798b2503e.tar.bz2
scummvm-rg350-ea29e41b86dd6efad5b044220505ded798b2503e.zip
SWORD25: Reimplemented package manager for ScummVM using Common::Archive
svn-id: r53194
-rw-r--r--engines/sword25/module.mk2
-rw-r--r--engines/sword25/package/packagemanager.cpp9
-rw-r--r--engines/sword25/package/packagemanager.h6
-rw-r--r--engines/sword25/package/physfspackagemanager.cpp497
-rw-r--r--engines/sword25/package/physfspackagemanager.h76
-rw-r--r--engines/sword25/package/scummvmpackagemanager.cpp367
-rw-r--r--engines/sword25/package/scummvmpackagemanager.h105
7 files changed, 482 insertions, 580 deletions
diff --git a/engines/sword25/module.mk b/engines/sword25/module.mk
index 5bd81dd81e..e1320252b1 100644
--- a/engines/sword25/module.mk
+++ b/engines/sword25/module.mk
@@ -68,7 +68,7 @@ MODULE_OBJS := \
math/walkregion.o \
package/packagemanager.o \
package/packagemanager_script.o \
- package/physfspackagemanager.o \
+ package/scummvmpackagemanager.o \
script/luabindhelper.o \
script/luacallback.o \
script/luascript.o \
diff --git a/engines/sword25/package/packagemanager.cpp b/engines/sword25/package/packagemanager.cpp
index 3d7e36a71e..2dc07cfae9 100644
--- a/engines/sword25/package/packagemanager.cpp
+++ b/engines/sword25/package/packagemanager.cpp
@@ -42,10 +42,13 @@
// -----------------------------------------------------------------------------
-BS_PackageManager::BS_PackageManager(BS_Kernel * pKernel) : BS_Service(pKernel)
-{
+namespace Sword25 {
+
+BS_PackageManager::BS_PackageManager(BS_Kernel *pKernel) : BS_Service(pKernel) {
if (!_RegisterScriptBindings())
BS_LOG_ERRORLN("Script bindings could not be registered.");
else
BS_LOGLN("Script bindings registered.");
-} \ No newline at end of file
+}
+
+} // End of namespace Sword25
diff --git a/engines/sword25/package/packagemanager.h b/engines/sword25/package/packagemanager.h
index cb54f3240b..1d6c71074f 100644
--- a/engines/sword25/package/packagemanager.h
+++ b/engines/sword25/package/packagemanager.h
@@ -118,14 +118,14 @@ public:
* @param FileName The filename of the package to mount
* @param MountPosition The directory name under which the package should be mounted
* @return Returns true if the mount was successful, otherwise false.
- */
+ */
virtual bool LoadPackage(const Common::String &FileName, const Common::String &MountPosition) = 0;
/**
* Mounts the contents of a directory in the specified directory in the virtual directory tree.
* @param The name of the directory to mount
* @param MountPosition The directory name under which the package should be mounted
* @return Returns true if the mount was successful, otherwise false.
- */
+ */
virtual bool LoadDirectoryAsPackage(const Common::String &DirectoryName, const Common::String &MountPosition) = 0;
/**
* Downloads a file from the virtual directory tree
@@ -190,7 +190,7 @@ public:
* Determines whether a file exists
* @param FileName The filename
* @return Returns true if the file exists, otherwise false.
- */
+ */
virtual bool FileExists(const Common::String & FileName) = 0;
private:
diff --git a/engines/sword25/package/physfspackagemanager.cpp b/engines/sword25/package/physfspackagemanager.cpp
deleted file mode 100644
index 52aab7d4d6..0000000000
--- a/engines/sword25/package/physfspackagemanager.cpp
+++ /dev/null
@@ -1,497 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-/*
- * This code is based on Broken Sword 2.5 engine
- *
- * Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdoerfer
- *
- * Licensed under GNU GPL v2
- *
- */
-
-// -----------------------------------------------------------------------------
-// Includes
-// -----------------------------------------------------------------------------
-
-#include "sword25/package/physfspackagemanager.h"
-
-#include "sword25/kernel/memlog_off.h"
-#include <vector>
-#include <sstream>
-#include "sword25/kernel/memlog_on.h"
-
-using namespace std;
-
-// -----------------------------------------------------------------------------
-
-#define BS_LOG_PREFIX "PHYSFSPACKAGEMANAGER"
-
-// -----------------------------------------------------------------------------
-// Hilfsfunktionen
-// -----------------------------------------------------------------------------
-
-namespace
-{
- const char * SafeGetLastError()
- {
- const char * ErrorMessage = PHYSFS_getLastError();
- return ErrorMessage ? ErrorMessage : "unknown";
- }
-
- // -------------------------------------------------------------------------
-
- void LogPhysfsError(const char * FunctionName)
- {
- BS_LOG_ERRORLN("%s() failed. Reason: %s.", FunctionName, SafeGetLastError());
- }
-
- // -------------------------------------------------------------------------
-
- void LogPhysfsError(const char * FunctionName, const char * FileName)
- {
- BS_LOG_ERRORLN("%s() on file \"%s\" failed. Reason: %s.", FunctionName, FileName, SafeGetLastError());
- }
-
- // -------------------------------------------------------------------------
-
- const char PATH_SEPARATOR = '/';
- const char NAVIGATION_CHARACTER = '.';
-
- // -------------------------------------------------------------------------
-
- std::string RemoveRedundantPathSeparators(const std::string & Path)
- {
- std::string Result;
-
- // Über alle Zeichen des Eingabepfades iterieren.
- std::string::const_iterator It = Path.begin();
- while (It != Path.end())
- {
- if (*It == PATH_SEPARATOR)
- {
- // Verzeichnistrenner gefunden.
-
- // Folgen von Verzeichnistrennern überspringen.
- while (It != Path.end() && *It == PATH_SEPARATOR) ++It;
-
- // Einzelnen Verzeichnistrenner ausgeben, nur am Ende des Pfades wird kein Verzeichnistrenner mehr ausgegeben.
- if (It != Path.end()) Result.push_back(PATH_SEPARATOR);
- }
- else
- {
- // Normales Zeichen gefunden, wird unverändert ausgegeben.
- Result.push_back(*It);
- ++It;
- }
- }
-
- return Result;
- }
-
- // ---------------------------------------------------------------------
-
- struct PathElement
- {
- public:
- PathElement(std::string::const_iterator Begin, std::string::const_iterator End) : m_Begin(Begin), m_End(End) {}
-
- std::string::const_iterator GetBegin() const { return m_Begin; }
- std::string::const_iterator GetEnd() const { return m_End; }
-
- private:
- std::string::const_iterator m_Begin;
- std::string::const_iterator m_End;
- };
-
- // -------------------------------------------------------------------------
-
- std::string NormalizePath(const std::string & Path, const std::string & CurrentDirectory)
- {
- // Feststellen, ob der Pfad absolut (beginnt mit /) oder relativ ist und im relativen Fall dem Gesamtpfad das aktuelle Verzeichnis
- // voranstellen.
- std::string WholePath = (Path.size() >= 1 && Path[0] == PATH_SEPARATOR) ? "" : CurrentDirectory + PATH_SEPARATOR;
-
- // Alle gedoppelten und nachfolgende Verzeichnistrenner aus dem übergebenen Pfad entfernen und den Gesamtpfad zusammensetzen.
- // CurrentDirectory wird nicht auf diese Weise gesäubert. Es wird vorrausgesetzt, dass CurrentDirectory keine überflüssigen
- // Verzeichnistrenner beinhaltet.
- WholePath += RemoveRedundantPathSeparators(Path);
-
- // Gesamtpfad parsen und in Einzelelemente aufteilen. Dabei werden Vorkommen von ".." und "." korrekt behandelt.
- vector<PathElement> PathElements;
- size_t SeparatorPos = 0;
- while (SeparatorPos < WholePath.size())
- {
- // Nächsten Verzeichnistrenner finden.
- size_t NextSeparatorPos = WholePath.find(PATH_SEPARATOR, SeparatorPos + 1);
- if (NextSeparatorPos == std::string::npos) NextSeparatorPos = WholePath.size();
-
- // Anfang und Ende vom Pfadelement berechnen.
- std::string::const_iterator ElementBegin = WholePath.begin() + SeparatorPos + 1;
- std::string::const_iterator ElementEnd = WholePath.begin() + NextSeparatorPos;
-
- if (ElementEnd - ElementBegin == 2 &&
- ElementBegin[0] == NAVIGATION_CHARACTER &&
- ElementBegin[1] == NAVIGATION_CHARACTER)
- {
- // Element ist "..", daher wird das vorangegangene Pfadelement aus dem vector entfernt.
- if (PathElements.size()) PathElements.pop_back();
- }
- else if (ElementEnd - ElementBegin == 1 &&
- ElementBegin[0] == NAVIGATION_CHARACTER)
- {
- // Element ist ".", wir tun gar nichts.
- }
- else
- {
- // Normales Element in den vector einfügen.
- PathElements.push_back(PathElement(WholePath.begin() + SeparatorPos + 1, WholePath.begin() + NextSeparatorPos));
- }
-
- SeparatorPos = NextSeparatorPos;
- }
-
- if (PathElements.size())
- {
- // Die einzelnen Pfadelemente werden durch Verzeichnistrenner getrennt aneinandergesetzt.
- // Der so entstandene String wird als Ergebnis zurückgegeben.
- ostringstream PathBuilder;
- vector<PathElement>::const_iterator It = PathElements.begin();
- while (It != PathElements.end())
- {
- PathBuilder << PATH_SEPARATOR << std::string(It->GetBegin(), It->GetEnd());
- ++It;
- }
-
- return PathBuilder.str();
- }
- else
- {
- // Nach dem Parsen sind keine Pfadelemente mehr übrig geblieben, daher wird des Root-Verzeichnis zurückgegeben.
- return std::string(1, PATH_SEPARATOR);
- }
- }
-
- // -------------------------------------------------------------------------
- // RAII-Klasse für PHYSFS-Filehandles.
- // -------------------------------------------------------------------------
-
- class PhysfsHandleHolder
- {
- public:
- PhysfsHandleHolder(PHYSFS_File * Handle) : m_Handle(Handle) {}
- ~PhysfsHandleHolder()
- {
- if (m_Handle)
- {
- if (!PHYSFS_close(m_Handle)) LogPhysfsError("PHYSFS_close");
- }
- }
-
- PHYSFS_File * Get() { return m_Handle; }
- PHYSFS_File * Release()
- {
- PHYSFS_File * Result = m_Handle;
- m_Handle = 0;
- return Result;
- }
-
- private:
- PHYSFS_File * m_Handle;
- };
-
- // -------------------------------------------------------------------------
- // RAII-Klasse für PHYSFS-Listen.
- // -------------------------------------------------------------------------
-
- template<typename T>
- class PhysfsListHolder
- {
- public:
- PhysfsListHolder(T List) : m_List(List) {};
- ~PhysfsListHolder() { if (m_List) PHYSFS_freeList(m_List); }
-
- T Get() { return m_List; }
-
- private:
- T m_List;
- };
-
- // -------------------------------------------------------------------------
-
- PHYSFS_File * OpenFileAndGetSize(const std::string & FileName, const std::string & CurrentDirectory, unsigned int & FileSize)
- {
- // Datei öffnen.
- PhysfsHandleHolder Handle(PHYSFS_openRead(NormalizePath(FileName, CurrentDirectory).c_str()));
- if (!Handle.Get())
- {
- LogPhysfsError("PHYSFS_openRead", FileName.c_str());
- return 0;
- }
-
- // Dateigröße bestimmen.
- PHYSFS_sint64 LongFileSize = PHYSFS_fileLength(Handle.Get());
- if (LongFileSize == -1)
- {
- BS_LOG_ERRORLN("Unable to determine filelength on PhysicsFS file \"%s\".", FileName.c_str());
- return 0;
- }
- if (LongFileSize >= UINT_MAX)
- {
- BS_LOG_ERRORLN("File \"%s\" is too big.", FileName.c_str());
- return 0;
- }
-
- // Rückgabewerte setzen.
- FileSize = static_cast<unsigned int>(LongFileSize);
- return Handle.Release();
- }
-}
-
-// -----------------------------------------------------------------------------
-// Konstruktion / Destruktion
-// -----------------------------------------------------------------------------
-
-BS_PhysfsPackageManager::BS_PhysfsPackageManager(BS_Kernel * KernelPtr) :
- BS_PackageManager(KernelPtr),
- m_CurrentDirectory(1, PATH_SEPARATOR)
-{
- if (!PHYSFS_init(0)) LogPhysfsError("PHYSFS_init");
-}
-
-// -----------------------------------------------------------------------------
-
-BS_PhysfsPackageManager::~BS_PhysfsPackageManager()
-{
- if (!PHYSFS_deinit()) LogPhysfsError("PHYSFS_deinit");
-}
-
-// -----------------------------------------------------------------------------
-
-BS_Service * BS_PhysfsPackageManager_CreateObject(BS_Kernel * KernelPtr) { return new BS_PhysfsPackageManager(KernelPtr); }
-
-// -----------------------------------------------------------------------------
-
-bool BS_PhysfsPackageManager::LoadPackage(const std::string & FileName, const std::string & MountPosition)
-{
- if (!PHYSFS_mount(FileName.c_str(), NormalizePath(MountPosition, m_CurrentDirectory).c_str(), 0))
- {
- BS_LOG_ERRORLN("Unable to mount file \"%s\" to \"%s\". Reason: %s.", FileName.c_str(), MountPosition.c_str(), SafeGetLastError());
- return false;
- }
- else
- {
- BS_LOGLN("Package '%s' mounted as '%s'.", FileName.c_str(), MountPosition.c_str());
- return true;
- }
-}
-
-// -----------------------------------------------------------------------------
-
-bool BS_PhysfsPackageManager::LoadDirectoryAsPackage(const std::string & DirectoryName, const std::string & MountPosition)
-{
- if (!PHYSFS_mount(DirectoryName.c_str(), NormalizePath(MountPosition, m_CurrentDirectory).c_str(), 0))
- {
- BS_LOG_ERRORLN("Unable to mount directory \"%s\" to \"%s\". Reason: %s.", DirectoryName.c_str(), MountPosition.c_str(), SafeGetLastError());
- return false;
- }
- else
- {
- BS_LOGLN("Directory '%s' mounted as '%s'.", DirectoryName.c_str(), MountPosition.c_str());
- return true;
- }
-}
-
-// -----------------------------------------------------------------------------
-
-void * BS_PhysfsPackageManager::GetFile(const std::string & FileName, unsigned int * FileSizePtr)
-{
- // Datei öffnen und deren Größe bestimmen.
- unsigned int FileSize;
- PhysfsHandleHolder Handle(OpenFileAndGetSize(FileName, m_CurrentDirectory, FileSize));
- if (!Handle.Get()) return 0;
-
- // Falls gewünscht, die Größe der Datei zurückgeben.
- if (FileSizePtr) *FileSizePtr = FileSize;
-
- // Datei einlesen.
- char * Buffer = new char[FileSize];
- if (PHYSFS_read(Handle.Get(), Buffer, 1, FileSize) <= 0)
- {
- LogPhysfsError("PHYSFS_read", FileName.c_str());
- delete [] Buffer;
- return 0;
- }
-
- return Buffer;
-}
-
-// -----------------------------------------------------------------------------
-
-std::string BS_PhysfsPackageManager::GetCurrentDirectory()
-{
- return m_CurrentDirectory;
-}
-
-// -----------------------------------------------------------------------------
-
-bool BS_PhysfsPackageManager::ChangeDirectory(const std::string & Directory)
-{
- // Pfad normalisieren.
- std::string CleanedDirectory = NormalizePath(Directory, m_CurrentDirectory);
-
- // Interne Variable setzen, wenn das Verzeichnis tatsächlich existiert oder das Wurzelverzeichnis ist.
- if (CleanedDirectory == std::string(1, PATH_SEPARATOR) || PHYSFS_isDirectory(CleanedDirectory.c_str()))
- {
- m_CurrentDirectory = CleanedDirectory;
- return true;
- }
- // Fehler ausgeben, wenn das Verzeichnis nicht existiert.
- else
- {
- BS_LOG_ERRORLN("Tried to change to non-existing directory \"%s\". Call is ignored", Directory.c_str());
- return false;
- }
-}
-
-// -----------------------------------------------------------------------------
-
-std::string BS_PhysfsPackageManager::GetAbsolutePath(const std::string & FileName)
-{
- return NormalizePath(FileName, m_CurrentDirectory);
-}
-
-// -----------------------------------------------------------------------------
-
-unsigned int BS_PhysfsPackageManager::GetFileSize(const std::string & FileName)
-{
- // Datei öffnen und deren Größe bestimmen.
- unsigned int FileSize;
- PhysfsHandleHolder Handle(OpenFileAndGetSize(FileName, m_CurrentDirectory, FileSize));
- if (!Handle.Get()) return 0xffffffff;
-
- // Größe der Datei zurückgeben.
- return FileSize;
-}
-
-// -----------------------------------------------------------------------------
-
-unsigned int BS_PhysfsPackageManager::GetFileType(const std::string & FileName)
-{
- std::string NormalizedPath = NormalizePath(FileName, m_CurrentDirectory);
-
- if (PHYSFS_exists(NormalizedPath.c_str()))
- {
- return PHYSFS_isDirectory(NormalizedPath.c_str()) ? BS_PackageManager::FT_DIRECTORY : BS_PackageManager::FT_FILE;
- }
- else
- {
- BS_LOG_ERRORLN("Cannot determine type of non-existant file \"%s\".", NormalizedPath.c_str());
- return 0;
- }
-}
-
-// -----------------------------------------------------------------------------
-
-bool BS_PhysfsPackageManager::FileExists(const std::string & FileName)
-{
- std::string NormalizedPath = NormalizePath(FileName, m_CurrentDirectory);
- return PHYSFS_exists(NormalizedPath.c_str()) != 0;
-}
-
-// -----------------------------------------------------------------------------
-// Dateien suchen
-// -----------------------------------------------------------------------------
-
-class PhysfsFileSearch : public BS_PackageManager::FileSearch
-{
-public:
- // Path muss normalisiert sein.
- PhysfsFileSearch(BS_PackageManager & PackageManager, const vector<std::string> & FoundFiles) :
- m_PackageManager(PackageManager),
- m_FoundFiles(FoundFiles),
- m_FoundFilesIt(m_FoundFiles.begin())
- {
- }
-
- virtual std::string GetCurFileName()
- {
- return *m_FoundFilesIt;
- }
-
- virtual unsigned int GetCurFileType()
- {
- return m_PackageManager.GetFileType(*m_FoundFilesIt);
- }
-
- virtual unsigned int GetCurFileSize()
- {
- return m_PackageManager.GetFileSize(*m_FoundFilesIt);
- }
-
- virtual bool NextFile()
- {
- ++m_FoundFilesIt;
- return m_FoundFilesIt != m_FoundFiles.end();
- }
-
- BS_PackageManager & m_PackageManager;
- vector<std::string> m_FoundFiles;
- vector<std::string>::const_iterator m_FoundFilesIt;
-};
-
-// -----------------------------------------------------------------------------
-
-BS_PackageManager::FileSearch * BS_PhysfsPackageManager::CreateSearch(const std::string& Filter, const std::string& Path, unsigned int TypeFilter)
-{
- std::string NormalizedPath = NormalizePath(Path, m_CurrentDirectory);
-
- // Nach Wildcards gefilterte Ergebnisliste erstellen.
- PhysfsListHolder<char **> FilesPtr(PHYSFSEXT_enumerateFilesWildcard(NormalizedPath.c_str(), Filter.c_str(), 1));
-
- // Diese Liste muss nun wiederum nach den gewünschten Dateitype gefiltert werden. Das Ergebnis wird in einem vector gespeichert, der dann
- // einem PhysfsFileSearch-Objekt übergeben wird.
- vector<std::string> FoundFiles;
- for (char ** CurFilePtr = FilesPtr.Get(); *CurFilePtr != 0; ++CurFilePtr)
- {
- // Vollständigen Pfad zur gefunden Datei konstruieren.
- std::string FullFilePath = NormalizedPath + std::string(1, PATH_SEPARATOR) + *CurFilePtr;
-
- // Feststellen, ob der Dateityp erwünscht ist und nur dann den Dateinamen dem Ergebnisvektor hinzufügen.
- unsigned int FileType = GetFileType(FullFilePath);
- if (FileType & TypeFilter) FoundFiles.push_back(FullFilePath);
- }
-
- // Falls überhaupt eine Datei gefunden wurde, wird ein FileSearch-Objekt zurückgegeben mit dem über die gefundenen Dateien iteriert werden kann.
- // Anderenfalls wird 0 zurückgegeben.
- if (FoundFiles.size())
- {
- return new PhysfsFileSearch(*this, FoundFiles);
- }
- else
- {
- return 0;
- }
-}
diff --git a/engines/sword25/package/physfspackagemanager.h b/engines/sword25/package/physfspackagemanager.h
deleted file mode 100644
index 121b99f44d..0000000000
--- a/engines/sword25/package/physfspackagemanager.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-/*
- * This code is based on Broken Sword 2.5 engine
- *
- * Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdoerfer
- *
- * Licensed under GNU GPL v2
- *
- */
-
-#ifndef SWORD25_PHYSFS_PACKAGE_MANAGER_H
-#define SWORD25_PHYSFS_PACKAGE_MANAGER_H
-
-// -----------------------------------------------------------------------------
-// Includes
-// -----------------------------------------------------------------------------
-
-#include "sword25/kernel/common.h"
-#include "sword25/package/packagemanager.h"
-
-// -----------------------------------------------------------------------------
-// Forward declarations
-// -----------------------------------------------------------------------------
-
-class BS_Kernel;
-
-// -----------------------------------------------------------------------------
-// Klassendefinition
-// -----------------------------------------------------------------------------
-
-class BS_PhysfsPackageManager : public BS_PackageManager
-{
-public:
- BS_PhysfsPackageManager(BS_Kernel * KernelPtr);
- virtual ~BS_PhysfsPackageManager();
-
- virtual bool LoadPackage(const std::string & FileName, const std::string& MountPosition);
- virtual bool LoadDirectoryAsPackage(const std::string & DirectoryName, const std::string& MountPosition);
- virtual void* GetFile(const std::string& FileName, unsigned int * FileSizePtr = 0);
- virtual std::string GetCurrentDirectory();
- virtual bool ChangeDirectory(const std::string & Directory);
- virtual std::string GetAbsolutePath(const std::string & FileName);
- virtual FileSearch* CreateSearch(const std::string & Filter, const std::string& Path, unsigned int TypeFilter = FT_DIRECTORY | FT_FILE);
- virtual unsigned int GetFileSize(const std::string & FileName);
- virtual unsigned int GetFileType(const std::string & FileName);
- virtual bool FileExists(const std::string & FileName);
-
-private:
- std::string m_CurrentDirectory;
-};
-
-#endif
diff --git a/engines/sword25/package/scummvmpackagemanager.cpp b/engines/sword25/package/scummvmpackagemanager.cpp
new file mode 100644
index 0000000000..fa2001dbed
--- /dev/null
+++ b/engines/sword25/package/scummvmpackagemanager.cpp
@@ -0,0 +1,367 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+// -----------------------------------------------------------------------------
+// Includes
+// -----------------------------------------------------------------------------
+
+#include "common/archive.h"
+#include "common/config-manager.h"
+#include "common/str-array.h"
+#include "common/unzip.h"
+#include "sword25/package/scummvmpackagemanager.h"
+
+// -----------------------------------------------------------------------------
+
+#define BS_LOG_PREFIX "SCUMMVMPACKAGEMANAGER"
+
+namespace Sword25 {
+
+const char PATH_SEPARATOR = '/';
+const char NAVIGATION_CHARACTER = '.';
+
+// -----------------------------------------------------------------------------
+// Support functions and classes
+// -----------------------------------------------------------------------------
+
+static Common::String RemoveRedundantPathSeparators(const Common::String &Path) {
+ Common::String Result;
+
+ // Iterate over all the chracters of the input path
+ Common::String::const_iterator It = Path.begin();
+ while (It != Path.end()) {
+ if (*It == PATH_SEPARATOR) {
+ // Directory separater found
+
+ // Skip over directory separator(s)
+ while (It != Path.end() && *It == PATH_SEPARATOR) ++It;
+
+ // Unless it's the end of the path, add the separator
+ if (It != Path.end()) Result += PATH_SEPARATOR;
+ } else {
+ // Normal characters are copied over unchanged
+ Result += *It;
+ ++It;
+ }
+ }
+
+ return Result;
+}
+
+// ---------------------------------------------------------------------
+
+static PathElementArray SeparatePath(const Common::String &Path, const Common::String &CurrentDirectory) {
+ // Determine whether the path is absolute (begins with /) or relative, in which case it's added
+ // to the current directory
+ Common::String wholePath = (Path.size() >= 1 && Path[0] == PATH_SEPARATOR) ? "" : CurrentDirectory + PATH_SEPARATOR;
+
+ // Add in the provided path
+ wholePath += RemoveRedundantPathSeparators(Path);
+
+ // Parse the path and divide into it's components. This ensures that occurences of ".." and "."
+ // are handled correctly.
+ PathElementArray pathElements;
+ size_t separatorPos = 0;
+ while (separatorPos < wholePath.size()) {
+ // Find next directory separator
+ const char *p = strchr(wholePath.c_str() + separatorPos + 1, PATH_SEPARATOR);
+ size_t nextseparatorPos = (p == NULL) ? wholePath.size() : p - wholePath.c_str();
+
+ // Calculate the beginning and end of the path element
+ Common::String::const_iterator elementBegin = wholePath.begin() + separatorPos + 1;
+ Common::String::const_iterator elementEnd = wholePath.begin() + nextseparatorPos;
+
+ if (elementEnd - elementBegin == 2 &&
+ elementBegin[0] == NAVIGATION_CHARACTER &&
+ elementBegin[1] == NAVIGATION_CHARACTER) {
+ // element is "..", therefore the previous path element should be removed
+ if (pathElements.size()) pathElements.pop_back();
+ } else if (elementEnd - elementBegin == 1 &&
+ elementBegin[0] == NAVIGATION_CHARACTER) {
+ // element is ".", so we do nothing
+ } else {
+ // Normal elements get added to the list
+ pathElements.push_back(PathElement(wholePath.begin() + separatorPos + 1, wholePath.begin() + nextseparatorPos));
+ }
+
+ separatorPos = nextseparatorPos;
+ }
+
+ return pathElements;
+}
+
+static Common::String NormalizePath(const Common::String &Path, const Common::String &CurrentDirectory) {
+ // Get the path elements for the file
+ PathElementArray pathElements = SeparatePath(Path, CurrentDirectory);
+
+ if (pathElements.size()) {
+ // The individual path elements are fitted together, separated by a directory
+ // separator. The resulting string is returned as a result
+ Common::String Result;
+
+ PathElementArray::const_iterator It = pathElements.begin();
+ while (It != pathElements.end()) {
+ Result += PATH_SEPARATOR;
+ Result += Common::String(It->GetBegin(), It->GetEnd());
+ ++It;
+ }
+
+ return Result;
+ } else {
+ // The path list has no elements, therefore the root directory is returned
+ return Common::String(PATH_SEPARATOR);
+ }
+}
+
+// -----------------------------------------------------------------------------
+// Constructor / Destructor
+// -----------------------------------------------------------------------------
+
+BS_ScummVMPackageManager::BS_ScummVMPackageManager(BS_Kernel *KernelPtr) :
+ BS_PackageManager(KernelPtr),
+ _currentDirectory(PATH_SEPARATOR),
+ _rootFolder(ConfMan.get("path")) {
+}
+
+// -----------------------------------------------------------------------------
+
+BS_ScummVMPackageManager::~BS_ScummVMPackageManager() {
+}
+
+// -----------------------------------------------------------------------------
+
+BS_Service *BS_ScummVMPackageManager_CreateObject(BS_Kernel *KernelPtr) {
+ return new BS_ScummVMPackageManager(KernelPtr);
+}
+
+// -----------------------------------------------------------------------------
+
+/**
+ * Scans through the archive list for a specified file
+ */
+Common::FSNode BS_ScummVMPackageManager::GetFSNode(const Common::String &FileName) {
+ // Get the path elements for the file
+ PathElementArray pathElements = SeparatePath(FileName, _currentDirectory);
+
+ // Loop through checking each archive
+ Common::List<ArchiveEntry>::iterator i;
+ for (i = _archiveList.begin(); i != _archiveList.end(); ++i) {
+ if (i->MountPath.size() > pathElements.size())
+ // The mount path has more subfolder depth than the search entry, so skip it
+ continue;
+
+ // Check the path against that of the archive
+ PathElementArray::iterator iPath = pathElements.begin();
+ PathElementArray::iterator iEntry = i->MountPath.begin();
+
+ for (; iEntry != i->MountPath.end(); ++iEntry, ++iPath) {
+ if (Common::String(iPath->GetBegin(), iPath->GetEnd()) ==
+ Common::String(iEntry->GetBegin(), iEntry->GetEnd()))
+ break;
+ }
+
+ if (iEntry == i->MountPath.end()) {
+ // Look into the archive for the desired file
+// Common::Archive *archiveFolder = i->Archive;
+
+ // TODO: Loop through any folders in the archive
+ for (; iPath != pathElements.end(); ++iPath) {
+
+ }
+
+ // Return the found node
+ return Common::FSNode();
+ }
+ }
+
+ return Common::FSNode();
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_ScummVMPackageManager::LoadPackage(const Common::String &FileName, const Common::String &MountPosition) {
+ // Get the path elements for the file
+ PathElementArray pathElements = SeparatePath(MountPosition, _currentDirectory);
+
+ Common::Archive *zipFile = Common::makeZipArchive(FileName);
+ if (zipFile == NULL) {
+ BS_LOG_ERRORLN("Unable to mount file \"%s\" to \"%s\"", FileName.c_str(), MountPosition.c_str());
+ return false;
+ } else {
+ BS_LOGLN("Package '%s' mounted as '%s'.", FileName.c_str(), MountPosition.c_str());
+ _archiveList.push_back(ArchiveEntry(zipFile, pathElements));
+ return true;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_ScummVMPackageManager::LoadDirectoryAsPackage(const Common::String &DirectoryName, const Common::String &MountPosition) {
+ // Get the path elements for the file
+ PathElementArray pathElements = SeparatePath(MountPosition, _currentDirectory);
+
+ Common::FSNode directory(DirectoryName);
+ Common::Archive *folderArchive = new Common::FSDirectory(directory);
+ if (!directory.exists() || (folderArchive == NULL)) {
+ BS_LOG_ERRORLN("Unable to mount directory \"%s\" to \"%s\".", DirectoryName.c_str(), MountPosition.c_str());
+ return false;
+ } else {
+ BS_LOGLN("Directory '%s' mounted as '%s'.", DirectoryName.c_str(), MountPosition.c_str());
+ _archiveList.push_front(ArchiveEntry(folderArchive, pathElements));
+ return true;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void *BS_ScummVMPackageManager::GetFile(const Common::String &FileName, unsigned int *FileSizePtr) {
+ Common::File f;
+ Common::FSNode fileNode = GetFSNode(FileName);
+ if (!fileNode.exists()) return 0;
+ if (!f.open(fileNode)) return 0;
+
+ // If the filesize is desired, then output the size
+ if (FileSizePtr) *FileSizePtr = f.size();
+
+ // Read the file
+ byte *buffer = new byte[f.size()];
+ if (!f.read(buffer, f.size())) return 0;
+
+ f.close();
+ return buffer;
+}
+
+// -----------------------------------------------------------------------------
+
+Common::String BS_ScummVMPackageManager::GetCurrentDirectory() {
+ return _currentDirectory;
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_ScummVMPackageManager::ChangeDirectory(const Common::String &Directory) {
+ // Get the path elements for the file
+ _currentDirectory = NormalizePath(Directory, _currentDirectory);
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+
+Common::String BS_ScummVMPackageManager::GetAbsolutePath(const Common::String &FileName) {
+ return NormalizePath(FileName, _currentDirectory);
+}
+
+// -----------------------------------------------------------------------------
+
+unsigned int BS_ScummVMPackageManager::GetFileSize(const Common::String &FileName) {
+ Common::File f;
+ Common::FSNode fileNode = GetFSNode(FileName);
+ if (!fileNode.exists()) return 0;
+ if (!f.open(fileNode)) return 0;
+
+ uint32 fileSize = f.size();
+ f.close();
+ return fileSize;
+}
+
+// -----------------------------------------------------------------------------
+
+unsigned int BS_ScummVMPackageManager::GetFileType(const Common::String &FileName) {
+ Common::File f;
+ Common::FSNode fileNode = GetFSNode(FileName);
+ if (!fileNode.exists()) return 0;
+
+ return fileNode.isDirectory() ? BS_PackageManager::FT_DIRECTORY : BS_PackageManager::FT_FILE;
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_ScummVMPackageManager::FileExists(const Common::String &FileName) {
+ Common::FSNode fileNode = GetFSNode(FileName);
+ return fileNode.exists();
+}
+
+// -----------------------------------------------------------------------------
+// File find
+// -----------------------------------------------------------------------------
+
+class ArchiveFileSearch : public BS_PackageManager::FileSearch {
+public:
+ // Path must be normalised
+ ArchiveFileSearch(BS_PackageManager &PackageManager, const Common::StringArray &FoundFiles) :
+ _packageManager(PackageManager),
+ _foundFiles(FoundFiles),
+ _foundFilesIt(_foundFiles.begin()) {
+ }
+
+ virtual Common::String GetCurFileName() {
+ return *_foundFilesIt;
+ }
+
+ virtual unsigned int GetCurFileType() {
+ return _packageManager.GetFileType(*_foundFilesIt);
+ }
+
+ virtual unsigned int GetCurFileSize() {
+ return _packageManager.GetFileSize(*_foundFilesIt);
+ }
+
+ virtual bool NextFile() {
+ ++_foundFilesIt;
+ return _foundFilesIt != _foundFiles.end();
+ }
+
+ BS_PackageManager & _packageManager;
+ Common::StringArray _foundFiles;
+ Common::StringArray::const_iterator _foundFilesIt;
+};
+
+// -----------------------------------------------------------------------------
+
+BS_PackageManager::FileSearch *BS_ScummVMPackageManager::CreateSearch(
+ const Common::String &Filter, const Common::String &Path, unsigned int TypeFilter) {
+ Common::String NormalizedPath = NormalizePath(Path, _currentDirectory);
+
+ Common::FSNode folderNode = GetFSNode(Path);
+ if (!folderNode.exists() || !folderNode.isDirectory()) return NULL;
+
+ Common::Archive *folder = new Common::FSDirectory(folderNode);
+ Common::ArchiveMemberList memberList;
+
+ if (folder->listMatchingMembers(memberList, Filter) == 0)
+ return NULL;
+
+ // Create a list of the matching names
+ Common::StringArray nameList;
+ for (Common::ArchiveMemberList::iterator i = memberList.begin(); i != memberList.end(); ++i) {
+ nameList.push_back((*i)->getName());
+ }
+
+ // Return a ArchiveFileSearch object that encapsulates the name list
+ return new ArchiveFileSearch(*this, nameList);
+}
+
+} // End of namespace Sword25
+
diff --git a/engines/sword25/package/scummvmpackagemanager.h b/engines/sword25/package/scummvmpackagemanager.h
new file mode 100644
index 0000000000..d279b7e8ad
--- /dev/null
+++ b/engines/sword25/package/scummvmpackagemanager.h
@@ -0,0 +1,105 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef SWORD25_SCUMMVM_PACKAGE_MANAGER_H
+#define SWORD25_SCUMMVM_PACKAGE_MANAGER_H
+
+// -----------------------------------------------------------------------------
+// Includes
+// -----------------------------------------------------------------------------
+
+#include "common/archive.h"
+#include "common/array.h"
+#include "common/fs.h"
+#include "common/str.h"
+#include "sword25/kernel/common.h"
+#include "sword25/package/packagemanager.h"
+
+namespace Sword25 {
+
+// -----------------------------------------------------------------------------
+// Forward declarations
+// -----------------------------------------------------------------------------
+
+class BS_Kernel;
+
+// -----------------------------------------------------------------------------
+// Class definitions
+// -----------------------------------------------------------------------------
+
+struct PathElement {
+public:
+ PathElement() { }
+ PathElement(Common::String::const_iterator Begin, Common::String::const_iterator End) : m_Begin(Begin), m_End(End) {}
+
+ Common::String::const_iterator GetBegin() const { return m_Begin; }
+ Common::String::const_iterator GetEnd() const { return m_End; }
+
+private:
+ Common::String::const_iterator m_Begin;
+ Common::String::const_iterator m_End;
+};
+
+typedef Common::Array<PathElement> PathElementArray;
+
+class BS_ScummVMPackageManager : public BS_PackageManager {
+private:
+ class ArchiveEntry {
+ public:
+ Common::Archive *Archive;
+ PathElementArray MountPath;
+
+ ArchiveEntry(Common::Archive *Archive_, const PathElementArray &MountPath_):
+ Archive(Archive_), MountPath(MountPath_) {
+ }
+ ~ArchiveEntry() {
+ delete Archive;
+ }
+ };
+
+ Common::String _currentDirectory;
+ Common::FSNode _rootFolder;
+ Common::List<ArchiveEntry> _archiveList;
+
+ Common::FSNode GetFSNode(const Common::String &FileName);
+public:
+ BS_ScummVMPackageManager(BS_Kernel * KernelPtr);
+ virtual ~BS_ScummVMPackageManager();
+
+ virtual bool LoadPackage(const Common::String &FileName, const Common::String &MountPosition);
+ virtual bool LoadDirectoryAsPackage(const Common::String &DirectoryName, const Common::String &MountPosition);
+ virtual void *GetFile(const Common::String &FileName, unsigned int *FileSizePtr = 0);
+ virtual Common::String GetCurrentDirectory();
+ virtual bool ChangeDirectory(const Common::String &Directory);
+ virtual Common::String GetAbsolutePath(const Common::String &FileName);
+ virtual FileSearch *CreateSearch(const Common::String &Filter, const Common::String &Path, unsigned int TypeFilter = FT_DIRECTORY | FT_FILE);
+ virtual unsigned int GetFileSize(const Common::String &FileName);
+ virtual unsigned int GetFileType(const Common::String &FileName);
+ virtual bool FileExists(const Common::String &FileName);
+};
+
+} // End of namespace Sword25
+
+#endif