aboutsummaryrefslogtreecommitdiff
path: root/engines/sword25/main.cpp
blob: 0ef59ac7d7a27241493fcdd3639e4dda88d97ab9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
// -----------------------------------------------------------------------------
// This file is part of Broken Sword 2.5
// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsd�rfer
//
// Broken Sword 2.5 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.
//
// Broken Sword 2.5 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 Broken Sword 2.5; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// Includes
// -----------------------------------------------------------------------------

#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

#include "kernel/common.h"
#include "kernel/kernel.h"
#include "kernel/filesystemutil.h"
#include "kernel/debug/memorydumper.h"
#include "script/script.h"
#include "package/packagemanager.h"

#define BS_LOG_PREFIX "MAIN"

// -----------------------------------------------------------------------------

namespace
{
	const char * const PACKAGE_MANAGER = "physfs";
	const char * const DEFAULT_SCRIPT_FILE = "/system/boot.lua";
	const char * const MOUNT_DIR_PARAMETER = "-mount-dir";

	// -------------------------------------------------------------------------

	void LogToStdout(const char * Message)
	{
		printf("%s", Message);
	}

	// -------------------------------------------------------------------------

	bool LoadPackages()
	{
		BS_PackageManager * PackageManagerPtr = reinterpret_cast<BS_PackageManager *>(BS_Kernel::GetInstance()->GetService("package"));
		BS_ASSERT(PackageManagerPtr);

		// Das Hauptpaket laden.
		if (!PackageManagerPtr->LoadPackage("data.b25c", "/")) return false;

		// Den Inhalt des Programmverzeichnisses bestimmen und alphabetisch sortieren.
		vector<string> Filenames = BS_FileSystemUtil::GetInstance().GetFilesInDirectory(".");
		sort(Filenames.begin(), Filenames.end());

		// Alle Patch-Pakete identifizieren und mounten.
		// Die Dateinamen der Patch-Pakete besitzen die Form: patch???.b25c, wobei die Fragezeichen Platzhalter f�r Ziffern sind.
		// Da die Dateinamen sortiert wurden, werden Patches mit niedrigen Zahlen vor Patches mit hohen Zahlen gemounted.
		// Dies ist wichtig, da neu gemountete Pakete vorhandene Dateien im virtuellen Dateisystem �berschreiben, wenn sie
		// gleichnamige Dateien beinhalten.
		for (vector<string>::const_iterator it = Filenames.begin(); it != Filenames.end(); ++it)
		{
			const string & CurFilename = *it;

			// Ist aktuelle Datei ein Patch-Paket?
			static const string PatchPattern = "patch???.b25c";
			if (CurFilename.size() == PatchPattern.size())
			{
				// Pattern Zeichen f�r Zeichen mit dem Dateinamen vergleichen.
				string::const_iterator PatchPatternIt = PatchPattern.begin();
				string::const_iterator CurFilenameIt = CurFilename.begin();
				for (; PatchPatternIt != PatchPattern.end(); ++PatchPatternIt, ++CurFilenameIt)
				{
					if (*PatchPatternIt == '?')
					{
						if (*CurFilenameIt < '0' || *CurFilenameIt > '9') break;
					}
					else
					{
						if (*PatchPatternIt != *CurFilenameIt) break;
					}
				}

				if (PatchPatternIt == PatchPattern.end())
				{
					// Pattern stimmt, Datei muss gemountet werden.
					if (!PackageManagerPtr->LoadPackage(CurFilename, "/")) return false;
				}
			}
		}

		// Alle Sprach-Pakete identifizieren und mounten.
		// Die Dateinamen der Sprach-Pakete besitzen die Form: lang_*.b25c (z.B. lang_de.b25c).
		for (vector<string>::const_iterator it = Filenames.begin(); it != Filenames.end(); ++it)
		{
			const string & CurFilename = *it;

			static const string Prefix = "lang_";
			static const string Suffix = ".b25c";

			if ((CurFilename.size() >= Prefix.size() && string(CurFilename.begin(), CurFilename.begin() + Prefix.size()) == Prefix) &&	// Pr�fix testen.
				(CurFilename.size() >= Suffix.size() && string(CurFilename.end() - Suffix.size(), CurFilename.end()) == Suffix) &&		// Suffix testen.
				(CurFilename.size() > Prefix.size() + Suffix.size())) // Sicherstellen, dass der Dateiname weitere Buchstaben zwischen Pr�fix und Suffix besitzt.
			{
				// Pattern stimmt, Datei muss gemountet werden.
				if (!PackageManagerPtr->LoadPackage(CurFilename, "/")) return false;
			}
		}	

		return true;
	}
}

// -----------------------------------------------------------------------------

bool AppStart(const vector<string> & CommandLineParameters)
{
	// Alle Lognachrichten werden auch auf die Standardausgabe ausgegeben.
	BS_Log::RegisterLogListener(LogToStdout);

	// Kernel initialisieren.
	if (!BS_Kernel::GetInstance()->GetInitSuccess())
	{
		BS_LOG_ERRORLN("Kernel initialization failed.");
		return false;
	}

	// Package-Manager starten, damit die Packfiles geladen werden k�nnen.
	BS_PackageManager * PackageManagerPtr = static_cast<BS_PackageManager *>(BS_Kernel::GetInstance()->NewService("package", PACKAGE_MANAGER));
	if (!PackageManagerPtr)
	{
		BS_LOG_ERRORLN("Packagemanager initialization failed.");
		return false;
	}

	// Packages laden oder das aktuelle Verzeichnis mounten, wenn das �ber Kommandozeile angefordert wurde.
	if (find(CommandLineParameters.begin(), CommandLineParameters.end(), MOUNT_DIR_PARAMETER) != CommandLineParameters.end())
	{
		if (!PackageManagerPtr->LoadDirectoryAsPackage(".", "/")) return false;
	}
	else
	{
		if (!LoadPackages()) return false;
	}

	// Einen Pointer auf den Skript-Engine holen.
	BS_ScriptEngine * ScriptPtr = static_cast<BS_ScriptEngine *>(BS_Kernel::GetInstance()->GetService("script"));
	if (!ScriptPtr)
	{
		BS_LOG_ERRORLN("Skript intialization failed.");
		return false;
	}

	// Die Kommandozeilen-Parameter der Skriptumgebung zug�nglich machen.
	ScriptPtr->SetCommandLine(CommandLineParameters);

	return true;
}

// -----------------------------------------------------------------------------

bool AppEnd()
{
	// Den Kernel herunterfahren und alle Subsysteme deinitialisieren.
	BS_Kernel::DeleteInstance();

	return true;
}

// -----------------------------------------------------------------------------

bool AppMain()
{
	// Das Hauptskript starten. Dieses Skript l�dt alle anderen Skripte und startet das eigentliche Spiel.
	BS_ScriptEngine * ScriptPtr = static_cast<BS_ScriptEngine *>(BS_Kernel::GetInstance()->GetService("script"));
	BS_ASSERT(ScriptPtr);
	ScriptPtr->ExecuteFile(DEFAULT_SCRIPT_FILE);

	return true;
}