]> git.mxchange.org Git - quix0rs-blobwars.git/blob - src/init.cpp
Remove font size guessing hack.
[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         SDL_mutexP(medalServer.lock);
213         
214         char connectMessage[1024];
215         snprintf(connectMessage, sizeof connectMessage, "Contacting Medal Server - %s:%d", MEDAL_SERVER_HOST, MEDAL_SERVER_PORT);
216         
217         graphics.showMedalMessage(-1, connectMessage);
218         
219         char keyPath[PATH_MAX];
220         char privateKey[20];
221
222         snprintf(keyPath, sizeof keyPath, "%smedalKey", engine.userHomeDirectory);
223         
224         debug(("Loading private key from %s\n", keyPath));
225         
226         FILE *fp = fopen(keyPath, "rb");
227         
228         if (!fp)
229         {
230                 graphics.showMedalMessage(-1, "No Medal Key found - Online functions disabled");
231                 SDL_mutexV(medalServer.lock);
232                 return 0;
233         }
234         
235         if (fscanf(fp, "%19s", privateKey) != 1)
236         {
237                 graphics.showMedalMessage(-1, "Medal Key file corrupt - Online functions disabled");
238                 SDL_mutexV(medalServer.lock);
239                 fclose(fp);
240                 return 0;
241         }
242         
243         fclose(fp);
244                 
245         if (!medalServer.connect(privateKey))
246         {
247                 graphics.showMedalMessage(-1, "Medal Server Connection Failed - Online functions disabled");
248                 return 0;
249         }
250         
251         graphics.showMedalMessage(-1, "Connected to Medal Server");
252         
253         SDL_mutexV(medalServer.lock);
254         
255         return 1;
256 }
257
258 void initConfig()
259 {
260         #if UNIX
261         setupUserHomeDirectory();
262         #endif
263
264         displayLicense = loadConfig();
265 }
266
267 /*
268 Chugg chugg chugg.... brrr... chugg chugg chugg...brrrrrr... chugg ch..
269 BRRRRRRRRRRRRRRRRRMMMMMMMMMMMMMMMMMMM!! Well, hopefully anyway! ;)
270 */
271 void initSystem()
272 {
273         long flags = SDL_INIT_VIDEO|SDL_INIT_JOYSTICK;
274                         
275         if (engine.useAudio)
276         {
277                 flags |= SDL_INIT_AUDIO;
278         }
279
280         /* Initialize the SDL library */
281         if (SDL_Init(flags) < 0)
282         {
283                 printf("Couldn't initialize SDL: %s\n", SDL_GetError());
284                 exit(1);
285         }
286
287         graphics.screen = SDL_CreateRGBSurface(0, 640, 480, 32, 0xff0000, 0xff00, 0xff, 0xff000000);
288
289         if (graphics.screen == NULL)
290         {
291                 printf("Couldn't set 640x480 video mode: %s\n", SDL_GetError());
292                 exit(1);
293         }
294
295         // Increase the size of the window if we have large desktop resolutions
296         SDL_DisplayMode displayMode{0};
297         SDL_GetDesktopDisplayMode(0, &displayMode);
298         int w = graphics.screen->w;
299         int h = graphics.screen->h;
300         while (displayMode.w > w * 2 && displayMode.h > h * 2)
301         {
302                 w *= 2;
303                 h *= 2;
304         }
305
306         graphics.window = SDL_CreateWindow("Blobwars: Metal Blob Solid", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, SDL_WINDOW_RESIZABLE);
307
308         if (graphics.window == NULL)
309         {
310                 printf("Couldn't create %dx%d window: %s\n", w, h, SDL_GetError());
311                 exit(1);
312         }
313
314         graphics.renderer = SDL_CreateRenderer(graphics.window, -1, SDL_RENDERER_PRESENTVSYNC);
315
316         if (graphics.renderer == NULL)
317         {
318                 printf("Couldn't create renderer: %s\n", SDL_GetError());
319                 exit(1);
320         }
321
322         SDL_RenderSetLogicalSize(graphics.renderer, graphics.screen->w, graphics.screen->h);
323         graphics.texture = SDL_CreateTexture(graphics.renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, graphics.screen->w, graphics.screen->h);
324
325         if (graphics.texture == NULL)
326         {
327                 printf("Could not create %dx%d texture: %s\n", graphics.screen->w, graphics.screen->h, SDL_GetError());
328                 exit(1);
329         }
330
331         SDL_SetWindowFullscreen(graphics.window, engine.fullScreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
332
333         // This (attempts to) set the gamma correction. We attempt to catch an error here
334         // in case someone has done something really stupid in the config file(!!)
335         if (game.brightness != -1) {
336                 Math::limitInt(&game.brightness, 1, 20);
337                 float brightness = game.brightness;
338                 brightness /= 10;
339                 uint16_t ramp[256];
340                 SDL_CalculateGammaRamp(brightness, ramp);
341                 SDL_SetWindowGammaRamp(graphics.window, ramp, ramp, ramp);
342         }
343
344         if (TTF_Init() < 0)
345         {
346                 printf("Couldn't initialize SDL TTF: %s\n", SDL_GetError());
347                 exit(1);
348         }
349
350         if (engine.useAudio)
351         {
352                 if (Mix_OpenAudio(22050, AUDIO_S16, engine.useAudio, 1024) < 0)
353                 {
354                         printf("Warning: Couldn't set 44100 Hz 16-bit audio - Reason: %s\n", Mix_GetError());
355                         printf("Sound and Music will be disabled\n");
356                         engine.useAudio = 0;
357                 }
358         }
359
360         debug(("Found %d Joysticks...\n", SDL_NumJoysticks()));
361
362         if (SDL_NumJoysticks() > 0)
363         {
364                 debug(("Opening Joystick - %s...\n", SDL_JoystickName(0)));
365                 SDL_JoystickEventState(SDL_ENABLE);
366                 config.sdlJoystick = SDL_JoystickOpen(0);
367         }
368
369         SDL_ShowCursor(SDL_DISABLE);
370         SDL_EventState(SDL_MOUSEMOTION, SDL_DISABLE);
371
372         graphics.registerEngine(&engine);
373         graphics.mapColors();
374
375         audio.registerEngine(&engine);
376         audio.setSoundVolume(game.soundVol);
377         audio.setMusicVolume(game.musicVol);
378         audio.output = game.output;
379
380         debug(("Sound Volume = %d\n", game.soundVol));
381         debug(("Music Volume = %d\n", game.musicVol));
382         debug(("Output Type = %d\n", game.output));
383         debug(("Brightness = %d\n", game.brightness));
384         debug(("tmp dir = %s\n", engine.userHomeDirectory));
385         debug(("Pack Dir = %s\n", PAKLOCATION));
386         debug(("Loading Fonts...\n"));
387
388         #if USEPAK
389                 if (!engine.unpack("data/vera.ttf", PAK_FONT))
390                 {
391                         engine.reportFontFailure();
392                 }
393         #endif
394
395         graphics.loadFont(0, "data/vera.ttf", 12);
396         graphics.loadFont(1, "data/vera.ttf", 15);
397         graphics.loadFont(2, "data/vera.ttf", 19);
398         graphics.loadFont(3, "data/vera.ttf", 23);
399         graphics.loadFont(4, "data/vera.ttf", 24);
400
401         debug(("Font sizes all loaded!!\n"));
402
403         audio.loadSound(SND_CHEAT, "sound/Lock And Load!!!");
404         audio.loadSound(SND_HIGHLIGHT, "sound/menu");
405         audio.loadSound(SND_SELECT, "sound/select");
406         
407         graphics.medal[0] = graphics.loadImage("gfx/main/medal_bronze_1.png");
408         graphics.medal[1] = graphics.loadImage("gfx/main/award_star_silver_3.png");
409         graphics.medal[2] = graphics.loadImage("gfx/main/shield.png");
410         graphics.medal[3] = graphics.loadImage("gfx/main/ruby.png");
411
412         graphics.license[0] = graphics.loadImage("gfx/main/cc-by.png", true);
413         graphics.license[1] = graphics.loadImage("gfx/main/cc-by-sa.png", true);
414
415         SDL_Surface *device = graphics.loadImage("gfx/main/alienDevice.png");
416
417         SDL_FreeSurface(device);
418         
419         if (strstr(engine.userHomeDirectory, "/root"))
420         {
421                 graphics.showRootWarning();
422         }
423
424         if (displayLicense)
425         {
426                 showLicense();
427         }
428         else
429         {
430                 checkForLicense();
431         }
432         
433         if (SDLNet_Init() < 0)
434         {
435                 printf("SDLNet_Init: %s\n", SDLNet_GetError());
436         }
437         else
438         {
439                 SDL_Thread *thread = SDL_CreateThread(initMedalService, "MedalService", NULL);
440         
441                 if (thread == NULL)
442                 {
443                         printf("Unable to create thread: %s\n", SDL_GetError());
444                         printf("Calling medal server directly\n");
445                         initMedalService(NULL);
446                         return;
447                 }
448         }
449         
450         engine.saveConfig = true;
451
452         debug(("Init Complete...\n"));
453 }
454
455 /*
456 Removes [hopefully] all the resources that has been
457 loaded and created during the game. This is called by
458 atexit();
459 */
460 void cleanup()
461 {
462         char tempPath[PATH_MAX];
463         
464         debug(("Cleaning Up...\n"));
465         
466         debug(("Updating Replay Data\n"));
467         replayData.header.score = game.score;
468
469         debug(("Freeing Audio...\n"));
470         audio.destroy();
471
472         debug(("Removing Music...\n"));
473         snprintf(tempPath, sizeof tempPath, "%smusic.mod", engine.userHomeDirectory);
474         remove(tempPath);
475
476         debug(("Freeing Game Info...\n"));
477         game.destroy();
478
479         debug(("Freeing Map Data...\n"));
480         map.destroy();
481
482         debug(("Freeing Engine Data...\n"));
483         engine.destroy();
484
485         debug(("Freeing Graphics...\n"));
486         graphics.destroy();
487
488         debug(("Saving Config...\n"));
489         if (engine.saveConfig)
490         {
491                 saveConfig();
492         }
493
494         debug(("Removing Font File...\n"));
495         snprintf(tempPath, sizeof tempPath, "%sfont.ttf", engine.userHomeDirectory);
496         remove(tempPath);
497         
498         if (SDL_NumJoysticks() > 0)
499         {
500                 SDL_JoystickEventState(SDL_DISABLE);
501                 for (int i = 0 ; i < SDL_NumJoysticks() ; i++)
502                 {
503                         debug(("Closing Joystick #%d\n", i));
504                         SDL_JoystickClose(config.sdlJoystick);
505                 }
506         }
507
508         debug(("Closing Audio...\n"));
509         if (engine.useAudio)
510         {
511                 Mix_CloseAudio();
512         }
513
514         debug(("Closing TTF...\n"));
515         TTF_Quit();
516         
517         debug(("Closing NET...\n"));
518         SDLNet_Quit();
519
520         debug(("Closing SDL Sub System...\n"));
521         SDL_Quit();
522
523         debug(("All Done.\n"));
524         
525         if (replayData.replayMode == REPLAY_MODE::PLAYBACK)
526         {
527                 printf("\n==== ACTUAL PLAYBACK DATA ====\n");
528                 replayData.printReplayInformation();
529         }
530 }
531