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