]> icculus.org git repositories - taylor/freespace2.git/blob - src/cmdline/cmdline.cpp
added copyright header
[taylor/freespace2.git] / src / cmdline / cmdline.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Cmdline/cmdline.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * $Log$
16  * Revision 1.3  2002/06/09 04:41:15  relnev
17  * added copyright header
18  *
19  * Revision 1.2  2002/05/07 03:16:43  theoddone33
20  * The Great Newline Fix
21  *
22  * Revision 1.1.1.1  2002/05/03 03:28:08  root
23  * Initial import.
24  *
25  * 
26  * 8     8/26/99 8:51p Dave
27  * Gave multiplayer TvT messaging a heavy dose of sanity. Cheat codes.
28  * 
29  * 7     7/15/99 3:07p Dave
30  * 32 bit detection support. Mouse coord commandline.
31  * 
32  * 6     7/13/99 1:15p Dave
33  * 32 bit support. Whee!
34  * 
35  * 5     6/22/99 9:37p Dave
36  * Put in pof spewing.
37  * 
38  * 4     1/12/99 5:45p Dave
39  * Moved weapon pipeline in multiplayer to almost exclusively client side.
40  * Very good results. Bandwidth goes down, playability goes up for crappy
41  * connections. Fixed object update problem for ship subsystems.
42  * 
43  * 3     11/17/98 11:12a Dave
44  * Removed player identification by address. Now assign explicit id #'s.
45  * 
46  * 2     10/07/98 10:52a Dave
47  * Initial checkin.
48  * 
49  * 1     10/07/98 10:48a Dave
50  * 
51  * 38    10/02/98 3:22p Allender
52  * fix up the -connect option and fix the -port option
53  * 
54  * 37    9/15/98 4:04p Allender
55  * added back in the -ip_addr command line switch because it needs to be
56  * in the standalone server only executable
57  * 
58  * 36    9/14/98 11:52a Allender
59  * don't use cfile
60  * 
61  * 35    9/14/98 11:28a Allender
62  * support for server bashing of address when received from client.  Added
63  * a cmdline.cfg file to process command line arguments from a file
64  * 
65  * 34    9/08/98 2:20p Allender
66  * temporary code to force IP address to a specific value.
67  * 
68  * 33    8/20/98 5:30p Dave
69  * Put in handy multiplayer logfile system. Now need to put in useful
70  * applications of it all over the code.
71  * 
72  * 32    8/07/98 10:39a Allender
73  * fixed debug standalone problem where stats would continually get sent
74  * to tracker.  more debug code to help find stats problem
75  * 
76  * 31    7/24/98 11:14a Allender
77  * start of new command line options for version 1.04
78  * 
79  * 30    5/21/98 1:50a Dave
80  * Remove obsolete command line functions. Reduce shield explosion packets
81  * drastically. Tweak PXO screen even more. Fix file xfer system so that
82  * we can guarantee file uniqueness.
83  * 
84  * 29    5/18/98 9:10p Dave
85  * Put in many new PXO features. Fixed skill level bashing in multiplayer.
86  * Removed several old command line options. Put in network config files.
87  * 
88  * 28    5/09/98 7:16p Dave
89  * Put in CD checking. Put in standalone host password. Made pilot into
90  * popup scrollable.
91  * 
92  * 27    4/23/98 8:27p Allender
93  * basic support for cutscene playback.  Into movie code in place.  Tech
94  * room can view cutscenes stored in CDROM_dir variable
95  * 
96  * 26    4/09/98 5:43p Dave
97  * Remove all command line processing from the demo. Began work fixing up
98  * the new multi host options screen.
99  * 
100  * 25    4/02/98 11:40a Lawrance
101  * check for #ifdef DEMO instead of #ifdef DEMO_RELEASE
102  * 
103  * 24    4/01/98 5:56p Dave
104  * Fixed a messaging bug which caused msg_all mode in multiplayer not to
105  * work. Compile out a host of multiplayer options not available in the
106  * demo.
107  * 
108  * 23    3/14/98 2:48p Dave
109  * Cleaned up observer joining code. Put in support for file xfers to
110  * ingame joiners (observers or not). Revamped and reinstalled pseudo
111  * lag/loss system.
112  * 
113  * 22    2/22/98 12:19p John
114  * Externalized some strings
115  * 
116  * 21    1/31/98 4:32p Dave
117  * Put in new support for VMT player validation, game logging in and game
118  * logging out.
119  * 
120  * 20    12/10/97 4:45p Dave
121  * Added in more detailed support for multiplayer packet lag/loss. Fixed
122  * some multiplayer stuff. Added some controls to the standalone.
123  * 
124  * 19    12/09/97 6:14p Lawrance
125  * add -nomusic flag
126  * 
127  * 18    12/01/97 5:10p Dave
128  * Fixed a syntax bug.
129  * 
130  * 17    12/01/97 4:59p Dave
131  * Synchronized multiplayer debris objects. Put in pilot popup in main
132  * hall. Optimized simulated multiplayer lag module. Fixed a potential
133  * file_xfer bug.
134  * 
135  * 16    11/28/97 7:04p Dave
136  * Emergency checkin due to big system crash.
137  * 
138  * 15    11/28/97 5:06p Dave
139  * Put in facilities for simulating multiplayer lag.
140  * 
141  * 14    11/24/97 5:42p Dave
142  * Fixed a file xfer buffer free/malloc problem. Lengthened command line
143  * switch string parse length.
144  * 
145  * 13    11/12/97 4:39p Dave
146  * Put in multiplayer campaign support parsing, loading and saving. Made
147  * command-line variables better named. Changed some things on the initial
148  * pilot select screen.
149  * 
150  * 12    11/11/97 4:54p Dave
151  * Put in support for single vs. multiplayer pilots. Put in initial player
152  * selection screen (no command line option yet). Started work on
153  * multiplayer campaign file save gaming.
154  * 
155  * 11    11/11/97 11:55a Allender
156  * initialize network at beginning of application.  create new call to set
157  * which network protocol to use
158  * 
159  * 10    9/18/97 10:12p Dave
160  * Added -gimmemedals, which gives the current pilot all the medals in the
161  * game (debug)
162  * 
163  * 9     9/18/97 9:20a Dave
164  * Minor modifications
165  * 
166  * 8     9/15/97 11:40p Lawrance
167  * remove demo granularity switch
168  * 
169  * 7     9/09/97 3:39p Sandeep
170  * warning level 4 bugs
171  * 
172  * 6     9/03/97 5:03p Lawrance
173  * add support for -nosound command line parm
174  * 
175  * 5     8/22/97 8:52a Dave
176  * Removed a return statement which would have broken the parser out too
177  * early.
178  * 
179  * 4     8/21/97 4:55p Dave
180  * Added a switch for multiplayer chat streaming. Added a section for
181  * global command line vars.
182  * 
183  * 3     8/06/97 2:26p Dave
184  * Made the command line parse more robust. Made it easier to add and
185  * process new command-line switches.
186  * 
187  * 2     8/04/97 3:13p Dave
188  * Added command line functions. See cmdline.cpp for directions on adding
189  * new switches
190  * 
191  * 1     8/04/97 9:58a Dave
192  * 
193  * $NoKeywords: $
194  */
195
196 #include <string.h>
197 #include <stdlib.h>
198 #include "cmdline.h"
199 #include "linklist.h"
200 #include "systemvars.h"
201 #include "multi.h"
202 #include "cfile.h"
203
204 // variables
205 class cmdline_parm {
206 public:
207         cmdline_parm *next, *prev;
208         char *name;                                             // name of parameter, must start with '-' char
209         char *help;                                             // help text for this parameter
210         char *args;                                             // string value for parameter arguements (NULL if no arguements)
211         int name_found;                         // true if parameter on command line, otherwise false
212
213         cmdline_parm(char *name, char *help);
214         ~cmdline_parm();
215         int found();
216         int get_int();
217         float get_float();
218         char *str();
219 };
220
221 // here are the command line parameters that we will be using for FreeSpace
222 cmdline_parm standalone_arg("-standalone", NULL);
223 cmdline_parm nosound_arg("-nosound", NULL);
224 cmdline_parm nomusic_arg("-nomusic", NULL);
225 cmdline_parm startgame_arg("-startgame", NULL);
226 cmdline_parm gamename_arg("-gamename", NULL);
227 cmdline_parm gamepassword_arg("-password", NULL);
228 cmdline_parm gameclosed_arg("-closed", NULL);
229 cmdline_parm gamerestricted_arg("-restricted", NULL);
230 cmdline_parm allowabove_arg("-allowabove", NULL);
231 cmdline_parm allowbelow_arg("-allowbelow", NULL);
232 cmdline_parm port_arg("-port", NULL);
233 cmdline_parm connect_arg("-connect", NULL);
234 cmdline_parm multilog_arg("-multilog", NULL);
235 cmdline_parm server_firing_arg("-oldfire", NULL);
236 cmdline_parm client_dodamage("-clientdamage", NULL);
237 cmdline_parm pof_spew("-pofspew", NULL);
238 cmdline_parm d3d_32bit("-32bit", NULL);
239 cmdline_parm mouse_coords("-coords", NULL);
240 cmdline_parm timeout("-timeout", NULL);
241 cmdline_parm d3d_window("-window", NULL);
242
243 int Cmdline_multi_stream_chat_to_file = 0;
244 int Cmdline_freespace_no_sound = 0;
245 int Cmdline_freespace_no_music = 0;
246 int Cmdline_gimme_all_medals = 0;
247 int Cmdline_use_last_pilot = 0;
248 int Cmdline_multi_protocol = -1;
249 int Cmdline_cd_check = 1;
250 int Cmdline_start_netgame = 0;
251 int Cmdline_closed_game = 0;
252 int Cmdline_restricted_game = 0;
253 int Cmdline_network_port = -1;
254 char *Cmdline_game_name = NULL;
255 char *Cmdline_game_password = NULL;
256 char *Cmdline_rank_above= NULL;
257 char *Cmdline_rank_below = NULL;
258 char *Cmdline_connect_addr = NULL;
259 int Cmdline_multi_log = 0;
260 int Cmdline_server_firing = 0;
261 int Cmdline_client_dodamage = 0;
262 int Cmdline_spew_pof_info = 0;
263 int Cmdline_force_32bit = 0;
264 int Cmdline_mouse_coords = 0;
265 int Cmdline_timeout = -1;
266
267 int Cmdline_window = 0;
268
269 static cmdline_parm Parm_list(NULL, NULL);
270 static int Parm_list_inited = 0;
271
272
273 //      Return true if this character is an extra char (white space and quotes)
274 int is_extra_space(char ch)
275 {
276         return ((ch == ' ') || (ch == '\t') || (ch == 0x0a) || (ch == '\'') || (ch == '\"'));
277 }
278
279
280 // eliminates all leading and trailing extra chars from a string.  Returns pointer passed in.
281 char *drop_extra_chars(char *str)
282 {
283         int s, e;
284
285         s = 0;
286         while (str[s] && is_extra_space(str[s]))
287                 s++;
288
289         e = strlen(str) - 1;
290         while (e > s) {
291                 if (!is_extra_space(str[e])){
292                         break;
293                 }
294
295                 e--;
296         }
297
298         if (e > s){
299                 memmove(str, str + s, e - s + 1);
300         }
301
302         str[e - s + 1] = 0;
303         return str;
304 }
305
306
307 // internal function - copy the value for a parameter agruement into the cmdline_parm arg field
308 void parm_stuff_args(cmdline_parm *parm, char *cmdline)
309 {
310         char buffer[1024];
311         memset(buffer, 0, 1024);
312         char *dest = buffer;
313
314         cmdline += strlen(parm->name);
315
316         while ((*cmdline != 0) && (*cmdline != '-')) {
317                 *dest++ = *cmdline++;
318         }
319
320         drop_extra_chars(buffer);
321
322         // mwa 9/14/98 -- made it so that newer command line arguments found will overwrite
323         // the old arguments
324 //      Assert(parm->args == NULL);
325         if ( parm->args != NULL ) {
326                 delete( parm->args );
327                 parm->args = NULL;
328         }
329
330         int size = strlen(buffer) + 1;
331         if (size > 0) {
332                 parm->args = new char[size];
333                 memset(parm->args, 0, size);
334                 strcpy(parm->args, buffer);
335         }
336 }
337
338
339 // internal function - parse the command line, extracting parameter arguements if they exist
340 // cmdline - command line string passed to the application
341 void os_parse_parms(char *cmdline)
342 {
343         // locate command line parameters
344         cmdline_parm *parmp;
345         char *cmdline_offset;
346
347         for (parmp = GET_FIRST(&Parm_list); parmp !=END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp) ) {
348                 cmdline_offset = strstr(cmdline, parmp->name);
349                 if (cmdline_offset) {
350                         parmp->name_found = 1;
351                         parm_stuff_args(parmp, cmdline_offset);
352                 }
353         }
354 }
355
356
357 // validate the command line parameters.  Display an error if an unrecognized parameter is located.
358 void os_validate_parms(char *cmdline)
359 {
360         cmdline_parm *parmp;
361         char seps[] = " ,\t\n";
362         char *token;
363         int parm_found;
364
365    token = strtok(cmdline, seps);
366    while(token != NULL) {
367         
368                 if (token[0] == '-') {
369                         parm_found = 0;
370                         for (parmp = GET_FIRST(&Parm_list); parmp !=END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp) ) {
371                                 if (!stricmp(parmp->name, token)) {
372                                         parm_found = 1;
373                                         break;
374                                 }
375                         }
376
377                         if (parm_found == 0) {
378                                 Error(LOCATION,"Unrecogzined command line parameter %s", token);
379                         }
380                 }
381
382                 token = strtok(NULL, seps);
383         }
384 }
385
386
387 // Call once to initialize the command line system
388 //
389 // cmdline - command line string passed to the application
390 void os_init_cmdline(char *cmdline)
391 {
392         FILE *fp;
393
394         // read the cmdline.cfg file from the data folder, and pass the command line arguments to
395         // the the parse_parms and validate_parms line.  Read these first so anything actually on
396         // the command line will take precedence
397         fp = fopen("data\\cmdline.cfg", "rt");
398
399         // if the file exists, get a single line, and deal with it
400         if ( fp ) {
401                 char buf[1024], *p;
402
403                 fgets(buf, 1024, fp);
404
405                 // replace the newline character with a NUL:
406                 if ( (p = strrchr(buf, '\n')) != NULL ) {
407                         *p = '\0';
408                 }
409
410                 os_parse_parms(buf);
411                 os_validate_parms(buf);
412                 fclose(fp);
413         }
414
415
416
417         os_parse_parms(cmdline);
418         os_validate_parms(cmdline);
419
420 }
421
422
423 // arg constructor
424 // name_ - name of the parameter, must start with '-' character
425 // help_ - help text for this parameter
426 cmdline_parm::cmdline_parm(char *name_, char *help_)
427 {
428         name = name_;
429         help = help_;
430         args = NULL;
431         name_found = 0;
432
433         if (Parm_list_inited == 0) {
434                 list_init(&Parm_list);
435                 Parm_list_inited = 1;
436         }
437
438         if (name != NULL) {
439                 list_append(&Parm_list, this);
440         }
441 }
442
443
444 // destructor - frees any allocated memory
445 cmdline_parm::~cmdline_parm()
446 {
447         if (args) {
448                 delete [] args;
449                 args = NULL;
450         }
451 }
452
453
454 // returns - true if the parameter exists on the command line, otherwise false
455 int cmdline_parm::found()
456 {
457         return name_found;
458 }
459
460
461 // returns - the interger representation for the parameter arguement
462 int cmdline_parm::get_int()
463 {
464         Assert(args);
465         return atoi(args);
466 }
467
468
469 // returns - the float representation for the parameter arguement
470 float cmdline_parm::get_float()
471 {
472         Assert(args);
473         return (float)atof(args);
474 }
475
476
477 // returns - the string value for the parameter arguement
478 char *cmdline_parm::str()
479 {
480         Assert(args);
481         return args;
482 }
483
484 // external entry point into this modules
485 int parse_cmdline(char *cmdline)
486 {
487         os_init_cmdline(cmdline);
488
489         // is this a standalone server??
490         if (standalone_arg.found()) {
491                 Is_standalone = 1;
492         }
493
494         // run with no sound
495         if ( nosound_arg.found() ) {
496                 Cmdline_freespace_no_sound = 1;
497         }
498
499         // run with no music
500         if ( nomusic_arg.found() ) {
501                 Cmdline_freespace_no_music = 1;
502         }
503
504         // should we start a network game
505         if ( startgame_arg.found() ) {
506                 Cmdline_use_last_pilot = 1;
507                 Cmdline_start_netgame = 1;
508         }
509
510         // closed network game
511         if ( gameclosed_arg.found() ) {
512                 Cmdline_closed_game = 1;
513         }
514
515         // restircted network game
516         if ( gamerestricted_arg.found() ) {
517                 Cmdline_restricted_game = 1;
518         }
519
520         // get the name of the network game
521         if ( gamename_arg.found() ) {
522                 Cmdline_game_name = gamename_arg.str();
523
524                 // be sure that this string fits in our limits
525                 if ( strlen(Cmdline_game_name) > MAX_GAMENAME_LEN ) {
526                         Cmdline_game_name[MAX_GAMENAME_LEN-1] = '\0';
527                 }
528         }
529
530         // get the password for a pssword game
531         if ( gamepassword_arg.found() ) {
532                 Cmdline_game_password = gamepassword_arg.str();
533
534                 // be sure that this string fits in our limits
535                 if ( strlen(Cmdline_game_name) > MAX_PASSWD_LEN ) {
536                         Cmdline_game_name[MAX_PASSWD_LEN-1] = '\0';
537                 }
538         }
539
540         // set the rank above/below arguments
541         if ( allowabove_arg.found() ) {
542                 Cmdline_rank_above = allowabove_arg.str();
543         }
544         if ( allowbelow_arg.found() ) {
545                 Cmdline_rank_below = allowbelow_arg.str();
546         }
547
548         // get the port number for games
549         if ( port_arg.found() ) {
550                 Cmdline_network_port = port_arg.get_int();
551         }
552
553         // the connect argument specifies to join a game at this particular address
554         if ( connect_arg.found() ) {
555                 Cmdline_use_last_pilot = 1;
556                 Cmdline_connect_addr = connect_arg.str();
557         }
558
559         // see if the multilog flag was set
560         if ( multilog_arg.found() ){
561                 Cmdline_multi_log = 1;
562         }       
563
564         // maybe use old-school server-side firing
565         if (server_firing_arg.found() ){
566                 Cmdline_server_firing = 1;
567         }
568
569         // maybe use old-school client damage
570         if(client_dodamage.found()){
571                 Cmdline_client_dodamage = 1;
572         }       
573
574         // spew pof info
575         if(pof_spew.found()){
576                 Cmdline_spew_pof_info = 1;
577         }
578
579         // 32 bit
580         if(d3d_32bit.found()){
581                 Cmdline_force_32bit = 1;
582         }
583
584         // mouse coords
585         if(mouse_coords.found()){
586                 Cmdline_mouse_coords = 1;
587         }
588
589         // net timeout
590         if(timeout.found()){
591                 Cmdline_timeout = timeout.get_int();
592         }
593
594         // d3d windowed
595         if(d3d_window.found()){
596                 Cmdline_window = 1;
597         }
598
599         return 1;
600 }
601