1 /*
2  * OpenTyrian: A modern cross-platform port of Tyrian
3  * Copyright (C) 2007-2009  The OpenTyrian Development Team
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.  See the
13  * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  */
19 #include "config.h"
20 #include "destruct.h"
21 #include "editship.h"
22 #include "episodes.h"
23 #include "file.h"
24 #include "font.h"
25 #include "helptext.h"
26 #include "hg_revision.h"
27 #include "joystick.h"
28 #include "jukebox.h"
29 #include "keyboard.h"
30 #include "loudness.h"
31 #include "mainint.h"
32 #include "mtrand.h"
33 #include "musmast.h"
34 #include "network.h"
35 #include "nortsong.h"
36 #include "opentyr.h"
37 #include "params.h"
38 #include "picload.h"
39 #include "scroller.h"
40 #include "setup.h"
41 #include "sprite.h"
42 #include "tyrian2.h"
43 #include "xmas.h"
44 #include "varz.h"
45 #include "vga256d.h"
46 #include "video.h"
47 #include "video_scale.h"
48 
49 #include "SDL.h"
50 
51 #include <assert.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <time.h>
55 
56 const char *opentyrian_str = "OpenTyrian",
57            *opentyrian_version = HG_REV;
58 
59 /* zero-terminated strncpy */
strnztcpy(char * to,const char * from,size_t count)60 char *strnztcpy( char *to, const char *from, size_t count )
61 {
62 	to[count] = '\0';
63 	return strncpy(to, from, count);
64 }
65 
opentyrian_menu(void)66 void opentyrian_menu( void )
67 {
68 	typedef enum
69 	{
70 		MENU_ABOUT = 0,
71 		MENU_FULLSCREEN,
72 		MENU_SCALER,
73 		// MENU_DESTRUCT,
74 		MENU_JUKEBOX,
75 		MENU_RETURN,
76 		MenuOptions_MAX
77 	} MenuOptions;
78 
79 	static const char *menu_items[] =
80 	{
81 		"About OpenTyrian",
82 		"Toggle Fullscreen",
83 		"Scaler: None",
84 		// "Play Destruct",
85 		"Jukebox",
86 		"Return to Main Menu",
87 	};
88 	bool menu_items_disabled[] =
89 	{
90 		false,
91 		!can_init_any_scaler(false) || !can_init_any_scaler(true),
92 		false,
93 		// false,
94 		false,
95 		false,
96 	};
97 
98 	assert(COUNTOF(menu_items) == MenuOptions_MAX);
99 	assert(COUNTOF(menu_items_disabled) == MenuOptions_MAX);
100 
101 	fade_black(10);
102 	JE_loadPic(VGAScreen, 13, false);
103 
104 	draw_font_hv(VGAScreen, VGAScreen->w / 2, 5, opentyrian_str, large_font, centered, 15, -3);
105 
106 	memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h);
107 
108 	JE_showVGA();
109 
110 	play_song(36); // A Field for Mag
111 
112 	MenuOptions sel = 0;
113 
114 	uint temp_scaler = scaler;
115 
116 	bool fade_in = true, quit = false;
117 	do
118 	{
119 		memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->pitch * VGAScreen->h);
120 
121 		for (MenuOptions i = 0; i < MenuOptions_MAX; i++)
122 		{
123 			const char *text = menu_items[i];
124 			char buffer[100];
125 
126 			if (i == MENU_SCALER)
127 			{
128 				snprintf(buffer, sizeof(buffer), "Scaler: %s", scalers[temp_scaler].name);
129 				text = buffer;
130 			}
131 
132 			int y = i != MENU_RETURN ? i * 16 + 32 : 118;
133 			draw_font_hv(VGAScreen, VGAScreen->w / 2, y, text, normal_font, centered, 15, menu_items_disabled[i] ? -8 : i != sel ? -4 : -2);
134 		}
135 
136 		JE_showVGA();
137 
138 		if (fade_in)
139 		{
140 			fade_in = false;
141 			fade_palette(colors, 20, 0, 255);
142 			wait_noinput(true, false, false);
143 		}
144 
145 		tempW = 0;
146 		JE_textMenuWait(&tempW, false);
147 
148 		if (newkey)
149 		{
150 			switch (lastkey_sym)
151 			{
152 			case SDLK_UP:
153 				do
154 				{
155 					if (sel-- == 0)
156 						sel = MenuOptions_MAX - 1;
157 				}
158 				while (menu_items_disabled[sel]);
159 
160 				JE_playSampleNum(S_CURSOR);
161 				break;
162 			case SDLK_DOWN:
163 				do
164 				{
165 					if (++sel >= MenuOptions_MAX)
166 						sel = 0;
167 				}
168 				while (menu_items_disabled[sel]);
169 
170 				JE_playSampleNum(S_CURSOR);
171 				break;
172 
173 			case SDLK_LEFT:
174 				if (sel == MENU_SCALER)
175 				{
176 					do
177 					{
178 						if (temp_scaler == 0)
179 							temp_scaler = scalers_count;
180 						temp_scaler--;
181 					}
182 					while (!can_init_scaler(temp_scaler, fullscreen_enabled));
183 
184 					JE_playSampleNum(S_CURSOR);
185 				}
186 				break;
187 			case SDLK_RIGHT:
188 				if (sel == MENU_SCALER)
189 				{
190 					do
191 					{
192 						temp_scaler++;
193 						if (temp_scaler == scalers_count)
194 							temp_scaler = 0;
195 					}
196 					while (!can_init_scaler(temp_scaler, fullscreen_enabled));
197 
198 					JE_playSampleNum(S_CURSOR);
199 				}
200 				break;
201 
202 			case SDLK_RETURN:
203 				switch (sel)
204 				{
205 				case MENU_ABOUT:
206 					JE_playSampleNum(S_SELECT);
207 
208 					scroller_sine(about_text);
209 
210 					memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->pitch * VGAScreen->h);
211 					JE_showVGA();
212 					fade_in = true;
213 					break;
214 
215 				case MENU_FULLSCREEN:
216 					JE_playSampleNum(S_SELECT);
217 
218 					if (!init_scaler(scaler, !fullscreen_enabled) && // try new fullscreen state
219 						!init_any_scaler(!fullscreen_enabled) &&     // try any scaler in new fullscreen state
220 						!init_scaler(scaler, fullscreen_enabled))    // revert on fail
221 					{
222 						exit(EXIT_FAILURE);
223 					}
224 					set_palette(colors, 0, 255); // for switching between 8 bpp scalers
225 					break;
226 
227 				case MENU_SCALER:
228 					JE_playSampleNum(S_SELECT);
229 
230 					if (scaler != temp_scaler)
231 					{
232 						if (!init_scaler(temp_scaler, fullscreen_enabled) &&   // try new scaler
233 							!init_scaler(temp_scaler, !fullscreen_enabled) &&  // try other fullscreen state
234 							!init_scaler(scaler, fullscreen_enabled))          // revert on fail
235 						{
236 							exit(EXIT_FAILURE);
237 						}
238 						set_palette(colors, 0, 255); // for switching between 8 bpp scalers
239 					}
240 					break;
241 
242 				case MENU_JUKEBOX:
243 					JE_playSampleNum(S_SELECT);
244 
245 					fade_black(10);
246 					jukebox();
247 
248 					memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->pitch * VGAScreen->h);
249 					JE_showVGA();
250 					fade_in = true;
251 					break;
252 
253 				case MENU_RETURN:
254 					quit = true;
255 					JE_playSampleNum(S_SPRING);
256 					break;
257 
258 				case MenuOptions_MAX:
259 					assert(false);
260 					break;
261 				}
262 				break;
263 
264 			case SDLK_ESCAPE:
265 				quit = true;
266 				JE_playSampleNum(S_SPRING);
267 				break;
268 
269 			default:
270 				break;
271 			}
272 		}
273 	} while (!quit);
274 }
275 
main(int argc,char * argv[])276 int main( int argc, char *argv[] )
277 {
278 	mt_srand(time(NULL));
279 
280 	printf("\nWelcome to... >> %s %s <<\n\n", opentyrian_str, opentyrian_version);
281 
282 	printf("Copyright (C) 2007-2013 The OpenTyrian Development Team\n\n");
283 
284 	printf("This program comes with ABSOLUTELY NO WARRANTY.\n");
285 	printf("This is free software, and you are welcome to redistribute it\n");
286 	printf("under certain conditions.  See the file GPL.txt for details.\n\n");
287 
288 	if (SDL_Init(0))
289 	{
290 		printf("Failed to initialize SDL: %s\n", SDL_GetError());
291 		return -1;
292 	}
293 
294 	JE_loadConfiguration();
295 
296 	xmas = xmas_time();  // arg handler may override
297 
298 	JE_paramCheck(argc, argv);
299 
300 	JE_scanForEpisodes();
301 
302 	init_video();
303 	init_keyboard();
304 	init_joysticks();
305 	printf("assuming mouse detected\n"); // SDL can't tell us if there isn't one
306 
307 	if (xmas && (!dir_file_exists(data_dir(), "tyrianc.shp") || !dir_file_exists(data_dir(), "voicesc.snd")))
308 	{
309 		xmas = false;
310 
311 		fprintf(stderr, "warning: Christmas is missing.\n");
312 	}
313 
314 	JE_loadPals();
315 	JE_loadMainShapeTables(xmas ? "tyrianc.shp" : "tyrian.shp");
316 
317 	if (xmas && !xmas_prompt())
318 	{
319 		xmas = false;
320 
321 		free_main_shape_tables();
322 		JE_loadMainShapeTables("tyrian.shp");
323 	}
324 
325 
326 	/* Default Options */
327 	youAreCheating = false;
328 	smoothScroll = true;
329 	loadDestruct = false;
330 
331 	if (!audio_disabled)
332 	{
333 		printf("initializing SDL audio...\n");
334 
335 		init_audio();
336 
337 		load_music();
338 
339 		JE_loadSndFile("tyrian.snd", xmas ? "voicesc.snd" : "voices.snd");
340 	}
341 	else
342 	{
343 		printf("audio disabled\n");
344 	}
345 
346 	if (record_demo)
347 		printf("demo recording enabled (input limited to keyboard)\n");
348 
349 	JE_loadExtraShapes();  /*Editship*/
350 
351 	JE_loadHelpText();
352 	/*debuginfo("Help text complete");*/
353 
354 	if (isNetworkGame)
355 	{
356 #ifdef WITH_NETWORK
357 		if (network_init())
358 		{
359 			network_tyrian_halt(3, false);
360 		}
361 #else
362 		fprintf(stderr, "OpenTyrian was compiled without networking support.");
363 		JE_tyrianHalt(5);
364 #endif
365 	}
366 
367 #ifdef NDEBUG
368 	if (!isNetworkGame)
369 		intro_logos();
370 #endif
371 
372 	for (; ; )
373 	{
374 		JE_initPlayerData();
375 		JE_sortHighScores();
376 
377 		if (JE_titleScreen(true))
378 			break;  // user quit from title screen
379 
380 		if (loadDestruct)
381 		{
382 			JE_destructGame();
383 			loadDestruct = false;
384 		}
385 		else
386 		{
387 			JE_main();
388 		}
389 	}
390 
391 	JE_tyrianHalt(0);
392 
393 	return 0;
394 }
395 
396