OSDN Git Service

日本語版
[nazghul-jp/nazghul-jp.git] / src / nazghul.c
1 // nazghul - an old-school RPG engine
2 // Copyright (C) 2002, 2003 Gordon McNutt
3 //
4 // This program is free software; you can redistribute it and/or modify it
5 // under the terms of the GNU General Public License as published by the Free
6 // Software Foundation; either version 2 of the License, or (at your option)
7 // any later version.
8 //
9 // This program is distributed in the hope that it will be useful, but WITHOUT
10 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12 // more details.
13 //
14 // You should have received a copy of the GNU General Public License along with
15 // this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
16 // Suite 330, Boston, MA 02111-1307 USA
17 //
18 // Gordon McNutt
19 // gmcnutt@users.sourceforge.net
20 //
21 #include "../config.h"
22 #include "foogod.h"
23 #include "constants.h"
24 #include "file.h"
25 #include "dimensions.h"
26 #include "screen.h"
27 #include "sound.h"
28 #include "play.h"
29 #include "event.h"
30 #include "combat.h"
31 #include "images.h"
32 #include "sprite.h"
33 #include "player.h"
34 #include "place.h"
35 #include "wind.h"
36 #include "cmdwin.h"
37 #include "formation.h"
38 #include "map.h"
39 #include "vmask.h"
40 #include "status.h"
41 #include "log.h"
42 #include "tick.h"
43 #include "cmd.h"
44 #include "session.h"
45 #include "kern.h"
46 #include "cfg.h"
47 #include "menus.h"
48 #include "nazghul.h"
49 #include "conv.h"
50
51 #include <errno.h>
52 #include <signal.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <SDL.h>
56 #include <SDL_image.h>
57 #include <SDL_thread.h>
58 #include <unistd.h>
59 #include <getopt.h>
60
61 /* Name of the file to load the game from. */
62 static char *nazghul_load_fname = 0;
63
64 int FullScreenMode = 0;
65 int DeveloperMode = 0;
66 int ExitProgram = 0;
67
68 static char program_name[] = "nazghul";
69
70 static void print_version(void)
71 {
72         printf("%s %s\n", program_name, PACKAGE_VERSION);
73         printf("Copyright (C) 2003 Gordon McNutt, Sam Glasby\n"
74                "%s comes with NO WARRANTY,\n"
75                "to the extent permitted by law.\n"
76                "You may redistribute copies of %s\n"
77                "under the terms of the GNU General Public License.\n"
78                "For more information about these matters,\n"
79                "see the file named COPYING.\n",
80                program_name, program_name
81                 );
82 }
83
84 static void print_usage(void)
85 {
86         printf("Usage:  %s [options] <load-file>\n"
87                "Options: \n"
88                "    -h: help\n"
89                "    -v: version\n"
90                "    -d: developer mode\n"
91                "    -f: fullscreen mode\n"
92                "    -t: tick <period in msec> \n"
93                "    -a: animation <period in ticks> \n"
94                "    -s: sound <0 to disable> \n"
95                "    -R: recorder <filename>    \n"
96                "    -P: playback <filename>  \n"
97                "    -S: speed <playback ms delay> \n"
98                "    -I: game data dir\n"
99                "    -G: save game dir\n"
100                "    -r: screen size <pixels> (eg, 640x480)\n"
101                "    -T: show all terrain\n"
102                "<load-file>\n",
103                program_name);
104 }                               // print_usage()
105
106 static void parse_args(int argc, char **argv)
107 {
108         int c = 0;
109
110         TickMilliseconds = MS_PER_TICK;
111         AnimationTicks = ANIMATION_TICKS;
112
113         while ((c = getopt(argc, argv, "t:a:s:TdfR:S:P:I:G:vhr:")) != -1) {
114                 switch (c) {
115                 case 't':
116                         TickMilliseconds = atoi(optarg);
117                         break;
118                 case 'a':
119                         AnimationTicks = atoi(optarg);
120                         break;
121                 case 's':
122                         cfg_set("sound-enabled", 
123                                 atoi(optarg) != 0 ? "yes" : "no");
124                         break;
125                 case 'T':
126                         ShowAllTerrain = 1;
127                         break;
128                 case 'd':
129                         DeveloperMode = 1;
130                         break;
131                 case 'f':
132                         FullScreenMode = 1;
133                         break;
134                 case 'R':
135                         /* Set the filename for recording keystrokes. */
136                         cfg_set("record-filename", optarg);
137                         break;
138                 case 'S':
139                         /* Set the speed to play back recorded keystrokes. */
140                         cfg_set("playback-speed", optarg);
141                         break;
142                 case 'P':
143                         /* Set the file to play back keystrokes from. */
144                         cfg_set("playback-filename", optarg);
145                         break;
146                 case 'I':
147                         /* Set the directory for read-only game and cfg
148                          * files. */
149                         cfg_set("include-dirname", optarg);
150                         break;
151                 case 'G':
152                         /* Set the directory for read-write game and cfg
153                          * files. */
154                         cfg_set("saved-games-dirname", optarg);
155                         break;
156                 case 'v':
157                         print_version();
158                         exit(0);
159                         break;
160                 case 'h':
161                         print_usage();
162                         exit(0);
163                 case 'r':
164                         /* set the screen dimensions */
165                         cfg_set("screen-dims", optarg);
166                         break;
167                 case '?':
168                 default:
169                         print_usage();
170                         exit(-1);
171                         break;
172                 }               // switch (c)
173         }                       // while (c)
174
175         // --------------------------------------------------------------------
176         // Any remaining option is assumed to be the save-file to load the game
177         // from. If there is none then abort.
178         // --------------------------------------------------------------------
179
180         if (optind < argc) {
181                 nazghul_load_fname = argv[optind];
182         }
183 }                               // parse_args()
184
185 /**
186  * This initializes the various submodules.
187  */
188 static void nazghul_init_internal_libs(void)
189 {
190         struct lib_entry {
191                 const char *name;
192                 int (*init)(void);
193         };
194
195         struct lib_entry libs[] = {
196                 { "commonInit",     commonInit     },
197                 { "screenInit",     screenInit     },
198                 { "asciiInit",      asciiInit      },
199                 { "sprite_init",    sprite_init    },
200                 { "eventInit",      eventInit      },
201                 { "windInit",       windInit       },
202                 { "formation_init", formation_init },
203                 { "astar_init",     astar_init     },
204                 { "cmdwin_init",    cmdwin_init    },
205                 { "consoleInit",    consoleInit    },
206                 { "mapInit",        mapInit        },
207                 { "vmask_init",     vmask_init     },
208                 { "combatInit",     combatInit     },
209                 { "statusInit",     statusInit     },
210                 { "foogodInit",     foogodInit     },
211                 { "menu_init",      menu_init      },
212                 { "conv_init",      conv_init      }
213         };
214
215         int i;
216
217         for (i = 0; i < array_sz(libs); i++) {
218                 if (libs[i].init() < 0) {
219                         /* this will not return: */
220                         menu_startup_error("Error in %s", libs[i].name);
221                 }
222         }
223
224         log_init();
225
226         if (!strcmp("yes", cfg_get("sound-enabled"))) {
227                 sound_init();
228                 music_init();
229                 set_music_volume(cfg_get("music-volume"));
230         }
231
232 }
233
234 /* nazghul_splash -- show the splash image */
235 void nazghul_splash(void)
236 {
237         static SDL_Surface *splash = 0;
238         SDL_Rect rect;
239
240         /* The first time through load the splash image from a file. */
241         if (! splash) {
242                 char *dims = cfg_get("screen-dims");
243                 const char *suffix = "-splash-image-filename";
244                 char *key;
245                 char *basename;
246                 char *filename;
247                 
248                 /* Build a key for the splash image filename based on the
249                  * screen dimensions. */
250                 key = (char*)malloc(strlen(dims) + strlen(suffix) + 1);
251                 assert(key);
252                 strcpy(key, dims);
253                 strcat(key, suffix);
254                 
255                 /* Lookup the filename. */
256                 basename = cfg_get(key);
257                 if (! basename) {
258                         warn("cfg_get: no key matches '%s'", key);
259                         free(key);
260                         return;
261                 }
262                 free(key);
263                 
264                 /* Look for the splash image, check the include dir first, then
265                  * check the current working dir */
266                 filename = file_mkpath(cfg_get("include-dirname"), basename);
267                 if (filename) {
268                         splash = IMG_Load(filename);
269                         free(filename);
270                 }
271                 if (! splash) {
272                         warn("IMG_Load failed: %s\n", SDL_GetError());
273                         return;
274                 }
275
276         }
277
278         rect.x = MAP_X;
279         rect.y = MAP_Y;
280         rect.w = MAP_W;
281         rect.h = MAP_H;
282         screenErase(&rect);
283
284         /* Fill out the screen destination rect */
285         rect.x = max(0, (MAP_W - splash->w) / 2) + MAP_X;
286         rect.y = max(0, (MAP_H - splash->h) / 2) + MAP_Y;
287         rect.w = min(splash->w, MAP_W);
288         rect.h = min(splash->h, MAP_H);
289
290         screenBlit(splash, NULL, &rect);
291         screenUpdate(&rect);
292 }
293
294 /* init_default_cfg -- initialize the global cfg settings to start-up defaults
295  * and prepare it for loading the cfg script */
296 static void init_default_cfg()
297 {
298         cfg_init();
299         cfg_set("init-script-filename", "kern-init.scm");
300         cfg_set("options-script-filename", "options.scm");
301         cfg_set("splash-image-filename", "splash.png");
302         cfg_set("screen-dims", "1280x960" /*"640x480"*/);
303         cfg_set("sound-enabled", "yes");
304         cfg_set("music-volume", "100%");
305         cfg_set("keyword-highlighting", "yes");
306 }
307
308 int main(int argc, char **argv)
309 {
310         int print_version = 1;
311
312         /* Initialize the cfg environment before parsing args. */
313         init_default_cfg();
314
315         parse_args(argc, argv);
316
317         /* Load the cfg script after parsing args */
318         if (file_load_from_include_dir(cfg_get("init-script-filename"))) {
319                 menu_startup_error("Error loading %s: %s", 
320                                    cfg_get("init-script-filename"), 
321                                    file_get_error());
322         }
323
324         /* Load the options script */
325         if (file_exists_in_save_dir(cfg_get("options-script-filename"))) {
326                 if (file_load_from_save_dir
327                     (cfg_get("options-script-filename"))) {
328                         warn("Could not load options script\n");
329                 }
330         }
331
332         if (dimensions_init()) {
333                 err("dimensions_init() failed\n");
334                 exit(-1);
335         }
336
337         nazghul_init_internal_libs();
338
339         tick_start(TickMilliseconds);
340
341  main_loop:
342         /* blank out the whole screen */
343         screenErase(NULL);
344         screenUpdate(NULL);
345
346         /* pause animation tick generation */
347         tick_pause();
348
349         /* Show the splash screen on startup */
350         nazghul_splash();
351         
352         /* The first time we start print the vesrsion info. */
353         if (print_version) {
354                 print_version = 0;
355                 log_banner("^c+bNazghul^c- ^c+G%s ÆüËܸìÈÇ^c-", PACKAGE_VERSION );
356         }
357
358         /* paint the border for the first time */
359         screen_repaint_frame();
360
361         /* if no load file specified on the command line then run the main
362          * menu */
363         if (! nazghul_load_fname)
364                 nazghul_load_fname = main_menu();
365
366         /* Clear out the vmask cache */
367         vmask_flush_all();
368
369         /* run the game, don't return until the user quits */
370         playRun(nazghul_load_fname);
371
372         /* cleanup modules that need it */
373         eventExit();
374
375         /* FIXME: need to free nazghul_load_fname */
376         /* reset save file so main menu runs */
377         nazghul_load_fname=0;
378
379         /* ExitProgram is set when the player closes the window; in that case
380          * drop out of the program without showing the main menu again. */
381         if (! ExitProgram) {
382                 /* In the past, memory leaks made this a bad idea. Let's give
383                  * it another go and try to work through them if they crop up
384                  * again. */
385                 goto main_loop;
386         }
387
388         tick_kill();
389
390         return 0;
391 }
392