]> git.mxchange.org Git - quix0rs-blobwars.git/blob - src/init.cpp
Use time_t to store time data.
[quix0rs-blobwars.git] / src / init.cpp
1 /*
2 Copyright (C) 2004-2011 Parallel Realities
3 Copyright (C) 2011-2015 Perpendicular Dimensions
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
14 See the GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20 */
21
22 #include "init.h"
23
24 static bool displayLicense;
25
26 void checkForLicense()
27 {
28         if (!engine.loadData(_("data/license")))
29         {
30                 graphics.showLicenseErrorAndExit();
31         }
32 }
33
34 /*
35 Show the GNU Public License the first time the game is played. Waits 4 seconds
36 and then proceeds. THIS MUST NOT BE REMOVED!!!!!
37 */
38 void showLicense()
39 {
40         SDL_FillRect(graphics.screen, NULL, graphics.black);
41         graphics.delay(1000);
42
43         SDL_FillRect(graphics.screen, NULL, graphics.black);
44         SDL_Surface *pic = graphics.loadImage("gfx/main/licensePic.png");
45         graphics.blit(pic, 0, 0, graphics.screen, false);
46         SDL_FreeSurface(pic);
47
48         checkForLicense();
49
50         char line[255];
51         int y = 0;
52
53         char *token = strtok((char*)engine.dataBuffer, "\n");
54
55         while (true)
56         {
57                 sscanf(token, "%d %[^\n\r]", &y, line);
58                 
59                 if (y == -1)
60                 {
61                         break;
62                 }
63
64                 graphics.drawString(line, 320, y, true, graphics.screen);
65
66                 token = strtok(NULL, "\n");
67
68                 if (token == NULL)
69                 {
70                         break;
71                 }
72         }
73
74         graphics.delay(4000);
75
76         graphics.drawString(_("Press Space to Continue..."), 320, 440, true, graphics.screen);
77
78         engine.flushInput();
79         engine.clearInput();
80
81         while (true)
82         {
83                 graphics.updateScreen();
84                 engine.getInput();
85                 config.populate();
86                 if (engine.userAccepts())
87                         break;
88                 SDL_Delay(16);
89         }
90         
91         SDL_FillRect(graphics.screen, NULL, graphics.black);
92         graphics.delay(1000);
93 }
94
95 #if UNIX
96 void setupUserHomeDirectory()
97 {
98         char *userHome = getenv("HOME");
99         
100         if ((!userHome) || (userHome == NULL))
101         {
102                 printf("Couldn't determine user home directory! Exitting.\n");
103                 exit(1);
104         }
105
106         debug(("User Home = %s\n", userHome));
107         
108         char dir[PATH_MAX];
109         dir[0] = 0;
110
111         snprintf(dir, sizeof dir, "%s/.parallelrealities", userHome);
112         if ((mkdir(dir, S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH) != 0) && (errno != EEXIST))
113         {
114                 printf("Couldn't create required directory '%s'", dir);
115                 exit(1);
116         }
117
118         snprintf(dir, sizeof dir, "%s/.parallelrealities/blobwars", userHome);
119         if ((mkdir(dir, S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH) != 0) && (errno != EEXIST))
120         {
121                 printf("Couldn't create required directory '%s'", dir);
122                 exit(1);
123         }
124
125         char gameSavePath[PATH_MAX];
126         snprintf(gameSavePath, sizeof gameSavePath, "%s/.parallelrealities/blobwars/", userHome);
127         engine.setUserHome(gameSavePath);
128 }
129 #endif
130
131 bool loadConfig()
132 {
133         float version = 0;
134         int release = 0;
135         bool rtn = false;
136
137         char configPath[PATH_MAX];
138
139         snprintf(configPath, sizeof configPath, "%sconfig", engine.userHomeDirectory);
140
141         debug(("Loading Config from %s\n", configPath));
142
143         FILE *fp = fopen(configPath, "rb");
144
145         if (!fp)
146         {
147                 return true;
148         }
149
150         if (fscanf(fp, "%10f %10d", &version, &release) != 2)
151         {
152                 rtn = true;
153         }
154
155         debug(("Version = %.2f - Expected %.2f\n", version, VERSION));
156         debug(("Release = %d - Expected %d\n", release, RELEASE));
157
158         if ((version != VERSION) && (release != RELEASE))
159         {
160                 rtn = true;
161         }
162
163         if (fscanf(fp, "%10d %10d %10d %10d %10d %10d %10d", &engine.fullScreen, &game.musicVol, &game.soundVol, &game.output, &game.brightness, &engine.extremeAvailable, &game.gore) != 7)
164         {
165                 rtn = true;
166         }
167
168         fclose(fp);
169
170         debug(("Extreme Mode = %d\n", engine.extremeAvailable));
171         debug(("Output Type = %d\n", game.output));
172
173         // Override audio if there is no sound available
174         if ((engine.useAudio) && (game.output))
175         {
176                 engine.useAudio = game.output;
177         }
178                 
179         config.loadKeyConfig();
180         config.loadJoystickConfig();
181
182         return rtn;
183 }
184
185 void saveConfig()
186 {
187         char configPath[PATH_MAX];
188
189         snprintf(configPath, sizeof configPath, "%sconfig", engine.userHomeDirectory);
190
191         FILE *fp = fopen(configPath, "wb");
192
193         if (!fp)
194         {
195                 printf("Error Saving Config to %s\n", configPath);
196                 return;
197         }
198
199         fprintf(fp, "%f %d\n", VERSION, RELEASE);
200         fprintf(fp, "%d %d %d %d %d %d %d\n", engine.fullScreen, game.musicVol, game.soundVol, game.output, game.brightness, engine.extremeAvailable, game.gore);
201
202         fclose(fp);
203         
204         debug(("Output Type = %d\n", game.output));
205 }
206
207 //
208 // see if we can load the private keyState
209 //
210 int initMedalService(void *data)
211 {
212         (void)data;
213
214         SDL_mutexP(medalServer.lock);
215         
216         char connectMessage[1024];
217         snprintf(connectMessage, sizeof connectMessage, "Contacting Medal Server - %s:%d", MEDAL_SERVER_HOST, MEDAL_SERVER_PORT);
218         
219         graphics.showMedalMessage(-1, connectMessage);
220         
221         char keyPath[PATH_MAX];
222         char privateKey[20];
223
224         snprintf(keyPath, sizeof keyPath, "%smedalKey", engine.userHomeDirectory);
225         
226         debug(("Loading private key from %s\n", keyPath));
227         
228         FILE *fp = fopen(keyPath, "rb");
229         
230         if (!fp)
231         {
232                 graphics.showMedalMessage(-1, "No Medal Key found - Online functions disabled");
233                 SDL_mutexV(medalServer.lock);
234                 return 0;
235         }
236         
237         if (fscanf(fp, "%19s", privateKey) != 1)
238         {
239                 graphics.showMedalMessage(-1, "Medal Key file corrupt - Online functions disabled");
240                 SDL_mutexV(medalServer.lock);
241                 fclose(fp);
242                 return 0;
243         }
244         
245         fclose(fp);
246                 
247         if (!medalServer.connect(privateKey))
248         {
249                 graphics.showMedalMessage(-1, "Medal Server Connection Failed - Online functions disabled");
250                 return 0;
251         }
252         
253         graphics.showMedalMessage(-1, "Connected to Medal Server");
254         
255         SDL_mutexV(medalServer.lock);
256         
257         return 1;
258 }
259
260 void initConfig()
261 {
262         #if UNIX
263         setupUserHomeDirectory();
264         #endif
265
266         displayLicense = loadConfig();
267 }
268
269 /*
270 Chugg chugg chugg.... brrr... chugg chugg chugg...brrrrrr... chugg ch..
271 BRRRRRRRRRRRRRRRRRMMMMMMMMMMMMMMMMMMM!! Well, hopefully anyway! ;)
272 */
273 void initSystem()
274 {
275         long flags = SDL_INIT_VIDEO|SDL_INIT_JOYSTICK;
276                         
277         if (engine.useAudio)
278         {
279                 flags |= SDL_INIT_AUDIO;
280         }
281
282         /* Initialize the SDL library */
283         if (SDL_Init(flags) < 0)
284         {
285                 printf("Couldn't initialize SDL: %s\n", SDL_GetError());
286                 exit(1);
287         }
288
289         graphics.screen = SDL_CreateRGBSurface(0, 640, 480, 32, 0xff0000, 0xff00, 0xff, 0xff000000);
290
291         if (graphics.screen == NULL)
292         {
293                 printf("Couldn't set 640x480 video mode: %s\n", SDL_GetError());
294                 exit(1);
295         }
296
297         // Increase the size of the window if we have large desktop resolutions
298         SDL_DisplayMode displayMode = {};
299         SDL_GetDesktopDisplayMode(0, &displayMode);
300         int w = graphics.screen->w;
301         int h = graphics.screen->h;
302         while (displayMode.w > w * 2 && displayMode.h > h * 2)
303         {
304                 w *= 2;
305                 h *= 2;
306         }
307
308         graphics.window = SDL_CreateWindow("Blobwars: Metal Blob Solid", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, SDL_WINDOW_RESIZABLE);
309
310         if (graphics.window == NULL)
311         {
312                 printf("Couldn't create %dx%d window: %s\n", w, h, SDL_GetError());
313                 exit(1);
314         }
315
316         graphics.renderer = SDL_CreateRenderer(graphics.window, -1, SDL_RENDERER_PRESENTVSYNC);
317
318         if (graphics.renderer == NULL)
319         {
320                 printf("Couldn't create renderer: %s\n", SDL_GetError());
321                 exit(1);
322         }
323
324         SDL_RenderSetLogicalSize(graphics.renderer, graphics.screen->w, graphics.screen->h);
325         graphics.texture = SDL_CreateTexture(graphics.renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, graphics.screen->w, graphics.screen->h);
326
327         if (graphics.texture == NULL)
328         {
329                 printf("Could not create %dx%d texture: %s\n", graphics.screen->w, graphics.screen->h, SDL_GetError());
330                 exit(1);
331         }
332
333         SDL_SetWindowFullscreen(graphics.window, engine.fullScreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
334
335         // This (attempts to) set the gamma correction. We attempt to catch an error here
336         // in case someone has done something really stupid in the config file(!!)
337         if (game.brightness != -1) {
338                 Math::limitInt(&game.brightness, 1, 20);
339                 float brightness = game.brightness;
340                 brightness /= 10;
341                 uint16_t ramp[256];
342                 SDL_CalculateGammaRamp(brightness, ramp);
343                 SDL_SetWindowGammaRamp(graphics.window, ramp, ramp, ramp);
344         }
345
346         if (TTF_Init() < 0)
347         {
348                 printf("Couldn't initialize SDL TTF: %s\n", SDL_GetError());
349                 exit(1);
350         }
351
352         if (engine.useAudio)
353         {
354                 if (Mix_OpenAudio(22050, AUDIO_S16, engine.useAudio, 1024) < 0)
355                 {
356                         printf("Warning: Couldn't set 44100 Hz 16-bit audio - Reason: %s\n", Mix_GetError());
357                         printf("Sound and Music will be disabled\n");
358                         engine.useAudio = 0;
359                 }
360         }
361
362         debug(("Found %d Joysticks...\n", SDL_NumJoysticks()));
363
364         if (SDL_NumJoysticks() > 0)
365         {
366                 debug(("Opening Joystick - %s...\n", SDL_JoystickName(0)));
367                 SDL_JoystickEventState(SDL_ENABLE);
368                 config.sdlJoystick = SDL_JoystickOpen(0);
369         }
370
371         SDL_ShowCursor(SDL_DISABLE);
372
373         graphics.registerEngine(&engine);
374         graphics.mapColors();
375
376         audio.registerEngine(&engine);
377         audio.setSoundVolume(game.soundVol);
378         audio.setMusicVolume(game.musicVol);
379         audio.output = game.output;
380
381         debug(("Sound Volume = %d\n", game.soundVol));
382         debug(("Music Volume = %d\n", game.musicVol));
383         debug(("Output Type = %d\n", game.output));
384         debug(("Brightness = %d\n", game.brightness));
385         debug(("tmp dir = %s\n", engine.userHomeDirectory));
386         debug(("Pack Dir = %s\n", PAKLOCATION));
387         debug(("Loading Fonts...\n"));
388
389         #if USEPAK
390                 if (!engine.unpack("data/vera.ttf", PAK_FONT))
391                 {
392                         engine.reportFontFailure();
393                 }
394         #endif
395
396         graphics.loadFont(0, "data/vera.ttf", 12);
397         graphics.loadFont(1, "data/vera.ttf", 15);
398         graphics.loadFont(2, "data/vera.ttf", 19);
399         graphics.loadFont(3, "data/vera.ttf", 23);
400         graphics.loadFont(4, "data/vera.ttf", 24);
401
402         debug(("Font sizes all loaded!!\n"));
403
404         audio.loadSound(SND_CHEAT, "sound/Lock And Load!!!");
405         audio.loadSound(SND_HIGHLIGHT, "sound/menu");
406         audio.loadSound(SND_SELECT, "sound/select");
407         
408         graphics.medal[0] = graphics.loadImage("gfx/main/medal_bronze_1.png");
409         graphics.medal[1] = graphics.loadImage("gfx/main/award_star_silver_3.png");
410         graphics.medal[2] = graphics.loadImage("gfx/main/shield.png");
411         graphics.medal[3] = graphics.loadImage("gfx/main/ruby.png");
412
413         graphics.license[0] = graphics.loadImage("gfx/main/cc-by.png", true);
414         graphics.license[1] = graphics.loadImage("gfx/main/cc-by-sa.png", true);
415
416         SDL_Surface *device = graphics.loadImage("gfx/main/alienDevice.png");
417         SDL_SetWindowIcon(graphics.window, device);
418         SDL_FreeSurface(device);
419         
420         if (strstr(engine.userHomeDirectory, "/root"))
421         {
422                 graphics.showRootWarning();
423         }
424
425         if (displayLicense)
426         {
427                 showLicense();
428         }
429         else
430         {
431                 checkForLicense();
432         }
433         
434         if (SDLNet_Init() < 0)
435         {
436                 printf("SDLNet_Init: %s\n", SDLNet_GetError());
437         }
438         else
439         {
440                 SDL_Thread *thread = SDL_CreateThread(initMedalService, "MedalService", NULL);
441         
442                 if (thread == NULL)
443                 {
444                         printf("Unable to create thread: %s\n", SDL_GetError());
445                         printf("Calling medal server directly\n");
446                         initMedalService(NULL);
447                         return;
448                 }
449         }
450         
451         engine.saveConfig = true;
452
453         debug(("Init Complete...\n"));
454 }
455
456 /*
457 Removes [hopefully] all the resources that has been
458 loaded and created during the game. This is called by
459 atexit();
460 */
461 void cleanup()
462 {
463         char tempPath[PATH_MAX];
464         
465         debug(("Cleaning Up...\n"));
466         
467         debug(("Updating Replay Data\n"));
468         replayData.header.score = game.score;
469
470         debug(("Freeing Audio...\n"));
471         audio.destroy();
472
473         debug(("Removing Music...\n"));
474         snprintf(tempPath, sizeof tempPath, "%smusic.mod", engine.userHomeDirectory);
475         remove(tempPath);
476
477         debug(("Freeing Game Info...\n"));
478         game.destroy();
479
480         debug(("Freeing Map Data...\n"));
481         map.destroy();
482
483         debug(("Freeing Engine Data...\n"));
484         engine.destroy();
485
486         debug(("Freeing Graphics...\n"));
487         graphics.destroy();
488
489         debug(("Saving Config...\n"));
490         if (engine.saveConfig)
491         {
492                 saveConfig();
493         }
494
495         debug(("Removing Font File...\n"));
496         snprintf(tempPath, sizeof tempPath, "%sfont.ttf", engine.userHomeDirectory);
497         remove(tempPath);
498         
499         if (SDL_NumJoysticks() > 0)
500         {
501                 SDL_JoystickEventState(SDL_DISABLE);
502                 for (int i = 0 ; i < SDL_NumJoysticks() ; i++)
503                 {
504                         debug(("Closing Joystick #%d\n", i));
505                         SDL_JoystickClose(config.sdlJoystick);
506                 }
507         }
508
509         debug(("Closing Audio...\n"));
510         if (engine.useAudio)
511         {
512                 Mix_CloseAudio();
513         }
514
515         debug(("Closing TTF...\n"));
516         TTF_Quit();
517         
518         debug(("Closing NET...\n"));
519         SDLNet_Quit();
520
521         debug(("Closing SDL Sub System...\n"));
522         SDL_Quit();
523
524         debug(("All Done.\n"));
525         
526         if (replayData.replayMode == REPLAY_MODE::PLAYBACK)
527         {
528                 printf("\n==== ACTUAL PLAYBACK DATA ====\n");
529                 replayData.printReplayInformation();
530         }
531 }
532