1
2 /**
3 *
4 * @file main.cpp
5 *
6 * Part of the OpenJazz project
7 *
8 * @par History:
9 * - 23rd August 2005: Created main.c
10 * - 22nd July 2008: Created util.c from parts of main.c
11 * - 3rd February 2009: Renamed main.c to main.cpp
12 * - 4th February 2009: Created palette.cpp from parts of main.cpp and util.cpp
13 * - 13th July 2009: Created controls.cpp from parts of main.cpp
14 * - 21st July 2013: Created setup.cpp from parts of main.cpp and setupmenu.cpp
15 *
16 * @par Licence:
17 * Copyright (c) 2005-2017 Alister Thomson
18 *
19 * OpenJazz is distributed under the terms of
20 * the GNU General Public License, version 2.0
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 *
26 * @par Description:
27 * Contains the main function.
28 *
29 */
30
31
32 #define EXTERN
33
34 #include "game/game.h"
35 #include "io/controls.h"
36 #include "io/file.h"
37 #include "io/gfx/font.h"
38 #include "io/gfx/video.h"
39 #include "io/network.h"
40 #include "io/sound.h"
41 #include "jj2level/jj2level.h"
42 #include "jj1level/jj1level.h"
43 #include "menu/menu.h"
44 #include "player/player.h"
45 #include "jj1scene/jj1scene.h"
46 #include "loop.h"
47 #include "setup.h"
48 #include "util.h"
49
50 #ifdef PSP
51 #include <pspsdk.h>
52 #include <pspkernel.h>
53 #include <pspthreadman.h>
54 #include <pspmoduleinfo.h>
55 #include <pspdebug.h>
56 #include <psputility.h>
57 #include <pspdisplay.h>
58 #elif defined(_3DS)
59 #include <3ds.h>
60 #elif defined(__HAIKU__)
61 #include <Alert.h>
62 #include <FindDirectory.h>
63 #include <fs_info.h>
64 #endif
65
66 #include <string.h>
67
68 #if defined(WIZ) || defined(GP2X)
69 #include "platforms/wiz.h"
70 #endif
71
72 #ifdef __SYMBIAN32__
73 extern char KOpenJazzPath[256];
74 extern float sinf (float);
75 #else
76 #include <math.h>
77 #endif
78
79 #define PI 3.141592f
80
81
82 /**
83 * Initialises OpenJazz.
84 *
85 * Establishes the paths from which to read files, loads configuration, sets up
86 * the game window and loads required data.
87 *
88 * @param argc Number of arguments, as passed to main function
89 * @param argv Array of argument strings, as passed to main function
90 */
startUp(int argc,char * argv[])91 void startUp (int argc, char *argv[]) {
92
93 File* file;
94 unsigned char* pixels = NULL;
95 int count;
96 int screenW = DEFAULT_SCREEN_WIDTH;
97 int screenH = DEFAULT_SCREEN_HEIGHT;
98 int scaleFactor = 1;
99 #ifdef FULLSCREEN_ONLY
100 bool fullscreen = true;
101 #else
102 bool fullscreen = false;
103 #endif
104
105
106 // Determine paths
107
108 // Use hard-coded paths, if available
109
110 #ifdef DATAPATH
111 firstPath = new Path(NULL, createString(DATAPATH));
112 #else
113 firstPath = NULL;
114 #endif
115
116 #ifdef __HAIKU__
117 dev_t volume = dev_for_path("/boot");
118 char buffer[10 + B_PATH_NAME_LENGTH + B_FILE_NAME_LENGTH];
119 status_t result;
120
121 result = find_directory(B_SYSTEM_DATA_DIRECTORY,
122 volume, false, buffer, sizeof(buffer));
123 strncat(buffer, "/openjazz/", sizeof(buffer));
124 firstPath = new Path(firstPath, createString(buffer));
125
126 result = find_directory(B_USER_NONPACKAGED_DATA_DIRECTORY,
127 volume, false, buffer, sizeof(buffer));
128 strncat(buffer, "/openjazz/", sizeof(buffer));
129 firstPath = new Path(firstPath, createString(buffer));
130 #endif
131
132 #ifdef __SYMBIAN32__
133 #ifdef UIQ3
134 firstPath = new Path(firstPath, createString("c:\\shared\\openjazz\\"));
135 #else
136 firstPath = new Path(firstPath, createString("c:\\data\\openjazz\\"));
137 #endif
138 firstPath = new Path(firstPath, createString(KOpenJazzPath));
139 #endif
140
141
142 // Use any provided paths, appending a directory separator as necessary
143
144 for (count = 1; count < argc; count++) {
145
146 // If it isn't an option, it should be a path
147 if (argv[count][0] != '-') {
148
149 #ifdef _WIN32
150 if (argv[count][strlen(argv[count]) - 1] != '\\') {
151
152 firstPath = new Path(firstPath, createString(argv[count], "\\"));
153 #else
154 if (argv[count][strlen(argv[count]) - 1] != '/') {
155
156 firstPath = new Path(firstPath, createString(argv[count], "/"));
157 #endif
158
159 } else {
160
161 firstPath = new Path(firstPath, createString(argv[count]));
162
163 }
164
165 }
166
167 }
168
169
170 // Use the path of the program
171
172 count = strlen(argv[0]) - 1;
173
174 // Search for directory separator
175 #ifdef _WIN32
176 while ((argv[0][count] != '\\') && (count >= 0)) count--;
177 #else
178 while ((argv[0][count] != '/') && (count >= 0)) count--;
179 #endif
180
181 // If a directory was found, copy it to the path
182 if (count > 0) {
183
184 firstPath = new Path(firstPath, new char[count + 2]);
185 memcpy(firstPath->path, argv[0], count + 1);
186 firstPath->path[count + 1] = 0;
187
188 }
189
190
191 // Use the user's home directory, if available
192
193 #ifdef HOMEDIR
194 #ifdef _WIN32
195 firstPath = new Path(firstPath, createString(getenv("HOME"), "\\"));
196 #else
197 firstPath = new Path(firstPath, createString(getenv("HOME"), "/."));
198 #endif
199 #endif
200
201
202 // Use the current working directory
203
204 firstPath = new Path(firstPath, createString(""));
205
206
207
208 // Default settings
209
210 // Sound settings
211 #if defined(WIZ) || defined(GP2X)
212 volume = 40;
213 #endif
214
215 // Create the network address
216 netAddress = createString(NET_ADDRESS);
217
218
219 // Load settings from config file
220 setup.load(&screenW, &screenH, &fullscreen, &scaleFactor);
221
222
223 // Get command-line override
224 for (count = 1; count < argc; count++) {
225
226 // If there's a hyphen, it should be an option
227 if (argv[count][0] == '-') {
228
229 #ifndef FULLSCREEN_ONLY
230 if (argv[count][1] == 'f') fullscreen = true;
231 #endif
232 if (argv[count][1] == 'm') {
233 setMusicVolume(0);
234 setSoundVolume(0);
235 }
236
237 }
238
239 }
240
241
242 // Create the game's window
243
244 canvas = NULL;
245
246 if (!video.init(screenW, screenH, fullscreen)) {
247
248 delete firstPath;
249
250 throw E_VIDEO;
251
252 }
253
254 #ifdef SCALE
255 video.setScaleFactor(scaleFactor);
256 #endif
257
258
259 if (SDL_NumJoysticks() > 0) SDL_JoystickOpen(0);
260
261
262 // Set up audio
263 openAudio();
264
265
266
267 // Load fonts
268
269 // Open the panel, which contains two fonts
270
271 try {
272
273 file = new File("PANEL.000", false);
274
275 } catch (int e) {
276
277 closeAudio();
278
279 delete firstPath;
280
281 log("Unable to find game data files. When launching OpenJazz, pass the location");
282 log("of the original game data, eg:");
283 log(" OpenJazz ~/jazz1");
284
285 #ifdef __HAIKU__
286 char alertBuffer[100+B_PATH_NAME_LENGTH+B_FILE_NAME_LENGTH];
287 strcpy(alertBuffer, "Unable to find game data files!\n"
288 "Put the data into the folder:\n");
289 strncat(alertBuffer, buffer, sizeof(alertBuffer));
290 BAlert* alert = new BAlert("OpenJazz", alertBuffer, "Exit", NULL, NULL,
291 B_WIDTH_AS_USUAL, B_STOP_ALERT);
292 alert->Go();
293 #endif
294
295 throw e;
296
297 }
298
299 pixels = file->loadRLE(46272);
300
301 delete file;
302
303 panelBigFont = NULL;
304 panelSmallFont = NULL;
305 font2 = NULL;
306 fontbig = NULL;
307 fontiny = NULL;
308 fontmn1 = NULL;
309
310 try {
311
312 panelBigFont = new Font(pixels + (40 * 320), true);
313 panelSmallFont = new Font(pixels + (48 * 320), false);
314 font2 = new Font("FONT2.0FN");
315 fontbig = new Font("FONTBIG.0FN");
316 fontiny = new Font("FONTINY.0FN");
317 fontmn1 = new Font("FONTMN1.0FN");
318 fontmn2 = new Font("FONTMN2.0FN");
319
320 } catch (int e) {
321
322 if (panelBigFont) delete panelBigFont;
323 if (panelSmallFont) delete panelSmallFont;
324 if (font2) delete font2;
325 if (fontbig) delete fontbig;
326 if (fontiny) delete fontiny;
327 if (fontmn1) delete fontmn1;
328
329 delete[] pixels;
330
331 closeAudio();
332
333 delete firstPath;
334
335 throw e;
336
337 }
338
339 delete[] pixels;
340
341
342 // Establish arbitrary timing
343 globalTicks = SDL_GetTicks() - 20;
344
345
346 // Fill trigonometric function look-up tables
347 for (count = 0; count < 1024; count++)
348 sinLut[count] = fixed(sinf(2 * PI * float(count) / 1024.0f) * 1024.0f);
349
350
351 // Initiate networking
352 net = new Network();
353
354
355 level = NULL;
356 jj2Level = NULL;
357
358 }
359
360
361 /**
362 * De-initialises OpenJazz.
363 *
364 * Frees data, writes configuration, and shuts down SDL.
365 */
366 void shutDown () {
367
368 delete net;
369
370 delete panelBigFont;
371 delete panelSmallFont;
372 delete font2;
373 delete fontbig;
374 delete fontiny;
375 delete fontmn1;
376 delete fontmn2;
377
378 #ifdef SCALE
379 if (video.getScaleFactor() > 1) SDL_FreeSurface(canvas);
380 #endif
381
382 closeAudio();
383
384
385 // Save settings to config file
386 setup.save();
387
388
389 delete firstPath;
390
391 }
392
393
394 /**
395 * Run the cutscenes and the main menu.
396 *
397 * @return Error code
398 */
399 int play () {
400
401 MainMenu *mainMenu = NULL;
402 JJ1Scene *scene = NULL;
403
404 // Load and play the startup cutscene
405
406 try {
407
408 scene = new JJ1Scene("STARTUP.0SC");
409
410 } catch (int e) {
411
412 return e;
413
414 }
415
416 if (scene->play() == E_QUIT) {
417
418 delete scene;
419
420 return E_NONE;
421
422 }
423
424 delete scene;
425
426
427 // Load and run the menu
428
429 try {
430
431 mainMenu = new MainMenu();
432
433 } catch (int e) {
434
435 return e;
436
437 }
438
439 if (mainMenu->main() == E_QUIT) {
440
441 delete mainMenu;
442
443 return E_NONE;
444
445 }
446
447 delete mainMenu;
448
449
450 // Load and play the ending cutscene
451
452 try {
453
454 scene = new JJ1Scene("END.0SC");
455
456 } catch (int e) {
457
458 return e;
459
460 }
461
462 scene->play();
463
464 delete scene;
465
466
467 return E_NONE;
468
469 }
470
471
472 /**
473 * Process iteration.
474 *
475 * Called once per game iteration. Updates timing, video, and input
476 *
477 * @param type Type of loop. Normal, typing, or input configuration
478 * @param paletteEffects Palette effects to apply to video output
479 *
480 * @return Error code
481 */
482 int loop (LoopType type, PaletteEffect* paletteEffects) {
483
484 SDL_Event event;
485 int prevTicks, ret;
486
487
488 // Update tick count
489 prevTicks = globalTicks;
490 globalTicks = SDL_GetTicks();
491
492 if (globalTicks - prevTicks < 4) {
493
494 // Limit framerate
495 SDL_Delay(4 + prevTicks - globalTicks);
496 globalTicks = SDL_GetTicks();
497
498 }
499
500 // Show what has been drawn
501 video.flip(globalTicks - prevTicks, paletteEffects);
502
503
504 // Process system events
505 while (SDL_PollEvent(&event)) {
506
507 if (event.type == SDL_QUIT) return E_QUIT;
508
509 ret = controls.update(&event, type);
510
511 if (ret != E_NONE) return ret;
512
513 video.update(&event);
514
515 #if defined(WIZ) || defined(GP2X)
516 if ((event.type == SDL_JOYBUTTONDOWN) ||
517 (event.type == SDL_JOYBUTTONUP)) {
518
519 if (event.jbutton.button == GP2X_BUTTON_VOLUP ) {
520 if( event.type == SDL_JOYBUTTONDOWN )
521 volume_direction = VOLUME_UP;
522 else
523 volume_direction = VOLUME_NOCHG;
524 }
525 if (event.jbutton.button == GP2X_BUTTON_VOLDOWN ) {
526 if( event.type == SDL_JOYBUTTONDOWN )
527 volume_direction = VOLUME_DOWN;
528 else
529 volume_direction = VOLUME_NOCHG;
530 }
531
532 }
533 #endif
534
535 }
536
537 controls.loop();
538
539
540 #if defined(WIZ) || defined(GP2X)
541 WIZ_AdjustVolume( volume_direction );
542 #endif
543
544 return E_NONE;
545
546 }
547
548 #ifdef PSP
549 PSP_MODULE_INFO("OpenJazz", PSP_MODULE_USER, 0, 1);
550 PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER);
551 PSP_HEAP_SIZE_KB(-2048);
552 #endif
553
554 /**
555 * Main.
556 *
557 * Initialises SDL and launches game.
558 */
559 int main(int argc, char *argv[]) {
560
561 int ret;
562
563 #ifdef PSP
564 pspDebugScreenInit();
565 atexit(sceKernelExitGame);
566 sceIoChdir("ms0:/PSP/GAME/OpenJazz");
567 #endif
568 // Initialise SDL
569
570 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK) < 0) {
571
572 logError("Could not start SDL", SDL_GetError());
573
574 return -1;
575
576 }
577
578
579 // Load configuration and establish a window
580
581 try {
582
583 startUp(argc, argv);
584
585 } catch (int e) {
586
587 SDL_Quit();
588
589 return -1;
590
591 }
592
593
594 // Play the opening cutscene, run the main menu, etc.
595
596 ret = play();
597
598
599 // Save configuration and shut down
600
601 shutDown();
602
603 SDL_Quit();
604
605 return ret;
606
607 }
608
609
610