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