1 /******************************
2 ** Tsunagari Tile Engine **
4 ** Copyright 2011 OmegaSDG **
5 ******************************/
14 #include <boost/config.hpp>
15 #include <boost/program_options.hpp>
16 #include <boost/program_options/detail/config_file.hpp>
17 #include <boost/program_options/parsers.hpp>
18 #include <boost/scoped_ptr.hpp>
19 #include <boost/shared_ptr.hpp>
20 #include <libxml/parser.h>
32 /* Output compiled-in engine defaults. */
33 static void defaultsQuery()
35 std::cerr
<< "CLIENT_CONF_FILE: "
36 << CLIENT_CONF_FILE
<< std::endl
;
37 std::cerr
<< "MESSAGE_MODE: ";
38 if (MESSAGE_MODE
== MM_DEBUG
)
39 std::cerr
<< "MM_DEBUG" << std::endl
;
40 else if (MESSAGE_MODE
== MM_DEVELOPER
)
41 std::cerr
<< "MM_DEVELOPER" << std::endl
;
43 std::cerr
<< "MM_ERROR" << std::endl
;
44 std::cerr
<< "GAME_MODE: ";
45 if (GAME_MODE
== JUMP_MOVE
)
46 std::cerr
<< "JUMP_MOVE" << std::endl
;
47 else if (GAME_MODE
== SLIDE_MOVE
)
48 std::cerr
<< "SLIDE_MOVE" << std::endl
;
50 std::cerr
<< "FREE_MOVE" << std::endl
;
51 std::cerr
<< "ROGUELIKE_PERSIST_DELAY_INIT: "
52 << ROGUELIKE_PERSIST_DELAY_INIT
<< std::endl
;
53 std::cerr
<< "ROGUELIKE_PERSIST_DELAY_CONSECUTIVE: "
54 << ROGUELIKE_PERSIST_DELAY_CONSECUTIVE
<< std::endl
;
55 std::cerr
<< "CACHE_EMPTY_TTL: "
56 << CACHE_EMPTY_TTL
<< std::endl
;
57 std::cerr
<< "CACHE_MAX_SIZE: "
58 << CACHE_MAX_SIZE
<< std::endl
;
62 * Load the values we need to start initializing the game from an ini file.
64 * We need to know what size window to create and which World to load. This
65 * information will be stored in an ini file which we parse here.
67 * @param filename Name of the ini file to load from.
69 * @return ClientValues object if successful
71 static ClientValues
* parseConfig(const char* filename
)
73 namespace pod
= boost::program_options::detail
;
75 ClientValues
* conf
= new ClientValues
;
77 conf
->cache_enabled
= CACHE_EMPTY_TTL
&& CACHE_MAX_SIZE
;
79 std::ifstream
config(filename
);
81 Log::err(filename
, "could not parse config");
86 std::set
<std::string
> options
;
87 std::map
<std::string
, std::string
> parameters
;
90 for (pod::config_file_iterator
i(config
, options
), e
; i
!= e
; ++i
) {
91 parameters
[i
->string_key
] = i
->value
[0];
94 if (parameters
["engine.world"].empty()) {
95 Log::err(filename
, "\"[engine] world\" option expected");
99 conf
->world
= parameters
["engine.world"];
101 if (parameters
["engine.dtddir"].empty()) {
102 Log::err(filename
, "\"[engine] dtddir\" option expected");
106 conf
->dtdDir
= parameters
["engine.dtddir"];
108 if (parameters
["window.width"].empty()) {
109 Log::err(filename
, "\"[window] width\" option expected");
113 conf
->windowsize
.x
= atoi(parameters
["window.width"].c_str());
115 if (parameters
["window.height"].empty()) {
116 Log::err(filename
, "\"[window] height\" option expected");
120 conf
->windowsize
.y
= atoi(parameters
["window.height"].c_str());
122 if (parameters
["window.fullscreen"].empty()) {
123 Log::err(filename
, "\"[window] fullscreen\" option expected");
127 conf
->fullscreen
= parseBool(parameters
["window.fullscreen"]);
129 if (!parameters
["cache.enable"].empty()) {
130 if (parseBool(parameters
["cache.enable"]))
131 conf
->cache_enabled
= true;
133 conf
->cache_enabled
= false;
136 if (parameters
["cache.ttl"].empty())
137 conf
->cache_ttl
= CACHE_EMPTY_TTL
;
139 if (atoi(parameters
["cache.ttl"].c_str()) == 0)
140 conf
->cache_enabled
= 0;
141 conf
->cache_ttl
= atoi(parameters
["cache.ttl"].c_str());
144 if (parameters
["cache.size"].empty())
145 conf
->cache_size
= CACHE_MAX_SIZE
;
147 if (atoi(parameters
["cache.size"].c_str()) == 0)
148 conf
->cache_enabled
= 0;
149 conf
->cache_size
= atoi(parameters
["cache.size"].c_str());
152 if (parameters
["engine.loglevel"].empty())
153 conf
->loglevel
= MESSAGE_MODE
;
154 else if (parameters
["engine.loglevel"] == "error" ||
155 parameters
["engine.loglevel"] == "Error" ||
156 parameters
["engine.loglevel"] == "ERROR")
157 conf
->loglevel
= MM_SILENT
;
158 else if (parameters
["engine.loglevel"] == "devel" ||
159 parameters
["engine.loglevel"] == "Devel" ||
160 parameters
["engine.loglevel"] == "DEVEL")
161 conf
->loglevel
= MM_DEVELOPER
;
162 else if (parameters
["engine.loglevel"] == "debug" ||
163 parameters
["engine.loglevel"] == "Debug" ||
164 parameters
["engine.loglevel"] == "DEBUG")
165 conf
->loglevel
= MM_DEBUG
;
167 Log::err(filename
, "unknown value for \"[engine] loglevel\", using default");
168 conf
->loglevel
= MESSAGE_MODE
;
174 /* Parse and process command line options and arguments. */
175 static bool parseCommandLine(int argc
, char* argv
[], ClientValues
* conf
)
177 CommandLineOptions
cmd(argc
, argv
);
179 cmd
.insert("-h", "--help", "", "Display this help message");
180 cmd
.insert("-g", "--gameworld", "<world file>", "Game world to load");
181 cmd
.insert("-c", "--config", "<config file>", "Client config file to use");
182 cmd
.insert("-v", "--verbosity", "<error,devel,debug>", "Log message level");
183 cmd
.insert("-t", "--cache-ttl", "<seconds>", "Cache time-to-live in seconds");
184 cmd
.insert("-m", "--cache-size", "<megabytes>", "Cache size in megabytes");
185 cmd
.insert("-s", "--size", "<WxH>", "Window dimensions");
186 cmd
.insert("-f", "--fullscreen", "", "Run in fullscreen mode");
187 cmd
.insert("-w", "--window", "", "Run in windowed mode");
188 cmd
.insert("-q", "--query", "", "Query compiled-in engine defaults");
189 cmd
.insert("", "--version", "", "Print the engine version string");
192 Log::err(argv
[0], "bad command line");
197 if (cmd
.check("--help")) {
202 if (cmd
.check("--version")) {
203 std::cerr
<< TSUNAGARI_RELEASE_VERSION
<< std::endl
;
207 if (cmd
.check("--query")) {
212 if (cmd
.check("--config")) {
214 conf
= parseConfig(cmd
.get("--config").c_str());
216 Log::err(cmd
.get("--config"), "loading config failed");
221 if (cmd
.check("--gameworld"))
222 conf
->world
= cmd
.get("--gameworld");
224 if (cmd
.check("--verbosity")) {
225 if (!cmd
.get("--verbosity").compare("error"))
226 conf
->loglevel
= MM_SILENT
;
227 else if (!cmd
.get("--verbosity").compare("devel"))
228 conf
->loglevel
= MM_DEVELOPER
;
229 else if (!cmd
.get("--verbosity").compare("debug"))
230 conf
->loglevel
= MM_DEBUG
;
232 Log::err(argv
[0], "invalid argument for --verbosity");
237 if (cmd
.check("--cache-ttl")) {
238 conf
->cache_ttl
= atoi(cmd
.get("--cache-ttl").c_str());
239 if (conf
->cache_ttl
== 0)
240 conf
->cache_enabled
= false;
243 if (cmd
.check("--cache-size")) {
244 conf
->cache_size
= atoi(cmd
.get("--cache-size").c_str());
245 if (conf
->cache_size
== 0)
246 conf
->cache_enabled
= false;
249 if (cmd
.check("--size")) {
250 std::vector
<std::string
> dim
= splitStr(cmd
.get("--size"), "x");
251 if (dim
.size() != 2) {
252 Log::err(argv
[0], "invalid argument for --size");
255 conf
->windowsize
.x
= atoi(dim
[0].c_str());
256 conf
->windowsize
.y
= atoi(dim
[1].c_str());
259 if (cmd
.check("--fullscreen") && cmd
.check("--window")) {
260 Log::err(argv
[0], "--fullscreen and --window mutually exclusive");
264 if (cmd
.check("--fullscreen"))
265 conf
->fullscreen
= true;
267 if (cmd
.check("--window"))
268 conf
->fullscreen
= false;
273 static void initLibraries()
276 * This initializes the library and checks for potential ABI mismatches
277 * between the version it was compiled for and the actual shared
283 static void cleanupLibraries()
285 // Clean the XML library.
290 * Load client config and instantiate window.
292 * The client config tells us our window parameters along with which World
293 * we're going to load. The GameWindow class then loads and plays the game.
295 int main(int argc
, char** argv
)
297 #if _WINDOWS /* Fix console output on Windows */
298 if (AttachConsole(ATTACH_PARENT_PROCESS
)) {
299 freopen("CONOUT$","wb",stdout
);
300 freopen("CONOUT$","wb",stderr
);
306 ClientValues
* conf
= parseConfig(CLIENT_CONF_FILE
);
308 if (!parseCommandLine(argc
, argv
, conf
)) {
313 if (conf
&& conf
->loglevel
)
314 Log::setMode(conf
->loglevel
);
317 Log::err(CLIENT_CONF_FILE
, "loading config failed");
322 GameWindow
window((unsigned)conf
->windowsize
.x
,
323 (unsigned)conf
->windowsize
.y
,
326 if (window
.init(conf
))