1 ////////////////////////////////////////////////////////////////////////////////
2 // Copyright (C) 2004-2010 by The Allacrost Project
3 // All Rights Reserved
4 //
5 // This code is licensed under the GNU GPL version 2. It is free software
6 // and you may modify it and/or redistribute it under the terms of this license.
7 // See http://www.gnu.org/copyleft/gpl.html for details.
8 ////////////////////////////////////////////////////////////////////////////////
9
10 /** ****************************************************************************
11 *** \file system.cpp
12 *** \author Tyler Olsen, roots@allacrost.org
13 *** \author Andy Gardner, chopperdave@allacrost.org
14 *** \brief Source file for system code management
15 *** ***************************************************************************/
16
17 #ifdef _WIN32
18 #include <direct.h>
19 #include <stdlib.h> // defines _MAX_PATH constant
20 #define PATH_MAX _MAX_PATH // redefine _MAX_PATH to be compatible with Darwin's PATH_MAX
21 #elif defined __MACH__
22 #include <unistd.h>
23 #include <cstdlib>
24 #elif defined __linux__
25 #include <limits.h>
26 #endif
27
28 // #include "gettext.h"
29 #include <libintl.h>
30
31 #include "system.h"
32 #include "audio.h"
33 #include "script.h"
34
35 using namespace std;
36
37 using namespace hoa_utils;
38 using namespace hoa_audio;
39 using namespace hoa_script;
40 using namespace hoa_mode_manager;
41
42 template<> hoa_system::SystemEngine* Singleton<hoa_system::SystemEngine>::_singleton_reference = NULL;
43
44 namespace hoa_system {
45
46 SystemEngine* SystemManager = NULL;
47 bool SYSTEM_DEBUG = false;
48
49
50
Translate(const string & text)51 string Translate(const string& text) {
52 // gettext is a C library so the gettext() function takes/returns a C-style char* string
53 return string(gettext(text.c_str()));
54 }
55
56
57
UTranslate(const string & text)58 ustring UTranslate(const string& text) {
59 return MakeUnicodeString(Translate(text));
60 }
61
62 // -----------------------------------------------------------------------------
63 // SystemTimer Class
64 // -----------------------------------------------------------------------------
65
SystemTimer()66 SystemTimer::SystemTimer() :
67 _state(SYSTEM_TIMER_INVALID),
68 _auto_update(false),
69 _duration(0),
70 _number_loops(0),
71 _mode_owner(NULL),
72 _time_expired(0),
73 _times_completed(0)
74 {}
75
76
77
SystemTimer(uint32 duration,int32 loops)78 SystemTimer::SystemTimer(uint32 duration, int32 loops) :
79 _state(SYSTEM_TIMER_INITIAL),
80 _auto_update(false),
81 _duration(duration),
82 _number_loops(loops),
83 _mode_owner(NULL),
84 _time_expired(0),
85 _times_completed(0)
86 {}
87
88
89
~SystemTimer()90 SystemTimer::~SystemTimer() {
91 if (_auto_update == true) {
92 SystemManager->RemoveAutoTimer(this);
93 }
94 }
95
96
97
Initialize(uint32 duration,int32 number_loops)98 void SystemTimer::Initialize(uint32 duration, int32 number_loops) {
99 _state = SYSTEM_TIMER_INITIAL;
100 _duration = duration;
101 _number_loops = number_loops;
102 _time_expired = 0;
103 _times_completed = 0;
104 }
105
106
107
EnableAutoUpdate(GameMode * owner)108 void SystemTimer::EnableAutoUpdate(GameMode* owner) {
109 if (_auto_update == true) {
110 IF_PRINT_WARNING(SYSTEM_DEBUG) << "timer already had auto update enabled" << endl;
111 return;
112 }
113
114 _auto_update = true;
115 _mode_owner = owner;
116 SystemManager->AddAutoTimer(this);
117 }
118
119
120
EnableManualUpdate()121 void SystemTimer::EnableManualUpdate() {
122 if (_auto_update == false) {
123 IF_PRINT_WARNING(SYSTEM_DEBUG) << "timer was already in manual update mode" << endl;
124 return;
125 }
126
127 SystemManager->RemoveAutoTimer(this);
128 _auto_update = false;
129 _mode_owner = NULL;
130 }
131
132
133
Update()134 void SystemTimer::Update() {
135 Update(SystemManager->GetUpdateTime());
136 }
137
138
139
Update(uint32 time)140 void SystemTimer::Update(uint32 time) {
141 if (_auto_update == true) {
142 IF_PRINT_WARNING(SYSTEM_DEBUG) << "update failed because timer is in automatic update mode" << endl;
143 return;
144 }
145 if (IsRunning() == false) {
146 return;
147 }
148
149 _UpdateTimer(time);
150 }
151
152
153
PercentComplete() const154 float SystemTimer::PercentComplete() const {
155 switch (_state) {
156 case SYSTEM_TIMER_INITIAL:
157 return 0.0f;
158 case SYSTEM_TIMER_RUNNING:
159 case SYSTEM_TIMER_PAUSED:
160 return static_cast<float>(_time_expired) / static_cast<float>(_duration);
161 case SYSTEM_TIMER_FINISHED:
162 return 1.0f;
163 default:
164 return 0.0f;
165 }
166 }
167
168
169
SetDuration(uint32 duration)170 void SystemTimer::SetDuration(uint32 duration) {
171 if (IsInitial() == false) {
172 IF_PRINT_WARNING(SYSTEM_DEBUG) << "function called when the timer was not in the initial state" << endl;
173 return;
174 }
175
176 _duration = duration;
177 }
178
179
180
SetNumberLoops(int32 loops)181 void SystemTimer::SetNumberLoops(int32 loops) {
182 if (IsInitial() == false) {
183 IF_PRINT_WARNING(SYSTEM_DEBUG) << "function called when the timer was not in the initial state" << endl;
184 return;
185 }
186
187 _number_loops = loops;
188 }
189
190
191
SetModeOwner(hoa_mode_manager::GameMode * owner)192 void SystemTimer::SetModeOwner(hoa_mode_manager::GameMode* owner) {
193 if (IsInitial() == false) {
194 IF_PRINT_WARNING(SYSTEM_DEBUG) << "function called when the timer was not in the initial state" << endl;
195 return;
196 }
197
198 _mode_owner = owner;
199 }
200
201
202
_AutoUpdate()203 void SystemTimer::_AutoUpdate() {
204 if (_auto_update == false) {
205 IF_PRINT_WARNING(SYSTEM_DEBUG) << "tried to automatically update a timer that does not have auto updates enabled" << endl;
206 return;
207 }
208 if (IsRunning() == false) {
209 return;
210 }
211
212 _UpdateTimer(SystemManager->GetUpdateTime());
213 }
214
215
216
_UpdateTimer(uint32 time)217 void SystemTimer::_UpdateTimer(uint32 time) {
218 _time_expired += time;
219
220 if (_time_expired >= _duration) {
221 _times_completed++;
222
223 // Check if infinite looping is enabled
224 if (_number_loops < 0) {
225 _time_expired -= _duration;
226 }
227 // Check if the last loop has been completed
228 else if (_times_completed >= static_cast<uint32>(_number_loops)) {
229 _time_expired = 0;
230 _state = SYSTEM_TIMER_FINISHED;
231 }
232 // Otherwise there are still additional loops to complete
233 else {
234 _time_expired -= _duration;
235 }
236 }
237 }
238
239 // -----------------------------------------------------------------------------
240 // SystemEngine Class
241 // -----------------------------------------------------------------------------
242
SystemEngine()243 SystemEngine::SystemEngine() {
244 IF_PRINT_DEBUG(SYSTEM_DEBUG) << "constructor invoked" << endl;
245
246 _not_done = true;
247 SetLanguage("en"); //Default language is English
248 }
249
250
251
~SystemEngine()252 SystemEngine::~SystemEngine() {
253 IF_PRINT_DEBUG(SYSTEM_DEBUG) << "destructor invoked" << endl;
254 }
255
256
257
SingletonInitialize()258 bool SystemEngine::SingletonInitialize() {
259 // Initialize the gettext library
260 setlocale(LC_ALL, "");
261 setlocale(LC_NUMERIC, "C");
262
263 #if defined(_WIN32) || defined(__MACH__)
264 char buffer[PATH_MAX];
265 // Get the current working directory.
266 string cwd(getcwd(buffer, PATH_MAX));
267 cwd.append("/translations/");
268 bindtextdomain("allacrost", cwd.c_str());
269 bind_textdomain_codeset("allacrost", "UTF-8");
270 textdomain("allacrost");
271 #elif (defined(__linux__) || defined(__FreeBSD__)) && !defined(RELEASE_BUILD)
272 // Look for translation files in LOCALEDIR only if they are not available in the
273 // current directory.
274 if (!ifstream("dat/config/settings.lua")) {
275 bindtextdomain(PACKAGE, LOCALEDIR);
276 bind_textdomain_codeset(PACKAGE, "UTF-8");
277 textdomain(PACKAGE);
278 }
279 else {
280 char buffer[PATH_MAX];
281 // Get the current working directory.
282 string cwd(getcwd(buffer, PATH_MAX));
283 cwd.append("/txt/");
284 bindtextdomain(PACKAGE, cwd.c_str());
285 bind_textdomain_codeset(PACKAGE, "UTF-8");
286 textdomain(PACKAGE);
287 }
288 #else
289 bindtextdomain(PACKAGE, LOCALEDIR);
290 bind_textdomain_codeset(PACKAGE, "UTF-8");
291 textdomain(PACKAGE);
292 #endif
293
294 // Called here to set the default English language to use nice quote characters.
295 SetLanguage("en@quot");
296
297 return true;
298 }
299
300
301
InitializeTimers()302 void SystemEngine::InitializeTimers() {
303 _last_update = SDL_GetTicks();
304 _update_time = 1; // Set to non-zero, otherwise bad things may happen...
305 _hours_played = 0;
306 _minutes_played = 0;
307 _seconds_played = 0;
308 _milliseconds_played = 0;
309 _auto_system_timers.clear();
310 }
311
312
313
AddAutoTimer(SystemTimer * timer)314 void SystemEngine::AddAutoTimer(SystemTimer* timer) {
315 if (timer == NULL) {
316 IF_PRINT_WARNING(SYSTEM_DEBUG) << "function received NULL argument" << endl;
317 return;
318 }
319 if (timer->IsAutoUpdate() == false) {
320 IF_PRINT_WARNING(SYSTEM_DEBUG) << "timer did not have auto update feature enabled" << endl;
321 return;
322 }
323
324 // pair<set<SystemTimer*>::iterator, bool> return_value;
325 if (_auto_system_timers.insert(timer).second == false) {
326 IF_PRINT_WARNING(SYSTEM_DEBUG) << "timer already existed in auto system timer container" << endl;
327 }
328 }
329
330
331
RemoveAutoTimer(SystemTimer * timer)332 void SystemEngine::RemoveAutoTimer(SystemTimer* timer) {
333 if (timer == NULL) {
334 IF_PRINT_WARNING(SYSTEM_DEBUG) << "function received NULL argument" << endl;
335 return;
336 }
337 if (timer->IsAutoUpdate() == false) {
338 IF_PRINT_WARNING(SYSTEM_DEBUG) << "timer did not have auto update feature enabled" << endl;
339 }
340
341 if (_auto_system_timers.erase(timer) == 0) {
342 IF_PRINT_WARNING(SYSTEM_DEBUG) << "timer was not found in auto system timer container" << endl;
343 }
344 }
345
346
347
UpdateTimers()348 void SystemEngine::UpdateTimers() {
349 // ----- (1): Update the update game timer
350 uint32 tmp = _last_update;
351 _last_update = SDL_GetTicks();
352 _update_time = _last_update - tmp;
353
354 // ----- (2): Update the game play timer
355 _milliseconds_played += _update_time;
356 if (_milliseconds_played >= 1000) {
357 _seconds_played += _milliseconds_played / 1000;
358 _milliseconds_played = _milliseconds_played % 1000;
359 if (_seconds_played >= 60) {
360 _minutes_played += _seconds_played / 60;
361 _seconds_played = _seconds_played % 60;
362 if (_minutes_played >= 60) {
363 _hours_played += _minutes_played / 60;
364 _minutes_played = _minutes_played % 60;
365 }
366 }
367 }
368
369 // ----- (3): Update all SystemTimer objects
370 for (set<SystemTimer*>::iterator i = _auto_system_timers.begin(); i != _auto_system_timers.end(); i++)
371 (*i)->_AutoUpdate();
372 }
373
374
375
ExamineSystemTimers()376 void SystemEngine::ExamineSystemTimers() {
377 GameMode* active_mode = ModeManager->GetTop();
378 GameMode* timer_mode = NULL;
379
380 for (set<SystemTimer*>::iterator i = _auto_system_timers.begin(); i != _auto_system_timers.end(); i++) {
381 timer_mode = (*i)->GetModeOwner();
382 if (timer_mode == NULL)
383 continue;
384
385 if (timer_mode == active_mode)
386 (*i)->Run();
387 else
388 (*i)->Pause();
389 }
390 }
391
392
393
SetLanguage(std::string lang)394 void SystemEngine::SetLanguage(std::string lang) {
395 _language = lang;
396
397 /// @TODO, implement a cross-platform wrapper for setenv in utils code
398 #ifdef _WIN32
399 SetEnvironmentVariable("LANGUAGE", _language.c_str());
400 #else
401 setenv("LANGUAGE", _language.c_str(), 1);
402 #endif
403 }
404
405
406
WaitForThread(Thread * thread)407 void SystemEngine::WaitForThread(Thread * thread) {
408 #if (THREAD_TYPE == SDL_THREADS)
409 SDL_WaitThread(thread, NULL);
410 #endif
411 }
412
413
414
CreateSemaphore(int max)415 Semaphore * SystemEngine::CreateSemaphore(int max) {
416 #if (THREAD_TYPE == SDL_THREADS)
417 return SDL_CreateSemaphore(max);
418 #endif
419 }
420
421
422
DestroySemaphore(Semaphore * s)423 void SystemEngine::DestroySemaphore(Semaphore * s) {
424 #if (THREAD_TYPE == SDL_THREADS)
425 SDL_DestroySemaphore(s);
426 #endif
427 }
428
429
430
LockThread(Semaphore * s)431 void SystemEngine::LockThread(Semaphore * s) {
432 #if (THREAD_TYPE == SDL_THREADS)
433 SDL_SemWait(s);
434 #endif
435 }
436
437
438
UnlockThread(Semaphore * s)439 void SystemEngine::UnlockThread(Semaphore * s) {
440 #if (THREAD_TYPE == SDL_THREADS)
441 SDL_SemPost(s);
442 #endif
443 }
444
445 } // namespace hoa_system
446