diff options
author | Johannes Schickel | 2010-10-13 03:57:44 +0000 |
---|---|---|
committer | Johannes Schickel | 2010-10-13 03:57:44 +0000 |
commit | 75e8452b6e6a2bf4fb2f588aa00b428a60d873b5 (patch) | |
tree | f29541d55309487a94bd1d38e8b53bb3dde9aec6 /engines/sword25/kernel | |
parent | 48ee83b88957dab86bc763e9ef21a70179fa8679 (diff) | |
parent | e9f50882ea5b6beeefa994040be9d3bab6a1f107 (diff) | |
download | scummvm-rg350-75e8452b6e6a2bf4fb2f588aa00b428a60d873b5.tar.gz scummvm-rg350-75e8452b6e6a2bf4fb2f588aa00b428a60d873b5.tar.bz2 scummvm-rg350-75e8452b6e6a2bf4fb2f588aa00b428a60d873b5.zip |
OPENGL: Merged from trunk, from rev 52105 to 53396.
This includes an rather hacky attempt to merge all the recent gp2x backend
changes into the branch. I suppose the gp2x backend and probably all new
backends, i.e. gph, dingux etc., might not compile anymore.
Since I have no way of testing those it would be nice if porters could look
into getting those up to speed in this branch.
svn-id: r53399
Diffstat (limited to 'engines/sword25/kernel')
32 files changed, 5595 insertions, 0 deletions
diff --git a/engines/sword25/kernel/bs_stdint.h b/engines/sword25/kernel/bs_stdint.h new file mode 100644 index 0000000000..c1970bff3e --- /dev/null +++ b/engines/sword25/kernel/bs_stdint.h @@ -0,0 +1,54 @@ +/* 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 + * + */ + +// TODO: Properly replace all game occurances that use these types with proper ScummVM types, and remove this file + +#ifndef SWORD25_STDINT_H +#define SWORD25_STDINT_H + +#include "common/scummsys.h" + +typedef uint8 uint8_t; +typedef uint16 uint16_t; +typedef uint32 uint32_t; +typedef int8 int8_t; +typedef int16 int16_t; +typedef int32 int32_t; + +typedef unsigned long long uint64_t; +typedef signed long long int64_t; +typedef unsigned long long uint64; +typedef signed long long int64; + +#endif diff --git a/engines/sword25/kernel/callbackregistry.cpp b/engines/sword25/kernel/callbackregistry.cpp new file mode 100644 index 0000000000..32b2597334 --- /dev/null +++ b/engines/sword25/kernel/callbackregistry.cpp @@ -0,0 +1,131 @@ +/* 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 + * + */ + +// Alle Callbackfunktionen die von Objekten gerufen werden, die persistiert werden können, müssen hier registriert werden. +// Beim Speichern wird statt des Pointers der Bezeichner gespeichert. Beim Laden wird der Bezeichner wieder in einen Pointer umgewandelt. +// Diese Klasse führt also so etwas ähnliches wie eine Importtabelle für Callback-Funktionen. +// +// Dieses Vorgehen hat mehrere Vorteile: +// 1. Die Speicherstände sind plattformunabhängig. Es werden keine Pointer auf Funktionen gespeichert, sondern nur Namen von Callbackfunktionen. +// Diese können beim Laden über diese Klasse in systemabhängige Pointer umgewandelt werden. +// 2. Speicherstände können auch nach einem Engineupdate weiterhin benutzt werden. Beim Erstellen einer neun Binary verschieben sich häufig die +// Funktionen. Eine Callbackfunktion könnte sich also nach einem Update an einer anderen Stelle befinden als davor. Wenn im Spielstand der +// Pointer gespeichert war, stürtzt das Programm beim Äufrufen dieser Callbackfunktion ab. Durch das Auflösungverfahren wird beim Laden der +// Callbackbezeichner in den neuen Funktionspointer umgewandelt und der Aufruf kann erfolgen. + +// ----------------------------------------------------------------------------- +// Logging +// ----------------------------------------------------------------------------- + +#define BS_LOG_PREFIX "CALLBACKREGISTRY" + +// ----------------------------------------------------------------------------- +// Includes +// ----------------------------------------------------------------------------- + +#include "sword25/kernel/callbackregistry.h" + +namespace Sword25 { + +// ----------------------------------------------------------------------------- + +bool CallbackRegistry::registerCallbackFunction(const Common::String &name, CallbackPtr ptr) { + if (name == "") { + BS_LOG_ERRORLN("The empty string is not allowed as a callback function name."); + return false; + } + + if (findPtrByName(name) != 0) { + BS_LOG_ERRORLN("There is already a callback function with the name \"%s\".", name.c_str()); + return false; + } + if (findNameByPtr(ptr) != "") { + BS_LOG_ERRORLN("There is already a callback function with the pointer 0x%x.", ptr); + return false; + } + + storeCallbackFunction(name, ptr); + + return true; +} + +// ----------------------------------------------------------------------------- + +CallbackPtr CallbackRegistry::resolveCallbackFunction(const Common::String &name) const { + CallbackPtr result = findPtrByName(name); + + if (!result) { + BS_LOG_ERRORLN("There is no callback function with the name \"%s\".", name.c_str()); + } + + return result; +} + +// ----------------------------------------------------------------------------- + +Common::String CallbackRegistry::resolveCallbackPointer(CallbackPtr ptr) const { + const Common::String &result = findNameByPtr(ptr); + + if (result == "") { + BS_LOG_ERRORLN("There is no callback function with the pointer 0x%x.", ptr); + } + + return result; +} + +// ----------------------------------------------------------------------------- + +CallbackPtr CallbackRegistry::findPtrByName(const Common::String &name) const { + // Eintrag in der Map finden und den Pointer zurückgeben. + NameToPtrMap::const_iterator it = _nameToPtrMap.find(name); + return it == _nameToPtrMap.end() ? 0 : it->_value; +} + +// ----------------------------------------------------------------------------- + +Common::String CallbackRegistry::findNameByPtr(CallbackPtr ptr) const { + // Eintrag in der Map finden und den Namen zurückgeben. + PtrToNameMap::const_iterator it = _ptrToNameMap.find(ptr); + return it == _ptrToNameMap.end() ? "" : it->_value; +} + +// ----------------------------------------------------------------------------- + +void CallbackRegistry::storeCallbackFunction(const Common::String &name, CallbackPtr ptr) { + // Callback-Funktion in beide Maps eintragen. + _nameToPtrMap[name] = ptr; + _ptrToNameMap[ptr] = name; +} + +} // End of namespace Sword25 diff --git a/engines/sword25/kernel/callbackregistry.h b/engines/sword25/kernel/callbackregistry.h new file mode 100644 index 0000000000..c5076d22f5 --- /dev/null +++ b/engines/sword25/kernel/callbackregistry.h @@ -0,0 +1,93 @@ +/* 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_CALLBACK_REGISTRY_H +#define SWORD25_CALLBACK_REGISTRY_H + +// ----------------------------------------------------------------------------- +// Includes +// ----------------------------------------------------------------------------- + +#include "common/scummsys.h" +#include "common/str.h" +#include "common/hash-str.h" +#include "common/hashmap.h" +#include "sword25/kernel/bs_stdint.h" +#include "sword25/kernel/common.h" + +namespace Sword25 { + +// ----------------------------------------------------------------------------- +// Klassendeklaration +// ----------------------------------------------------------------------------- + +typedef void (*CallbackPtr)(int command); + +class CallbackRegistry { +public: + static CallbackRegistry &getInstance() { + static CallbackRegistry _instance; + return _instance; + } + + bool registerCallbackFunction(const Common::String &name, CallbackPtr ptr); + CallbackPtr resolveCallbackFunction(const Common::String &name) const; + Common::String resolveCallbackPointer(CallbackPtr ptr) const; + +private: + typedef Common::HashMap<Common::String, CallbackPtr, Common::CaseSensitiveString_Hash, Common::CaseSensitiveString_EqualTo> NameToPtrMap; + NameToPtrMap _nameToPtrMap; + + struct CallbackPtr_EqualTo { + bool operator()(CallbackPtr x, CallbackPtr y) const { + return x == y; + } + }; + struct CallbackPtr_Hash { + uint operator()(CallbackPtr x) const { + return static_cast<uint>((int64)x % ((int64)1 << sizeof(uint))); + } + }; + + typedef Common::HashMap<CallbackPtr, Common::String, CallbackPtr_Hash, CallbackPtr_EqualTo> PtrToNameMap; + PtrToNameMap _ptrToNameMap; + + CallbackPtr findPtrByName(const Common::String &name) const; + Common::String findNameByPtr(CallbackPtr ptr) const; + void storeCallbackFunction(const Common::String &name, CallbackPtr ptr); +}; + +} // End of namespace Sword25 + +#endif diff --git a/engines/sword25/kernel/common.h b/engines/sword25/kernel/common.h new file mode 100644 index 0000000000..7b11fe901f --- /dev/null +++ b/engines/sword25/kernel/common.h @@ -0,0 +1,60 @@ +/* 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 + * + */ + +/* + * common.h + * ----------- + * This file contains functions or macros that are used across the entire project. + * It is therefore extremely important that this header file be referenced in all + * the other header files in the project. + * + * Autor: Malte Thiesen + */ + +#ifndef SWORD25_COMMON_H +#define SWORD25_COMMON_H + +// Global constants +#define DEBUG + +#define BS_ACTIVATE_LOGGING // When defined, logging is activated + +// Engine Includes +#include "sword25/kernel/log.h" + +#include "common/debug.h" + +#define BS_ASSERT(EXP) assert(EXP) + +#endif diff --git a/engines/sword25/kernel/filesystemutil.cpp b/engines/sword25/kernel/filesystemutil.cpp new file mode 100644 index 0000000000..853e6b247f --- /dev/null +++ b/engines/sword25/kernel/filesystemutil.cpp @@ -0,0 +1,152 @@ +/* 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 "common/config-manager.h" +#include "common/fs.h" +#include "common/savefile.h" +#include "common/system.h" +#include "sword25/kernel/filesystemutil.h" +#include "sword25/kernel/persistenceservice.h" + +namespace Sword25 { + +#define BS_LOG_PREFIX "FILESYSTEMUTIL" + +// ----------------------------------------------------------------------------- +// Constants and utility functions +// ----------------------------------------------------------------------------- + +Common::String GetAbsolutePath(const Common::String &Path) { + Common::FSNode node(Path); + + if (!node.exists()) { + // An error has occurred finding the node + // We can do nothing at this pointer than return an empty string + BS_LOG_ERRORLN("A call to GetAbsolutePath failed."); + return ""; + } + + // Return the result + return node.getPath(); +} + +// ----------------------------------------------------------------------------- +// Class definitions +// ----------------------------------------------------------------------------- + +class BS_FileSystemUtilScummVM : public FileSystemUtil { +public: + virtual Common::String GetUserdataDirectory() { + Common::String path = ConfMan.get("savepath"); + + if (path.empty()) { + error("No save path has been defined"); + return ""; + } + + // Return the path + return path; + } + + virtual Common::String GetPathSeparator() { + return Common::String("/"); + } + + virtual int64 GetFileSize(const Common::String &Filename) { + Common::FSNode node(Filename); + + // If the file does not exist, return -1 as a result + if (!node.exists()) + return -1; + + // Get the size of the file and return it + Common::File f; + f.open(node); + uint32 size = f.size(); + f.close(); + + return size; + } + + virtual TimeDate GetFileTime(const Common::String &Filename) { + // TODO: There isn't any way in ScummVM to get a file's modified date/time. We will need to check + // what code makes use of it. If it's only the save game code, for example, we may be able to + // encode the date/time inside the savegame files themselves. + TimeDate result; + g_system->getTimeAndDate(result); + return result; + } + + virtual bool FileExists(const Common::String &Filename) { + Common::File f; + if (f.exists(Filename)) + return true; + + // Check if the file exists in the save folder + Common::FSNode folder(PersistenceService::GetSavegameDirectory()); + Common::FSNode fileNode = folder.getChild(FileSystemUtil::GetInstance().GetPathFilename(Filename)); + return fileNode.exists(); + } + + virtual bool CreateDirectory(const Common::String &DirectoryName) { + // ScummVM doesn't support creating folders, so this is only a stub + BS_LOG_ERRORLN("CreateDirectory method called"); + return false; + } + + virtual Common::String GetPathFilename(const Common::String &Path) { + for (int i = Path.size() - 1; i >= 0; --i) { + if ((Path[i] == '/') || (Path[i] == '\\')) { + return Common::String(&Path.c_str()[i + 1]); + } + } + + return Path; + } +}; + +// ----------------------------------------------------------------------------- +// Singleton method of parent class +// ----------------------------------------------------------------------------- + +FileSystemUtil &FileSystemUtil::GetInstance() { + static BS_FileSystemUtilScummVM Instance; + return Instance; +} + +} // End of namespace Sword25 diff --git a/engines/sword25/kernel/filesystemutil.h b/engines/sword25/kernel/filesystemutil.h new file mode 100644 index 0000000000..43ce7c908e --- /dev/null +++ b/engines/sword25/kernel/filesystemutil.h @@ -0,0 +1,114 @@ +/* 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 + * + */ + +/* + * + * The class BS_FileSystemUtil represents a wrapper for file system specific + * operations that do not have equivalents in the C/C++ libraries. + * + * Each supported platform must implement this interface, and the method + * BS_FileSystemUtil Singleton::getInstance() + */ + +#ifndef SWORD25_FILESYSTEMUTIL_H +#define SWORD25_FILESYSTEMUTIL_H + +// ----------------------------------------------------------------------------- +// Includes +// ----------------------------------------------------------------------------- + +#include "common/system.h" +#include "common/str.h" +#include "common/str-array.h" +#include "sword25/kernel/common.h" +#include "sword25/kernel/bs_stdint.h" + +namespace Sword25 { + +// ----------------------------------------------------------------------------- +// Class definitions +// ----------------------------------------------------------------------------- + +class FileSystemUtil { +public: + static FileSystemUtil &GetInstance(); + virtual ~FileSystemUtil() {}; + + /** + * This function returns the name of the directory in which all user data is to be stored. + * + * These are for example Screenshots, game saves, configuration files, log files, ... + * @return Returns the name of the directory for user data. + */ + virtual Common::String GetUserdataDirectory() = 0; + /** + * @return Returns the path seperator + */ + virtual Common::String GetPathSeparator() = 0; + /** + * @param Filename The path to a file. + * @return Returns the size of the specified file. If the size could not be + * determined, or the file does not exist, returns -1 + */ + virtual int64 GetFileSize(const Common::String &Filename) = 0; + /** + * @param Filename The path to a file. + * @return Returns the timestamp of the specified file. + */ + virtual TimeDate GetFileTime(const Common::String &Filename) = 0; + /** + * @param Filename The path to a file. + * @return Returns true if the file exists. + */ + virtual bool FileExists(const Common::String &Filename) = 0; + /** + * This function creates a directory + * + * If the parameter is "\b\c\d\e" is passed, and "\b\c" already exists, then folder 'd' + * will be created, and subdirectory 'e' under it. + * @param DirectoryName The name of the directory to be created + * @return Returns true if the folder(s) could be created, otherwise false. + */ + virtual bool CreateDirectory(const Common::String &DirectoryName) = 0; + /** + * Gets the filename from a path and filename + * @param Filename The full path and filename + * @return Returns just the filename + */ + virtual Common::String GetPathFilename(const Common::String &Path) = 0; +}; + +} // End of namespace Sword25 + +#endif diff --git a/engines/sword25/kernel/inputpersistenceblock.cpp b/engines/sword25/kernel/inputpersistenceblock.cpp new file mode 100644 index 0000000000..b51b1037a7 --- /dev/null +++ b/engines/sword25/kernel/inputpersistenceblock.cpp @@ -0,0 +1,182 @@ +/* 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 + * + */ + +#define BS_LOG_PREFIX "INPUTPERSISTENCEBLOCK" + +// ----------------------------------------------------------------------------- +// Includes +// ----------------------------------------------------------------------------- + +#include "sword25/kernel/inputpersistenceblock.h" + +namespace Sword25 { + +// ----------------------------------------------------------------------------- +// Constructor / Destructor +// ----------------------------------------------------------------------------- + +InputPersistenceBlock::InputPersistenceBlock(const void *Data, uint DataLength) : + m_Data(static_cast<const byte *>(Data), DataLength), + m_ErrorState(NONE) { + m_Iter = m_Data.begin(); +} + +// ----------------------------------------------------------------------------- + +InputPersistenceBlock::~InputPersistenceBlock() { + if (m_Iter != m_Data.end()) BS_LOG_WARNINGLN("Persistence block was not read to the end."); +} + +// ----------------------------------------------------------------------------- +// Reading +// ----------------------------------------------------------------------------- + +void InputPersistenceBlock::read(int16 &Value) { + signed int v; + read(v); + Value = static_cast<int16>(v); +} + +// ----------------------------------------------------------------------------- + +void InputPersistenceBlock::read(signed int &Value) { + if (CheckMarker(SINT_MARKER)) { + RawRead(&Value, sizeof(signed int)); + Value = ConvertEndianessFromStorageToSystem(Value); + } else { + Value = 0; + } +} + +// ----------------------------------------------------------------------------- + +void InputPersistenceBlock::read(uint &Value) { + if (CheckMarker(UINT_MARKER)) { + RawRead(&Value, sizeof(uint)); + Value = ConvertEndianessFromStorageToSystem(Value); + } else { + Value = 0; + } +} + +// ----------------------------------------------------------------------------- + +void InputPersistenceBlock::read(float &Value) { + if (CheckMarker(FLOAT_MARKER)) { + RawRead(&Value, sizeof(float)); + Value = ConvertEndianessFromStorageToSystem(Value); + } else { + Value = 0.0f; + } +} + +// ----------------------------------------------------------------------------- + +void InputPersistenceBlock::read(bool &Value) { + if (CheckMarker(BOOL_MARKER)) { + uint UIntBool; + RawRead(&UIntBool, sizeof(float)); + UIntBool = ConvertEndianessFromStorageToSystem(UIntBool); + Value = UIntBool == 0 ? false : true; + } else { + Value = 0.0f; + } +} + +// ----------------------------------------------------------------------------- + +void InputPersistenceBlock::read(Common::String &Value) { + Value = ""; + + if (CheckMarker(STRING_MARKER)) { + uint Size; + read(Size); + + if (CheckBlockSize(Size)) { + Value = Common::String(reinterpret_cast<const char *>(&*m_Iter), Size); + m_Iter += Size; + } + } +} + +// ----------------------------------------------------------------------------- + +void InputPersistenceBlock::read(Common::Array<byte> &Value) { + if (CheckMarker(BLOCK_MARKER)) { + uint Size; + read(Size); + + if (CheckBlockSize(Size)) { + Value = Common::Array<byte>(m_Iter, Size); + m_Iter += Size; + } + } +} + +// ----------------------------------------------------------------------------- + +void InputPersistenceBlock::RawRead(void *DestPtr, size_t Size) { + if (CheckBlockSize(Size)) { + memcpy(DestPtr, &*m_Iter, Size); + m_Iter += Size; + } +} + +// ----------------------------------------------------------------------------- + +bool InputPersistenceBlock::CheckBlockSize(int Size) { + if (m_Data.end() - m_Iter >= Size) { + return true; + } else { + m_ErrorState = END_OF_DATA; + BS_LOG_ERRORLN("Unexpected end of persistence block."); + return false; + } +} + +// ----------------------------------------------------------------------------- + +bool InputPersistenceBlock::CheckMarker(byte Marker) { + if (!isGood() || !CheckBlockSize(1)) return false; + + if (*m_Iter++ == Marker) { + return true; + } else { + m_ErrorState = OUT_OF_SYNC; + BS_LOG_ERRORLN("Wrong type marker found in persistence block."); + return false; + } +} + +} // End of namespace Sword25 diff --git a/engines/sword25/kernel/inputpersistenceblock.h b/engines/sword25/kernel/inputpersistenceblock.h new file mode 100644 index 0000000000..a6978e5899 --- /dev/null +++ b/engines/sword25/kernel/inputpersistenceblock.h @@ -0,0 +1,90 @@ +/* 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_INPUTPERSISTENCEBLOCK_H +#define SWORD25_INPUTPERSISTENCEBLOCK_H + +// ----------------------------------------------------------------------------- +// Includes +// ----------------------------------------------------------------------------- + +#include "common/array.h" +#include "sword25/kernel/common.h" +#include "sword25/kernel/persistenceblock.h" + +namespace Sword25 { + +// ----------------------------------------------------------------------------- +// Class declaration +// ----------------------------------------------------------------------------- + +class InputPersistenceBlock : public PersistenceBlock { +public: + enum ErrorState { + NONE, + END_OF_DATA, + OUT_OF_SYNC + }; + + InputPersistenceBlock(const void *Data, uint DataLength); + virtual ~InputPersistenceBlock(); + + void read(int16 &Value); + void read(signed int &Value); + void read(uint &Value); + void read(float &Value); + void read(bool &Value); + void read(Common::String &Value); + void read(Common::Array<byte> &Value); + + bool isGood() const { + return m_ErrorState == NONE; + } + ErrorState GetErrorState() const { + return m_ErrorState; + } + +private: + bool CheckMarker(byte Marker); + bool CheckBlockSize(int Size); + void RawRead(void *DestPtr, size_t Size); + + Common::Array<byte> m_Data; + Common::Array<byte>::const_iterator m_Iter; + ErrorState m_ErrorState; +}; + +} // End of namespace Sword25 + +#endif diff --git a/engines/sword25/kernel/kernel.cpp b/engines/sword25/kernel/kernel.cpp new file mode 100644 index 0000000000..3e7e7f125f --- /dev/null +++ b/engines/sword25/kernel/kernel.cpp @@ -0,0 +1,454 @@ +/* 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 + * + */ + +#include "common/system.h" +#include "sword25/gfx/graphicengine.h" +#include "sword25/fmv/movieplayer.h" +#include "sword25/input/inputengine.h" +#include "sword25/kernel/kernel.h" +#include "sword25/kernel/persistenceservice.h" +#include "sword25/kernel/service_ids.h" +#include "sword25/package/packagemanager.h" +#include "sword25/script/script.h" +#include "sword25/sfx/soundengine.h" + +namespace Sword25 { + +#define BS_LOG_PREFIX "KERNEL" + +Kernel *Kernel::_Instance = 0; + +Kernel::Kernel() : + _pWindow(NULL), + _Running(false), + _pResourceManager(NULL), + _InitSuccess(false) { + + // Log that the kernel is beign created + BS_LOGLN("created."); + + // Read the BS_SERVICE_TABLE and prepare kernel structures + for (uint i = 0; i < BS_SERVICE_COUNT; i++) { + // Is the superclass already registered? + Superclass *pCurSuperclass = NULL; + Common::Array<Superclass *>::iterator Iter; + for (Iter = _SuperclassList.begin(); Iter != _SuperclassList.end(); ++Iter) + if ((*Iter)->GetIdentifier() == BS_SERVICE_TABLE[i].SuperclassIdentifier) { + pCurSuperclass = *Iter; + break; + } + + // If the superclass isn't already registered, then add it in + if (!pCurSuperclass) + _SuperclassList.push_back(new Superclass(this, BS_SERVICE_TABLE[i].SuperclassIdentifier)); + } + + // Create window object + _pWindow = Window::CreateBSWindow(0, 0, 0, 0, false); + if (!_pWindow) { + BS_LOG_ERRORLN("Failed to create the window."); + } else + BS_LOGLN("Window created."); + + // Create the resource manager + _pResourceManager = new ResourceManager(this); + + // Initialise the script engine + ScriptEngine *pScript = static_cast<ScriptEngine *>(NewService("script", "lua")); + if (!pScript || !pScript->init()) { + _InitSuccess = false; + return; + } + + // Register kernel script bindings + if (!_RegisterScriptBindings()) { + BS_LOG_ERRORLN("Script bindings could not be registered."); + _InitSuccess = false; + return; + } + BS_LOGLN("Script bindings registered."); + + _InitSuccess = true; +} + +Kernel::~Kernel() { + // Services are de-registered in reverse order of creation + while (!_ServiceCreationOrder.empty()) { + Superclass *superclass = GetSuperclassByIdentifier(_ServiceCreationOrder.top()); + if (superclass) superclass->DisconnectService(); + _ServiceCreationOrder.pop(); + } + + // Empty the Superclass list + while (_SuperclassList.size()) { + delete _SuperclassList.back(); + _SuperclassList.pop_back(); + } + + // Release the window object + delete _pWindow; + BS_LOGLN("Window destroyed."); + + // Resource-Manager freigeben + delete _pResourceManager; + + BS_LOGLN("destroyed."); +} + +// Service Methoden +// ---------------- + +Kernel::Superclass::Superclass(Kernel *pKernel, const Common::String &Identifier) : + _pKernel(pKernel), + _Identifier(Identifier), + _ServiceCount(0), + _ActiveService(NULL) { + for (uint i = 0; i < BS_SERVICE_COUNT; i++) + if (BS_SERVICE_TABLE[i].SuperclassIdentifier == _Identifier) + _ServiceCount++; +} + +Kernel::Superclass::~Superclass() { + DisconnectService(); +} + +/** + * Gets the identifier of a service with a given superclass. + * The number of services in a superclass can be learned with GetServiceCount(). + * @param SuperclassIdentifier The name of the superclass + * z.B: "sfx", "gfx", "package" ... + * @param Number die Nummer des Services, dessen Bezeichner man erfahren will.<br> + * Hierbei ist zu beachten, dass der erste Service die Nummer 0 erhält. Number muss also eine Zahl zwischen + * 0 und GetServiceCount() - 1 sein. + */ +Common::String Kernel::Superclass::GetServiceIdentifier(uint Number) { + if (Number > _ServiceCount) return NULL; + + uint CurServiceOrd = 0; + for (uint i = 0; i < BS_SERVICE_COUNT; i++) { + if (BS_SERVICE_TABLE[i].SuperclassIdentifier == _Identifier) { + if (Number == CurServiceOrd) + return BS_SERVICE_TABLE[i].ServiceIdentifier; + else + CurServiceOrd++; + } + } + + return Common::String(""); +} + +/** + * Creates a new service with the given identifier. Returns a pointer to the service, or null if the + * service could not be created + * Note: All services must be registered in service_ids.h, otherwise they cannot be created here + * @param SuperclassIdentifier The name of the superclass of the service + * z.B: "sfx", "gfx", "package" ... + * @param ServiceIdentifier The name of the service + * For the superclass "sfx" an example could be "Fmod" or "directsound" + */ +Service *Kernel::Superclass::NewService(const Common::String &ServiceIdentifier) { + for (uint i = 0; i < BS_SERVICE_COUNT; i++) + if (BS_SERVICE_TABLE[i].SuperclassIdentifier == _Identifier && + BS_SERVICE_TABLE[i].ServiceIdentifier == ServiceIdentifier) { + Service *NewService_ = BS_SERVICE_TABLE[i].CreateMethod(_pKernel); + + if (NewService_) { + DisconnectService(); + BS_LOGLN("Service '%s' created from superclass '%s'.", ServiceIdentifier.c_str(), _Identifier.c_str()); + _ActiveService = NewService_; + _ActiveServiceName = BS_SERVICE_TABLE[i].ServiceIdentifier; + return _ActiveService; + } else { + BS_LOG_ERRORLN("Failed to create service '%s' from superclass '%s'.", ServiceIdentifier.c_str(), _Identifier.c_str()); + return NULL; + } + } + + BS_LOG_ERRORLN("Service '%s' is not avaliable from superclass '%s'.", ServiceIdentifier.c_str(), _Identifier.c_str()); + return NULL; +} + +/** + * Ends the current service of a superclass. Returns true on success, and false if the superclass + * does not exist or if not service was active + * @param SuperclassIdentfier The name of the superclass which is to be disconnected + * z.B: "sfx", "gfx", "package" ... + */ +bool Kernel::Superclass::DisconnectService() { + if (_ActiveService) { + delete _ActiveService; + _ActiveService = 0; + BS_LOGLN("Active service '%s' disconnected from superclass '%s'.", _ActiveServiceName.c_str(), _Identifier.c_str()); + return true; + } + + return false; +} + +Kernel::Superclass *Kernel::GetSuperclassByIdentifier(const Common::String &Identifier) { + Common::Array<Superclass *>::iterator Iter; + for (Iter = _SuperclassList.begin(); Iter != _SuperclassList.end(); ++Iter) { + if ((*Iter)->GetIdentifier() == Identifier) + return *Iter; + } + + // BS_LOG_ERRORLN("Superclass '%s' does not exist.", Identifier.c_str()); + return NULL; +} + +/** + * Returns the number of register superclasses + */ +uint Kernel::GetSuperclassCount() { + return _SuperclassList.size(); +} + +/** + * Returns the name of a superclass with the specified index. + * Note: The number of superclasses can be retrieved using GetSuperclassCount + * @param Number The number of the superclass to return the identifier for. + * It should be noted that the number should be between 0 und GetSuperclassCount() - 1. + */ +Common::String Kernel::GetSuperclassIdentifier(uint Number) { + if (Number > _SuperclassList.size()) return NULL; + + uint CurSuperclassOrd = 0; + Common::Array<Superclass *>::iterator Iter; + for (Iter = _SuperclassList.begin(); Iter != _SuperclassList.end(); ++Iter) { + if (CurSuperclassOrd == Number) + return ((*Iter)->GetIdentifier()); + + CurSuperclassOrd++; + } + + return Common::String(""); +} + +/** + * Returns the number of services registered with a given superclass + * @param SuperclassIdentifier The name of the superclass + * z.B: "sfx", "gfx", "package" ... + */ +uint Kernel::GetServiceCount(const Common::String &SuperclassIdentifier) { + Superclass *pSuperclass; + if (!(pSuperclass = GetSuperclassByIdentifier(SuperclassIdentifier))) + return 0; + + return pSuperclass->GetServiceCount(); + +} + +/** + * Gets the identifier of a service with a given superclass. + * The number of services in a superclass can be learned with GetServiceCount(). + * @param SuperclassIdentifier The name of the superclass + * z.B: "sfx", "gfx", "package" ... + * @param Number die Nummer des Services, dessen Bezeichner man erfahren will.<br> + * Hierbei ist zu beachten, dass der erste Service die Nummer 0 erhält. Number muss also eine Zahl zwischen + * 0 und GetServiceCount() - 1 sein. + */ +Common::String Kernel::GetServiceIdentifier(const Common::String &SuperclassIdentifier, uint Number) { + Superclass *pSuperclass; + if (!(pSuperclass = GetSuperclassByIdentifier(SuperclassIdentifier))) return NULL; + + return (pSuperclass->GetServiceIdentifier(Number)); +} + +/** + * Creates a new service with the given identifier. Returns a pointer to the service, or null if the + * service could not be created + * Note: All services must be registered in service_ids.h, otherwise they cannot be created here + * @param SuperclassIdentifier The name of the superclass of the service + * z.B: "sfx", "gfx", "package" ... + * @param ServiceIdentifier The name of the service + * For the superclass "sfx" an example could be "Fmod" or "directsound" + */ +Service *Kernel::NewService(const Common::String &SuperclassIdentifier, const Common::String &ServiceIdentifier) { + Superclass *pSuperclass; + if (!(pSuperclass = GetSuperclassByIdentifier(SuperclassIdentifier))) return NULL; + + // Die Reihenfolge merken, in der Services erstellt werden, damit sie später in umgekehrter Reihenfolge entladen werden können. + _ServiceCreationOrder.push(SuperclassIdentifier); + + return pSuperclass->NewService(ServiceIdentifier); +} + +/** + * Ends the current service of a superclass. Returns true on success, and false if the superclass + * does not exist or if not service was active + * @param SuperclassIdentfier The name of the superclass which is to be disconnected + * z.B: "sfx", "gfx", "package" ... + */ +bool Kernel::DisconnectService(const Common::String &SuperclassIdentifier) { + Superclass *pSuperclass; + if (!(pSuperclass = GetSuperclassByIdentifier(SuperclassIdentifier))) return false; + + return pSuperclass->DisconnectService(); +} + +/** + * Returns a pointer to the currently active service object of a superclass + * @param SuperclassIdentfier The name of the superclass + * z.B: "sfx", "gfx", "package" ... + */ +Service *Kernel::GetService(const Common::String &SuperclassIdentifier) { + Superclass *pSuperclass; + if (!(pSuperclass = GetSuperclassByIdentifier(SuperclassIdentifier))) return NULL; + + return (pSuperclass->GetActiveService()); +} + +/** + * Returns the name of the currentl active service object of a superclass. + * If an error occurs, then an empty string is returned + * @param SuperclassIdentfier The name of the superclass + * z.B: "sfx", "gfx", "package" ... + */ +Common::String Kernel::GetActiveServiceIdentifier(const Common::String &SuperclassIdentifier) { + Superclass *pSuperclass = GetSuperclassByIdentifier(SuperclassIdentifier); + if (!pSuperclass) return Common::String(""); + + return (pSuperclass->GetActiveServiceName()); +} + +// ----------------------------------------------------------------------------- + +/** + * Returns a random number + * @param Min The minimum allowed value + * @param Max The maximum allowed value + */ +int Kernel::GetRandomNumber(int Min, int Max) { + BS_ASSERT(Min <= Max); + + return Min + _rnd.getRandomNumber(Max - Min + 1); +} + +/** + * Returns the elapsed time since startup in milliseconds + */ +uint Kernel::GetMilliTicks() { + return g_system->getMillis(); +} + +/** + * Returns the elapsed time since the system start in microseconds. + * This method should be used only if GetMilliTick() for the desired application is inaccurate. + */ +uint64 Kernel::GetMicroTicks() { + return g_system->getMillis() * 1000; +} + +// Other methods +// ----------------- + +/** + * Returns how much memory is being used + */ +size_t Kernel::GetUsedMemory() { + return 0; + +#ifdef SCUMMVM_DISABLED_CODE + PROCESS_MEMORY_COUNTERS pmc; + pmc.cb = sizeof(pmc); + if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) { + return pmc.WorkingSetSize; + } else { + BS_LOG_ERRORLN("Call to GetProcessMemoryInfo() failed. Error code: %d", GetLastError()); + return 0; + } +#endif +} + +// ----------------------------------------------------------------------------- + +/** + * Returns a pointer to the active Gfx Service, or NULL if no Gfx service is active + */ +GraphicEngine *Kernel::GetGfx() { + return static_cast<GraphicEngine *>(GetService("gfx")); +} + +// ----------------------------------------------------------------------------- + +/** + * Returns a pointer to the active Sfx Service, or NULL if no Sfx service is active + */ +SoundEngine *Kernel::GetSfx() { + return static_cast<SoundEngine *>(GetService("sfx")); +} + +// ----------------------------------------------------------------------------- + +/** + * Returns a pointer to the active input service, or NULL if no input service is active + */ +InputEngine *Kernel::GetInput() { + return static_cast<InputEngine *>(GetService("input")); +} + +// ----------------------------------------------------------------------------- + +/** + * Returns a pointer to the active package manager, or NULL if no manager is active + */ +PackageManager *Kernel::GetPackage() { + return static_cast<PackageManager *>(GetService("package")); +} + +// ----------------------------------------------------------------------------- + +/** + * Returns a pointer to the script engine, or NULL if it is not active + */ +ScriptEngine *Kernel::GetScript() { + return static_cast<ScriptEngine *>(GetService("script")); +} + +// ----------------------------------------------------------------------------- + +/** + * Returns a pointer to the movie player, or NULL if it is not active + */ +MoviePlayer *Kernel::GetFMV() { + return static_cast<MoviePlayer *>(GetService("fmv")); +} + +// ----------------------------------------------------------------------------- + +void Kernel::Sleep(uint Msecs) const { + g_system->delayMillis(Msecs); +} + +} // End of namespace Sword25 diff --git a/engines/sword25/kernel/kernel.h b/engines/sword25/kernel/kernel.h new file mode 100644 index 0000000000..55a64c783f --- /dev/null +++ b/engines/sword25/kernel/kernel.h @@ -0,0 +1,370 @@ +/* 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 + * + */ + +/* + * BS_Kernel + * --------- + * This is the main class of the engine. + * This class creates and manages all other Engine elements: the sound engine, graphics engine ... + * It is not necessary to release all the items individually, this is performed by the Kernel class. + * + * Autor: Malte Thiesen + */ + +#ifndef SWORD25_KERNEL_H +#define SWORD25_KERNEL_H + +// Includes +#include "common/scummsys.h" +#include "common/random.h" +#include "common/stack.h" +#include "common/util.h" +#include "engines/engine.h" + +#include "sword25/kernel/common.h" +#include "sword25/kernel/bs_stdint.h" +#include "sword25/kernel/window.h" +#include "sword25/kernel/resmanager.h" + +namespace Sword25 { + +// Class definitions +class Service; +class GraphicEngine; +class ScriptEngine; +class SoundEngine; +class InputEngine; +class PackageManager; +class MoviePlayer; + +/** + * This is the main engine class + * + * This class creates and manages all other engine components such as sound engine, graphics engine ... + * It is not necessary to release all the items individually, this is performed by the Kernel class. +*/ +class Kernel { +public: + // Window methods + // ---------------- + + /** + * Returns a pointer to the window object + */ + Window *GetWindow() { + return _pWindow; + } + + // Service Methods + // --------------- + + /** + * Creates a new service with the given identifier. Returns a pointer to the service, or null if the + * service could not be created + * Note: All services must be registered in service_ids.h, otherwise they cannot be created here + * @param SuperclassIdentifier The name of the superclass of the service + * z.B: "sfx", "gfx", "package" ... + * @param ServiceIdentifier The name of the service + * For the superclass "sfx" an example could be "Fmod" or "directsound" + */ + Service *NewService(const Common::String &SuperclassIdentifier, const Common::String &ServiceIdentifier); + + /** + * Ends the current service of a superclass. Returns true on success, and false if the superclass + * does not exist or if not service was active + * @param SuperclassIdentfier The name of the superclass which is to be disconnected + * z.B: "sfx", "gfx", "package" ... + */ + bool DisconnectService(const Common::String &SuperclassIdentifier); + + /** + * Returns a pointer to the currently active service object of a superclass + * @param SuperclassIdentfier The name of the superclass + * z.B: "sfx", "gfx", "package" ... + */ + Service *GetService(const Common::String &SuperclassIdentifier); + + /** + * Returns the name of the currentl active service object of a superclass. + * If an error occurs, then an empty string is returned + * @param SuperclassIdentfier The name of the superclass + * z.B: "sfx", "gfx", "package" ... + */ + Common::String GetActiveServiceIdentifier(const Common::String &SuperclassIdentifier); + + /** + * Returns the number of register superclasses + */ + uint GetSuperclassCount(); + + /** + * Returns the name of a superclass with the specified index. + * Note: The number of superclasses can be retrieved using GetSuperclassCount + * @param Number The number of the superclass to return the identifier for. + * It should be noted that the number should be between 0 und GetSuperclassCount() - 1. + */ + Common::String GetSuperclassIdentifier(uint Number); + + /** + * Returns the number of services registered with a given superclass + * @param SuperclassIdentifier The name of the superclass + * z.B: "sfx", "gfx", "package" ... + */ + uint GetServiceCount(const Common::String &SuperclassIdentifier); + + /** + * Gets the identifier of a service with a given superclass. + * The number of services in a superclass can be learned with GetServiceCount(). + * @param SuperclassIdentifier The name of the superclass + * z.B: "sfx", "gfx", "package" ... + * @param Number die Nummer des Services, dessen Bezeichner man erfahren will.<br> + * Hierbei ist zu beachten, dass der erste Service die Nummer 0 erhält. Number muss also eine Zahl zwischen + * 0 und GetServiceCount() - 1 sein. + */ + Common::String GetServiceIdentifier(const Common::String &SuperclassIdentifier, uint Number); + + /** + * Returns the elapsed time since startup in milliseconds + */ + uint GetMilliTicks(); + + /** + * Returns the elapsed time since the system start in microseconds. + * This method should be used only if GetMilliTick() for the desired application is inaccurate. + */ + uint64 GetMicroTicks(); + + /** + * Specifies whether the kernel was successfully initialised + */ + bool GetInitSuccess() { + return _InitSuccess; + } + /** + * Returns a pointer to the BS_ResourceManager + */ + ResourceManager *GetResourceManager() { + return _pResourceManager; + } + /** + * Returns how much memory is being used + */ + size_t GetUsedMemory(); + /** + * Returns a random number + * @param Min The minimum allowed value + * @param Max The maximum allowed value + */ + int GetRandomNumber(int Min, int Max); + /** + * Returns a pointer to the active Gfx Service, or NULL if no Gfx service is active + */ + GraphicEngine *GetGfx(); + /** + * Returns a pointer to the active Sfx Service, or NULL if no Sfx service is active + */ + SoundEngine *GetSfx(); + /** + * Returns a pointer to the active input service, or NULL if no input service is active + */ + InputEngine *GetInput(); + /** + * Returns a pointer to the active package manager, or NULL if no manager is active + */ + PackageManager *GetPackage(); + /** + * Returns a pointer to the script engine, or NULL if it is not active + */ + ScriptEngine *GetScript(); + /** + * Returns a pointer to the movie player, or NULL if it is not active + */ + MoviePlayer *GetFMV(); + + /** + * Pauses for the specified amount of time + * @param Msecs The amount of time in milliseconds + */ + void Sleep(uint Msecs) const; + + /** + * Returns the singleton instance for the kernel + */ + static Kernel *GetInstance() { + if (!_Instance) _Instance = new Kernel(); + return _Instance; + } + + /** + * Destroys the kernel instance + * This method should only be called when the game is ended. No subsequent calls to any kernel + * methods should be done after calling this method. + */ + static void DeleteInstance() { + if (_Instance) { + delete _Instance; + _Instance = NULL; + } + } + + /** + * Raises an error. This method is used in crashing testing. + */ + void Crash() const { + error("BS_Kernel::Crash"); + } + +private: + // ----------------------------------------------------------------------------- + // Constructor / destructor + // Private singleton methods + // ----------------------------------------------------------------------------- + + Kernel(); + virtual ~Kernel(); + + // ----------------------------------------------------------------------------- + // Singleton instance + // ----------------------------------------------------------------------------- + static Kernel *_Instance; + + // Superclass class + // ---------------- + class Superclass { + private: + Kernel *_pKernel; + uint _ServiceCount; + Common::String _Identifier; + Service *_ActiveService; + Common::String _ActiveServiceName; + + public: + Superclass(Kernel *pKernel, const Common::String &Identifier); + ~Superclass(); + + uint GetServiceCount() const { + return _ServiceCount; + } + Common::String GetIdentifier() const { + return _Identifier; + } + Service *GetActiveService() const { + return _ActiveService; + } + Common::String GetActiveServiceName() const { + return _ActiveServiceName; + } + Common::String GetServiceIdentifier(uint Number); + Service *NewService(const Common::String &ServiceIdentifier); + bool DisconnectService(); + }; + + Common::Array<Superclass *> _SuperclassList; + Common::Stack<Common::String> _ServiceCreationOrder; + Superclass *GetSuperclassByIdentifier(const Common::String &Identifier); + + bool _InitSuccess; // Specifies whether the engine was set up correctly + bool _Running; // Specifies whether the application should keep running on the next main loop iteration + + // Active window + // ------------- + Window *_pWindow; + + // Random number generator + // ----------------------- + Common::RandomSource _rnd; + + /* + // Features variables and methods + // ---------------------------------- + enum _CPU_FEATURES_BITMASKS + { + _MMX_BITMASK = (1 << 23), + _SSE_BITMASK = (1 << 25), + _SSE2_BITMASK = (1 << 26), + _3DNOW_BITMASK = (1 << 30), + _3DNOWEXT_BITMASK = (1 << 31) + }; + + bool _DetectCPU(); + + bool _MMXPresent; + bool _SSEPresent; + bool _SSE2Present; + bool _3DNowPresent; + bool _3DNowExtPresent; + CPU_TYPES _CPUType; + Common::String _CPUVendorID; + */ + + // Resourcemanager + // --------------- + ResourceManager *_pResourceManager; + + bool _RegisterScriptBindings(); +}; + +/** + * This is only a small class that manages the data of a service. It is a little ugly, I know, + * but with Common::String a simple struct could not be used. + */ +class BS_ServiceInfo { +public: + BS_ServiceInfo(const Common::String &SuperclassIdentifier_, const Common::String &ServiceIdentifier_, + Service*(*CreateMethod_)(Kernel *)) { + this->SuperclassIdentifier = SuperclassIdentifier_; + this->ServiceIdentifier = ServiceIdentifier_; + this->CreateMethod = CreateMethod_; + }; + + Common::String SuperclassIdentifier; + Common::String ServiceIdentifier; + Service*(*CreateMethod)(Kernel *); +}; + +template<class T> +void ReverseArray(Common::Array<T> &Arr) { + if (Arr.size() < 2) + return; + + for (uint i = 0; i <= (Arr.size() / 2 - 1); ++i) { + T temp = Arr[i]; + Arr[i] = Arr[Arr.size() - i - 1]; + Arr[Arr.size() - i - 1] = temp; + } +} + +} // End of namespace Sword25 + +#endif diff --git a/engines/sword25/kernel/kernel_script.cpp b/engines/sword25/kernel/kernel_script.cpp new file mode 100644 index 0000000000..1b87dfdc6e --- /dev/null +++ b/engines/sword25/kernel/kernel_script.cpp @@ -0,0 +1,739 @@ +/* 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/kernel/common.h" +#include "sword25/kernel/kernel.h" +#include "sword25/kernel/filesystemutil.h" +#include "sword25/kernel/window.h" +#include "sword25/kernel/resmanager.h" +#include "sword25/kernel/persistenceservice.h" +#include "sword25/script/script.h" +#include "sword25/script/luabindhelper.h" + +namespace Sword25 { + +// ----------------------------------------------------------------------------- + +static int DisconnectService(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + + lua_pushboolean(L, pKernel->DisconnectService(luaL_checkstring(L, 1))); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetActiveServiceIdentifier(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + + lua_pushstring(L, pKernel->GetActiveServiceIdentifier(luaL_checkstring(L, 1)).c_str()); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetSuperclassCount(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + + lua_pushnumber(L, pKernel->GetSuperclassCount()); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetSuperclassIdentifier(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + + lua_pushstring(L, pKernel->GetSuperclassIdentifier( + static_cast<uint>(luaL_checknumber(L, 1))).c_str()); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetServiceCount(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + + lua_pushnumber(L, pKernel->GetServiceCount(luaL_checkstring(L, 1))); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetServiceIdentifier(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + + lua_pushstring(L, pKernel->GetServiceIdentifier(luaL_checkstring(L, 1), + static_cast<uint>(luaL_checknumber(L, 2))).c_str()); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetMilliTicks(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + + lua_pushnumber(L, pKernel->GetMilliTicks()); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetTimer(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + + lua_pushnumber(L, static_cast<lua_Number>(pKernel->GetMicroTicks()) / 1000000.0); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int StartService(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + + lua_pushbooleancpp(L, pKernel->NewService(luaL_checkstring(L, 1), luaL_checkstring(L, 2)) != NULL); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int Sleep(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + pKernel->Sleep(static_cast<uint>(luaL_checknumber(L, 1) * 1000)); + return 0; +} + +// ----------------------------------------------------------------------------- + +static int Crash(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + pKernel->Crash(); + return 0; +} + +// ----------------------------------------------------------------------------- + +static int ExecuteFile(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + ScriptEngine *pSE = static_cast<ScriptEngine *>(pKernel->GetService("script")); + BS_ASSERT(pSE); + + lua_pushbooleancpp(L, pSE->executeFile(luaL_checkstring(L, 1))); + + return 0; +} + +// ----------------------------------------------------------------------------- + +static int GetUserdataDirectory(lua_State *L) { + lua_pushstring(L, FileSystemUtil::GetInstance().GetUserdataDirectory().c_str()); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetPathSeparator(lua_State *L) { + lua_pushstring(L, FileSystemUtil::GetInstance().GetPathSeparator().c_str()); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int FileExists(lua_State *L) { + lua_pushbooleancpp(L, FileSystemUtil::GetInstance().FileExists(luaL_checkstring(L, 1))); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int CreateDirectory(lua_State *L) { + lua_pushbooleancpp(L, FileSystemUtil::GetInstance().CreateDirectory(luaL_checkstring(L, 1))); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetWinCode(lua_State *L) { + lua_pushstring(L, "ScummVM"); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetSubversionRevision(lua_State *L) { + // ScummVM is 1337 + lua_pushnumber(L, 1337); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetUsedMemory(lua_State *L) { + lua_pushnumber(L, Kernel::GetInstance()->GetUsedMemory()); + return 1; +} + +// ----------------------------------------------------------------------------- + +static const char *KERNEL_LIBRARY_NAME = "Kernel"; + +static const luaL_reg KERNEL_FUNCTIONS[] = { + {"DisconnectService", DisconnectService}, + {"GetActiveServiceIdentifier", GetActiveServiceIdentifier}, + {"GetSuperclassCount", GetSuperclassCount}, + {"GetSuperclassIdentifier", GetSuperclassIdentifier}, + {"GetServiceCount", GetServiceCount}, + {"GetServiceIdentifier", GetServiceIdentifier}, + {"GetMilliTicks", GetMilliTicks}, + {"GetTimer", GetTimer}, + {"StartService", StartService}, + {"Sleep", Sleep}, + {"Crash", Crash}, + {"ExecuteFile", ExecuteFile}, + {"GetUserdataDirectory", GetUserdataDirectory}, + {"GetPathSeparator", GetPathSeparator}, + {"FileExists", FileExists}, + {"CreateDirectory", CreateDirectory}, + {"GetWinCode", GetWinCode}, + {"GetSubversionRevision", GetSubversionRevision}, + {"GetUsedMemory", GetUsedMemory}, + {0, 0} +}; + +// ----------------------------------------------------------------------------- + +static int IsVisible(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + Window *pWindow = pKernel->GetWindow(); + BS_ASSERT(pWindow); + + lua_pushbooleancpp(L, pWindow->IsVisible()); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int SetVisible(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + Window *pWindow = pKernel->GetWindow(); + BS_ASSERT(pWindow); + + pWindow->SetVisible(lua_tobooleancpp(L, 1)); + + return 0; +} + +// ----------------------------------------------------------------------------- + +static int GetX(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + Window *pWindow = pKernel->GetWindow(); + BS_ASSERT(pWindow); + + lua_pushnumber(L, pWindow->GetX()); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetY(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + Window *pWindow = pKernel->GetWindow(); + BS_ASSERT(pWindow); + + lua_pushnumber(L, pWindow->GetY()); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int SetX(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + Window *pWindow = pKernel->GetWindow(); + BS_ASSERT(pWindow); + + pWindow->SetX(static_cast<int>(luaL_checknumber(L, 1))); + + return 0; +} + +// ----------------------------------------------------------------------------- + +static int SetY(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + Window *pWindow = pKernel->GetWindow(); + BS_ASSERT(pWindow); + + pWindow->SetY(static_cast<int>(luaL_checknumber(L, 1))); + + return 0; +} + +// ----------------------------------------------------------------------------- + +static int GetClientX(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + Window *pWindow = pKernel->GetWindow(); + BS_ASSERT(pWindow); + + lua_pushnumber(L, pWindow->GetClientX()); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetClientY(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + Window *pWindow = pKernel->GetWindow(); + BS_ASSERT(pWindow); + + lua_pushnumber(L, pWindow->GetClientY()); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetWidth(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + Window *pWindow = pKernel->GetWindow(); + BS_ASSERT(pWindow); + + lua_pushnumber(L, pWindow->GetWidth()); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetHeight(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + Window *pWindow = pKernel->GetWindow(); + BS_ASSERT(pWindow); + + lua_pushnumber(L, pWindow->GetHeight()); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int SetWidth(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + Window *pWindow = pKernel->GetWindow(); + BS_ASSERT(pWindow); + + pWindow->SetWidth(static_cast<int>(luaL_checknumber(L, 1))); + + return 0; +} + +// ----------------------------------------------------------------------------- + +static int SetHeight(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + Window *pWindow = pKernel->GetWindow(); + BS_ASSERT(pWindow); + + pWindow->SetHeight(static_cast<int>(luaL_checknumber(L, 1))); + + return 0; +} + +// ----------------------------------------------------------------------------- + +static int GetTitle(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + Window *pWindow = pKernel->GetWindow(); + BS_ASSERT(pWindow); + + lua_pushstring(L, pWindow->GetTitle().c_str()); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int SetTitle(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + Window *pWindow = pKernel->GetWindow(); + BS_ASSERT(pWindow); + + pWindow->SetTitle(luaL_checkstring(L, 1)); + + return 0; +} + +// ----------------------------------------------------------------------------- + +static int ProcessMessages(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + Window *pWindow = pKernel->GetWindow(); + BS_ASSERT(pWindow); + + lua_pushbooleancpp(L, pWindow->ProcessMessages()); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int CloseWanted(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + Window *pWindow = pKernel->GetWindow(); + BS_ASSERT(pWindow); + + lua_pushbooleancpp(L, pWindow->CloseWanted()); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int WaitForFocus(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + Window *pWindow = pKernel->GetWindow(); + BS_ASSERT(pWindow); + + lua_pushbooleancpp(L, pWindow->WaitForFocus()); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int HasFocus(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + Window *pWindow = pKernel->GetWindow(); + BS_ASSERT(pWindow); + + lua_pushbooleancpp(L, pWindow->HasFocus()); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static const char *WINDOW_LIBRARY_NAME = "Window"; + +static const luaL_reg WINDOW_FUNCTIONS[] = { + {"IsVisible", IsVisible}, + {"SetVisible", SetVisible}, + {"GetX", GetX}, + {"SetX", SetX}, + {"GetY", GetY}, + {"SetY", SetY}, + {"GetClientX", GetClientX}, + {"GetClientY", GetClientY}, + {"GetWidth", GetWidth}, + {"GetHeight", GetHeight}, + {"SetWidth", SetWidth}, + {"SetHeight", SetHeight}, + {"GetTitle", GetTitle}, + {"SetTitle", SetTitle}, + {"ProcessMessages", ProcessMessages}, + {"CloseWanted", CloseWanted}, + {"WaitForFocus", WaitForFocus}, + {"HasFocus", HasFocus}, + {0, 0} +}; + +// ----------------------------------------------------------------------------- + +static int PrecacheResource(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + ResourceManager *pResource = pKernel->GetResourceManager(); + BS_ASSERT(pResource); + + lua_pushbooleancpp(L, pResource->PrecacheResource(luaL_checkstring(L, 1))); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int ForcePrecacheResource(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + ResourceManager *pResource = pKernel->GetResourceManager(); + BS_ASSERT(pResource); + + lua_pushbooleancpp(L, pResource->PrecacheResource(luaL_checkstring(L, 1), true)); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetMaxMemoryUsage(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + ResourceManager *pResource = pKernel->GetResourceManager(); + BS_ASSERT(pResource); + + lua_pushnumber(L, pResource->GetMaxMemoryUsage()); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int SetMaxMemoryUsage(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + ResourceManager *pResource = pKernel->GetResourceManager(); + BS_ASSERT(pResource); + + pResource->SetMaxMemoryUsage(static_cast<uint>(lua_tonumber(L, 1))); + + return 0; +} + +// ----------------------------------------------------------------------------- + +static int EmptyCache(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + ResourceManager *pResource = pKernel->GetResourceManager(); + BS_ASSERT(pResource); + + pResource->EmptyCache(); + + return 0; +} + +// ----------------------------------------------------------------------------- + +static int IsLogCacheMiss(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + ResourceManager *pResource = pKernel->GetResourceManager(); + BS_ASSERT(pResource); + + lua_pushbooleancpp(L, pResource->IsLogCacheMiss()); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static int SetLogCacheMiss(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + ResourceManager *pResource = pKernel->GetResourceManager(); + BS_ASSERT(pResource); + + pResource->SetLogCacheMiss(lua_tobooleancpp(L, 1)); + + return 0; +} + +// ----------------------------------------------------------------------------- + +static int DumpLockedResources(lua_State *L) { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + ResourceManager *pResource = pKernel->GetResourceManager(); + BS_ASSERT(pResource); + + pResource->DumpLockedResources(); + + return 0; +} + +// ----------------------------------------------------------------------------- + +static const char *RESOURCE_LIBRARY_NAME = "Resource"; + +static const luaL_reg RESOURCE_FUNCTIONS[] = { + {"PrecacheResource", PrecacheResource}, + {"ForcePrecacheResource", ForcePrecacheResource}, + {"GetMaxMemoryUsage", GetMaxMemoryUsage}, + {"SetMaxMemoryUsage", SetMaxMemoryUsage}, + {"EmptyCache", EmptyCache}, + {"IsLogCacheMiss", IsLogCacheMiss}, + {"SetLogCacheMiss", SetLogCacheMiss}, + {"DumpLockedResources", DumpLockedResources}, + {0, 0} +}; + +// ----------------------------------------------------------------------------- + +static int ReloadSlots(lua_State *L) { + PersistenceService::GetInstance().ReloadSlots(); + lua_pushnil(L); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetSlotCount(lua_State *L) { + lua_pushnumber(L, PersistenceService::GetInstance().GetSlotCount()); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int IsSlotOccupied(lua_State *L) { + lua_pushbooleancpp(L, PersistenceService::GetInstance().IsSlotOccupied( + static_cast<uint>(luaL_checknumber(L, 1)) - 1)); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetSavegameDirectory(lua_State *L) { + lua_pushstring(L, PersistenceService::GetInstance().GetSavegameDirectory().c_str()); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int IsSavegameCompatible(lua_State *L) { + lua_pushbooleancpp(L, PersistenceService::GetInstance().IsSavegameCompatible( + static_cast<uint>(luaL_checknumber(L, 1)) - 1)); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetSavegameDescription(lua_State *L) { + lua_pushstring(L, PersistenceService::GetInstance().GetSavegameDescription( + static_cast<uint>(luaL_checknumber(L, 1)) - 1).c_str()); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetSavegameFilename(lua_State *L) { + lua_pushstring(L, PersistenceService::GetInstance().GetSavegameFilename(static_cast<uint>(luaL_checknumber(L, 1)) - 1).c_str()); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int LoadGame(lua_State *L) { + lua_pushbooleancpp(L, PersistenceService::GetInstance().LoadGame(static_cast<uint>(luaL_checknumber(L, 1)) - 1)); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int SaveGame(lua_State *L) { + lua_pushbooleancpp(L, PersistenceService::GetInstance().SaveGame(static_cast<uint>(luaL_checknumber(L, 1)) - 1, luaL_checkstring(L, 2))); + return 1; +} + +// ----------------------------------------------------------------------------- + +static const char *PERSISTENCE_LIBRARY_NAME = "Persistence"; + +static const luaL_reg PERSISTENCE_FUNCTIONS[] = { + {"ReloadSlots", ReloadSlots}, + {"GetSlotCount", GetSlotCount}, + {"IsSlotOccupied", IsSlotOccupied}, + {"GetSavegameDirectory", GetSavegameDirectory}, + {"IsSavegameCompatible", IsSavegameCompatible}, + {"GetSavegameDescription", GetSavegameDescription}, + {"GetSavegameFilename", GetSavegameFilename}, + {"LoadGame", LoadGame}, + {"SaveGame", SaveGame}, + {0, 0} +}; + +// ----------------------------------------------------------------------------- + +bool Kernel::_RegisterScriptBindings() { + ScriptEngine *pScript = static_cast<ScriptEngine *>(GetService("script")); + BS_ASSERT(pScript); + lua_State *L = static_cast<lua_State *>(pScript->getScriptObject()); + BS_ASSERT(L); + + if (!LuaBindhelper::addFunctionsToLib(L, KERNEL_LIBRARY_NAME, KERNEL_FUNCTIONS)) return false; + if (!LuaBindhelper::addFunctionsToLib(L, WINDOW_LIBRARY_NAME, WINDOW_FUNCTIONS)) return false; + if (!LuaBindhelper::addFunctionsToLib(L, RESOURCE_LIBRARY_NAME, RESOURCE_FUNCTIONS)) return false; + if (!LuaBindhelper::addFunctionsToLib(L, PERSISTENCE_LIBRARY_NAME, PERSISTENCE_FUNCTIONS)) return false; + + return true; +} + +} // End of namespace Sword25 diff --git a/engines/sword25/kernel/log.cpp b/engines/sword25/kernel/log.cpp new file mode 100644 index 0000000000..259c02449f --- /dev/null +++ b/engines/sword25/kernel/log.cpp @@ -0,0 +1,214 @@ +/* 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 + * + */ + +#include "sword25/kernel/log.h" +#include "base/version.h" +#include "common/config-manager.h" +#include "common/fs.h" + +namespace Sword25 { + +// Constants +static const char *BF_LOG_FILENAME = "log.txt"; +static const size_t LOG_BUFFERSIZE = 1024 * 16; + +// Logging will take place only when it's activated +#ifdef BS_ACTIVATE_LOGGING + +Common::WriteStream *BS_Log::_LogFile = NULL; +bool BS_Log::_LineBegin = true; +const char *BS_Log::_Prefix = NULL; +const char *BS_Log::_File = NULL; +int BS_Log::_Line = 0; +bool BS_Log::_AutoNewline = false; +Common::Array<BS_Log::LOG_LISTENER_CALLBACK> BS_Log::_LogListener; + +bool BS_Log::_CreateLog() { + // Open the log file + Common::FSNode dataDir(ConfMan.get("path")); + Common::FSNode file = dataDir.getChild(BF_LOG_FILENAME); + + // Open the file for saving + _LogFile = file.createWriteStream(); + + if (_LogFile) { + // Add a title into the log file + Log("Broken Sword 2.5 Engine - Build: %s - %s - VersionID: %s\n", __DATE__, __TIME__, gScummVMFullVersion); + Log("-----------------------------------------------------------------------------------------------------\n"); + + return true; + } + + // Log file could not be created + return false; +} + +void BS_Log::_CloseLog() { + delete _LogFile; + _LogFile = NULL; +} + +void BS_Log::Log(const char *Format, ...) { + char Message[LOG_BUFFERSIZE]; + + // Create the message + va_list ArgList; + va_start(ArgList, Format); + vsnprintf(Message, sizeof(Message), Format, ArgList); + + // Log the message + _WriteLog(Message); + + _FlushLog(); +} + +void BS_Log::LogPrefix(const char *Prefix, const char *Format, ...) { + char Message[LOG_BUFFERSIZE]; + char ExtFormat[LOG_BUFFERSIZE]; + + // If the issue has ceased at the beginning of a new line, the new issue to begin with the prefix + ExtFormat[0] = 0; + if (_LineBegin) { + snprintf(ExtFormat, sizeof(ExtFormat), "%s%s: ", ExtFormat, Prefix); + _LineBegin = false; + } + // Format String pass line by line and each line with the initial prefix + for (;;) { + const char *NextLine = strstr(Format, "\n"); + if (!NextLine || *(NextLine + strlen("\n")) == 0) { + snprintf(ExtFormat, sizeof(ExtFormat), "%s%s", ExtFormat, Format); + if (NextLine) _LineBegin = true; + break; + } else { + strncat(ExtFormat, Format, (NextLine - Format) + strlen("\n")); + snprintf(ExtFormat, sizeof(ExtFormat), "%s%s: ", ExtFormat, Prefix); + } + + Format = NextLine + strlen("\n"); + } + + // Create message + va_list ArgList; + va_start(ArgList, Format); + vsnprintf(Message, sizeof(Message), ExtFormat, ArgList); + + // Log the message + _WriteLog(Message); + + _FlushLog(); +} + +void BS_Log::LogDecorated(const char *Format, ...) { + // Nachricht erzeugen + char Message[LOG_BUFFERSIZE]; + va_list ArgList; + va_start(ArgList, Format); + vsnprintf(Message, sizeof(Message), Format, ArgList); + + // Zweiten Prefix erzeugen, falls gewünscht + char SecondaryPrefix[1024]; + if (_File && _Line) + snprintf(SecondaryPrefix, sizeof(SecondaryPrefix), "(file: %s, line: %d) - ", _File, _Line); + + // Nachricht zeilenweise ausgeben und an jeden Zeilenanfang das Präfix setzen + char *MessageWalker = Message; + for (;;) { + char *NextLine = strstr(MessageWalker, "\n"); + if (NextLine) { + *NextLine = 0; + if (_LineBegin) { + _WriteLog(_Prefix); + if (_File && _Line) + _WriteLog(SecondaryPrefix); + } + _WriteLog(MessageWalker); + _WriteLog("\n"); + MessageWalker = NextLine + sizeof("\n") - 1; + _LineBegin = true; + } else { + if (_LineBegin) { + _WriteLog(_Prefix); + if (_File && _Line) + _WriteLog(SecondaryPrefix); + } + _WriteLog(MessageWalker); + _LineBegin = false; + break; + } + } + + // Falls gewünscht, wird ans Ende der Nachricht automatisch ein Newline angehängt. + if (_AutoNewline) { + _WriteLog("\n"); + _LineBegin = true; + } + + // Pseudoparameter zurücksetzen + _Prefix = NULL; + _File = 0; + _Line = 0; + _AutoNewline = false; + + _FlushLog(); +} + +int BS_Log::_WriteLog(const char *Message) { + if (!_LogFile) if (!_CreateLog()) return false; + + Common::Array<LOG_LISTENER_CALLBACK>::iterator Iter = _LogListener.begin(); + for (; Iter != _LogListener.end(); ++Iter) + (*Iter)(Message); + + _LogFile->writeString(Message); + + return true; +} + +void BS_Log::_FlushLog() { + _LogFile->flush(); +} + +void (*BS_LogPtr)(const char *, ...) = BS_Log::Log; + +void BS_Log_C(const char *Message) { + BS_LogPtr(Message); +} + +#else + +void BS_Log_C(const char *Message) {}; + +#endif + +} // End of namespace Sword25 diff --git a/engines/sword25/kernel/log.h b/engines/sword25/kernel/log.h new file mode 100644 index 0000000000..1fe9ff4ed6 --- /dev/null +++ b/engines/sword25/kernel/log.h @@ -0,0 +1,147 @@ +/* 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_LOG_H +#define SWORD25_LOG_H + +// Includes +#include "common/array.h" +#include "common/file.h" +#include "sword25/kernel/common.h" + +namespace Sword25 { + +// Logging soll nur stattfinden wenn es aktiviert ist +#ifdef BS_ACTIVATE_LOGGING + +// Logging-Makros +#define BS_LOG BS_Log::SetPrefix(BS_LOG_PREFIX ": "), BS_Log::LogDecorated +#define BS_LOGLN BS_Log::SetPrefix(BS_LOG_PREFIX ": "), BS_Log::SetAutoNewline(true), BS_Log::LogDecorated +#define BS_LOG_WARNING BS_Log::SetPrefix(BS_LOG_PREFIX ": WARNING - "), BS_Log::LogDecorated +#define BS_LOG_WARNINGLN BS_Log::SetPrefix(BS_LOG_PREFIX ": WARNING - "), BS_Log::SetAutoNewline(true), BS_Log::LogDecorated +#define BS_LOG_ERROR BS_Log::SetPrefix(BS_LOG_PREFIX ": ERROR - "), BS_Log::LogDecorated +#define BS_LOG_ERRORLN BS_Log::SetPrefix(BS_LOG_PREFIX ": ERROR - "), BS_Log::SetAutoNewline(true), BS_Log::LogDecorated +#define BS_LOG_EXTERROR BS_Log::SetPrefix(BS_LOG_PREFIX ": ERROR "), BS_Log::SetFile(__FILE__), BS_Log::SetLine(__LINE__), BS_Log::LogDecorated +#define BS_LOG_EXTERRORLN BS_Log::SetPrefix(BS_LOG_PREFIX ": ERROR "), BS_Log::SetFile(__FILE__), BS_Log::SetLine(__LINE__), BS_Log::SetAutoNewline(true), BS_Log::LogDecorated + +// Die Version der Logging-Klasse mit aktiviertem Logging +class BS_Log { +public: + static void Clear(); + static void Log(const char *Format, ...); + static void LogPrefix(const char *Prefix, const char *Format, ...); + static void LogDecorated(const char *Format, ...); + + static void SetPrefix(const char *Prefix) { + _Prefix = Prefix; + } + static void SetFile(const char *File) { + _File = File; + } + static void SetLine(int Line) { + _Line = Line; + } + static void SetAutoNewline(bool AutoNewline) { + _AutoNewline = AutoNewline; + } + + typedef void (*LOG_LISTENER_CALLBACK)(const char *); + static void RegisterLogListener(LOG_LISTENER_CALLBACK Callback) { + _LogListener.push_back(Callback); + } + static bool IsListenerRegistered(LOG_LISTENER_CALLBACK Callback) { + Common::Array<LOG_LISTENER_CALLBACK>::iterator i; + for (i = _LogListener.begin(); i != _LogListener.end(); ++i) { + if (**i == Callback) + return true; + } + return false; + } + static void _CloseLog(); + +private: + static Common::WriteStream *_LogFile; + static bool _LineBegin; + static const char *_Prefix; + static const char *_File; + static int _Line; + static bool _AutoNewline; + static Common::Array<LOG_LISTENER_CALLBACK> _LogListener; + + static bool _CreateLog(); + + static int _WriteLog(const char *Message); + static void _FlushLog(); +}; + +// Auxiliary function that allows to log C functions (needed for Lua). +#define BS_Log_C error + + +#else + +// Logging-Macros +#define BS_LOG +#define BS_LOGLN +#define BS_LOG_WARNING +#define BS_LOG_WARNINGLN +#define BS_LOG_ERROR +#define BS_LOG_ERRORLN +#define BS_LOG_EXTERROR +#define BS_LOG_EXTERRORLN + +// The version of the logging class with logging disabled +class BS_Log { +public: + // This version implements all the various methods as empty stubs + static void Log(const char *Text, ...) {}; + static void LogPrefix(const char *Prefix, const char *Format, ...) {}; + static void LogDecorated(const char *Format, ...) {}; + + static void SetPrefix(const char *Prefix) {}; + static void SetFile(const char *File) {}; + static void SetLine(int Line) {}; + static void SetAutoNewline(bool AutoNewline) {}; + + typedef void (*LOG_LISTENER_CALLBACK)(const char *); + static void RegisterLogListener(LOG_LISTENER_CALLBACK Callback) {}; +}; + +#define BS_Log_C error + +#endif + +} // End of namespace Sword25 + +#endif diff --git a/engines/sword25/kernel/objectregistry.h b/engines/sword25/kernel/objectregistry.h new file mode 100644 index 0000000000..dc702f2d75 --- /dev/null +++ b/engines/sword25/kernel/objectregistry.h @@ -0,0 +1,175 @@ +/* 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_OBJECTREGISTRY_H +#define SWORD25_OBJECTREGISTRY_H + +#include "common/func.h" +#include "common/hashmap.h" +#include "sword25/kernel/bs_stdint.h" +#include "sword25/kernel/common.h" + +namespace Sword25 { + +template<typename T> +class ObjectRegistry { +public: + ObjectRegistry() : _nextHandle(1) {} + virtual ~ObjectRegistry() {} + + uint registerObject(T *objectPtr) { + // Null-Pointer können nicht registriert werden. + if (objectPtr == 0) { + logErrorLn("Cannot register a null pointer."); + return 0; + } + + // Falls das Objekt bereits registriert wurde, wird eine Warnung ausgeben und das Handle zurückgeben. + uint handle = findHandleByPtr(objectPtr); + if (handle != 0) { + logWarningLn("Tried to register a object that was already registered."); + return handle; + } + // Ansonsten wird das Objekt in beide Maps eingetragen und das neue Handle zurückgeben. + else { + _handle2PtrMap[_nextHandle] = objectPtr; + _ptr2HandleMap[objectPtr] = _nextHandle; + + return _nextHandle++; + } + } + + uint registerObject(T *objectPtr, uint handle) { + // Null-Pointer und Null-Handle können nicht registriert werden. + if (objectPtr == 0 || handle == 0) { + logErrorLn("Cannot register a null pointer or a null handle."); + return 0; + } + + // Falls das Objekt bereits registriert wurde, wird ein Fehler ausgegeben und 0 zurückgeben. + uint handleTest = findHandleByPtr(objectPtr); + if (handleTest != 0) { + logErrorLn("Tried to register a object that was already registered."); + return 0; + } + // Falls das Handle bereits vergeben ist, wird ein Fehler ausgegeben und 0 zurückgegeben. + else if (findPtrByHandle(handle) != 0) { + logErrorLn("Tried to register a handle that is already taken."); + return 0; + } + // Ansonsten wird das Objekt in beide Maps eingetragen und das gewünschte Handle zurückgeben. + else { + _handle2PtrMap[handle] = objectPtr; + _ptr2HandleMap[objectPtr] = handle; + + // Falls das vergebene Handle größer oder gleich dem nächsten automatische vergebenen Handle ist, wird das nächste automatisch + // vergebene Handle erhöht. + if (handle >= _nextHandle) + _nextHandle = handle + 1; + + return handle; + } + } + + void deregisterObject(T *objectPtr) { + uint handle = findHandleByPtr(objectPtr); + + if (handle != 0) { + // Registriertes Objekt aus beiden Maps entfernen. + _handle2PtrMap.erase(findHandleByPtr(objectPtr)); + _ptr2HandleMap.erase(objectPtr); + } else { + logWarningLn("Tried to remove a object that was not registered."); + } + } + + T *resolveHandle(uint handle) { + // Zum Handle gehöriges Objekt in der Hash-Map finden. + T *objectPtr = findPtrByHandle(handle); + + // Pointer zurückgeben. Im Fehlerfall ist dieser 0. + return objectPtr; + } + + uint resolvePtr(T *objectPtr) { + // Zum Pointer gehöriges Handle in der Hash-Map finden. + uint handle = findHandleByPtr(objectPtr); + + // Handle zurückgeben. Im Fehlerfall ist dieses 0. + return handle; + } + +protected: + // FIXME: I'm not entirely sure my current hash function is legitimate + struct ClassPointer_EqualTo { + bool operator()(const T *x, const T *y) const { + return x == y; + } + }; + struct ClassPointer_Hash { + uint operator()(const T *x) const { + return static_cast<uint>((int64)x % ((int64)1 << sizeof(uint))); + } + }; + + typedef Common::HashMap<uint, T *> HANDLE2PTR_MAP; + typedef Common::HashMap<T *, uint, ClassPointer_Hash, ClassPointer_EqualTo> PTR2HANDLE_MAP; + + HANDLE2PTR_MAP _handle2PtrMap; + PTR2HANDLE_MAP _ptr2HandleMap; + uint _nextHandle; + + T *findPtrByHandle(uint handle) { + // Zum Handle gehörigen Pointer finden. + typename HANDLE2PTR_MAP::const_iterator it = _handle2PtrMap.find(handle); + + // Pointer zurückgeben, oder, falls keiner gefunden wurde, 0 zurückgeben. + return (it != _handle2PtrMap.end()) ? it->_value : 0; + } + + uint findHandleByPtr(T *objectPtr) { + // Zum Pointer gehöriges Handle finden. + typename PTR2HANDLE_MAP::const_iterator it = _ptr2HandleMap.find(objectPtr); + + // Handle zurückgeben, oder, falls keines gefunden wurde, 0 zurückgeben. + return (it != _ptr2HandleMap.end()) ? it->_value : 0; + } + + virtual void logErrorLn(const char *message) const = 0; + virtual void logWarningLn(const char *message) const = 0; +}; + +} // End of namespace Sword25 + +#endif diff --git a/engines/sword25/kernel/outputpersistenceblock.cpp b/engines/sword25/kernel/outputpersistenceblock.cpp new file mode 100644 index 0000000000..438fa7b222 --- /dev/null +++ b/engines/sword25/kernel/outputpersistenceblock.cpp @@ -0,0 +1,131 @@ +/* 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 + * + */ + +#define BS_LOG_PREFIX "OUTPUTPERSISTENCEBLOCK" + +// ----------------------------------------------------------------------------- +// Includes +// ----------------------------------------------------------------------------- + +#include "sword25/kernel/outputpersistenceblock.h" + +// ----------------------------------------------------------------------------- +// Constants +// ----------------------------------------------------------------------------- + +namespace { +const uint INITIAL_BUFFER_SIZE = 1024 * 64; +} + +namespace Sword25 { + +// ----------------------------------------------------------------------------- +// Construction / Destruction +// ----------------------------------------------------------------------------- + +OutputPersistenceBlock::OutputPersistenceBlock() { + m_Data.reserve(INITIAL_BUFFER_SIZE); +} + +// ----------------------------------------------------------------------------- +// Writing +// ----------------------------------------------------------------------------- + +void OutputPersistenceBlock::write(signed int Value) { + WriteMarker(SINT_MARKER); + Value = ConvertEndianessFromSystemToStorage(Value); + RawWrite(&Value, sizeof(Value)); +} + +// ----------------------------------------------------------------------------- + +void OutputPersistenceBlock::write(uint Value) { + WriteMarker(UINT_MARKER); + Value = ConvertEndianessFromSystemToStorage(Value); + RawWrite(&Value, sizeof(Value)); +} + +// ----------------------------------------------------------------------------- + +void OutputPersistenceBlock::write(float Value) { + WriteMarker(FLOAT_MARKER); + Value = ConvertEndianessFromSystemToStorage(Value); + RawWrite(&Value, sizeof(Value)); +} + +// ----------------------------------------------------------------------------- + +void OutputPersistenceBlock::write(bool Value) { + WriteMarker(BOOL_MARKER); + + uint UIntBool = Value ? 1 : 0; + UIntBool = ConvertEndianessFromSystemToStorage(UIntBool); + RawWrite(&UIntBool, sizeof(UIntBool)); +} + +// ----------------------------------------------------------------------------- + +void OutputPersistenceBlock::write(const Common::String &String) { + WriteMarker(STRING_MARKER); + + write(String.size()); + RawWrite(String.c_str(), String.size()); +} + +// ----------------------------------------------------------------------------- + +void OutputPersistenceBlock::write(const void *BufferPtr, size_t Size) { + WriteMarker(BLOCK_MARKER); + + write(Size); + RawWrite(BufferPtr, Size); +} + +// ----------------------------------------------------------------------------- + +void OutputPersistenceBlock::WriteMarker(byte Marker) { + m_Data.push_back(Marker); +} + +// ----------------------------------------------------------------------------- + +void OutputPersistenceBlock::RawWrite(const void *DataPtr, size_t Size) { + if (Size > 0) { + uint OldSize = m_Data.size(); + m_Data.resize(OldSize + Size); + memcpy(&m_Data[OldSize], DataPtr, Size); + } +} + +} // End of namespace Sword25 diff --git a/engines/sword25/kernel/outputpersistenceblock.h b/engines/sword25/kernel/outputpersistenceblock.h new file mode 100644 index 0000000000..154dbc9763 --- /dev/null +++ b/engines/sword25/kernel/outputpersistenceblock.h @@ -0,0 +1,78 @@ +/* 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_OUTPUTPERSISTENCEBLOCK_H +#define SWORD25_OUTPUTPERSISTENCEBLOCK_H + +// ----------------------------------------------------------------------------- +// Includes +// ----------------------------------------------------------------------------- + +#include "sword25/kernel/common.h" +#include "sword25/kernel/persistenceblock.h" + +namespace Sword25 { + +// ----------------------------------------------------------------------------- +// Class declaration +// ----------------------------------------------------------------------------- + +class OutputPersistenceBlock : public PersistenceBlock { +public: + OutputPersistenceBlock(); + + void write(signed int Value); + void write(uint Value); + void write(float Value); + void write(bool Value); + void write(const Common::String &String); + void write(const void *BufferPtr, size_t Size); + + const void *GetData() const { + return &m_Data[0]; + } + uint GetDataSize() const { + return m_Data.size(); + } + +private: + void WriteMarker(byte Marker); + void RawWrite(const void *DataPtr, size_t Size); + + Common::Array<byte> m_Data; +}; + +} // End of namespace Sword25 + +#endif diff --git a/engines/sword25/kernel/persistable.h b/engines/sword25/kernel/persistable.h new file mode 100644 index 0000000000..fc314688d5 --- /dev/null +++ b/engines/sword25/kernel/persistable.h @@ -0,0 +1,53 @@ +/* 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_PERSISTABLE_H +#define SWORD25_PERSISTABLE_H + +namespace Sword25 { + +class OutputPersistenceBlock; +class InputPersistenceBlock; + +class Persistable { +public: + virtual ~Persistable() {}; + + virtual bool persist(OutputPersistenceBlock &writer) = 0; + virtual bool unpersist(InputPersistenceBlock &reader) = 0; +}; + +} // End of namespace Sword25 + +#endif diff --git a/engines/sword25/kernel/persistenceblock.h b/engines/sword25/kernel/persistenceblock.h new file mode 100644 index 0000000000..1f043aa68a --- /dev/null +++ b/engines/sword25/kernel/persistenceblock.h @@ -0,0 +1,133 @@ +/* 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_PERSISTENCEBLOCK_H +#define SWORD25_PERSISTENCEBLOCK_H + +// ----------------------------------------------------------------------------- +// Includes +// ----------------------------------------------------------------------------- + +#include "sword25/kernel/common.h" + +namespace Sword25 { + +// ----------------------------------------------------------------------------- +// Class definition +// ----------------------------------------------------------------------------- + +class PersistenceBlock { +public: + static uint GetSInt32Size() { + return sizeof(signed int) + sizeof(byte); + } + static uint GetUInt32Size() { + return sizeof(uint) + sizeof(byte); + } + static uint GetFloat32Size() { + return sizeof(float) + sizeof(byte); + } + static uint GetBoolSize() { + return sizeof(byte) + sizeof(byte); + } + static uint GetStringSize(const Common::String &String) { + return static_cast<uint>(sizeof(uint) + String.size() + sizeof(byte)); + } + +protected: + enum { + SINT_MARKER, + UINT_MARKER, + FLOAT_MARKER, + STRING_MARKER, + BOOL_MARKER, + BLOCK_MARKER + }; + + // ----------------------------------------------------------------------------- + // Endianess Conversions + // ----------------------------------------------------------------------------- + // + // Everything is stored in Little Endian + // Big Endian Systems will need to be byte swapped during both saving and reading of saved values + // + + template<typename T> + static T ConvertEndianessFromSystemToStorage(T Value) { + if (IsBigEndian()) ReverseByteOrder(&Value); + return Value; + } + + template<typename T> + static T ConvertEndianessFromStorageToSystem(T Value) { + if (IsBigEndian()) ReverseByteOrder(&Value); + return Value; + } + +private: + static bool IsBigEndian() { + uint Dummy = 1; + byte *DummyPtr = reinterpret_cast<byte *>(&Dummy); + return DummyPtr[0] == 0; + } + + template<typename T> + static void Swap(T &One, T &Two) { + T Temp = One; + One = Two; + Two = Temp; + } + + static void ReverseByteOrder(void *Ptr) { + // Reverses the byte order of the 32-bit word pointed to by Ptr + byte *CharPtr = static_cast<byte *>(Ptr); + Swap(CharPtr[0], CharPtr[3]); + Swap(CharPtr[1], CharPtr[2]); + } +}; + +// ----------------------------------------------------------------------------- +// Compile time asserts +// ----------------------------------------------------------------------------- + +#define CTASSERT(ex) typedef char ctassert_type[(ex) ? 1 : -1] +CTASSERT(sizeof(byte) == 1); +CTASSERT(sizeof(signed int) == 4); +CTASSERT(sizeof(uint) == 4); +CTASSERT(sizeof(float) == 4); +#undef CTASSERT + +} // End of namespace Sword25 + +#endif diff --git a/engines/sword25/kernel/persistenceservice.cpp b/engines/sword25/kernel/persistenceservice.cpp new file mode 100644 index 0000000000..871bc37e2a --- /dev/null +++ b/engines/sword25/kernel/persistenceservice.cpp @@ -0,0 +1,465 @@ +/* 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 "common/fs.h" +#include "common/savefile.h" +#include "sword25/kernel/kernel.h" +#include "sword25/kernel/persistenceservice.h" +#include "sword25/kernel/inputpersistenceblock.h" +#include "sword25/kernel/outputpersistenceblock.h" +#include "sword25/kernel/filesystemutil.h" +#include "sword25/gfx/graphicengine.h" +#include "sword25/sfx/soundengine.h" +#include "sword25/input/inputengine.h" +#include "sword25/math/regionregistry.h" +#include "sword25/script/script.h" +#include <zlib.h> + +#define BS_LOG_PREFIX "PERSISTENCESERVICE" + +// ----------------------------------------------------------------------------- +// Constants and utility functions +// ----------------------------------------------------------------------------- + +namespace Sword25 { +const char *SAVEGAME_EXTENSION = ".b25s"; +const char *SAVEGAME_DIRECTORY = "saves"; +const char *FILE_MARKER = "BS25SAVEGAME"; +const uint SLOT_COUNT = 18; +const uint FILE_COPY_BUFFER_SIZE = 1024 * 10; +const char *VERSIONID = "SCUMMVM1"; + +// ------------------------------------------------------------------------- + +Common::String GenerateSavegameFilename(uint slotID) { + char buffer[10]; + sprintf(buffer, "%d%s", slotID, SAVEGAME_EXTENSION); + return Common::String(buffer); +} + +// ------------------------------------------------------------------------- + +Common::String GenerateSavegamePath(uint SlotID) { + Common::FSNode folder(PersistenceService::GetSavegameDirectory()); + + return folder.getChild(GenerateSavegameFilename(SlotID)).getPath(); +} + +// ------------------------------------------------------------------------- + +Common::String FormatTimestamp(TimeDate Time) { + // In the original BS2.5 engine, this used a local object to show the date/time as as a string. + // For now in ScummVM it's being hardcoded to 'dd-MON-yyyy hh:mm:ss' + Common::String monthList[12] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + char buffer[100]; + snprintf(buffer, 100, "%.2d-%s-%.4d %.2d:%.2d:%.2d", + Time.tm_mday, monthList[Time.tm_mon].c_str(), 1900 + Time.tm_year, + Time.tm_hour, Time.tm_min, Time.tm_sec + ); + + return Common::String(buffer); +} + +// ------------------------------------------------------------------------- + +Common::String LoadString(Common::InSaveFile *In, uint MaxSize = 999) { + Common::String Result; + + char ch = (char)In->readByte(); + while ((ch != '\0') && (ch != ' ')) { + Result += ch; + if (Result.size() >= MaxSize) break; + ch = (char)In->readByte(); + } + + return Result; +} + +} + +namespace Sword25 { + +// ----------------------------------------------------------------------------- +// Private Implementation +// ----------------------------------------------------------------------------- + +struct SavegameInformation { + bool IsOccupied; + bool IsCompatible; + Common::String Description; + Common::String Filename; + uint GamedataLength; + uint GamedataOffset; + uint GamedataUncompressedLength; + + SavegameInformation() { + Clear(); + } + + void Clear() { + IsOccupied = false; + IsCompatible = false; + Description = ""; + Filename = ""; + GamedataLength = 0; + GamedataOffset = 0; + GamedataUncompressedLength = 0; + } +}; + +struct PersistenceService::Impl { + SavegameInformation m_SavegameInformations[SLOT_COUNT]; + + // ----------------------------------------------------------------------------- + + Impl() { + ReloadSlots(); + } + + // ----------------------------------------------------------------------------- + + void ReloadSlots() { + // Über alle Spielstanddateien iterieren und deren Infos einlesen. + for (uint i = 0; i < SLOT_COUNT; ++i) { + ReadSlotSavegameInformation(i); + } + } + + void ReadSlotSavegameInformation(uint SlotID) { + // Aktuelle Slotinformationen in den Ausgangszustand versetzen, er wird im Folgenden neu gefüllt. + SavegameInformation &CurSavegameInfo = m_SavegameInformations[SlotID]; + CurSavegameInfo.Clear(); + + // Den Dateinamen für den Spielstand des Slots generieren. + Common::String Filename = GenerateSavegameFilename(SlotID); + + // Try to open the savegame for loading + Common::SaveFileManager *sfm = g_system->getSavefileManager(); + Common::InSaveFile *File = sfm->openForLoading(Filename); + + if (File) { + // Read in the header + Common::String StoredMarker = LoadString(File); + Common::String StoredVersionID = LoadString(File); + Common::String gameDataLength = LoadString(File); + CurSavegameInfo.GamedataLength = atoi(gameDataLength.c_str()); + Common::String gamedataUncompressedLength = LoadString(File); + CurSavegameInfo.GamedataUncompressedLength = atoi(gamedataUncompressedLength.c_str()); + + // If the header can be read in and is detected to be valid, we will have a valid file + if (StoredMarker == FILE_MARKER) { + // Der Slot wird als belegt markiert. + CurSavegameInfo.IsOccupied = true; + // Speichern, ob der Spielstand kompatibel mit der aktuellen Engine-Version ist. + CurSavegameInfo.IsCompatible = (StoredVersionID == Common::String(VERSIONID)); + // Dateinamen des Spielstandes speichern. + CurSavegameInfo.Filename = GenerateSavegameFilename(SlotID); + // Die Beschreibung des Spielstandes besteht aus einer textuellen Darstellung des Änderungsdatums der Spielstanddatei. + CurSavegameInfo.Description = FormatTimestamp(FileSystemUtil::GetInstance().GetFileTime(Filename)); + // Den Offset zu den gespeicherten Spieldaten innerhalb der Datei speichern. + // Dieses entspricht der aktuellen Position, da nach der letzten Headerinformation noch ein Leerzeichen als trenner folgt. + CurSavegameInfo.GamedataOffset = static_cast<uint>(File->pos()); + } + + delete File; + } + } +}; + +// ----------------------------------------------------------------------------- +// Construction / Destruction +// ----------------------------------------------------------------------------- + +PersistenceService &PersistenceService::GetInstance() { + static PersistenceService Instance; + return Instance; +} + +// ----------------------------------------------------------------------------- + +PersistenceService::PersistenceService() : m_impl(new Impl) { +} + +// ----------------------------------------------------------------------------- + +PersistenceService::~PersistenceService() { + delete m_impl; +} + +// ----------------------------------------------------------------------------- +// Implementation +// ----------------------------------------------------------------------------- + +void PersistenceService::ReloadSlots() { + m_impl->ReloadSlots(); +} + +// ----------------------------------------------------------------------------- + +uint PersistenceService::GetSlotCount() { + return SLOT_COUNT; +} + +// ----------------------------------------------------------------------------- + +Common::String PersistenceService::GetSavegameDirectory() { + Common::FSNode node(FileSystemUtil::GetInstance().GetUserdataDirectory()); + Common::FSNode childNode = node.getChild(SAVEGAME_DIRECTORY); + + // Try and return the path using the savegame subfolder. But if doesn't exist, fall back on the data directory + if (childNode.exists()) + return childNode.getPath(); + + return node.getPath(); +} + +// ----------------------------------------------------------------------------- + +namespace { +bool CheckSlotID(uint SlotID) { + // Überprüfen, ob die Slot-ID zulässig ist. + if (SlotID >= SLOT_COUNT) { + BS_LOG_ERRORLN("Tried to access an invalid slot (%d). Only slot ids from 0 to %d are allowed.", SlotID, SLOT_COUNT - 1); + return false; + } else { + return true; + } +} +} + +// ----------------------------------------------------------------------------- + +bool PersistenceService::IsSlotOccupied(uint SlotID) { + if (!CheckSlotID(SlotID)) return false; + return m_impl->m_SavegameInformations[SlotID].IsOccupied; +} + +// ----------------------------------------------------------------------------- + +bool PersistenceService::IsSavegameCompatible(uint SlotID) { + if (!CheckSlotID(SlotID)) return false; + return m_impl->m_SavegameInformations[SlotID].IsCompatible; +} + +// ----------------------------------------------------------------------------- + +Common::String &PersistenceService::GetSavegameDescription(uint SlotID) { + static Common::String EmptyString; + if (!CheckSlotID(SlotID)) return EmptyString; + return m_impl->m_SavegameInformations[SlotID].Description; +} + +// ----------------------------------------------------------------------------- + +Common::String &PersistenceService::GetSavegameFilename(uint SlotID) { + static Common::String EmptyString; + if (!CheckSlotID(SlotID)) return EmptyString; + return m_impl->m_SavegameInformations[SlotID].Filename; +} + +// ----------------------------------------------------------------------------- + +bool PersistenceService::SaveGame(uint SlotID, const Common::String &ScreenshotFilename) { + // Überprüfen, ob die Slot-ID zulässig ist. + if (SlotID >= SLOT_COUNT) { + BS_LOG_ERRORLN("Tried to save to an invalid slot (%d). Only slot ids form 0 to %d are allowed.", SlotID, SLOT_COUNT - 1); + return false; + } + + // Dateinamen erzeugen. + Common::String Filename = GenerateSavegameFilename(SlotID); + + // Sicherstellen, dass das Verzeichnis für die Spielstanddateien existiert. + FileSystemUtil::GetInstance().CreateDirectory(GetSavegameDirectory()); + + // Spielstanddatei öffnen und die Headerdaten schreiben. + Common::SaveFileManager *sfm = g_system->getSavefileManager(); + Common::OutSaveFile *File = sfm->openForSaving(Filename); + + File->writeString(FILE_MARKER); + File->writeByte(' '); + File->writeString(VERSIONID); + File->writeByte(' '); + + if (File->err()) { + error("Unable to write header data to savegame file \"%s\".", Filename.c_str()); + } + + // Alle notwendigen Module persistieren. + OutputPersistenceBlock Writer; + bool Success = true; + Success &= Kernel::GetInstance()->GetScript()->persist(Writer); + Success &= RegionRegistry::getInstance().persist(Writer); + Success &= Kernel::GetInstance()->GetGfx()->persist(Writer); + Success &= Kernel::GetInstance()->GetSfx()->persist(Writer); + Success &= Kernel::GetInstance()->GetInput()->persist(Writer); + if (!Success) { + error("Unable to persist modules for savegame file \"%s\".", Filename.c_str()); + } + + // Daten komprimieren. + uLongf CompressedLength = Writer.GetDataSize() + (Writer.GetDataSize() + 500) / 1000 + 12; + Bytef *CompressionBuffer = new Bytef[CompressedLength]; + + if (compress2(&CompressionBuffer[0], &CompressedLength, reinterpret_cast<const Bytef *>(Writer.GetData()), Writer.GetDataSize(), 6) != Z_OK) { + error("Unable to compress savegame data in savegame file \"%s\".", Filename.c_str()); + } + + // Länge der komprimierten Daten und der unkomprimierten Daten in die Datei schreiben. + char sBuffer[10]; + snprintf(sBuffer, 10, "%ld", CompressedLength); + File->writeString(sBuffer); + File->writeByte(' '); + snprintf(sBuffer, 10, "%u", Writer.GetDataSize()); + File->writeString(sBuffer); + File->writeByte(' '); + + // Komprimierte Daten in die Datei schreiben. + File->write(reinterpret_cast<char *>(&CompressionBuffer[0]), CompressedLength); + if (File->err()) { + error("Unable to write game data to savegame file \"%s\".", Filename.c_str()); + } + + // Get the screenshot + Common::MemoryReadStream *thumbnail = (static_cast<GraphicEngine *>( + Kernel::GetInstance()->GetService("gfx")))->getThumbnail(); + + if (thumbnail) { + byte *Buffer = new Byte[FILE_COPY_BUFFER_SIZE]; + while (!thumbnail->eos()) { + int bytesRead = thumbnail->read(&Buffer[0], FILE_COPY_BUFFER_SIZE); + File->write(&Buffer[0], bytesRead); + } + + delete[] Buffer; + } else { + BS_LOG_WARNINGLN("The screenshot file \"%s\" does not exist. Savegame is written without a screenshot.", Filename.c_str()); + } + + // Savegameinformationen für diesen Slot aktualisieren. + m_impl->ReadSlotSavegameInformation(SlotID); + + File->finalize(); + delete File; + delete[] CompressionBuffer; + + // Erfolg signalisieren. + return true; +} + +// ----------------------------------------------------------------------------- + +bool PersistenceService::LoadGame(uint SlotID) { + Common::SaveFileManager *sfm = g_system->getSavefileManager(); + Common::InSaveFile *File; + + // Überprüfen, ob die Slot-ID zulässig ist. + if (SlotID >= SLOT_COUNT) { + BS_LOG_ERRORLN("Tried to load from an invalid slot (%d). Only slot ids form 0 to %d are allowed.", SlotID, SLOT_COUNT - 1); + return false; + } + + SavegameInformation &CurSavegameInfo = m_impl->m_SavegameInformations[SlotID]; + + // Überprüfen, ob der Slot belegt ist. + if (!CurSavegameInfo.IsOccupied) { + BS_LOG_ERRORLN("Tried to load from an empty slot (%d).", SlotID); + return false; + } + + // Überprüfen, ob der Spielstand im angegebenen Slot mit der aktuellen Engine-Version kompatibel ist. + // Im Debug-Modus wird dieser Test übersprungen. Für das Testen ist es hinderlich auf die Einhaltung dieser strengen Bedingung zu bestehen, + // da sich die Versions-ID bei jeder Codeänderung mitändert. +#ifndef DEBUG + if (!CurSavegameInfo.IsCompatible) { + BS_LOG_ERRORLN("Tried to load a savegame (%d) that is not compatible with this engine version.", SlotID); + return false; + } +#endif + + byte *CompressedDataBuffer = new byte[CurSavegameInfo.GamedataLength]; + byte *UncompressedDataBuffer = new Bytef[CurSavegameInfo.GamedataUncompressedLength]; + + File = sfm->openForLoading(GenerateSavegameFilename(SlotID)); + + File->seek(CurSavegameInfo.GamedataOffset); + File->read(reinterpret_cast<char *>(&CompressedDataBuffer[0]), CurSavegameInfo.GamedataLength); + if (File->err()) { + BS_LOG_ERRORLN("Unable to load the gamedata from the savegame file \"%s\".", CurSavegameInfo.Filename.c_str()); + delete[] CompressedDataBuffer; + delete[] UncompressedDataBuffer; + return false; + } + + // Spieldaten dekomprimieren. + uLongf UncompressedBufferSize = CurSavegameInfo.GamedataUncompressedLength; + if (uncompress(reinterpret_cast<Bytef *>(&UncompressedDataBuffer[0]), &UncompressedBufferSize, + reinterpret_cast<Bytef *>(&CompressedDataBuffer[0]), CurSavegameInfo.GamedataLength) != Z_OK) { + BS_LOG_ERRORLN("Unable to decompress the gamedata from savegame file \"%s\".", CurSavegameInfo.Filename.c_str()); + delete[] UncompressedDataBuffer; + delete[] CompressedDataBuffer; + delete File; + return false; + } + + InputPersistenceBlock Reader(&UncompressedDataBuffer[0], CurSavegameInfo.GamedataUncompressedLength); + + // Einzelne Engine-Module depersistieren. + bool Success = true; + Success &= Kernel::GetInstance()->GetScript()->unpersist(Reader); + // Muss unbedingt nach Script passieren. Da sonst die bereits wiederhergestellten Regions per Garbage-Collection gekillt werden. + Success &= RegionRegistry::getInstance().unpersist(Reader); + Success &= Kernel::GetInstance()->GetGfx()->unpersist(Reader); + Success &= Kernel::GetInstance()->GetSfx()->unpersist(Reader); + Success &= Kernel::GetInstance()->GetInput()->unpersist(Reader); + + delete[] CompressedDataBuffer; + delete[] UncompressedDataBuffer; + delete File; + + if (!Success) { + BS_LOG_ERRORLN("Unable to unpersist the gamedata from savegame file \"%s\".", CurSavegameInfo.Filename.c_str()); + return false; + } + + return true; +} + +} // End of namespace Sword25 diff --git a/engines/sword25/kernel/persistenceservice.h b/engines/sword25/kernel/persistenceservice.h new file mode 100644 index 0000000000..d14185eac2 --- /dev/null +++ b/engines/sword25/kernel/persistenceservice.h @@ -0,0 +1,84 @@ +/* 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_PERSISTENCESERVICE_H +#define SWORD25_PERSISTENCESERVICE_H + +// ----------------------------------------------------------------------------- +// Includes +// ----------------------------------------------------------------------------- + +#include "sword25/kernel/common.h" + +namespace Sword25 { + +// ----------------------------------------------------------------------------- +// Class declaration +// ----------------------------------------------------------------------------- + +class PersistenceService { +public: + PersistenceService(); + virtual ~PersistenceService(); + + // ----------------------------------------------------------------------------- + // Singleton Method + // ----------------------------------------------------------------------------- + + static PersistenceService &GetInstance(); + + // ----------------------------------------------------------------------------- + // Interface + // ----------------------------------------------------------------------------- + + static uint GetSlotCount(); + static Common::String GetSavegameDirectory(); + + void ReloadSlots(); + bool IsSlotOccupied(uint SlotID); + bool IsSavegameCompatible(uint SlotID); + Common::String &GetSavegameDescription(uint SlotID); + Common::String &GetSavegameFilename(uint SlotID); + + bool SaveGame(uint SlotID, const Common::String &ScreenshotFilename); + bool LoadGame(uint SlotID); + +private: + struct Impl; + Impl *m_impl; +}; + +} // End of namespace Sword25 + +#endif diff --git a/engines/sword25/kernel/resmanager.cpp b/engines/sword25/kernel/resmanager.cpp new file mode 100644 index 0000000000..9e80f32f8d --- /dev/null +++ b/engines/sword25/kernel/resmanager.cpp @@ -0,0 +1,336 @@ +/* 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 + * + */ + +#include "sword25/kernel/resmanager.h" + +#include "sword25/kernel/resource.h" +#include "sword25/kernel/resservice.h" +#include "sword25/kernel/string.h" +#include "sword25/package/packagemanager.h" + +namespace Sword25 { + +#define BS_LOG_PREFIX "RESOURCEMANAGER" + +ResourceManager::~ResourceManager() { + // Clear all unlocked resources + EmptyCache(); + + // All remaining resources are not released, so print warnings and release + Common::List<Resource *>::iterator Iter = m_Resources.begin(); + for (; Iter != m_Resources.end(); ++Iter) { + BS_LOG_WARNINGLN("Resource \"%s\" was not released.", (*Iter)->getFileName().c_str()); + + // Set the lock count to zero + while ((*Iter)->GetLockCount() > 0) { + (*Iter)->release(); + }; + + // Delete the resource + delete(*Iter); + } +} + +/** + * Returns a resource by it's ordinal index. Returns NULL if any error occurs + * Note: This method is not optimised for speed and should be used only for debugging purposes + * @param Ord Ordinal number of the resource. Must be between 0 and GetResourceCount() - 1. + */ +Resource *ResourceManager::GetResourceByOrdinal(int Ord) const { + // Überprüfen ob der Index Ord innerhald der Listengrenzen liegt. + if (Ord < 0 || Ord >= GetResourceCount()) { + BS_LOG_ERRORLN("Resource ordinal (%d) out of bounds (0 - %d).", Ord, GetResourceCount() - 1); + return NULL; + } + + // Liste durchlaufen und die Resource mit dem gewünschten Index zurückgeben. + int CurOrd = 0; + Common::List<Resource *>::const_iterator Iter = m_Resources.begin(); + for (; Iter != m_Resources.end(); ++Iter, ++CurOrd) { + if (CurOrd == Ord) + return (*Iter); + } + + // Die Ausführung sollte nie an diesem Punkt ankommen. + BS_LOG_EXTERRORLN("Execution reached unexpected point."); + return NULL; +} + +/** + * Registers a RegisterResourceService. This method is the constructor of + * BS_ResourceService, and thus helps all resource services in the ResourceManager list + * @param pService Which service + */ +bool ResourceManager::RegisterResourceService(ResourceService *pService) { + if (!pService) { + BS_LOG_ERRORLN("Can't register NULL resource service."); + return false; + } + + m_ResourceServices.push_back(pService); + + return true; +} + +/** + * Deletes resources as necessary until the specified memory limit is not being exceeded. + */ +void ResourceManager::DeleteResourcesIfNecessary() { + // If enough memory is available, or no resources are loaded, then the function can immediately end + if (m_KernelPtr->GetUsedMemory() < m_MaxMemoryUsage || m_Resources.empty()) return; + + // Keep deleting resources until the memory usage of the process falls below the set maximum limit. + // The list is processed backwards in order to first release those resources who have been + // not been accessed for the longest + Common::List<Resource *>::iterator Iter = m_Resources.end(); + do { + --Iter; + + // The resource may be released only if it isn't locked + if ((*Iter)->GetLockCount() == 0) Iter = DeleteResource(*Iter); + } while (Iter != m_Resources.begin() && m_KernelPtr->GetUsedMemory() > m_MaxMemoryUsage); +} + +/** + * Releases all resources that are not locked. + **/ +void ResourceManager::EmptyCache() { + // Scan through the resource list + Common::List<Resource *>::iterator Iter = m_Resources.begin(); + while (Iter != m_Resources.end()) { + if ((*Iter)->GetLockCount() == 0) { + // Delete the resource + Iter = DeleteResource(*Iter); + } else + ++Iter; + } +} + +/** + * Returns a requested resource. If any error occurs, returns NULL + * @param FileName Filename of resource + */ +Resource *ResourceManager::RequestResource(const Common::String &FileName) { + // Get the absolute path to the file + Common::String UniqueFileName = GetUniqueFileName(FileName); + if (UniqueFileName == "") + return NULL; + + // Determine whether the resource is already loaded + // If the resource is found, it will be placed at the head of the resource list and returned + { + Resource *pResource = GetResource(UniqueFileName); + if (pResource) { + MoveToFront(pResource); + (pResource)->AddReference(); + return pResource; + } + } + + // The resource was not found, therefore, must not be loaded yet + if (m_LogCacheMiss) BS_LOG_WARNINGLN("\"%s\" was not precached.", UniqueFileName.c_str()); + + Resource *pResource; + if ((pResource = loadResource(UniqueFileName))) { + pResource->AddReference(); + return pResource; + } + + return NULL; +} + +/** + * Loads a resource into the cache + * @param FileName The filename of the resource to be cached + * @param ForceReload Indicates whether the file should be reloaded if it's already in the cache. + * This is useful for files that may have changed in the interim + */ +bool ResourceManager::PrecacheResource(const Common::String &FileName, bool ForceReload) { + // Get the absolute path to the file + Common::String UniqueFileName = GetUniqueFileName(FileName); + if (UniqueFileName == "") + return false; + + Resource *ResourcePtr = GetResource(UniqueFileName); + + if (ForceReload && ResourcePtr) { + if (ResourcePtr->GetLockCount()) { + BS_LOG_ERRORLN("Could not force precaching of \"%s\". The resource is locked.", FileName.c_str()); + return false; + } else { + DeleteResource(ResourcePtr); + ResourcePtr = 0; + } + } + + if (!ResourcePtr && loadResource(UniqueFileName) == NULL) { + BS_LOG_ERRORLN("Could not precache \"%s\",", FileName.c_str()); + return false; + } + + return true; +} + +/** + * Moves a resource to the top of the resource list + * @param pResource The resource + */ +void ResourceManager::MoveToFront(Resource *pResource) { + // Erase the resource from it's current position + m_Resources.erase(pResource->_iterator); + // Re-add the resource at the front of the list + m_Resources.push_front(pResource); + // Reset the resource iterator to the repositioned item + pResource->_iterator = m_Resources.begin(); +} + +/** + * Loads a resource and updates the m_UsedMemory total + * + * The resource must not already be loaded + * @param FileName The unique filename of the resource to be loaded + */ +Resource *ResourceManager::loadResource(const Common::String &fileName) { + // ResourceService finden, der die Resource laden kann. + for (uint i = 0; i < m_ResourceServices.size(); ++i) { + if (m_ResourceServices[i]->canLoadResource(fileName)) { + // If more memory is desired, memory must be released + DeleteResourcesIfNecessary(); + + // Load the resource + Resource *pResource; + if (!(pResource = m_ResourceServices[i]->loadResource(fileName))) { + BS_LOG_ERRORLN("Responsible service could not load resource \"%s\".", fileName.c_str()); + return NULL; + } + + // Add the resource to the front of the list + m_Resources.push_front(pResource); + pResource->_iterator = m_Resources.begin(); + + // Also store the resource in the hash table for quick lookup + m_ResourceHashTable[pResource->GetFileNameHash() % HASH_TABLE_BUCKETS].push_front(pResource); + + return pResource; + } + } + + BS_LOG_ERRORLN("Could not find a service that can load \"%s\".", fileName.c_str()); + return NULL; +} + +/** + * Returns the full path of a given resource filename. + * It will return an empty string if a path could not be created. +*/ +Common::String ResourceManager::GetUniqueFileName(const Common::String &FileName) const { + // Get a pointer to the package manager + PackageManager *pPackage = (PackageManager *)m_KernelPtr->GetService("package"); + if (!pPackage) { + BS_LOG_ERRORLN("Could not get package manager."); + return Common::String(""); + } + + // Absoluten Pfad der Datei bekommen und somit die Eindeutigkeit des Dateinamens sicherstellen + Common::String UniqueFileName = pPackage->getAbsolutePath(FileName); + if (UniqueFileName == "") + BS_LOG_ERRORLN("Could not create absolute file name for \"%s\".", FileName.c_str()); + + return UniqueFileName; +} + +/** + * Deletes a resource, removes it from the lists, and updates m_UsedMemory + */ +Common::List<Resource *>::iterator ResourceManager::DeleteResource(Resource *pResource) { + // Remove the resource from the hash table + m_ResourceHashTable[pResource->GetFileNameHash() % HASH_TABLE_BUCKETS].remove(pResource); + + Resource *pDummy = pResource; + + // Delete the resource from the resource list + Common::List<Resource *>::iterator Result = m_Resources.erase(pResource->_iterator); + + // Delete the resource + delete(pDummy); + + // Return the iterator + return Result; +} + +/** + * Returns a pointer to a loaded resource. If any error occurs, NULL will be returned. + * @param UniqueFileName The absolute path and filename + * Gibt einen Pointer auf die angeforderte Resource zurück, oder NULL, wenn die Resourcen nicht geladen ist. + */ +Resource *ResourceManager::GetResource(const Common::String &UniqueFileName) const { + // Determine whether the resource is already loaded + const Common::List<Resource *>& HashBucket = m_ResourceHashTable[ + BS_String::GetHash(UniqueFileName) % HASH_TABLE_BUCKETS]; + { + Common::List<Resource *>::const_iterator Iter = HashBucket.begin(); + for (; Iter != HashBucket.end(); ++Iter) { + // Wenn die Resource gefunden wurde wird sie zurückgegeben. + if ((*Iter)->getFileName() == UniqueFileName) + return *Iter; + } + } + + // Resource wurde nicht gefunden, ist also nicht geladen + return NULL; +} + +/** + * Writes the names of all currently locked resources to the log file + */ +void ResourceManager::DumpLockedResources() { + for (Common::List<Resource *>::iterator Iter = m_Resources.begin(); Iter != m_Resources.end(); ++Iter) { + if ((*Iter)->GetLockCount() > 0) { + BS_LOGLN("%s", (*Iter)->getFileName().c_str()); + } + } +} + +/** + * Specifies the maximum amount of memory the engine is allowed to use. + * If this value is exceeded, resources will be unloaded to make room. This value is meant + * as a guideline, and not as a fixed boundary. It is not guaranteed not to be exceeded; + * the whole game engine may still use more memory than any amount specified. + */ +void ResourceManager::SetMaxMemoryUsage(uint MaxMemoryUsage) { + m_MaxMemoryUsage = MaxMemoryUsage; + DeleteResourcesIfNecessary(); +} + +} // End of namespace Sword25 diff --git a/engines/sword25/kernel/resmanager.h b/engines/sword25/kernel/resmanager.h new file mode 100644 index 0000000000..578f121fec --- /dev/null +++ b/engines/sword25/kernel/resmanager.h @@ -0,0 +1,193 @@ +/* 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_RESOURCEMANAGER_H +#define SWORD25_RESOURCEMANAGER_H + +// Includes +#include "common/list.h" + +#include "sword25/kernel/common.h" + +namespace Sword25 { + +// Class definitions +class ResourceService; +class Resource; +class Kernel; + +class ResourceManager { + friend class Kernel; + +public: + /** + * Returns a requested resource. If any error occurs, returns NULL + * @param FileName Filename of resource + */ + Resource *RequestResource(const Common::String &FileName); + + /** + * Loads a resource into the cache + * @param FileName The filename of the resource to be cached + * @param ForceReload Indicates whether the file should be reloaded if it's already in the cache. + * This is useful for files that may have changed in the interim + */ + bool PrecacheResource(const Common::String &FileName, bool ForceReload = false); + + /** + * Returns the number of loaded resources + */ + int GetResourceCount() const { + return static_cast<int>(m_Resources.size()); + } + + /** + * Returns a resource by it's ordinal index. Returns NULL if any error occurs + * Note: This method is not optimised for speed and should be used only for debugging purposes + * @param Ord Ordinal number of the resource. Must be between 0 and GetResourceCount() - 1. + */ + Resource *GetResourceByOrdinal(int Ord) const; + + /** + * Registers a RegisterResourceService. This method is the constructor of + * BS_ResourceService, and thus helps all resource services in the ResourceManager list + * @param pService Which service + */ + bool RegisterResourceService(ResourceService *pService); + + /** + * Releases all resources that are not locked. + **/ + void EmptyCache(); + + /** + * Returns the maximum memory the kernel has used + */ + int GetMaxMemoryUsage() const { + return m_MaxMemoryUsage; + } + + /** + * Specifies the maximum amount of memory the engine is allowed to use. + * If this value is exceeded, resources will be unloaded to make room. This value is meant + * as a guideline, and not as a fixed boundary. It is not guaranteed not to be exceeded; + * the whole game engine may still use more memory than any amount specified. + */ + void SetMaxMemoryUsage(uint MaxMemoryUsage); + + /** + * Specifies whether a warning is written to the log when a cache miss occurs. + * THe default value is "false". + */ + bool IsLogCacheMiss() const { + return m_LogCacheMiss; + } + + /** + * Sets whether warnings are written to the log if a cache miss occurs. + * @param Flag If "true", then future warnings will be logged + */ + void SetLogCacheMiss(bool Flag) { + m_LogCacheMiss = Flag; + } + + /** + * Writes the names of all currently locked resources to the log file + */ + void DumpLockedResources(); + +private: + /** + * Creates a new resource manager + * Only the BS_Kernel class can generate copies this class. Thus, the constructor is private + */ + ResourceManager(Kernel *pKernel) : + m_KernelPtr(pKernel), + m_MaxMemoryUsage(100000000), + m_LogCacheMiss(false) + {}; + virtual ~ResourceManager(); + + enum { + HASH_TABLE_BUCKETS = 256 + }; + + /** + * Moves a resource to the top of the resource list + * @param pResource The resource + */ + void MoveToFront(Resource *pResource); + + /** + * Loads a resource and updates the m_UsedMemory total + * + * The resource must not already be loaded + * @param FileName The unique filename of the resource to be loaded + */ + Resource *loadResource(const Common::String &fileName); + + /** + * Returns the full path of a given resource filename. + * It will return an empty string if a path could not be created. + */ + Common::String GetUniqueFileName(const Common::String &FileName) const; + + /** + * Deletes a resource, removes it from the lists, and updates m_UsedMemory + */ + Common::List<Resource *>::iterator DeleteResource(Resource *pResource); + + /** + * Returns a pointer to a loaded resource. If any error occurs, NULL will be returned. + * @param UniqueFileName The absolute path and filename + * Gibt einen Pointer auf die angeforderte Resource zurück, oder NULL, wenn die Resourcen nicht geladen ist. + */ + Resource *GetResource(const Common::String &UniqueFileName) const; + + /** + * Deletes resources as necessary until the specified memory limit is not being exceeded. + */ + void DeleteResourcesIfNecessary(); + + Kernel *m_KernelPtr; + uint m_MaxMemoryUsage; + Common::Array<ResourceService *> m_ResourceServices; + Common::List<Resource *> m_Resources; + Common::List<Resource *> m_ResourceHashTable[HASH_TABLE_BUCKETS]; + bool m_LogCacheMiss; +}; + +} // End of namespace Sword25 + +#endif diff --git a/engines/sword25/kernel/resource.cpp b/engines/sword25/kernel/resource.cpp new file mode 100644 index 0000000000..f6f4f13f68 --- /dev/null +++ b/engines/sword25/kernel/resource.cpp @@ -0,0 +1,60 @@ +/* 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 + * + */ + +#include "sword25/kernel/resource.h" +#include "sword25/kernel/string.h" +#include "sword25/kernel/kernel.h" +#include "sword25/package/packagemanager.h" + +namespace Sword25 { + +#define BS_LOG_PREFIX "RESOURCE" + +Resource::Resource(const Common::String &fileName, RESOURCE_TYPES type) : + _type(type), + _refCount(0) { + BS_ASSERT(Kernel::GetInstance()->GetService("package")); + + _fileName = static_cast<PackageManager *>(Kernel::GetInstance()->GetService("package"))->getAbsolutePath(fileName); + _fileNameHash = BS_String::GetHash(fileName); +} + +void Resource::release() { + if (_refCount) { + --_refCount; + } else + BS_LOG_WARNINGLN("Released unlocked resource \"%s\".", _fileName.c_str()); +} + +} // End of namespace Sword25 diff --git a/engines/sword25/kernel/resource.h b/engines/sword25/kernel/resource.h new file mode 100644 index 0000000000..2a4d197138 --- /dev/null +++ b/engines/sword25/kernel/resource.h @@ -0,0 +1,118 @@ +/* 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_RESOURCE_H +#define SWORD25_RESOURCE_H + +#include "common/list.h" +#include "common/str.h" +#include "sword25/kernel/common.h" + +namespace Sword25 { + +class Kernel; +class ResourceManager; + +class Resource { + friend class ResourceManager; + +public: + enum RESOURCE_TYPES { + TYPE_UNKNOWN, + TYPE_BITMAP, + TYPE_ANIMATION, + TYPE_SOUND, + TYPE_FONT + }; + + Resource(const Common::String &uniqueFileName, RESOURCE_TYPES type); + + /** + * Prevents the resource from being released. + * @remarks This method allows a resource to be locked multiple times. + **/ + void AddReference() { + ++_refCount; + } + + /** + * Cancels a previous lock + * @remarks The resource can still be released more times than it was 'locked', although it is + * not recommended. + **/ + void release(); + + /** + * Returns the current lock count for the resource + * @return The current lock count + **/ + int GetLockCount() const { + return _refCount; + } + + /** + * Returns the absolute path of the given resource + */ + const Common::String &getFileName() const { + return _fileName; + } + + /** + * Returns the hash of the filename of a resource + */ + uint GetFileNameHash() const { + return _fileNameHash; + } + + /** + * Returns a resource's type + */ + uint GetType() const { + return _type; + } + +protected: + virtual ~Resource() {}; + +private: + Common::String _fileName; ///< The absolute filename + uint _fileNameHash; ///< The hash value of the filename + uint _refCount; ///< The number of locks + uint _type; ///< The type of the resource + Common::List<Resource *>::iterator _iterator; ///< Points to the resource position in the LRU list +}; + +} // End of namespace Sword25 + +#endif diff --git a/engines/sword25/kernel/resservice.h b/engines/sword25/kernel/resservice.h new file mode 100644 index 0000000000..d5961d52ae --- /dev/null +++ b/engines/sword25/kernel/resservice.h @@ -0,0 +1,75 @@ +/* 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_RESOURCESERVICE_H +#define SWORD25_RESOURCESERVICE_H + +// Includes +#include "sword25/kernel/common.h" +#include "sword25/kernel/service.h" +#include "sword25/kernel/kernel.h" +#include "sword25/kernel/resmanager.h" + +namespace Sword25 { + +class Resource; + +class ResourceService : public Service { +public: + ResourceService(Kernel *pKernel) : Service(pKernel) { + ResourceManager *pResource = pKernel->GetResourceManager(); + pResource->RegisterResourceService(this); + } + + virtual ~ResourceService() {} + + + /** + * Loads a resource + * @return Returns the resource if successful, otherwise NULL + */ + virtual Resource *loadResource(const Common::String &fileName) = 0; + + /** + * Checks whether the given name can be loaded by the resource service + * @param FileName Dateiname + * @return Returns true if the resource can be loaded. + */ + virtual bool canLoadResource(const Common::String &fileName) = 0; + +}; + +} // End of namespace Sword25 + +#endif diff --git a/engines/sword25/kernel/scummvmwindow.cpp b/engines/sword25/kernel/scummvmwindow.cpp new file mode 100644 index 0000000000..35fd27a05c --- /dev/null +++ b/engines/sword25/kernel/scummvmwindow.cpp @@ -0,0 +1,297 @@ +/* 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 + * + */ + +#include "common/system.h" +#include "engines/util.h" +#include "graphics/pixelformat.h" +#include "sword25/kernel/scummvmwindow.h" +#include "sword25/kernel/kernel.h" +#include "sword25/input/inputengine.h" + +#define BS_LOG_PREFIX "WIN32WINDOW" + +namespace Sword25 { + +bool ScummVMWindow::_ClassRegistered = false; + +// Constructor / Destructor +// ------------------------ +ScummVMWindow::ScummVMWindow(int X, int Y, int Width, int Height, bool Visible) { + // Presume that init will fail + _InitSuccess = false; + + // We don't support any window creation except at the origin 0,0 + assert(X == 0); + assert(Y == 0); + + if (!_ClassRegistered) { + // Nothing here currently + + _ClassRegistered = true; + } + + // Fenstersichtbarkeit setzen + SetVisible(Visible); + + // Indicate success + _InitSuccess = true; + _WindowAlive = true; + _CloseWanted = false; +} + +ScummVMWindow::~ScummVMWindow() { +} + +// Get Methods +// ------------ +int ScummVMWindow::GetX() { + return 0; +} + +int ScummVMWindow::GetY() { + return 0; +} + +int ScummVMWindow::GetClientX() { + return 0; +} + +int ScummVMWindow::GetClientY() { + return 0; +} + +int ScummVMWindow::GetWidth() { + return g_system->getWidth(); +} + +int ScummVMWindow::GetHeight() { + return g_system->getHeight(); +} + +Common::String ScummVMWindow::GetTitle() { + return Common::String(""); +} + +bool ScummVMWindow::IsVisible() { + return true; +} + +bool ScummVMWindow::HasFocus() { + // FIXME: Is there a way to tell if ScummVM has the focus in Windowed mode? + return true; +} + +uint ScummVMWindow::GetWindowHandle() { + return 0; +} + +void ScummVMWindow::SetWindowAlive(bool v) { + _WindowAlive = v; +} + + +// Set Methods +// ------------ + +void ScummVMWindow::SetX(int X) { + // No implementation +} + +void ScummVMWindow::SetY(int Y) { + // No implementation +} + +void ScummVMWindow::SetWidth(int Width) { + // No implementation +} + +void ScummVMWindow::SetHeight(int Height) { + // No implementation +} + +void ScummVMWindow::SetVisible(bool Visible) { + // No implementation +} + +void ScummVMWindow::SetTitle(const Common::String &Title) { + // No implementation +} + +bool ScummVMWindow::ProcessMessages() { + // All messages are handled separately in the input manager. The only thing we + // need to do here is to keep returning whether the window/game is still alive + return _WindowAlive; +} + +bool ScummVMWindow::WaitForFocus() { + // No implementation + return true; +} + +// FIXME: Special keys detected here need to be moved into the Input Engine +/* +// Die WindowProc aller Fenster der Klasse +LRESULT CALLBACK BS_ScummVMWindow::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_PAINT: + ValidateRect(hwnd, NULL); + break; + + case WM_DESTROY: + // Das Fenster wird zerstört + PostQuitMessage(0); + break; + + case WM_CLOSE: + { + BS_Window * WindowPtr = BS_Kernel::GetInstance()->GetWindow(); + if (WindowPtr) { + WindowPtr->SetCloseWanted(true); + } + break; + } + + case WM_KEYDOWN: + { + // Tastendrücke, die für das Inputmodul interessant sind, werden diesem gemeldet. + BS_InputEngine * InputPtr = BS_Kernel::GetInstance()->GetInput(); + + if (InputPtr) + { + switch (wParam) + { + case VK_RETURN: + InputPtr->ReportCommand(BS_InputEngine::KEY_COMMAND_ENTER); + break; + + case VK_LEFT: + InputPtr->ReportCommand(BS_InputEngine::KEY_COMMAND_LEFT); + break; + + case VK_RIGHT: + InputPtr->ReportCommand(BS_InputEngine::KEY_COMMAND_RIGHT); + break; + + case VK_HOME: + InputPtr->ReportCommand(BS_InputEngine::KEY_COMMAND_HOME); + break; + + case VK_END: + InputPtr->ReportCommand(BS_InputEngine::KEY_COMMAND_END); + break; + + case VK_BACK: + InputPtr->ReportCommand(BS_InputEngine::KEY_COMMAND_BACKSPACE); + break; + + case VK_TAB: + InputPtr->ReportCommand(BS_InputEngine::KEY_COMMAND_TAB); + break; + + case VK_INSERT: + InputPtr->ReportCommand(BS_InputEngine::KEY_COMMAND_INSERT); + break; + + case VK_DELETE: + InputPtr->ReportCommand(BS_InputEngine::KEY_COMMAND_DELETE); + break; + } + } + break; + } + + case WM_KEYUP: + case WM_SYSKEYUP: + // Alle Tastendrücke werden ignoriert, damit Windows per DefWindowProc() nicht darauf + // reagieren kann und damit unerwartete Seiteneffekte auslöst. + // Zum Beispiel würden ALT und F10 Tastendrücke das "Menü" aktivieren und somit den Message-Loop zum Stillstand bringen. + break; + + case WM_SYSCOMMAND: + // Verhindern, dass der Bildschirmschoner aktiviert wird, während das Spiel läuft + if (wParam != SC_SCREENSAVE) return DefWindowProc(hwnd,uMsg,wParam,lParam); + break; + + case WM_CHAR: + { + byte theChar = static_cast<byte>(wParam & 0xff); + + // Alle Zeichen, die keine Steuerzeichen sind, werden als Buchstaben dem Input-Service mitgeteilt. + if (theChar >= 32) + { + BS_InputEngine * InputPtr = BS_Kernel::GetInstance()->GetInput(); + if (InputPtr) InputPtr->ReportCharacter(theChar); + } + } + break; + + case WM_SETCURSOR: + { + // Der Systemcursor wird in der Client-Area des Fensters nicht angezeigt, jedoch in der nicht Client-Area, damit der Benutzer das Fenster wie gewohnt + // schließen und verschieben kann. + + // Koordinaten des Cursors in der Client-Area berechnen. + POINT pt; + GetCursorPos(&pt); + ScreenToClient(hwnd, &pt); + + // Feststellen, ob sich der Cursor in der Client-Area befindet. + // Get client rect + RECT rc; + GetClientRect(hwnd, &rc); + + // See if cursor is in client area + if(PtInRect(&rc, pt)) + // In der Client-Area keinen Cursor anzeigen. + SetCursor(NULL); + else + // Ausserhalb der Client-Area den Cursor anzeigen. + SetCursor(LoadCursor(NULL, IDC_ARROW)); + + return TRUE; + } + break; + + default: + // Um alle anderen Vorkommnisse kümmert sich Windows + return DefWindowProc(hwnd,uMsg,wParam,lParam); + } + + return 0; +} +*/ + +} // End of namespace Sword25 diff --git a/engines/sword25/kernel/scummvmwindow.h b/engines/sword25/kernel/scummvmwindow.h new file mode 100644 index 0000000000..2b5f514b7d --- /dev/null +++ b/engines/sword25/kernel/scummvmwindow.h @@ -0,0 +1,85 @@ +/* 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 + * + */ + +/* + BS_ScummVMWindow + ---------------- + Implementation of the BS_Window Interfaces for ScummVM +*/ + +#ifndef SWORD25_SCUMMVMWINDOW_H +#define SWORD25_SCUMMVMWINDOW_H + +// Includes +#include "sword25/kernel/common.h" +#include "sword25/kernel/window.h" + +namespace Sword25 { + +// Class definition +class ScummVMWindow : public Window { +public: + ScummVMWindow(int X, int Y, int Width, int Height, bool Visible); + virtual ~ScummVMWindow(); + + bool IsVisible(); + void SetVisible(bool Visible); + int GetX(); + void SetX(int X); + int GetY(); + void SetY(int X); + int GetClientX(); + int GetClientY(); + int GetWidth(); + void SetWidth(int Width); + int GetHeight(); + void SetHeight(int Height); + Common::String GetTitle(); + void SetWindowAlive(bool v); + void SetTitle(const Common::String &Title); + bool HasFocus(); + uint GetWindowHandle(); + bool WaitForFocus(); + bool ProcessMessages(); + +private: + static bool _ClassRegistered; + bool _WindowAlive; + int _ClientXDelta; + int _ClientYDelta; +}; + +} // End of namespace Sword25 + +#endif diff --git a/engines/sword25/kernel/service.h b/engines/sword25/kernel/service.h new file mode 100644 index 0000000000..addcf50a08 --- /dev/null +++ b/engines/sword25/kernel/service.h @@ -0,0 +1,75 @@ +/* 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 + * + */ + +/* + * BS_Service + * ------------- + * This is the base class for all engine services. + * A serivce is an essential part of the engine, ex. the graphics system. + * This was intended to allow, for example, different plug in modules for + * different kinds of hardware and/or systems. + * The services are created at runtime via the kernel method NewService and NEVER with new. + * + * Autor: Malte Thiesen +*/ + +#ifndef SWORD25_SERVICE_H +#define SWORD25_SERVICE_H + +// Includes +#include "sword25/kernel/common.h" + +namespace Sword25 { + +// Klassendefinition +class Kernel; + +class Service { +private: + Kernel *_pKernel; + +protected: + Service(Kernel *pKernel) : _pKernel(pKernel) {}; + + Kernel *GetKernel() const { + return _pKernel; + } + +public: + virtual ~Service() {}; +}; + +} // End of namespace Sword25 + +#endif diff --git a/engines/sword25/kernel/service_ids.h b/engines/sword25/kernel/service_ids.h new file mode 100644 index 0000000000..5ffd83d743 --- /dev/null +++ b/engines/sword25/kernel/service_ids.h @@ -0,0 +1,80 @@ +/* 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 + * + */ + +/* + * service_ids.h + * ------------- + * This file lists all the services. + * EVERY new service needs to be entered here, otherwise it cannot be instantiated + * by pKernel->NewService(..) + * + * Autor: Malte Thiesen + */ + +#ifndef SWORD25_SERVICE_IDS +#define SWORD25_SERVICE_IDS + +#include "sword25/kernel/common.h" + +namespace Sword25 { + +Service *GraphicEngine_CreateObject(Kernel *pKernel); +Service *PackageManager_CreateObject(Kernel *pKernel); +Service *InputEngine_CreateObject(Kernel *pKernel); +Service *SoundEngine_CreateObject(Kernel *pKernel); +Service *LuaScriptEngine_CreateObject(Kernel *pKernel); +Service *Geometry_CreateObject(Kernel *pKernel); +Service *OggTheora_CreateObject(Kernel *pKernel); + +// Services are recorded in this table +const BS_ServiceInfo BS_SERVICE_TABLE[] = { + // The first two parameters are the name of the superclass and service + // The third parameter is the static method of the class that creates an object + // of the class and returns it + // Example: + // BS_ServiceInfo("Superclass", "Service", CreateMethod) + BS_ServiceInfo("gfx", "opengl", GraphicEngine_CreateObject), + BS_ServiceInfo("package", "archiveFS", PackageManager_CreateObject), + BS_ServiceInfo("input", "winapi", InputEngine_CreateObject), + BS_ServiceInfo("sfx", "fmodex", SoundEngine_CreateObject), + BS_ServiceInfo("script", "lua", LuaScriptEngine_CreateObject), + BS_ServiceInfo("geometry", "std", Geometry_CreateObject), + BS_ServiceInfo("fmv", "oggtheora", OggTheora_CreateObject), +}; + +const uint BS_SERVICE_COUNT = sizeof(BS_SERVICE_TABLE) / sizeof(BS_ServiceInfo); + +} // End of namespace Sword25 + +#endif diff --git a/engines/sword25/kernel/string.h b/engines/sword25/kernel/string.h new file mode 100644 index 0000000000..b701e2312b --- /dev/null +++ b/engines/sword25/kernel/string.h @@ -0,0 +1,111 @@ +/* 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_STRING +#define SWORD25_STRING + +#include "common/str.h" + +namespace BS_String { + +inline uint GetHash(const Common::String &Str) { + uint Result = 0; + + for (uint i = 0; i < Str.size(); i++) + Result = ((Result << 5) - Result) + Str[i]; + + return Result; +} + +inline bool ToInt(const Common::String &Str, int &Result) { + Common::String::const_iterator Iter = Str.begin(); + + // Skip whitespaces + while (*Iter && (*Iter == ' ' || *Iter == '\t')) { + ++Iter; + } + if (Iter == Str.end()) return false; + + // Read sign, if available + bool IsNegative = false; + if (*Iter == '-') { + IsNegative = true; + ++Iter; + } else if (*Iter == '+') + ++Iter; + + // Skip whitespaces + while (*Iter && (*Iter == ' ' || *Iter == '\t')) { + ++Iter; + } + if (Iter == Str.end()) return false; + + // Convert string to integer + Result = 0; + while (Iter != Str.end()) { + if (*Iter < '0' || *Iter > '9') { + while (*Iter && (*Iter == ' ' || *Iter == '\t')) { + ++Iter; + } + if (Iter != Str.end()) return false; + break; + } + Result = (Result * 10) + (*Iter - '0'); + ++Iter; + } + + if (IsNegative) Result = -Result; + + return true; +} + +inline bool ToBool(const Common::String &Str, bool &Result) { + if (Str == "true" || Str == "TRUE") { + Result = true; + return true; + } else if (Str == "false" || Str == "FALSE") { + Result = false; + return true; + } + + return false; +} + +inline void ToLower(Common::String &Str) { + Str.toLowercase(); +} + +} // End of namespace BS_String + +#endif diff --git a/engines/sword25/kernel/window.cpp b/engines/sword25/kernel/window.cpp new file mode 100644 index 0000000000..8d2dc309e7 --- /dev/null +++ b/engines/sword25/kernel/window.cpp @@ -0,0 +1,69 @@ +/* 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 + * + */ + +#include "sword25/kernel/window.h" + +// Alle Implementationen von BS_Window müssen hier eingetragen werden +#include "sword25/kernel/scummvmwindow.h" + +namespace Sword25 { + +// Erstellt ein Fenster des GUI des aktuellen Betriebssystems +Window *Window::CreateBSWindow(int X, int Y, int Width, int Height, bool Visible) { + // Fenster erstellen + Window *pWindow = (Window *) new ScummVMWindow(X, Y, Width, Height, Visible); + + // Falls das Fenster erfolgreich initialisiert wurde, wird ein Pointer auf das Fensterobjekt + // zurückgegeben + if (pWindow->_InitSuccess) + return pWindow; + + // Ansonsten wird das Fensterobjekt zerstört und NULL zurückgegeben + delete pWindow; + return NULL; +} + +// Gibt True zurück wenn das Fenster WM_CLOSE empfangen hat - +// solange, bis RejectClose() aufgerufen wurde. +bool Window::CloseWanted() { + bool result = _CloseWanted; + _CloseWanted = false; + return result; +} + +void Window::SetCloseWanted(bool Wanted) { + _CloseWanted = Wanted; +} + +} // End of namespace Sword25 diff --git a/engines/sword25/kernel/window.h b/engines/sword25/kernel/window.h new file mode 100644 index 0000000000..aee23087cb --- /dev/null +++ b/engines/sword25/kernel/window.h @@ -0,0 +1,177 @@ +/* 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 + * + */ + +/* + * BS_Window + * --------- + * Simple window class interface. This is being encapsulated in a class for + * reasons of portability. + * + * Autor: Malte Thiesen + */ + +#ifndef SWORD25_WINDOW_H +#define SWORD25_WINDOW_H + +// Includes +#include "sword25/kernel/common.h" + +namespace Sword25 { + +// Class definitions + +/** + * A simple window class interface + * + * Windows are exclusively created by BS_Window::CreateBSWindow(). + * BS_Windows selects the correct class for the environment. + */ +class Window { +protected: + bool _InitSuccess; + bool _CloseWanted; + +public: + virtual ~Window() {}; + + /** + * Returns the visibility of the window. + */ + virtual bool IsVisible() = 0; + + /** + * Sets the visibility of the window + * @param Visible Specifies whether the window should be visible or hidden + */ + virtual void SetVisible(bool Visible) = 0; + /** + * Returns the X position of the window + */ + virtual int GetX() = 0; + /** + * Sets the X position of the window + * @paramX The new X position for the window, or -1 for centre aligned + */ + virtual void SetX(int X) = 0; + /** + * Gets the Y position of the window + */ + virtual int GetY() = 0; + /** + * Sets the Y position of the window + * @param Y The new Y position for the window, or -1 for centre aligned + */ + virtual void SetY(int X) = 0; + /** + * Returns the X position of the window's client area + */ + virtual int GetClientX() = 0; + /** + * Returns the Y position of the window's client area + */ + virtual int GetClientY() = 0; + /** + * Returns the width of the window without the frame + */ + virtual int GetWidth() = 0; + /** + * Sets the width of the window without the frame + */ + virtual void SetWidth(int Width) = 0; + /** + * Gets the height of the window without the frame + */ + virtual int GetHeight() = 0; + /** + * Sets the height of the window without the frame + */ + virtual void SetHeight(int Height) = 0; + /** + * Returns the title of the window + */ + virtual Common::String GetTitle() = 0; + /** + * Sets the title of the window + * @param Title The new window title + */ + virtual void SetTitle(const Common::String &Title) = 0; + /** + * Handle the processing of any pending window messages. This method should be called + * during the main loop. + */ + virtual bool ProcessMessages() = 0; + /** + * Pauses the applicaiton until the window has focus, or has been closed. + * Returns false if the window was closed. + */ + virtual bool WaitForFocus() = 0; + /** + * Returns true if the window has focus, false otherwise. + */ + virtual bool HasFocus() = 0; + /** + * Returns the system handle that represents the window. Note that any use of the handle + * will not be portable code. + */ + virtual uint GetWindowHandle() = 0; + + virtual void SetWindowAlive(bool v) = 0; + + /** + * Specifies whether the window is wanted to be closed. This is used together with CloseWanted() + * to allow scripts to query when the main window should be closed, or the user is asking it to close + **/ + void SetCloseWanted(bool Wanted); + /** + * Returns the previous value set in a call to SetCloseWanted. + * Note that calling this also resets the value back to false, until such time as the SetCloseWanted() + * method is called again. + **/ + bool CloseWanted(); + + /** + * Creates a new window instance. Returns a pointer to the window, or NULL if the creation failed. + * Note: It is the responsibility of the client to free the pointer when done with it. + * @param X The X position of the window, or -1 for centre horizontal alignment + * @param Y The Y position of the window, or -1 for centre vertical alignment + * @param Width The width of the window without the frame + * @param Height The height of the window without the frame + * @param Visible Specifies whether window should be visible + */ + static Window *CreateBSWindow(int X, int Y, int Width, int Height, bool Visible); +}; + +} // End of namespace Sword25 + +#endif |