1 |
/* |
/* |
2 |
$Id$ |
$Id$ |
3 |
|
|
4 |
Copyright (C) 2003/2004/2005 Kai Sterker <kaisterker@linuxgames.com> |
Copyright (C) 2003/2004/2005 Kai Sterker <kaisterker@linuxgames.com> |
5 |
Part of the Adonthell Project http://adonthell.linuxgames.com |
Part of the Adonthell Project http://adonthell.linuxgames.com |
6 |
|
|
7 |
Adonthell is free software; you can redistribute it and/or modify |
Adonthell is free software; you can redistribute it and/or modify |
8 |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
9 |
the Free Software Foundation; either version 2 of the License, or |
the Free Software Foundation; either version 2 of the License, or |
10 |
(at your option) any later version. |
(at your option) any later version. |
11 |
|
|
12 |
Adonthell is distributed in the hope that it will be useful, |
Adonthell is distributed in the hope that it will be useful, |
13 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 |
GNU General Public License for more details. |
GNU General Public License for more details. |
16 |
|
|
17 |
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
18 |
along with Adonthell; if not, write to the Free Software |
along with Adonthell; if not, write to the Free Software |
19 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 |
*/ |
*/ |
21 |
|
|
22 |
|
|
23 |
/** |
/** |
24 |
* @file main/adonthell.cc |
* @file main/adonthell.cc |
25 |
* @author Kai Sterker <kaisterker@linuxgames.com> |
* @author Kai Sterker <kaisterker@linuxgames.com> |
26 |
* |
* |
27 |
* @brief The main application class for programs using the Adonthell framework. |
* @brief The main application class for programs using the Adonthell framework. |
28 |
*/ |
*/ |
29 |
|
|
30 |
#ifdef HAVE_CONFIG_H |
#ifdef HAVE_CONFIG_H |
31 |
#include <config.h> |
#include <config.h> |
32 |
#endif |
#endif |
33 |
|
|
34 |
#include <iostream> |
#include <iostream> |
35 |
#include <unistd.h> |
#include <unistd.h> |
36 |
|
|
37 |
#include "gfx/gfx.h" |
#include "gfx/gfx.h" |
38 |
#include "base/base.h" |
#include "base/base.h" |
39 |
#include "input/input.h" |
#include "input/input.h" |
40 |
#include "python/python.h" |
#include "python/python.h" |
41 |
#include "main/adonthell.h" |
#include "main/adonthell.h" |
42 |
#include "event/time_event_manager.h" |
#include "event/time_event_manager.h" |
43 |
|
|
44 |
using namespace adonthell; |
using namespace adonthell; |
45 |
using std::cerr; |
using std::cerr; |
46 |
using std::endl; |
using std::endl; |
47 |
|
|
48 |
/// The handler of our library file. |
/// The handler of our library file. |
49 |
static lt_dlhandle dlhandle = 0; |
static lt_dlhandle dlhandle = 0; |
50 |
|
|
51 |
/// pointer to method with backend/platform specific intialization code. |
/// pointer to method with backend/platform specific intialization code. |
52 |
static bool (*init_p)(adonthell::app* application) = 0; |
static bool (*init_p)(adonthell::app* application) = 0; |
53 |
|
|
54 |
// dtor |
// dtor |
55 |
app::~app () |
app::~app () |
56 |
{ |
{ |
57 |
if (dlhandle) lt_dlclose (dlhandle); |
if (dlhandle) lt_dlclose (dlhandle); |
58 |
lt_dlexit (); |
lt_dlexit (); |
59 |
} |
} |
60 |
|
|
61 |
// initialize engine subsystems |
// initialize engine subsystems |
62 |
bool app::init_modules (const u_int16 & modules) |
bool app::init_modules (const u_int16 & modules) |
63 |
{ |
{ |
64 |
// don't initialize previously loaded modules |
// don't initialize previously loaded modules |
65 |
u_int16 m = Modules ^ modules; |
u_int16 m = Modules ^ modules; |
66 |
Modules |= m; |
Modules |= m; |
67 |
|
|
68 |
// startup python |
// startup python |
69 |
if (m & PYTHON) |
if (m & PYTHON) |
70 |
{ |
{ |
71 |
// but not if we're called from a Python script |
// but not if we're called from a Python script |
72 |
if (!Py_IsInitialized ()) |
if (!Py_IsInitialized ()) |
73 |
{ |
{ |
74 |
python::init (); |
python::init (); |
75 |
PySys_SetArgv (Argc, Argv); |
PySys_SetArgv (Argc, Argv); |
76 |
} |
} |
77 |
// avoid shutting down Python in that case |
// avoid shutting down Python in that case |
78 |
else |
else |
79 |
{ |
{ |
80 |
Modules -= PYTHON; |
Modules -= PYTHON; |
81 |
} |
} |
82 |
} |
} |
83 |
|
|
84 |
// startup graphics |
// startup graphics |
85 |
if (m & GFX) |
if (m & GFX) |
86 |
{ |
{ |
87 |
if (!gfx::init (Backend)) return false; |
if (!gfx::init (Backend)) return false; |
88 |
} |
} |
89 |
|
|
90 |
// startup input |
// startup input |
91 |
if (m & INPUT) |
if (m & INPUT) |
92 |
{ |
{ |
93 |
if (!input::init (Backend)) return false; |
if (!input::init (Backend)) return false; |
94 |
} |
} |
95 |
|
|
96 |
// startup event system |
// startup event system |
97 |
if (m & EVENT) |
if (m & EVENT) |
98 |
{ |
{ |
99 |
events::time_event_manager::init (); |
events::time_event_manager::init (); |
100 |
} |
} |
101 |
|
|
102 |
return true; |
return true; |
103 |
} |
} |
104 |
|
|
105 |
// read command line arguments |
// read command line arguments |
106 |
void app::parse_args (int & argc, char *argv[]) |
void app::parse_args (int & argc, char *argv[]) |
107 |
{ |
{ |
108 |
int c; |
int c; |
109 |
|
|
110 |
Argc = argc; |
Argc = argc; |
111 |
Argv = argv; |
Argv = argv; |
112 |
|
|
113 |
Game = ""; |
Game = ""; |
114 |
Backend = ""; |
Backend = ""; |
115 |
Userdatadir = ""; |
Userdatadir = ""; |
116 |
Config = "adonthell"; |
Config = "adonthell"; |
117 |
|
|
118 |
// Check for options |
// Check for options |
119 |
while ((c = getopt (argc, argv, "b:c:g:hv")) != -1) |
while ((c = getopt (argc, argv, "b:c:g:hv")) != -1) |
120 |
{ |
{ |
121 |
switch (c) |
switch (c) |
122 |
{ |
{ |
123 |
// backend: |
// backend: |
124 |
case 'b': |
case 'b': |
125 |
Backend = optarg; |
Backend = optarg; |
126 |
break; |
break; |
127 |
// configuration file: |
// configuration file: |
128 |
case 'c': |
case 'c': |
129 |
Config = optarg; |
Config = optarg; |
130 |
break; |
break; |
131 |
// user supplied data directory: |
// user supplied data directory: |
132 |
case 'g': |
case 'g': |
133 |
Userdatadir = optarg; |
Userdatadir = optarg; |
134 |
break; |
break; |
135 |
// help message: |
// help message: |
136 |
case 'h': |
case 'h': |
137 |
print_help (); |
print_help (); |
138 |
exit (0); |
exit (0); |
139 |
break; |
break; |
140 |
// version number: |
// version number: |
141 |
case 'v': |
case 'v': |
142 |
std::cout << VERSION << endl; |
std::cout << VERSION << endl; |
143 |
exit (0); |
exit (0); |
144 |
break; |
break; |
145 |
default: |
default: |
146 |
break; |
break; |
147 |
} |
} |
148 |
} |
} |
149 |
|
|
150 |
// check whether the GAME parameter is given |
// check whether the GAME parameter is given |
151 |
if (argc - optind == 1) |
if (argc - optind == 1) |
152 |
{ |
{ |
153 |
Game = argv[argc-1]; |
Game = argv[argc-1]; |
154 |
} |
} |
155 |
} |
} |
156 |
|
|
157 |
// initialize the Adonthell framework |
// initialize the Adonthell framework |
158 |
bool app::init () |
bool app::init () |
159 |
{ |
{ |
160 |
Modules = 0; |
Modules = 0; |
161 |
dlhandle = NULL; |
dlhandle = NULL; |
162 |
|
|
163 |
// init libltdl |
// init libltdl |
164 |
if (lt_dlinit ()) |
if (lt_dlinit ()) |
165 |
{ |
{ |
166 |
cerr << lt_dlerror() << endl; |
cerr << lt_dlerror() << endl; |
167 |
cerr << "Error initializing liblt!" << endl; |
cerr << "Error initializing liblt!" << endl; |
168 |
return false; |
return false; |
169 |
} |
} |
170 |
|
|
171 |
// init base module (required for reading config file) |
// init base module (required for reading config file) |
172 |
base::init (Userdatadir, Game); |
base::init (Userdatadir, Game); |
173 |
|
|
174 |
// load configuration file |
// load engine configuration file |
175 |
if (!Cfg.read (Config)) |
if (!Cfg.read (Config)) |
176 |
{ |
{ |
177 |
// print message if that fails, but don't panic yet ... |
// print message if that fails, but don't panic yet ... |
178 |
cerr << "Error reading configuration '" << Config << ".xml'" << endl; |
cerr << "Error reading engine configuration '" << Config << ".xml'" << endl; |
179 |
} |
} |
180 |
|
|
181 |
// if we have been given no backend on the command line, |
/* |
182 |
// try to get it from config file; fallback to sdl if that fails |
* FIXME: This requires some more thoughts ... how can the individual options |
183 |
if (Backend == "") |
* be saved to correct file again? How can config options added to the proper |
184 |
{ |
* file at runtime? etc ... |
185 |
Backend = Cfg.get_string ("General", "Backend", "sdl"); |
* |
186 |
// set type of config option (free form text entry) |
// merge with game specific config file |
187 |
Cfg.option ("General", "Backend", base::cfg_option::FREE); |
if (Game != "" && !Cfg.read (Game)) |
188 |
} |
{ |
189 |
|
// no big deal if that fails; being verbose just in case ... |
190 |
// load backend init module |
cerr << "Cannot read application specific configuration '" << Game << ".xml'" << endl; |
191 |
dlhandle = base::get_module (string ("/main/") + Backend); |
} |
192 |
if (!dlhandle) |
*/ |
193 |
{ |
|
194 |
cerr << lt_dlerror() << endl; |
// if we have been given no backend on the command line, |
195 |
return false; |
// try to get it from config file; fallback to sdl if that fails |
196 |
} |
if (Backend == "") |
197 |
|
{ |
198 |
// get pointer to init method |
Backend = Cfg.get_string ("General", "Backend", "sdl"); |
199 |
init_p = (bool (*)(app*)) lt_dlsym (dlhandle, "main_init"); |
// set type of config option (free form text entry) |
200 |
if (!init_p) |
Cfg.option ("General", "Backend", base::cfg_option::FREE); |
201 |
{ |
} |
202 |
cerr << lt_dlerror() << endl; |
|
203 |
return false; |
// load backend init module |
204 |
} |
dlhandle = base::get_module (string ("/main/") + Backend); |
205 |
|
if (!dlhandle) |
206 |
// platform / backend specific initialization |
{ |
207 |
return init_p (this); |
cerr << lt_dlerror() << endl; |
208 |
} |
return false; |
209 |
|
} |
210 |
// shutdown the Adonthell framework |
|
211 |
void app::cleanup () const |
// get pointer to init method |
212 |
{ |
init_p = (bool (*)(app*)) lt_dlsym (dlhandle, "main_init"); |
213 |
// save configuration to disk |
if (!init_p) |
214 |
Cfg.write (Config); |
{ |
215 |
|
cerr << lt_dlerror() << endl; |
216 |
// cleanup modules |
return false; |
217 |
if (Modules & EVENT) events::time_event_manager::cleanup (); |
} |
218 |
if (Modules & INPUT) input::cleanup (); |
|
219 |
if (Modules & GFX) gfx::cleanup (); |
// platform / backend specific initialization |
220 |
if (Modules & PYTHON) python::cleanup (); |
return init_p (this); |
221 |
} |
} |
222 |
|
|
223 |
// display a help message |
// shutdown the Adonthell framework |
224 |
void app::print_help () const |
void app::cleanup () const |
225 |
{ |
{ |
226 |
std::cout << "Usage: " << Argv[0] << " [OPTIONS] [GAME]" << endl; |
// save configuration to disk |
227 |
std::cout << endl; |
Cfg.write (Config); |
228 |
std::cout << "Where [OPTIONS] can be:\n"; |
|
229 |
std::cout << "-b <backend> specifiy the backend to use (default 'sdl')\n"; |
// cleanup modules |
230 |
std::cout << "-c <config> use given config file (default 'adonthell')\n"; |
if (Modules & EVENT) events::time_event_manager::cleanup (); |
231 |
std::cout << "-g <directory> specify user game directory\n"; |
if (Modules & INPUT) input::cleanup (); |
232 |
std::cout << "-h print this message and exit\n"; |
if (Modules & GFX) gfx::cleanup (); |
233 |
std::cout << "-v print engine version number and exit" << endl; |
if (Modules & PYTHON) python::cleanup (); |
234 |
} |
} |
235 |
|
|
236 |
|
// display a help message |
237 |
|
void app::print_help () const |
238 |
|
{ |
239 |
|
std::cout << "Usage: " << Argv[0] << " [OPTIONS] [GAME]" << endl; |
240 |
|
std::cout << endl; |
241 |
|
std::cout << "Where [OPTIONS] can be:\n"; |
242 |
|
std::cout << "-b <backend> specifiy the backend to use (default 'sdl')\n"; |
243 |
|
std::cout << "-c <config> use given config file (default 'adonthell')\n"; |
244 |
|
std::cout << "-g <directory> specify user game directory\n"; |
245 |
|
std::cout << "-h print this message and exit\n"; |
246 |
|
std::cout << "-v print engine version number and exit" << endl; |
247 |
|
} |