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