Files
fs2open.github.com/code/cmdline/cmdline.cpp
T
2002-07-07 19:56:00 +00:00

634 lines
16 KiB
C++

/*
* Copyright (C) Volition, Inc. 1999. All rights reserved.
*
* All source code herein is the property of Volition, Inc. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
/*
* $Logfile: /Freespace2/code/Cmdline/cmdline.cpp $
* $Revision: 2.1 $
* $Date: 2002-07-07 19:55:58 $
* $Author: penguin $
*
* $Log: not supported by cvs2svn $
* Revision 2.0 2002/06/03 04:02:21 penguin
* Warpcore CVS sync
*
* Revision 1.3 2002/05/08 17:29:17 mharris
* more port tweaks
*
* Revision 1.2 2002/05/07 13:22:14 mharris
* added pstypes.h include
*
* Revision 1.1 2002/05/02 18:03:04 mharris
* Initial checkin - converted filenames and includes to lower case
*
*
* 8 8/26/99 8:51p Dave
* Gave multiplayer TvT messaging a heavy dose of sanity. Cheat codes.
*
* 7 7/15/99 3:07p Dave
* 32 bit detection support. Mouse coord commandline.
*
* 6 7/13/99 1:15p Dave
* 32 bit support. Whee!
*
* 5 6/22/99 9:37p Dave
* Put in pof spewing.
*
* 4 1/12/99 5:45p Dave
* Moved weapon pipeline in multiplayer to almost exclusively client side.
* Very good results. Bandwidth goes down, playability goes up for crappy
* connections. Fixed object update problem for ship subsystems.
*
* 3 11/17/98 11:12a Dave
* Removed player identification by address. Now assign explicit id #'s.
*
* 2 10/07/98 10:52a Dave
* Initial checkin.
*
* 1 10/07/98 10:48a Dave
*
* 38 10/02/98 3:22p Allender
* fix up the -connect option and fix the -port option
*
* 37 9/15/98 4:04p Allender
* added back in the -ip_addr command line switch because it needs to be
* in the standalone server only executable
*
* 36 9/14/98 11:52a Allender
* don't use cfile
*
* 35 9/14/98 11:28a Allender
* support for server bashing of address when received from client. Added
* a cmdline.cfg file to process command line arguments from a file
*
* 34 9/08/98 2:20p Allender
* temporary code to force IP address to a specific value.
*
* 33 8/20/98 5:30p Dave
* Put in handy multiplayer logfile system. Now need to put in useful
* applications of it all over the code.
*
* 32 8/07/98 10:39a Allender
* fixed debug standalone problem where stats would continually get sent
* to tracker. more debug code to help find stats problem
*
* 31 7/24/98 11:14a Allender
* start of new command line options for version 1.04
*
* 30 5/21/98 1:50a Dave
* Remove obsolete command line functions. Reduce shield explosion packets
* drastically. Tweak PXO screen even more. Fix file xfer system so that
* we can guarantee file uniqueness.
*
* 29 5/18/98 9:10p Dave
* Put in many new PXO features. Fixed skill level bashing in multiplayer.
* Removed several old command line options. Put in network config files.
*
* 28 5/09/98 7:16p Dave
* Put in CD checking. Put in standalone host password. Made pilot into
* popup scrollable.
*
* 27 4/23/98 8:27p Allender
* basic support for cutscene playback. Into movie code in place. Tech
* room can view cutscenes stored in CDROM_dir variable
*
* 26 4/09/98 5:43p Dave
* Remove all command line processing from the demo. Began work fixing up
* the new multi host options screen.
*
* 25 4/02/98 11:40a Lawrance
* check for #ifdef DEMO instead of #ifdef DEMO_RELEASE
*
* 24 4/01/98 5:56p Dave
* Fixed a messaging bug which caused msg_all mode in multiplayer not to
* work. Compile out a host of multiplayer options not available in the
* demo.
*
* 23 3/14/98 2:48p Dave
* Cleaned up observer joining code. Put in support for file xfers to
* ingame joiners (observers or not). Revamped and reinstalled pseudo
* lag/loss system.
*
* 22 2/22/98 12:19p John
* Externalized some strings
*
* 21 1/31/98 4:32p Dave
* Put in new support for VMT player validation, game logging in and game
* logging out.
*
* 20 12/10/97 4:45p Dave
* Added in more detailed support for multiplayer packet lag/loss. Fixed
* some multiplayer stuff. Added some controls to the standalone.
*
* 19 12/09/97 6:14p Lawrance
* add -nomusic flag
*
* 18 12/01/97 5:10p Dave
* Fixed a syntax bug.
*
* 17 12/01/97 4:59p Dave
* Synchronized multiplayer debris objects. Put in pilot popup in main
* hall. Optimized simulated multiplayer lag module. Fixed a potential
* file_xfer bug.
*
* 16 11/28/97 7:04p Dave
* Emergency checkin due to big system crash.
*
* 15 11/28/97 5:06p Dave
* Put in facilities for simulating multiplayer lag.
*
* 14 11/24/97 5:42p Dave
* Fixed a file xfer buffer free/malloc problem. Lengthened command line
* switch string parse length.
*
* 13 11/12/97 4:39p Dave
* Put in multiplayer campaign support parsing, loading and saving. Made
* command-line variables better named. Changed some things on the initial
* pilot select screen.
*
* 12 11/11/97 4:54p Dave
* Put in support for single vs. multiplayer pilots. Put in initial player
* selection screen (no command line option yet). Started work on
* multiplayer campaign file save gaming.
*
* 11 11/11/97 11:55a Allender
* initialize network at beginning of application. create new call to set
* which network protocol to use
*
* 10 9/18/97 10:12p Dave
* Added -gimmemedals, which gives the current pilot all the medals in the
* game (debug)
*
* 9 9/18/97 9:20a Dave
* Minor modifications
*
* 8 9/15/97 11:40p Lawrance
* remove demo granularity switch
*
* 7 9/09/97 3:39p Sandeep
* warning level 4 bugs
*
* 6 9/03/97 5:03p Lawrance
* add support for -nosound command line parm
*
* 5 8/22/97 8:52a Dave
* Removed a return statement which would have broken the parser out too
* early.
*
* 4 8/21/97 4:55p Dave
* Added a switch for multiplayer chat streaming. Added a section for
* global command line vars.
*
* 3 8/06/97 2:26p Dave
* Made the command line parse more robust. Made it easier to add and
* process new command-line switches.
*
* 2 8/04/97 3:13p Dave
* Added command line functions. See cmdline.cpp for directions on adding
* new switches
*
* 1 8/04/97 9:58a Dave
*
* $NoKeywords: $
*/
#include <string.h>
#include <stdlib.h>
#include "pstypes.h"
#include "cmdline.h"
#include "linklist.h"
#include "systemvars.h"
#include "multi.h"
#include "cfile.h"
// variables
class cmdline_parm {
public:
cmdline_parm *next, *prev;
char *name; // name of parameter, must start with '-' char
char *help; // help text for this parameter
char *args; // string value for parameter arguements (NULL if no arguements)
int name_found; // true if parameter on command line, otherwise false
cmdline_parm(char *name, char *help);
~cmdline_parm();
int found();
int get_int();
float get_float();
char *str();
};
// here are the command line parameters that we will be using for FreeSpace
cmdline_parm standalone_arg("-standalone", NULL);
cmdline_parm nosound_arg("-nosound", NULL);
cmdline_parm nomusic_arg("-nomusic", NULL);
cmdline_parm startgame_arg("-startgame", NULL);
cmdline_parm gamename_arg("-gamename", NULL);
cmdline_parm gamepassword_arg("-password", NULL);
cmdline_parm gameclosed_arg("-closed", NULL);
cmdline_parm gamerestricted_arg("-restricted", NULL);
cmdline_parm allowabove_arg("-allowabove", NULL);
cmdline_parm allowbelow_arg("-allowbelow", NULL);
cmdline_parm port_arg("-port", NULL);
cmdline_parm connect_arg("-connect", NULL);
cmdline_parm multilog_arg("-multilog", NULL);
cmdline_parm server_firing_arg("-oldfire", NULL);
cmdline_parm client_dodamage("-clientdamage", NULL);
cmdline_parm pof_spew("-pofspew", NULL);
cmdline_parm d3d_32bit("-32bit", NULL);
cmdline_parm mouse_coords("-coords", NULL);
cmdline_parm timeout("-timeout", NULL);
cmdline_parm d3d_window("-window", NULL);
int Cmdline_multi_stream_chat_to_file = 0;
int Cmdline_freespace_no_sound = 0;
int Cmdline_freespace_no_music = 0;
int Cmdline_gimme_all_medals = 0;
int Cmdline_use_last_pilot = 0;
int Cmdline_multi_protocol = -1;
int Cmdline_cd_check = 1;
int Cmdline_start_netgame = 0;
int Cmdline_closed_game = 0;
int Cmdline_restricted_game = 0;
int Cmdline_network_port = -1;
char *Cmdline_game_name = NULL;
char *Cmdline_game_password = NULL;
char *Cmdline_rank_above= NULL;
char *Cmdline_rank_below = NULL;
char *Cmdline_connect_addr = NULL;
int Cmdline_multi_log = 0;
int Cmdline_server_firing = 0;
int Cmdline_client_dodamage = 0;
int Cmdline_spew_pof_info = 0;
int Cmdline_force_32bit = 0;
int Cmdline_mouse_coords = 0;
int Cmdline_timeout = -1;
int Cmdline_window = 0;
static cmdline_parm Parm_list(NULL, NULL);
static int Parm_list_inited = 0;
// Return true if this character is an extra char (white space and quotes)
int is_extra_space(char ch)
{
return ((ch == ' ') || (ch == '\t') || (ch == 0x0a) || (ch == '\'') || (ch == '\"'));
}
// eliminates all leading and trailing extra chars from a string. Returns pointer passed in.
char *drop_extra_chars(char *str)
{
int s, e;
s = 0;
while (str[s] && is_extra_space(str[s]))
s++;
e = strlen(str) - 1;
while (e > s) {
if (!is_extra_space(str[e])){
break;
}
e--;
}
if (e > s){
memmove(str, str + s, e - s + 1);
}
str[e - s + 1] = 0;
return str;
}
// internal function - copy the value for a parameter agruement into the cmdline_parm arg field
void parm_stuff_args(cmdline_parm *parm, char *cmdline)
{
char buffer[1024];
memset(buffer, 0, 1024);
char *dest = buffer;
cmdline += strlen(parm->name);
while ((*cmdline != 0) && (*cmdline != '-')) {
*dest++ = *cmdline++;
}
drop_extra_chars(buffer);
// mwa 9/14/98 -- made it so that newer command line arguments found will overwrite
// the old arguments
// Assert(parm->args == NULL);
if ( parm->args != NULL ) {
delete( parm->args );
parm->args = NULL;
}
int size = strlen(buffer) + 1;
if (size > 0) {
parm->args = new char[size];
memset(parm->args, 0, size);
strcpy(parm->args, buffer);
}
}
// internal function - parse the command line, extracting parameter arguements if they exist
// cmdline - command line string passed to the application
void os_parse_parms(char *cmdline)
{
// locate command line parameters
cmdline_parm *parmp;
char *cmdline_offset;
for (parmp = GET_FIRST(&Parm_list); parmp !=END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp) ) {
cmdline_offset = strstr(cmdline, parmp->name);
if (cmdline_offset) {
parmp->name_found = 1;
parm_stuff_args(parmp, cmdline_offset);
}
}
}
// validate the command line parameters. Display an error if an unrecognized parameter is located.
void os_validate_parms(char *cmdline)
{
cmdline_parm *parmp;
char seps[] = " ,\t\n";
char *token;
int parm_found;
token = strtok(cmdline, seps);
while(token != NULL) {
if (token[0] == '-') {
parm_found = 0;
for (parmp = GET_FIRST(&Parm_list); parmp !=END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp) ) {
if (!stricmp(parmp->name, token)) {
parm_found = 1;
break;
}
}
if (parm_found == 0) {
Error(LOCATION,"Unrecogzined command line parameter %s", token);
}
}
token = strtok(NULL, seps);
}
}
// Call once to initialize the command line system
//
// cmdline - command line string passed to the application
void os_init_cmdline(char *cmdline)
{
FILE *fp;
// read the cmdline.cfg file from the data folder, and pass the command line arguments to
// the the parse_parms and validate_parms line. Read these first so anything actually on
// the command line will take precedence
fp = fopen("data\\cmdline.cfg", "rt");
// if the file exists, get a single line, and deal with it
if ( fp ) {
char buf[1024], *p;
fgets(buf, 1024, fp);
// replace the newline character with a NUL:
if ( (p = strrchr(buf, '\n')) != NULL ) {
*p = '\0';
}
os_parse_parms(buf);
os_validate_parms(buf);
fclose(fp);
}
os_parse_parms(cmdline);
os_validate_parms(cmdline);
}
// arg constructor
// name_ - name of the parameter, must start with '-' character
// help_ - help text for this parameter
cmdline_parm::cmdline_parm(char *name_, char *help_)
{
name = name_;
help = help_;
args = NULL;
name_found = 0;
if (Parm_list_inited == 0) {
list_init(&Parm_list);
Parm_list_inited = 1;
}
if (name != NULL) {
list_append(&Parm_list, this);
}
}
// destructor - frees any allocated memory
cmdline_parm::~cmdline_parm()
{
if (args) {
delete [] args;
args = NULL;
}
}
// returns - true if the parameter exists on the command line, otherwise false
int cmdline_parm::found()
{
return name_found;
}
// returns - the interger representation for the parameter arguement
int cmdline_parm::get_int()
{
Assert(args);
return atoi(args);
}
// returns - the float representation for the parameter arguement
float cmdline_parm::get_float()
{
Assert(args);
return (float)atof(args);
}
// returns - the string value for the parameter arguement
char *cmdline_parm::str()
{
Assert(args);
return args;
}
// external entry point into this modules
#ifdef _WIN32
int parse_cmdline(char *cmdline)
#else
int parse_cmdline(int argc, char *argv[])
#endif
{
#ifdef _WIN32
os_init_cmdline(cmdline);
#else
if (argc > 1) {
// kind of silly -- combine arg list into single string for parsing,
// but it fits with the win32-centric existing code.
char *cmdline = NULL;
unsigned int arglen = 0;
int i;
for (i = 1; i < argc; i++)
arglen += strlen(argv[i]);
if (argc > 2)
arglen += argc - 2; // leave room for the separators
cmdline = new char [arglen+1];
i = 1;
strcpy(cmdline, argv[i]);
for ( ; i < argc; i++) {
strcat(cmdline, " ");
strcat(cmdline, argv[i]);
}
os_init_cmdline(cmdline);
delete [] cmdline;
} else {
// no cmdline args
os_init_cmdline("");
}
#endif
// is this a standalone server??
if (standalone_arg.found()) {
Is_standalone = 1;
}
// run with no sound
if ( nosound_arg.found() ) {
Cmdline_freespace_no_sound = 1;
}
// run with no music
if ( nomusic_arg.found() ) {
Cmdline_freespace_no_music = 1;
}
// should we start a network game
if ( startgame_arg.found() ) {
Cmdline_use_last_pilot = 1;
Cmdline_start_netgame = 1;
}
// closed network game
if ( gameclosed_arg.found() ) {
Cmdline_closed_game = 1;
}
// restircted network game
if ( gamerestricted_arg.found() ) {
Cmdline_restricted_game = 1;
}
// get the name of the network game
if ( gamename_arg.found() ) {
Cmdline_game_name = gamename_arg.str();
// be sure that this string fits in our limits
if ( strlen(Cmdline_game_name) > MAX_GAMENAME_LEN ) {
Cmdline_game_name[MAX_GAMENAME_LEN-1] = '\0';
}
}
// get the password for a pssword game
if ( gamepassword_arg.found() ) {
Cmdline_game_password = gamepassword_arg.str();
// be sure that this string fits in our limits
if ( strlen(Cmdline_game_name) > MAX_PASSWD_LEN ) {
Cmdline_game_name[MAX_PASSWD_LEN-1] = '\0';
}
}
// set the rank above/below arguments
if ( allowabove_arg.found() ) {
Cmdline_rank_above = allowabove_arg.str();
}
if ( allowbelow_arg.found() ) {
Cmdline_rank_below = allowbelow_arg.str();
}
// get the port number for games
if ( port_arg.found() ) {
Cmdline_network_port = port_arg.get_int();
}
// the connect argument specifies to join a game at this particular address
if ( connect_arg.found() ) {
Cmdline_use_last_pilot = 1;
Cmdline_connect_addr = connect_arg.str();
}
// see if the multilog flag was set
if ( multilog_arg.found() ){
Cmdline_multi_log = 1;
}
// maybe use old-school server-side firing
if (server_firing_arg.found() ){
Cmdline_server_firing = 1;
}
// maybe use old-school client damage
if(client_dodamage.found()){
Cmdline_client_dodamage = 1;
}
// spew pof info
if(pof_spew.found()){
Cmdline_spew_pof_info = 1;
}
// 32 bit
if(d3d_32bit.found()){
Cmdline_force_32bit = 1;
}
// mouse coords
if(mouse_coords.found()){
Cmdline_mouse_coords = 1;
}
// net timeout
if(timeout.found()){
Cmdline_timeout = timeout.get_int();
}
// d3d windowed
if(d3d_window.found()){
Cmdline_window = 1;
}
return 1;
}