Compare commits

...
Author SHA1 Message Date
asarium 1111dcf0a8 Add system for reading flags from stdin
This adds support for reading flags from the standard input stream
instead of from the command line. This allows more complex formats to be
used such as JSON which is implemented in this first version. This can
be used for implementing much more sophisticated ways of expressing
complex data structures such as the mod command line.
2019-06-07 18:31:33 +02:00
21 changed files with 840 additions and 708 deletions

No files matched your search

+2 -68
View File
@@ -38,9 +38,6 @@
#include <limits>
char Cfile_root_dir[CFILE_ROOT_DIRECTORY_LEN] = "";
char Cfile_user_dir[CFILE_ROOT_DIRECTORY_LEN] = "";
// During cfile_init, verify that Pathtypes[n].index == n for each item
// Each path must have a valid parent that can be tracable all the way back to the root
// so that we can create directories when we need to.
@@ -103,8 +100,6 @@ static char Cfile_stack[CFILE_STACK_MAX][CFILE_ROOT_DIRECTORY_LEN];
std::array<CFILE, MAX_CFILE_BLOCKS> Cfile_block_list;
static const char *Cfile_cdrom_dir = NULL;
//
// Function prototypes for internally-called functions
//
@@ -147,47 +142,15 @@ void cfile_close()
#define MIN_NUM_PATH_COMPONENTS 3 /* Drive + directory + file */
#endif
/**
* @brief Determine if the given path is in the root directory
*
* @param exe_path Path to executable
*
* @return true if root directory, false if not
*/
static bool cfile_in_root_dir(const char *exe_path)
{
int new_token;
int token_count = 0;
const char *p = exe_path;
Assert(exe_path != NULL);
do {
new_token = 0;
while (*p == DIR_SEPARATOR_CHAR) {
p++;
}
while ((*p != '\0') && (*p != DIR_SEPARATOR_CHAR)) {
new_token = 1;
p++;
}
token_count += new_token;
} while (*p != '\0');
return (token_count < MIN_NUM_PATH_COMPONENTS);
}
/**
* @brief Initialize the cfile system. Called once at application start.
*
* @param exe_dir Path to a file (not a directory)
* @param cdrom_dir Path to a CD drive mount point (may be NULL)
*
* @return 0 On success
* @return 1 On error
*/
int cfile_init(const char *exe_dir, const char *cdrom_dir)
int cfile_init(const SCP_vector<cfile::ModRoot>& modRoots)
{
// initialize encryption
encrypt_init();
@@ -196,36 +159,8 @@ int cfile_init(const char *exe_dir, const char *cdrom_dir)
return 0;
}
char buf[CFILE_ROOT_DIRECTORY_LEN];
strncpy(buf, exe_dir, CFILE_ROOT_DIRECTORY_LEN - 1);
buf[CFILE_ROOT_DIRECTORY_LEN - 1] = '\0';
// are we in a root directory?
if(cfile_in_root_dir(buf)){
os::dialogs::Message(os::dialogs::MESSAGEBOX_ERROR, "FreeSpace2/Fred2 cannot be run from a drive root directory!");
return 1;
}
// This needs to be set here because cf_build_secondary_filelist assumes it to be true
cfile_inited = 1;
/*
* Determine the executable's directory. Note that DIR_SEPARATOR_CHAR
* is guaranteed to be found in the string else cfile_in_root_dir()
* would have failed.
*/
char *p;
p = strrchr(buf, DIR_SEPARATOR_CHAR);
*p = '\0';
cfile_chdir(buf);
// set root directory
strcpy_s(Cfile_root_dir, buf);
strcpy_s(Cfile_user_dir, os_get_config_path().c_str());
// Initialize the block list with proper data
Cfile_block_list.fill({});
@@ -233,8 +168,7 @@ int cfile_init(const char *exe_dir, const char *cdrom_dir)
// 32 bit CRC table init
cf_chksum_long_init();
Cfile_cdrom_dir = cdrom_dir;
cf_build_secondary_filelist(Cfile_cdrom_dir);
cf_build_secondary_filelist(modRoots);
return 0;
}
+14 -3
View File
@@ -165,11 +165,22 @@ extern const char *Get_file_list_child;
// cfile directory. valid after cfile_init() returns successfully
#define CFILE_ROOT_DIRECTORY_LEN 256
extern char Cfile_root_dir[CFILE_ROOT_DIRECTORY_LEN];
extern char Cfile_user_dir[CFILE_ROOT_DIRECTORY_LEN];
namespace cfile {
enum class ModRootType { Unknown, Folder, Package };
enum class LocationType { Unknown, SecondaryMod, PrimaryMod, GameRoot };
struct ModRoot {
ModRootType type = ModRootType::Unknown;
SCP_string path;
LocationType location_type = LocationType::Unknown;
bool user_location = false;
};
} // namespace cfile
//================= LOW-LEVEL FUNCTIONS ==================
int cfile_init(const char *exe_dir, const char *cdrom_dir=NULL);
int cfile_init(const SCP_vector<cfile::ModRoot>& modRoots);
void cfile_close();
// add an extension to a filename if it doesn't already have it
+266
View File
@@ -0,0 +1,266 @@
#define _CFILE_INTERNAL
#include "cfilemod.h"
#include "cfile.h"
#include "cmdline/cmdline.h"
#include "osapi/osapi.h"
#include "cfilesystem.h"
#ifdef SCP_UNIX
#include <glob.h>
#include <sys/types.h>
#include <dirent.h>
#include <fnmatch.h>
#include <sys/stat.h>
#include <unistd.h>
#include <libgen.h>
#endif
namespace cfile {
namespace {
typedef struct cf_root_sort {
SCP_string path;
int cf_type;
} cf_root_sort;
// packfile sort function
bool cf_packfile_sort_func(const cf_root_sort& r1, const cf_root_sort& r2) {
// if the 2 directory types are the same, do a string compare
if (r1.cf_type == r2.cf_type) {
return (stricmp(r1.path.c_str(), r2.path.c_str()) < 0);
}
// otherwise return them in order of CF_TYPE_* precedence
return (r1.cf_type < r2.cf_type);
}
// Go through a root and look for pack files
void build_pack_list(SCP_vector<ModRoot>& mod_roots,
const SCP_string& search_path,
LocationType location_type,
bool user_location) {
char filespec[MAX_PATH_LEN];
// allocate a temporary array of temporary roots so we can easily sort them
SCP_vector<cf_root_sort> temp_roots_sort;
// now just setup all the root info
for (int i = CF_TYPE_ROOT; i < CF_MAX_PATH_TYPES; i++) {
strcpy_s(filespec, search_path.c_str());
if (strlen(Pathtypes[i].path)) {
strcat_s(filespec, Pathtypes[i].path);
if (filespec[strlen(filespec) - 1] != DIR_SEPARATOR_CHAR)
strcat_s(filespec, DIR_SEPARATOR_STR);
}
#if defined _WIN32
strcat_s( filespec, "*.vp" );
intptr_t find_handle;
_finddata_t find;
find_handle = _findfirst( filespec, &find );
if (find_handle != -1) {
do {
// add the new item
if (!(find.attrib & _A_SUBDIR)) {
// get a temp pointer
rptr_sort = &temp_roots_sort[root_index++];
// fill in all the proper info
strcpy_s(rptr_sort->path, root->path);
if(strlen(Pathtypes[i].path)) {
strcat_s(rptr_sort->path, Pathtypes[i].path );
strcat_s(rptr_sort->path, DIR_SEPARATOR_STR);
}
strcat_s(rptr_sort->path, find.name );
rptr_sort->roottype = CF_ROOTTYPE_PACK;
rptr_sort->cf_type = i;
}
} while (!_findnext(find_handle, &find));
_findclose( find_handle );
}
#elif defined SCP_UNIX
strcat_s(filespec, "*.[vV][pP]");
glob_t globinfo;
memset(&globinfo, 0, sizeof(globinfo));
int status = glob(filespec, 0, NULL, &globinfo);
if (status == 0) {
for (uint j = 0; j < globinfo.gl_pathc; j++) {
// Determine if this is a regular file
struct stat statbuf;
memset(&statbuf, 0, sizeof(statbuf));
stat(globinfo.gl_pathv[j], &statbuf);
if (S_ISREG(statbuf.st_mode)) {
cf_root_sort sort;
// fill in all the proper info
sort.path = globinfo.gl_pathv[j];
sort.cf_type = i;
temp_roots_sort.push_back(sort);
}
}
globfree(&globinfo);
}
#endif
}
// sort the roots
std::sort(temp_roots_sort.begin(), temp_roots_sort.end(), cf_packfile_sort_func);
// now insert them all into the real root list properly
for (const auto& pack_root : temp_roots_sort) {
ModRoot root;
root.type = ModRootType::Package;
root.path = pack_root.path;
root.user_location = user_location;
root.location_type = location_type;
mod_roots.push_back(root);
}
}
char normalize_directory_separator(char in) {
if (in == '/') {
return DIR_SEPARATOR_CHAR;
}
return in;
}
void
add_mod_roots(SCP_vector<ModRoot>& mod_roots, const char* mod_cmdline, const SCP_string& rootDirectory, bool user_location) {
if (mod_cmdline) {
bool primary = true;
for (const char* cur_pos = mod_cmdline; strlen(cur_pos) != 0; cur_pos += (strlen(cur_pos) + 1)) {
SCP_stringstream ss;
ss << rootDirectory;
if (rootDirectory.back() != DIR_SEPARATOR_CHAR) {
ss << DIR_SEPARATOR_CHAR;
}
ss << cur_pos << DIR_SEPARATOR_STR;
SCP_string rootPath = ss.str();
// normalize the path to the native path format
std::transform(rootPath.begin(), rootPath.end(), rootPath.begin(), normalize_directory_separator);
ModRoot root;
root.type = ModRootType::Folder;
root.path = rootPath;
root.user_location = user_location;
if (primary) {
root.location_type = LocationType::PrimaryMod;
} else {
root.location_type = LocationType::SecondaryMod;
}
mod_roots.push_back(root);
build_pack_list(mod_roots, rootPath, root.location_type, user_location);
primary = false;
}
}
}
}
SCP_vector<ModRoot> getModRootsFromModCmdline(const SCP_string& content_root, const char* mod_cmdline) {
SCP_vector<ModRoot> mod_roots;
if (os_is_legacy_mode()) {
// =========================================================================
#ifdef WIN32
// Nothing to do here, Windows uses the current directory as the base
#else
add_mod_roots(mod_roots, mod_cmdline, os_get_legacy_user_dir(), true);
ModRoot root;
root.type = ModRootType::Folder;
root.path = os_get_legacy_user_dir();
root.user_location = true;
root.location_type = LocationType::GameRoot;
// do we already have a slash? as in the case of a root directory install
if (root.path.back() != DIR_SEPARATOR_CHAR) {
root.path += DIR_SEPARATOR_STR; // put trailing backslash on for easier path construction
}
mod_roots.push_back(root);
// Next, check any VP files under the current directory.
build_pack_list(mod_roots, root.path, root.location_type, root.user_location);
#endif
// =========================================================================
} else if (!Cmdline_portable_mode) {
// =========================================================================
// now look for mods under the users HOME directory to use before system ones
add_mod_roots(mod_roots, mod_cmdline, os_get_config_path(), true);
// =========================================================================
// =========================================================================
// set users HOME directory as default for loading and saving files
ModRoot root;
root.type = ModRootType::Folder;
root.path = os_get_config_path();
root.user_location = true;
root.location_type = LocationType::GameRoot;
// do we already have a slash? as in the case of a root directory install
if (root.path.back() != DIR_SEPARATOR_CHAR) {
root.path += DIR_SEPARATOR_STR; // put trailing backslash on for easier path construction
}
mod_roots.push_back(root);
// Next, check any VP files under the current directory.
build_pack_list(mod_roots, root.path, root.location_type, root.user_location);
// =========================================================================
}
add_mod_roots(mod_roots, mod_cmdline, content_root, false);
ModRoot root;
root.type = ModRootType::Folder;
root.path = content_root;
root.user_location = false;
root.location_type = LocationType::GameRoot;
// do we already have a slash? as in the case of a root directory install
if (root.path.back() != DIR_SEPARATOR_CHAR) {
root.path += DIR_SEPARATOR_STR; // put trailing backslash on for easier path construction
}
mod_roots.push_back(root);
//======================================================
// Next, check any VP files under the current directory.
build_pack_list(mod_roots, root.path, root.location_type, root.user_location);
return mod_roots;
}
}
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#include "globalincs/pstypes.h"
#include "cfile/cfile.h"
namespace cfile {
SCP_vector<ModRoot> getModRootsFromModCmdline(const SCP_string& content_root, const char* mod_cmdline);
}
+86 -352
View File
@@ -160,379 +160,113 @@ cf_root *cf_create_root()
return &Root_blocks[block]->roots[offset];
}
// return the # of packfiles which exist
int cf_get_packfile_count(cf_root *root)
static bool has_mod_location(const SCP_vector<cfile::ModRoot>& modRoots)
{
SCP_string filespec;
int i;
int packfile_count;
// count up how many packfiles we're gonna have
packfile_count = 0;
for (i=CF_TYPE_ROOT; i<CF_MAX_PATH_TYPES; i++ )
for (const auto& root : modRoots)
{
filespec = root->path;
if(strlen(Pathtypes[i].path))
if (root.location_type == cfile::LocationType::PrimaryMod)
{
filespec += Pathtypes[ i ].path;
if ( filespec[ filespec.length( ) - 1 ] != DIR_SEPARATOR_CHAR )
{
filespec += DIR_SEPARATOR_STR;
}
}
#if defined _WIN32
filespec += "*.vp";
intptr_t find_handle;
_finddata_t find;
find_handle = _findfirst( filespec.c_str( ), &find );
if (find_handle != -1) {
do {
if (!(find.attrib & _A_SUBDIR)) {
packfile_count++;
}
} while (!_findnext(find_handle, &find));
_findclose( find_handle );
}
#elif defined SCP_UNIX
filespec += "*.[vV][pP]";
glob_t globinfo;
memset(&globinfo, 0, sizeof(globinfo));
int status = glob(filespec.c_str( ), 0, NULL, &globinfo);
if (status == 0) {
for (unsigned int j = 0; j < globinfo.gl_pathc; j++) {
// Determine if this is a regular file
struct stat statbuf;
memset(&statbuf, 0, sizeof(statbuf));
stat(globinfo.gl_pathv[j], &statbuf);
if (S_ISREG(statbuf.st_mode)) {
packfile_count++;
}
}
globfree(&globinfo);
}
#endif
}
return packfile_count;
}
// packfile sort function
bool cf_packfile_sort_func(const cf_root_sort &r1, const cf_root_sort &r2)
{
// if the 2 directory types are the same, do a string compare
if (r1.cf_type == r2.cf_type) {
return (stricmp(r1.path, r2.path) < 0);
}
// otherwise return them in order of CF_TYPE_* precedence
return (r1.cf_type < r2.cf_type);
}
// Go through a root and look for pack files
void cf_build_pack_list( cf_root *root )
{
char filespec[MAX_PATH_LEN];
int i;
cf_root_sort *temp_roots_sort, *rptr_sort;
int temp_root_count, root_index;
// determine how many packfiles there are
temp_root_count = cf_get_packfile_count(root);
if (temp_root_count <= 0)
return;
// allocate a temporary array of temporary roots so we can easily sort them
temp_roots_sort = (cf_root_sort*)vm_malloc(sizeof(cf_root_sort) * temp_root_count);
if (temp_roots_sort == NULL) {
Int3();
return;
}
// now just setup all the root info
root_index = 0;
for (i = CF_TYPE_ROOT; i < CF_MAX_PATH_TYPES; i++) {
strcpy_s( filespec, root->path );
if ( strlen(Pathtypes[i].path) ) {
strcat_s( filespec, Pathtypes[i].path );
if ( filespec[strlen(filespec)-1] != DIR_SEPARATOR_CHAR )
strcat_s( filespec, DIR_SEPARATOR_STR );
}
#if defined _WIN32
strcat_s( filespec, "*.vp" );
intptr_t find_handle;
_finddata_t find;
find_handle = _findfirst( filespec, &find );
if (find_handle != -1) {
do {
// add the new item
if (!(find.attrib & _A_SUBDIR)) {
Assert(root_index < temp_root_count);
// get a temp pointer
rptr_sort = &temp_roots_sort[root_index++];
// fill in all the proper info
strcpy_s(rptr_sort->path, root->path);
if(strlen(Pathtypes[i].path)) {
strcat_s(rptr_sort->path, Pathtypes[i].path );
strcat_s(rptr_sort->path, DIR_SEPARATOR_STR);
}
strcat_s(rptr_sort->path, find.name );
rptr_sort->roottype = CF_ROOTTYPE_PACK;
rptr_sort->cf_type = i;
}
} while (!_findnext(find_handle, &find));
_findclose( find_handle );
}
#elif defined SCP_UNIX
strcat_s( filespec, "*.[vV][pP]" );
glob_t globinfo;
memset(&globinfo, 0, sizeof(globinfo));
int status = glob(filespec, 0, NULL, &globinfo);
if (status == 0) {
for (uint j = 0; j < globinfo.gl_pathc; j++) {
// Determine if this is a regular file
struct stat statbuf;
memset(&statbuf, 0, sizeof(statbuf));
stat(globinfo.gl_pathv[j], &statbuf);
if ( S_ISREG(statbuf.st_mode) ) {
Assert(root_index < temp_root_count);
// get a temp pointer
rptr_sort = &temp_roots_sort[root_index++];
// fill in all the proper info
strcpy_s(rptr_sort->path, globinfo.gl_pathv[j] );
rptr_sort->roottype = CF_ROOTTYPE_PACK;
rptr_sort->cf_type = i;
}
}
globfree(&globinfo);
}
#endif
}
// these should always be the same
Assert(root_index == temp_root_count);
// sort the roots
std::sort(temp_roots_sort, temp_roots_sort + temp_root_count, cf_packfile_sort_func);
// now insert them all into the real root list properly
for (i = 0; i < temp_root_count; i++) {
auto new_root = cf_create_root();
new_root->location_flags = root->location_flags;
strcpy_s( new_root->path, root->path );
#ifndef NDEBUG
uint chksum = 0;
cf_chksum_pack(temp_roots_sort[i].path, &chksum);
mprintf(("Found root pack '%s' with a checksum of 0x%08x\n", temp_roots_sort[i].path, chksum));
#endif
// mwa -- 4/2/98 put in the next 2 lines because the path name needs to be there
// to find the files.
strcpy_s(new_root->path, temp_roots_sort[i].path);
new_root->roottype = CF_ROOTTYPE_PACK;
}
// free up the temp list
vm_free(temp_roots_sort);
}
static char normalize_directory_separator(char in)
{
if (in == '/')
{
return DIR_SEPARATOR_CHAR;
}
return in;
}
static void cf_add_mod_roots(const char* rootDirectory, uint32_t basic_location)
{
if (Cmdline_mod)
{
bool primary = true;
for (const char* cur_pos=Cmdline_mod; strlen(cur_pos) != 0; cur_pos+= (strlen(cur_pos)+1))
{
SCP_stringstream ss;
ss << rootDirectory;
if (rootDirectory[strlen(rootDirectory) - 1] != DIR_SEPARATOR_CHAR)
{
ss << DIR_SEPARATOR_CHAR;
}
ss << cur_pos << DIR_SEPARATOR_STR;
SCP_string rootPath = ss.str();
if (rootPath.size() + 1 >= CF_MAX_PATHNAME_LENGTH) {
Error(LOCATION, "The length of mod directory path '%s' exceeds the maximum of %d!\n", rootPath.c_str(), CF_MAX_PATHNAME_LENGTH);
}
// normalize the path to the native path format
std::transform(rootPath.begin(), rootPath.end(), rootPath.begin(), normalize_directory_separator);
cf_root* root = cf_create_root();
strncpy(root->path, rootPath.c_str(), CF_MAX_PATHNAME_LENGTH-1);
if (primary) {
root->location_flags = basic_location | CF_LOCATION_TYPE_PRIMARY_MOD;
} else {
root->location_flags = basic_location | CF_LOCATION_TYPE_SECONDARY_MODS;
}
root->roottype = CF_ROOTTYPE_PATH;
cf_build_pack_list(root);
primary = false;
return true;
}
}
return false;
}
void cf_build_root_list(const char *cdrom_dir)
void cf_build_root_list(const SCP_vector<cfile::ModRoot>& modRoots)
{
Num_roots = 0;
Num_path_roots = 0;
cf_root *root = nullptr;
auto has_mod = has_mod_location(modRoots);
if (os_is_legacy_mode())
mprintf(("CFile root configuration:\n"));
// Go through the roots specified and convert them to the internal data structure
for (const auto& root : modRoots)
{
// =========================================================================
#ifdef WIN32
// Nothing to do here, Windows uses the current directory as the base
#else
cf_add_mod_roots(os_get_legacy_user_dir(), CF_LOCATION_ROOT_USER);
root = cf_create_root();
strncpy(root->path, os_get_legacy_user_dir(), CF_MAX_PATHNAME_LENGTH - 1);
root->location_flags |= CF_LOCATION_ROOT_USER | CF_LOCATION_TYPE_ROOT;
if (Cmdline_mod == nullptr || strlen(Cmdline_mod) <= 0) {
// If there are no mods then the root is the primary mod
root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
if (root.path.size() >= CF_MAX_PATHNAME_LENGTH - 1)
{
Error(LOCATION, "Mod root path '%s' is longer than the maximum %d!", root.path.c_str(), CF_MAX_PATHNAME_LENGTH - 1);
return;
}
// do we already have a slash? as in the case of a root directory install
if ((strlen(root->path) < (CF_MAX_PATHNAME_LENGTH - 1)) && (root->path[strlen(root->path) - 1] != DIR_SEPARATOR_CHAR)) {
strcat_s(root->path, DIR_SEPARATOR_STR); // put trailing backslash on for easier path construction
}
root->roottype = CF_ROOTTYPE_PATH;
auto cfile_root = cf_create_root();
memset(cfile_root, 0, sizeof(*cfile_root));
// Next, check any VP files under the current directory.
cf_build_pack_list(root);
strcpy_s(cfile_root->path, root.path.c_str());
if (root.user_location)
{
cfile_root->location_flags |= CF_LOCATION_ROOT_USER;
} else {
cfile_root->location_flags |= CF_LOCATION_ROOT_GAME;
}
if (root.location_type == cfile::LocationType::SecondaryMod)
{
cfile_root->location_flags |= CF_LOCATION_TYPE_SECONDARY_MODS;
} else if (root.location_type == cfile::LocationType::PrimaryMod)
{
cfile_root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
} else if (root.location_type == cfile::LocationType::GameRoot)
{
cfile_root->location_flags |= CF_LOCATION_TYPE_ROOT;
if (!has_mod)
{
// If we do not have a mod then game roots are also primary mods
cfile_root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
}
} else {
UNREACHABLE("Unknown root location type!");
}
switch (root.type)
{
case cfile::ModRootType::Folder:
cfile_root->roottype = CF_ROOTTYPE_PATH;
break;
case cfile::ModRootType::Package:
cfile_root->roottype = CF_ROOTTYPE_PACK;
break;
default:
UNREACHABLE("Unknown root type!");
break;
}
if (root.type == cfile::ModRootType::Folder)
{
size_t path_len = strlen(cfile_root->path);
// do we already have a slash? as in the case of a root directory install
if ( (path_len < (CF_MAX_PATHNAME_LENGTH-1)) && (cfile_root->path[path_len-1] != DIR_SEPARATOR_CHAR) ) {
strcat_s(cfile_root->path, DIR_SEPARATOR_STR); // put trailing backslash on for easier path construction
}
}
#ifndef NDEBUG
switch (root.type)
{
case cfile::ModRootType::Folder:
mprintf((" Found root folder '%s'\n", root.path.c_str()));
break;
case cfile::ModRootType::Package: {
uint chksum = 0;
cf_chksum_pack(root.path.c_str(), &chksum);
mprintf((" Found root pack '%s' with a checksum of 0x%08x\n", root.path.c_str(), chksum));
break;
}
default:
UNREACHABLE("Unknown root type!");
break;
}
#endif
// =========================================================================
}
else if (!Cmdline_portable_mode)
{
// =========================================================================
// now look for mods under the users HOME directory to use before system ones
cf_add_mod_roots(Cfile_user_dir, CF_LOCATION_ROOT_USER);
// =========================================================================
// =========================================================================
// set users HOME directory as default for loading and saving files
root = cf_create_root();
strcpy_s(root->path, Cfile_user_dir);
root->location_flags |= CF_LOCATION_ROOT_USER | CF_LOCATION_TYPE_ROOT;
if (Cmdline_mod == nullptr || strlen(Cmdline_mod) <= 0) {
// If there are no mods then the root is the primary mod
root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
}
// do we already have a slash? as in the case of a root directory install
if ((strlen(root->path) < (CF_MAX_PATHNAME_LENGTH - 1)) && (root->path[strlen(root->path) - 1] != DIR_SEPARATOR_CHAR)) {
strcat_s(root->path, DIR_SEPARATOR_STR); // put trailing backslash on for easier path construction
}
root->roottype = CF_ROOTTYPE_PATH;
// Next, check any VP files under the current directory.
cf_build_pack_list(root);
// =========================================================================
}
char working_directory[CF_MAX_PATHNAME_LENGTH];
if ( !_getcwd(working_directory, CF_MAX_PATHNAME_LENGTH ) ) {
Error(LOCATION, "Can't get current working directory -- %d", errno );
}
cf_add_mod_roots(working_directory, CF_LOCATION_ROOT_GAME);
root = cf_create_root();
root->location_flags |= CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT;
if (Cmdline_mod == nullptr || strlen(Cmdline_mod) <= 0) {
// If there are no mods then the root is the primary mod
root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
}
strcpy_s(root->path, working_directory);
size_t path_len = strlen(root->path);
// do we already have a slash? as in the case of a root directory install
if ( (path_len < (CF_MAX_PATHNAME_LENGTH-1)) && (root->path[path_len-1] != DIR_SEPARATOR_CHAR) ) {
strcat_s(root->path, DIR_SEPARATOR_STR); // put trailing backslash on for easier path construction
}
root->roottype = CF_ROOTTYPE_PATH;
//======================================================
// Next, check any VP files under the current directory.
cf_build_pack_list(root);
//======================================================
// Check the real CD if one...
if ( cdrom_dir && (strlen(cdrom_dir) < CF_MAX_PATHNAME_LENGTH) ) {
root = cf_create_root();
strcpy_s( root->path, cdrom_dir );
root->roottype = CF_ROOTTYPE_PATH;
//======================================================
// Next, check any VP files in the CD-ROM directory.
cf_build_pack_list(root);
}
// The final root is the in-memory root
root = cf_create_root();
auto root = cf_create_root();
root->location_flags = CF_LOCATION_ROOT_MEMORY | CF_LOCATION_TYPE_ROOT;
memset(root->path, 0, sizeof(root->path));
root->roottype = CF_ROOTTYPE_MEMORY;
}
// Given a lower case list of file extensions
@@ -923,7 +657,7 @@ void cf_build_file_list()
}
void cf_build_secondary_filelist(const char *cdrom_dir)
void cf_build_secondary_filelist(const SCP_vector<cfile::ModRoot>& modRoots)
{
int i;
@@ -944,7 +678,7 @@ void cf_build_secondary_filelist(const char *cdrom_dir)
mprintf(( "Building file index...\n" ));
// build the list of searchable roots
cf_build_root_list(cdrom_dir);
cf_build_root_list(modRoots);
// build the list of files themselves
cf_build_file_list();
+1 -1
View File
@@ -15,7 +15,7 @@
#include "cfile/cfile.h"
// Builds a list of all the files
void cf_build_secondary_filelist( const char *cdrom_path );
void cf_build_secondary_filelist(const SCP_vector<cfile::ModRoot>& modRoots);
void cf_free_secondary_filelist();
// Internal stuff
+329 -177
View File
@@ -34,6 +34,9 @@
#include <CoreFoundation/CoreFoundation.h>
#endif
#include "cfile/cfile.h"
#include "cfile/cfilemod.h"
#ifdef SCP_UNIX
#include "osapi/osapi.h"
#include <dirent.h>
@@ -71,23 +74,36 @@ enum class flag_output_type {
Json_V1,
};
enum class flag_input_type {
Flags,
Stdin_Json_V1,
};
// variables
class cmdline_parm {
public:
cmdline_parm *next, *prev;
const char *name; // name of parameter, must start with '-' char
const char *help; // help text for this parameter
const bool stacks; // whether this arg stacks with each use or is replaced by newest use (should only be used for strings!!)
char *args; // string value for parameter arguments (NULL if no arguments)
int name_found; // true if parameter on command line, otherwise false
const int arg_type; // from enum cmdline_arg_type; used for help
cmdline_parm *next = nullptr, *prev = nullptr;
const char* name; // name of parameter, must start with '-' char
const char* help; // help text for this parameter
const bool stacks; // whether this arg stacks with each use or is replaced by newest use (should only be used for
// strings!!)
SCP_string args; // string value for parameter arguments (empty if no arguments)
bool name_found; // true if parameter on command line, otherwise false
const int arg_type; // from enum cmdline_arg_type; used for help
cmdline_parm(const char *name, const char *help, const int arg_type, const bool stacks = false);
~cmdline_parm();
int found();
cmdline_parm(const char* name, const char* help, const int arg_type, const bool stacks = false) noexcept;
~cmdline_parm() noexcept;
cmdline_parm(const cmdline_parm& other) = delete;
cmdline_parm& operator=(const cmdline_parm& other) = delete;
cmdline_parm(cmdline_parm&& other) = delete;
cmdline_parm& operator=(cmdline_parm&& other) = delete;
bool found();
int get_int();
float get_float();
char *str();
SCP_string str();
bool check_if_args_is_valid();
bool has_param();
};
@@ -275,11 +291,11 @@ cmdline_parm mouse_coords("-coords", NULL, AT_NONE); // Cmdline_mouse_coords
cmdline_parm timeout("-timeout", "Multiplayer network timeout (secs)", AT_INT); // Cmdline_timeout
cmdline_parm bit32_arg("-32bit", "Deprecated", AT_NONE); // (only here for retail compatibility reasons, doesn't actually do anything)
char *Cmdline_connect_addr = NULL;
char *Cmdline_game_name = NULL;
char *Cmdline_game_password = NULL;
char *Cmdline_rank_above = NULL;
char *Cmdline_rank_below = NULL;
SCP_string Cmdline_connect_addr;
SCP_string Cmdline_game_name;
SCP_string Cmdline_game_password;
SCP_string Cmdline_rank_above;
SCP_string Cmdline_rank_below;
int Cmdline_cd_check = 1;
int Cmdline_client_dodamage = 0;
int Cmdline_closed_game = 0;
@@ -392,7 +408,7 @@ int Cmdline_no_enhanced_sound = 0;
// MOD related
cmdline_parm mod_arg("-mod", "List of folders to overwrite/add-to the default data", AT_STRING, true); // Cmdline_mod -- DTP modsupport
char *Cmdline_mod = NULL; //DTP for mod argument
SCP_vector<cfile::ModRoot> Cmdline_mod; // DTP for mod argument
// Multiplayer/Network related
cmdline_parm almission_arg("-almission", "Autoload multiplayer mission", AT_STRING); // Cmdline_almission -- DTP for autoload Multi mission
@@ -402,15 +418,19 @@ cmdline_parm missioncrcspew_arg("-missioncrcs", NULL, AT_STRING); // Cmdline_sp
cmdline_parm tablecrcspew_arg("-tablecrcs", NULL, AT_STRING); // Cmdline_spew_table_crcs
cmdline_parm objupd_arg("-cap_object_update", "Multiplayer object update cap (0-3)", AT_INT);
char *Cmdline_almission = NULL; //DTP for autoload multi mission.
SCP_string Cmdline_almission; // DTP for autoload multi mission.
int Cmdline_ingamejoin = 0;
int Cmdline_mpnoreturn = 0;
char *Cmdline_spew_mission_crcs = NULL;
char *Cmdline_spew_table_crcs = NULL;
SCP_string Cmdline_spew_mission_crcs;
SCP_string Cmdline_spew_table_crcs;
int Cmdline_objupd = 3; // client object updates on LAN by default
// Launcher related options
cmdline_parm portable_mode("-portable_mode", NULL, AT_NONE);
cmdline_parm
stdin_flags("-stdin_flags",
"Tells FSO to read flags from stdin. Parameter is format if data supplied. Possible values: json_v1",
AT_STRING);
bool Cmdline_portable_mode = false;
@@ -442,7 +462,7 @@ int Cmdline_no_pbo = 0;
int Cmdline_ati_color_swap = 0;
int Cmdline_no_3d_sound = 0;
int Cmdline_drawelements = 0;
char* Cmdline_keyboard_layout = NULL;
SCP_string Cmdline_keyboard_layout;
bool Cmdline_gl_finish = false;
bool Cmdline_no_geo_sdr_effects = false;
bool Cmdline_set_cpu_affinity = false;
@@ -479,8 +499,7 @@ cmdline_parm show_video_info("-show_video_info", NULL, AT_NONE); //Cmdline_show_
cmdline_parm frame_profile_arg("-profile_frame_time", NULL, AT_NONE); //Cmdline_frame_profile
cmdline_parm debug_window_arg("-debug_window", NULL, AT_NONE); // Cmdline_debug_window
char *Cmdline_start_mission = NULL;
SCP_string Cmdline_start_mission;
int Cmdline_dis_collisions = 0;
int Cmdline_dis_weapons = 0;
bool Cmdline_output_sexp_info = false;
@@ -495,8 +514,8 @@ int Cmdline_show_stats = 0;
int Cmdline_save_render_targets = 0;
int Cmdline_window = 0;
int Cmdline_fullscreen_window = 0;
char *Cmdline_res = 0;
char *Cmdline_center_res = 0;
SCP_string Cmdline_res;
SCP_string Cmdline_center_res;
int Cmdline_verify_vps = 0;
int Cmdline_reparse_mainhall = 0;
bool Cmdline_profile_write_file = false;
@@ -547,8 +566,8 @@ void cmdline_debug_print_cmdline()
for (parmp = GET_FIRST(&Parm_list); parmp !=END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp) ) {
if ( parmp->name_found ) {
if ( parmp->args != NULL ) {
mprintf(("\n %s %s", parmp->name, parmp->args));
if (!parmp->args.empty()) {
mprintf(("\n %s %s", parmp->name, parmp->args.c_str()));
} else {
mprintf(("\n %s", parmp->name));
}
@@ -654,14 +673,13 @@ char *drop_extra_chars(char *str)
return str;
}
/*
* @brief Processes one argument for the given parameter
*
* @param param The parameter to check
* @param argc The argument count
* @param argc The argument values
* @param argc The current index
* @param argv The argument values
* @param index The current index
* @return @c true when an extra parameter was found, @c false otherwise
*/
bool parm_stuff_args(cmdline_parm *parm, int argc, char *argv[], int index)
@@ -678,47 +696,17 @@ bool parm_stuff_args(cmdline_parm *parm, int argc, char *argv[], int index)
}
else
{
char* saved_args = NULL;
if (parm->args != NULL) {
if (parm->stacks) {
saved_args = parm->args;
if (parm->stacks) {
if (!parm->args.empty())
{
// Avoid adding the , at the start
parm->args += ",";
}
else {
delete[] parm->args;
}
parm->args = NULL;
}
size_t argsize = strlen(argv[index + 1]);
size_t buffersize = argsize;
if (saved_args != NULL)
{
// Add one for the , separating args
buffersize += strlen(saved_args) + 1;
}
buffersize += 1; // Null-terminator
parm->args = new char[buffersize];
memset(parm->args, 0, buffersize);
if (saved_args != NULL)
{
// saved args go first, then new arg
strcpy_s(parm->args, buffersize, saved_args);
// add a separator too, so that we can tell the args apart
strcat_s(parm->args, buffersize, ",");
// now the new arg
strcat_s(parm->args, buffersize, argv[index + 1]);
delete[] saved_args;
parm->args += argv[index + 1];
}
else
{
strcpy_s(parm->args, buffersize, argv[index + 1]);
parm->args = argv[index + 1];
}
return true;
@@ -750,7 +738,7 @@ void os_parse_parms(int argc, char *argv[])
for (parmp = GET_FIRST(&Parm_list); parmp != END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp)) {
if (!stricmp(parmp->name, argv[i]))
{
parmp->name_found = 1;
parmp->name_found = true;
if (parm_stuff_args(parmp, argc, argv, i))
{
i++;
@@ -931,11 +919,8 @@ bool has_cmdline_only_flag(int argc, char *argv[])
static void reset_cmdline_parms()
{
for (cmdline_parm *parmp = GET_FIRST(&Parm_list); parmp != END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp)) {
if (parmp->args != NULL) {
delete[] parmp->args;
parmp->args = NULL;
}
parmp->name_found = 0;
parmp->args.clear();
parmp->name_found = false;
}
}
@@ -1031,11 +1016,14 @@ void os_init_cmdline(int argc, char *argv[])
* @param arg_type_ parameters arguement type (if any)
* @param stacks_ can the parameter be stacked
*/
cmdline_parm::cmdline_parm(const char *name_, const char *help_, const int arg_type_, const bool stacks_):
name(name_), help(help_), stacks(stacks_), arg_type(arg_type_)
cmdline_parm::cmdline_parm(const char* name_, const char* help_, const int arg_type_, const bool stacks_) noexcept
: name(name_), help(help_), stacks(stacks_), arg_type(arg_type_)
{
args = NULL;
name_found = 0;
if (stacks) {
Assertion(arg_type == AT_STRING, "Only string arguments can stack!");
}
name_found = false;
if (Parm_list_inited == 0) {
Assertion(&Parm_list == this, "Coding error! 1st initialised cmdline_parm must be static Parm_list\n");
@@ -1054,20 +1042,12 @@ cmdline_parm::cmdline_parm(const char *name_, const char *help_, const int arg_t
// destructor - frees any allocated memory
cmdline_parm::~cmdline_parm()
{
#ifndef FRED
if (args) {
delete [] args;
args = NULL;
}
#endif
}
cmdline_parm::~cmdline_parm() noexcept = default;
// checks if the objects args variable is valid
// returns true if it is, shows an error box and returns false if not valid.
bool cmdline_parm::check_if_args_is_valid() {
if ( args == NULL ) {
if (args.empty()) {
Error(__FILE__, __LINE__,
"Command line flag passed that requires an argument, but the argument is missing!\r\n"
"The flag is '%s', make sure that you have an argument that follows it.\r\n"
@@ -1081,10 +1061,7 @@ bool cmdline_parm::check_if_args_is_valid() {
// returns - true if the parameter exists on the command line, otherwise false
int cmdline_parm::found()
{
return name_found;
}
bool cmdline_parm::found() { return name_found; }
// returns - the interger representation for the parameter argument
int cmdline_parm::get_int()
@@ -1092,22 +1069,12 @@ int cmdline_parm::get_int()
Assertion(arg_type == AT_INT, "Coding error! Cmdline arg (%s) called cmdline_parm::get_int() with invalid arg_type (%s)", name, cmdline_arg_types[arg_type]);
check_if_args_is_valid();
size_t offset = 0;
if (stacks) {
// first off, DON'T STACK NON-STRINGS!!
Int3();
// secondly, we still need to get it right for the user's sake...
char *moron = strstr(args, ",");
if ( moron && ((strlen(moron) + 1) < strlen(args)) ) {
// we get the last arg, since it's the newest one
offset = strlen(args) - strlen(moron) + 1;
}
try {
return std::stoi(args);
} catch (const std::exception& e) {
Warning(LOCATION, "Failed to convert '%s' to a float for parameter '%s'!", args.c_str(), name);
return 0;
}
return atoi(args+offset);
}
@@ -1117,36 +1084,24 @@ float cmdline_parm::get_float()
Assertion(arg_type == AT_FLOAT, "Coding error! Cmdline arg (%s) called cmdline_parm::get_float() with invalid arg_type (%s)", name, cmdline_arg_types[arg_type]);
check_if_args_is_valid();
size_t offset = 0;
if (stacks) {
// first off, DON'T STACK NON-STRINGS!!
Int3();
// secondly, we still need to get it right for the user's sake
char *moron = strstr(args, ",");
if ( moron && ((strlen(moron) + 1) < strlen(args)) ) {
// we get the last arg, since it's the newest one
offset = strlen(args) - strlen(moron) + 1;
}
try {
return std::stof(args);
} catch (const std::exception& e) {
Warning(LOCATION, "Failed to convert '%s' to a float for parameter '%s'!", args.c_str(), name);
return 0.0f;
}
return (float)atof(args+offset);
}
// returns - the string value for the parameter argument
char *cmdline_parm::str()
SCP_string cmdline_parm::str()
{
Assertion(arg_type == AT_STRING, "Coding error! Cmdline arg (%s) called cmdline_parm::str() with invalid arg_type (%s)", name, cmdline_arg_types[arg_type]);
check_if_args_is_valid();
return args;
}
bool cmdline_parm::has_param() {
return args != nullptr;
}
bool cmdline_parm::has_param() { return !args.empty(); }
#ifdef SCP_UNIX
// Return a vector with all filesystem names of "parent/dir" relative to parent.
@@ -1207,39 +1162,31 @@ static SCP_vector<SCP_string> unix_get_dir_names(const SCP_string& parent, const
}
// For case sensitive filesystems (e.g. Linux/BSD) perform case-insensitive dir matches.
static void handle_unix_modlist(char **modlist, size_t *len)
static SCP_string handle_unix_modlist(const SCP_string& modlist)
{
// search filesystem for given paths
SCP_vector<SCP_string> mod_paths;
for (char *cur_mod = strtok(*modlist, ","); cur_mod != NULL; cur_mod = strtok(NULL, ","))
{
SCP_stringstream iss(modlist);
SCP_string cur_mod;
while (std::getline(iss, cur_mod, ',')) {
SCP_vector<SCP_string> this_mod_paths = unix_get_dir_names(".", cur_mod);
// Ignore non-existing mods for unit tests
if (!running_unittests && this_mod_paths.empty()) {
ReleaseWarning(LOCATION, "Can't find mod '%s'. Ignoring.", cur_mod);
ReleaseWarning(LOCATION, "Can't find mod '%s'. Ignoring.", cur_mod.c_str());
}
mod_paths.insert(mod_paths.end(), this_mod_paths.begin(), this_mod_paths.end());
}
// create new char[] to replace modlist
size_t total_len = 0;
SCP_vector<SCP_string>::iterator ii, end = mod_paths.end();
for (ii = mod_paths.begin(); ii != end; ++ii) {
total_len += ii->length() + 1;
}
char *new_modlist = new char[total_len + 1];
memset(new_modlist, 0, total_len + 1);
end = mod_paths.end();
for (ii = mod_paths.begin(); ii != end; ++ii) {
strcat_s(new_modlist, total_len + 1, ii->c_str());
strcat_s(new_modlist, total_len + 1, ","); // replace later with NUL
// create new string to replace modlist
SCP_string new_modlist;
for (const auto& path : mod_paths) {
new_modlist += path;
new_modlist += ","; // replace later with NUL
}
// make the rest of the modlist manipulation unaware that anything happened here
delete [] *modlist;
*modlist = new_modlist;
*len = total_len;
return new_modlist;
}
#endif /* SCP_UNIX */
@@ -1297,6 +1244,7 @@ static json_t* json_get_v1() {
json_array_append_new(caps_array, json_string("No D3D"));
json_array_append_new(caps_array, json_string("New Sound"));
json_array_append_new(caps_array, json_string("SDL"));
json_array_append_new(caps_array, json_string("Stdin Flags: Json V1"));
json_object_set_new(root, "caps", caps_array);
}
@@ -1487,16 +1435,218 @@ static void write_flags() {
case flag_output_type::Binary:
write_flags_file();
break;
case flag_output_type::Json_V1:
case flag_output_type::Json_V1: {
json_t* root = json_get_v1();
json_dumpf(root, stdout, JSON_INDENT(4));
json_decref(root);
break;
}
}
}
bool SetCmdlineParams()
static bool validate_version(json_t* rootEl)
{
const auto version_el = json_object_get(rootEl, "version");
if (version_el == nullptr) {
printf("Version element is missing!\n");
return false;
}
if (!json_is_number(version_el)) {
printf("Version value is not a number!\n");
return false;
}
if (json_integer_value(version_el) != 1) {
printf("Version value %" JSON_INTEGER_FORMAT " is not supported!\n", json_integer_value(version_el));
return false;
}
return true;
}
static cfile::ModRootType mapModRootType(const char* rootStr) {
if (!stricmp(rootStr, "folder")) {
return cfile::ModRootType::Folder;
} else if (!stricmp(rootStr, "package")) {
return cfile::ModRootType::Package;
} else {
return cfile::ModRootType::Unknown;
}
}
static cfile::LocationType mapLocationType(const char* rootStr) {
if (!stricmp(rootStr, "game_root")) {
return cfile::LocationType::GameRoot;
} else if (!stricmp(rootStr, "primary_mod")) {
return cfile::LocationType::PrimaryMod;
} else if (!stricmp(rootStr, "secondary_mod")) {
return cfile::LocationType::SecondaryMod;
} else {
return cfile::LocationType::Unknown;
}
}
static void stuff_mod_option(cmdline_parm* param, json_t* el)
{
if (!json_is_array(el))
{
printf("Value for option %s must be an array!", param->name);
return;
}
SCP_vector<cfile::ModRoot> roots;
size_t i;
json_t* modObj;
json_array_foreach(el, i, modObj)
{
const auto typeEl = json_object_get(modObj, "type");
const auto pathEl = json_object_get(modObj, "path");
const auto locationEl = json_object_get(modObj, "location_type");
if (typeEl == nullptr || pathEl == nullptr || locationEl == nullptr)
{
printf("A required mod root element is missing: Type %p, Path %p, Location %p", typeEl, pathEl, locationEl);
continue;
}
if (!json_is_string(typeEl) || !json_is_string(pathEl) || !json_is_string(locationEl))
{
printf("An element had a wrong type: Type %d, Path %d, Location %d", json_typeof(typeEl), json_typeof(pathEl), json_typeof(locationEl));
continue;
}
const auto userEl = json_object_get(modObj, "user");
if (userEl != nullptr && !json_is_boolean(userEl))
{
printf("User element type is not a boolean!");
continue;
}
cfile::ModRoot root;
root.type = mapModRootType(json_string_value(typeEl));
root.path = json_string_value(pathEl);
root.location_type = mapLocationType(json_string_value(locationEl));
root.user_location = userEl == nullptr ? false : json_boolean_value(userEl);
roots.push_back(root);
}
Cmdline_mod = roots;
}
static void stuff_json_option(cmdline_parm* param, json_t* el)
{
if (param == &mod_arg)
{
// The -mod parameter is handled specially since it is not a simple string
stuff_mod_option(param, el);
return;
}
switch (param->arg_type) {
case AT_NONE:
if (!json_is_boolean(el)) {
printf("Value for option %s must be a boolean!", param->name);
return;
}
param->name_found = json_is_true(el);
break;
case AT_INT:
if (!json_is_number(el)) {
printf("Value for option %s must be a number!", param->name);
return;
}
param->name_found = true;
param->args = std::to_string(json_integer_value(el));
break;
case AT_FLOAT:
if (!json_is_number(el)) {
printf("Value for option %s must be a number!", param->name);
return;
}
param->name_found = true;
param->args = std::to_string(json_real_value(el));
break;
case AT_STRING:
if (!json_is_string(el)) {
printf("Value for option %s must be a string!", param->name);
return;
}
param->name_found = true;
param->args.assign(json_string_value(el), json_string_length(el));
break;
default:
UNREACHABLE("Unknown arg type %d.", param->arg_type);
return;
}
}
static bool parse_json_flags(json_t* rootEl)
{
if (!json_is_object(rootEl)) {
printf("Root element must be an object!\n");
return false;
}
if (!validate_version(rootEl)) {
return false;
}
const auto flagsEl = json_object_get(rootEl, "flags");
if (flagsEl == nullptr) {
printf("Flags element is missing!\n");
return false;
}
if (!json_is_object(flagsEl)) {
printf("Flags element is not an object!\n");
return false;
}
const char* flagName;
json_t* flagValue;
json_object_foreach(flagsEl, flagName, flagValue)
{
for (auto parmp = GET_FIRST(&Parm_list); parmp != END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp)) {
if (!stricmp(parmp->name, flagName)) {
stuff_json_option(parmp, flagValue);
}
}
}
return true;
}
static bool SetCmdlineParams(flag_input_type inputType);
static bool SetCmdlineParamsFromStdin(const SCP_string& format)
{
if (format != "json_v1") {
// Invalid format!
printf("INPUT TYPE '%s' IS NOT SUPPORTED!\n", format.c_str());
return false;
}
json_error_t error;
json_t* flagsEl = json_loadf(stdin, JSON_DISABLE_EOF_CHECK, &error);
if (flagsEl == nullptr) {
printf("Failed to parse JSON: %s(%d:%d): %s\n", error.source, error.line, error.column, error.text);
return false;
}
if (!parse_json_flags(flagsEl)) {
return false;
}
return SetCmdlineParams(flag_input_type::Stdin_Json_V1);
}
static bool SetCmdlineParams(flag_input_type inputType)
// Sets externed variables used for communication cmdline information
{
//getcwd(FreeSpace_Directory, 256); // set the directory to our fs2 root
@@ -1508,6 +1658,10 @@ bool SetCmdlineParams()
return false;
}
if (inputType == flag_input_type::Flags && stdin_flags.found()) {
return SetCmdlineParamsFromStdin(stdin_flags.str());
}
if (no_fpscap.found())
{
Cmdline_NoFPSCap = 1;
@@ -1539,8 +1693,8 @@ bool SetCmdlineParams()
Cmdline_spew_mission_crcs = missioncrcspew_arg.str();
// strip off blank space at end if it's there
if ( Cmdline_spew_mission_crcs[strlen(Cmdline_spew_mission_crcs)-1] == ' ' ) {
Cmdline_spew_mission_crcs[strlen(Cmdline_spew_mission_crcs)-1] = '\0';
if (Cmdline_spew_mission_crcs.back() == ' ') {
Cmdline_spew_mission_crcs.resize(Cmdline_spew_mission_crcs.size() - 1);
}
}
@@ -1548,8 +1702,8 @@ bool SetCmdlineParams()
Cmdline_spew_table_crcs = tablecrcspew_arg.str();
// strip off blank space at end if it's there
if ( Cmdline_spew_table_crcs[strlen(Cmdline_spew_table_crcs)-1] == ' ' ) {
Cmdline_spew_table_crcs[strlen(Cmdline_spew_table_crcs)-1] = '\0';
if (Cmdline_spew_table_crcs.back() == ' ') {
Cmdline_spew_table_crcs.resize(Cmdline_spew_table_crcs.size() - 1);
}
}
@@ -1615,8 +1769,8 @@ bool SetCmdlineParams()
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';
if (Cmdline_game_name.size() > MAX_GAMENAME_LEN - 1) {
Cmdline_game_name.resize(MAX_GAMENAME_LEN - 1);
}
}
@@ -1625,8 +1779,8 @@ bool SetCmdlineParams()
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';
if (Cmdline_game_password.size() > MAX_GAMENAME_LEN - 1) {
Cmdline_game_password.resize(MAX_GAMENAME_LEN - 1);
}
}
@@ -1695,12 +1849,13 @@ bool SetCmdlineParams()
int width = 0;
int height = 0;
if ( sscanf(Cmdline_res, "%dx%d", &width, &height) == 2 ) {
if (sscanf(Cmdline_res.c_str(), "%dx%d", &width, &height) == 2) {
SCP_string override;
sprintf(override, "{\"width\":%d,\"height\":%d}", width, height);
sprintf(override, R"({"width":%d,"height":%d})", width, height);
options::OptionsManager::instance()->setOverride("Graphics.Resolution", override);
} else {
mprintf(("Failed to parse -res parameter \"%s\". Must be in format \"<width>x<height>\".", Cmdline_res));
mprintf(("Failed to parse -res parameter \"%s\". Must be in format \"<width>x<height>\".",
Cmdline_res.c_str()));
}
}
if(center_res_arg.found()){
@@ -1733,35 +1888,32 @@ bool SetCmdlineParams()
Cmdline_noparseerrors = 1;
}
if(mod_arg.found() ) {
Cmdline_mod = mod_arg.str();
// Legacy mod handling is handled here
if (inputType == flag_input_type::Flags && mod_arg.found()) {
auto modCmdline = mod_arg.str();
// strip off blank space it it's there
if ( Cmdline_mod[strlen(Cmdline_mod)-1] == ' ' ) {
Cmdline_mod[strlen(Cmdline_mod)-1] = '\0';
if (modCmdline.back() == ' ') {
modCmdline.resize(modCmdline.size() - 1);
}
// Ok - mod stacking support
size_t len = strlen(Cmdline_mod);
char *modlist = new char[len+2];
memset( modlist, 0, len + 2 );
strcpy_s(modlist, len+2, Cmdline_mod);
#ifdef SCP_UNIX
// handle case-insensitive searching
handle_unix_modlist(&modlist, &len);
modCmdline = handle_unix_modlist(modCmdline);
#endif
// null terminate each individual
for (size_t i = 0; i < len; i++)
for (auto& ch : modCmdline)
{
if (modlist[i] == ',')
modlist[i] = '\0';
if (ch == ',')
ch = '\0';
}
//copy over - we don't have to delete[] Cmdline_mod because it's a pointer to an automatic global char*
Cmdline_mod = modlist;
char whee[MAX_PATH_LEN];
memset(whee, 0, sizeof(whee));
_getcwd(whee, MAX_PATH_LEN-1);
Cmdline_mod = cfile::getModRootsFromModCmdline(whee, modCmdline.c_str());
}
@@ -2185,7 +2337,7 @@ int parse_cmdline(int argc, char *argv[])
// --------------- Kazan -------------
// If you're looking for the list of if (someparam.found()) { cmdline_someparam = something; } look above at this function
// I did this because of fred2_parse_cmdline()
return SetCmdlineParams();
return SetCmdlineParams(flag_input_type::Flags);
}
const char * get_param_desc(const char *flag_name)
+18 -13
View File
@@ -12,6 +12,7 @@
#ifndef FS_CMDLINE_HEADER_FILE
#define FS_CMDLINE_HEADER_FILE
#include "globalincs/pstypes.h"
int parse_cmdline(int argc, char *argv[]);
@@ -24,11 +25,11 @@ int parse_cmdline(int argc, char *argv[]);
// RETAIL OPTIONS ----------------------------------------------
extern char *Cmdline_connect_addr;
extern char *Cmdline_game_name;
extern char *Cmdline_game_password;
extern char *Cmdline_rank_above;
extern char *Cmdline_rank_below;
extern SCP_string Cmdline_connect_addr;
extern SCP_string Cmdline_game_name;
extern SCP_string Cmdline_game_password;
extern SCP_string Cmdline_rank_above;
extern SCP_string Cmdline_rank_below;
extern int Cmdline_cd_check;
extern int Cmdline_client_dodamage;
extern int Cmdline_closed_game;
@@ -46,8 +47,8 @@ extern int Cmdline_timeout;
extern int Cmdline_use_last_pilot;
extern int Cmdline_window;
extern int Cmdline_fullscreen_window;
extern char *Cmdline_res;
extern char *Cmdline_center_res;
extern SCP_string Cmdline_res;
extern SCP_string Cmdline_center_res;
// FSO OPTIONS -------------------------------------------------
@@ -96,14 +97,18 @@ extern int Cmdline_stretch_menu;
extern int Cmdline_voice_recognition;
extern int Cmdline_no_enhanced_sound;
namespace cfile {
struct ModRoot;
} // namespace cfile
// MOD related
extern char *Cmdline_mod; // DTP for mod support
extern SCP_vector<cfile::ModRoot> Cmdline_mod; // DTP for mod support
// Multiplayer/Network related
extern char *Cmdline_almission; // DTP for autoload mission (for multi only)
extern SCP_string Cmdline_almission; // DTP for autoload mission (for multi only)
extern int Cmdline_ingamejoin;
extern int Cmdline_mpnoreturn;
extern char *Cmdline_spew_mission_crcs;
extern char *Cmdline_spew_table_crcs;
extern SCP_string Cmdline_spew_mission_crcs;
extern SCP_string Cmdline_spew_table_crcs;
extern int Cmdline_objupd;
// Launcher related options
@@ -119,7 +124,7 @@ extern int Cmdline_mipmap;
extern int Cmdline_ati_color_swap;
extern int Cmdline_no_3d_sound;
extern int Cmdline_drawelements;
extern char* Cmdline_keyboard_layout;
extern SCP_string Cmdline_keyboard_layout;
extern bool Cmdline_gl_finish;
extern bool Cmdline_no_geo_sdr_effects;
extern bool Cmdline_set_cpu_affinity;
@@ -130,7 +135,7 @@ extern bool Cmdline_alternate_registry_path;
#endif
// Developer/Testing related
extern char *Cmdline_start_mission;
extern SCP_string Cmdline_start_mission;
extern int Cmdline_dis_collisions;
extern int Cmdline_dis_weapons;
extern bool Cmdline_output_sexp_info;
+48
View File
@@ -0,0 +1,48 @@
{
"version": 1,
"flags": {
"-bool_option": false,
"-number_option": 5.8,
"-string_option": "asdf",
"-mod": [
{
"type": "folder",
"path": "/home/fso/mediavps",
"user": true,
"location_type": "primary_mod"
},
{
"type": "folder",
"path": "/home/fso",
"user": true,
"location_type": "game_root"
},
{
"type": "folder",
"path": "/path/to/fso/mediavps",
"user": false,
"location_type": "primary_mod"
},
{
"type": "package",
"path": "/path/to/fso/mediavps/MVPS-Z.vp",
"location_type": "primary_mod"
},
{
"type": "package",
"path": "/path/to/fso/mediavps/MVPS-X.vp",
"location_type": "primary_mod"
},
{
"type": "folder",
"path": "/path/to/fso",
"location_type": "game_root"
},
{
"type": "package",
"path": "/path/to/fso/retail.vp",
"location_type": "game_root"
}
]
}
}
+2 -2
View File
@@ -1678,7 +1678,7 @@ void fs2netd_spew_table_checksums(const char *outfile)
char description[512] = { 0 };
char filename[65] = { 0 };
size_t offset = 0;
char *p = NULL;
const char *p = nullptr;
if ( Table_valid_status.empty() ) {
return;
@@ -1693,7 +1693,7 @@ void fs2netd_spew_table_checksums(const char *outfile)
return;
}
p = Cmdline_spew_table_crcs;
p = Cmdline_spew_table_crcs.c_str();
while (*p && (offset < sizeof(description))) {
if (*p == '"' && offset < sizeof(description)-1) {
+4 -4
View File
@@ -1248,11 +1248,11 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,
}
}
if (Cmdline_res != nullptr) {
if (!Cmdline_res.empty()) {
int tmp_width = 0;
int tmp_height = 0;
if ( sscanf(Cmdline_res, "%dx%d", &tmp_width, &tmp_height) == 2 ) {
if ( sscanf(Cmdline_res.c_str(), "%dx%d", &tmp_width, &tmp_height) == 2 ) {
width = tmp_width;
height = tmp_height;
}
@@ -1260,11 +1260,11 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,
Gr_enable_soft_particles = Cmdline_softparticles != 0;
}
if (Cmdline_center_res != NULL) {
if (!Cmdline_center_res.empty()) {
int tmp_center_width = 0;
int tmp_center_height = 0;
if ( (sscanf(Cmdline_center_res, "%dx%d", &tmp_center_width, &tmp_center_height) == 2) && (tmp_center_width > 0) && (tmp_center_height > 0) ) {
if ( (sscanf(Cmdline_center_res.c_str(), "%dx%d", &tmp_center_width, &tmp_center_height) == 2) && (tmp_center_width > 0) && (tmp_center_height > 0) ) {
center_aspect_ratio = (float)tmp_center_width / (float)tmp_center_height;
}
}
-14
View File
@@ -883,20 +883,6 @@ static void opengl_purge_shader_cache_type(const char* ext) {
SCP_string filter("*.");
filter += ext;
// Previously the cache files were stored in the mod directory. Since we have a better system now, those files
// should be cleaned out. This is only needed if we have a mod directory since otherwise we would delete the actual
// cache files
if (Cmdline_mod != nullptr && strlen(Cmdline_mod) > 0) {
SCP_vector<SCP_string> cache_files;
cf_get_file_list(cache_files, CF_TYPE_CACHE, filter.c_str(), CF_SORT_NONE, nullptr,
CF_LOCATION_TYPE_PRIMARY_MOD | CF_LOCATION_TYPE_SECONDARY_MODS);
for (auto& file : cache_files) {
cf_delete((file + "." + ext).c_str(), CF_TYPE_CACHE,
CF_LOCATION_TYPE_PRIMARY_MOD | CF_LOCATION_TYPE_SECONDARY_MODS);
}
}
SCP_vector<SCP_string> cache_files;
SCP_vector<file_list_info> file_info;
cf_get_file_list(cache_files, CF_TYPE_CACHE, filter.c_str(), CF_SORT_NONE, &file_info,
+20 -7
View File
@@ -5688,16 +5688,29 @@ bool parse_mission(mission *pm, int flags)
strcat_s(text, pm->name);
}
strcat_s(text, "\", and the current mod is \"");
strcat_s(text, "\", and the current mod root is \"");
if (Cmdline_mod == NULL || *Cmdline_mod == 0) {
strcat_s(text, "<retail default> ");
} else {
for (char *mod_token = Cmdline_mod; *mod_token != '\0'; mod_token += strlen(mod_token) + 1) {
strcat_s(text, mod_token);
strcat_s(text, " ");
// Try to find the first non-user, folder root and display that. Not ideal but better than nothing I guess...
// We go through all the specified mod roots and find the first non-user folder. If that does not exist then
// user folders will be considered next. If that also fails, a default value is used.
SCP_string modRoot = "<Unknown>";
for (const auto& consider_user : {false, true})
{
for (const auto& root : Cmdline_mod)
{
if (root.type != cfile::ModRootType::Folder)
{
continue;
}
if (root.user_location && !consider_user) {
continue;
}
modRoot = root.path;
}
}
strcat_s(text, modRoot.c_str());
strcpy(text + strlen(text) - 1, "\".)\n\n You can continue to load the mission, but it is quite likely that you will encounter a large number of mysterious errors. It is recommended that you either select a ");
strcat(text, (Game_mode & GM_CAMPAIGN_MODE) ? "campaign" : "mission");
+2 -2
View File
@@ -1370,8 +1370,8 @@ void process_accept_player_data( ubyte *data, header *hinfo )
if ( stop == APD_END_DATA ) {
// if joining a game automatically, set the connect address to NULl so we don't try and
// do this next time we enter a game
if (Cmdline_connect_addr != NULL) {
Cmdline_connect_addr = NULL;
if (!Cmdline_connect_addr.empty()) {
Cmdline_connect_addr.clear();
}
// send my stats to the server if I'm not in observer mode
+23 -26
View File
@@ -945,8 +945,7 @@ void multi_join_game_init()
// if starting a network game, then go to the create game screen
if ( Cmdline_start_netgame ) {
multi_join_create_game();
} else if ( Cmdline_connect_addr != NULL ) {
char *p;
} else if ( !Cmdline_connect_addr.empty() ) {
short port_num;
int ip_addr;
@@ -956,13 +955,11 @@ void multi_join_game_init()
// create the address, looking out for port number at the end
port_num = DEFAULT_GAME_PORT;
p = strrchr(Cmdline_connect_addr, ':');
if ( p ) {
*p = '\0';
p++;
port_num = (short)atoi(p);
const auto number_end = Cmdline_connect_addr.find(':');
if ( number_end != SCP_string::npos ) {
port_num = (short)atoi(Cmdline_connect_addr.substr(0, number_end).c_str());
}
ip_addr = inet_addr(Cmdline_connect_addr);
ip_addr = inet_addr(Cmdline_connect_addr.c_str());
memcpy(Multi_autojoin_addr.addr, &ip_addr, 4);
Multi_autojoin_addr.port = port_num;
@@ -1006,7 +1003,7 @@ void multi_join_game_do_frame()
}
// when joining a network game, wait for the server query to come back, and then join the game
if ( Cmdline_connect_addr != NULL ) {
if ( !Cmdline_connect_addr.empty() ) {
int rval;
if ( !Multi_did_autojoin ) {
@@ -1014,7 +1011,7 @@ void multi_join_game_do_frame()
if ( rval == 0 ) {
// cancel was hit. Send the user back to the main hall
gameseq_post_event(GS_EVENT_MAIN_MENU);
Cmdline_connect_addr = NULL; // reset this value.
Cmdline_connect_addr.clear(); // reset this value.
}
// when we get here, we have the data -- join the game.
@@ -2270,7 +2267,7 @@ void multi_sg_select_rank_default();
// function which takes a rank name and returns the index. Useful for commandline options
// for above and below rank. We return the index of the rank in the Ranks[] array. If
// the rank isn't found, we return -1
int multi_start_game_rank_from_name( char *rank ) {
int multi_start_game_rank_from_name( const char *rank ) {
int i;
for ( i = 0; i <= MAX_FREESPACE2_RANK; i++ ) {
@@ -2355,8 +2352,8 @@ void multi_start_game_init()
// if starting a netgame, set the name of the game and any other options that are appropriate
if ( Cmdline_start_netgame ) {
if ( Cmdline_game_name != NULL ) {
strcpy_s( Multi_sg_netgame->name, Cmdline_game_name );
if ( !Cmdline_game_name.empty() ) {
strcpy_s( Multi_sg_netgame->name, Cmdline_game_name.c_str() );
Multi_sg_game_name.set_text(Multi_sg_netgame->name);
}
@@ -2366,21 +2363,21 @@ void multi_start_game_init()
Multi_sg_netgame->mode = NG_MODE_CLOSED;
} else if ( Cmdline_restricted_game ) {
Multi_sg_netgame->mode = NG_MODE_RESTRICTED;
} else if ( Cmdline_game_password != NULL ) {
} else if ( !Cmdline_game_password.empty() ) {
Multi_sg_netgame->mode = NG_MODE_PASSWORD;
strcpy_s(Multi_sg_netgame->passwd, Cmdline_game_password);
strcpy_s(Multi_sg_netgame->passwd, Cmdline_game_password.c_str());
Multi_sg_game_passwd.set_text(Multi_sg_netgame->passwd);
}
// deal with rank above and rank below
if ( (Cmdline_rank_above != NULL) || (Cmdline_rank_below != NULL) ) {
if ( (!Cmdline_rank_above.empty()) || (!Cmdline_rank_below.empty()) ) {
int rank;
char *rank_str;
const char *rank_str;
if ( Cmdline_rank_above != NULL ) {
rank_str = Cmdline_rank_above;
if ( !Cmdline_rank_above.empty() ) {
rank_str = Cmdline_rank_above.c_str();
} else {
rank_str = Cmdline_rank_below;
rank_str = Cmdline_rank_below.c_str();
}
// try and get the rank index from the name -- if found, then set the rank base
@@ -2391,7 +2388,7 @@ void multi_start_game_init()
Multi_sg_netgame->rank_base = Multi_sg_rank_select;
// now an arbitrary decision
if ( Cmdline_rank_above != NULL ) {
if ( !Cmdline_rank_above.empty() ) {
Multi_sg_netgame->mode = NG_MODE_RANK_ABOVE;
} else {
Multi_sg_netgame->mode = NG_MODE_RANK_BELOW;
@@ -3647,7 +3644,7 @@ void multi_create_game_do()
//DTP CHECK ALMISSION FLAG HERE AND SKIP THE BITMAP LOADING PROGRESS
//SINCE WE ALREADY HAVE A MISSION SELECTED IF THIS MISSION IS A VALID MULTIPLAYER MISSION
//IF NOT A VALID MULTIPLAYER MISSION CONTINUE LOADING, MAYBE CALL POPUP.
if ((Cmdline_almission) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)) { //
if ((!Cmdline_almission.empty()) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)) { //
multi_create_list_do(); //uhm here because off, hehe, my mind is failing right now
// DTP Var section for the is mission multi player Check.
@@ -3655,7 +3652,7 @@ void multi_create_game_do()
char mission_name[NAME_LENGTH+1];
int flags;
char *filename;
filename = cf_add_ext( Cmdline_almission, FS_MISSION_FILE_EXT ); //DTP ADD EXTENSION needed next line
filename = cf_add_ext( Cmdline_almission.c_str(), FS_MISSION_FILE_EXT ); //DTP ADD EXTENSION needed next line
flags = mission_parse_is_multi(filename, mission_name); //DTP flags will set if mission is multi
if (flags) { //only continue if mission is multiplayer mission
@@ -3663,7 +3660,7 @@ void multi_create_game_do()
ng = &Netgame;
char almissionname[256]; // needed, for the strncpy below
strncpy(almissionname, Cmdline_almission,MAX_FILENAME_LEN); //DTP; copying name from cmd_almission line
strncpy(almissionname, Cmdline_almission.c_str(), MAX_FILENAME_LEN); //DTP; copying name from cmd_almission line
Netgame.options.respawn = 99; //override anything //for debugging, i often forget this.
ng->respawn = Netgame.options.respawn;
@@ -3676,13 +3673,13 @@ void multi_create_game_do()
Multi_sync_mode = MULTI_SYNC_PRE_BRIEFING; //DTP must be set before a call to gameseq_post_event(GS_EVENT_MULTI_MISSION_SYNC) is done as it is below.
gameseq_post_event(GS_EVENT_MULTI_MISSION_SYNC);//DTP STart game
Cmdline_almission = NULL; // we don't want to autoload anymore do we, we will be able to quit. halleluja. Startgame has already been disabled, so no need to turn of "Cmdline_start_netgame"
Cmdline_almission.clear(); // we don't want to autoload anymore do we, we will be able to quit. halleluja. Startgame has already been disabled, so no need to turn of "Cmdline_start_netgame"
return; // we don't need to check or set regarding ships/weapons anything as we are already progressing into mission so return
}
else {
popup(PF_BODY_BIG | PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR(" Not a multi player-mission",9999)); //DTP startgame popup pilot error
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
Cmdline_almission = NULL; //DTP make sure this gets nullified.
Cmdline_almission.clear(); //DTP make sure this gets nullified.
}
}
+2 -2
View File
@@ -3263,7 +3263,7 @@ void multi_spew_pxo_checksums(int max_files, const char *outfile)
char filename[65] = { 0 };
char gametype[32] = { 0 };
size_t offset = 0;
char *p = NULL;
const char *p = nullptr;
// allocate filename space
file_names = (char**)vm_malloc(sizeof(char*) * max_files);
@@ -3285,7 +3285,7 @@ void multi_spew_pxo_checksums(int max_files, const char *outfile)
if (out == NULL)
goto Done;
p = Cmdline_spew_mission_crcs;
p = Cmdline_spew_mission_crcs.c_str();
while (*p && (offset < sizeof(description))) {
if (*p == '"') {
+2
View File
@@ -62,6 +62,8 @@ add_file_folder("CFile"
cfile/cfilearchive.cpp
cfile/cfilearchive.h
cfile/cfilelist.cpp
cfile/cfilemod.cpp
cfile/cfilemod.h
cfile/cfilesystem.cpp
cfile/cfilesystem.h
)
+10 -24
View File
@@ -35,6 +35,7 @@
#include "autopilot/autopilot.h"
#include "bmpman/bmpman.h"
#include "cfile/cfile.h"
#include "cfile/cfilemod.h"
#include "cmdline/cmdline.h"
#include "cmeasure/cmeasure.h"
#include "cutscene/cutscenes.h"
@@ -1684,7 +1685,6 @@ void game_init()
{
int s1 __UNUSED, e1 __UNUSED;
const char *ptr;
char whee[MAX_PATH_LEN];
Game_current_mission_filename[0] = 0;
@@ -1725,17 +1725,11 @@ void game_init()
cmdline_debug_print_cmdline();
#endif
memset(whee, 0, sizeof(whee));
_getcwd(whee, MAX_PATH_LEN-1);
strcat_s(whee, DIR_SEPARATOR_STR);
strcat_s(whee, EXE_FNAME);
//Initialize the libraries
s1 = timer_get_milliseconds();
if ( cfile_init(whee, NULL) ) { // initialize before calling any cfopen stuff!!!
// initialize before calling any cfopen stuff!!!
if ( cfile_init(Cmdline_mod) ) {
exit(1);
}
@@ -5686,17 +5680,17 @@ void game_enter_state( int old_state, int new_state )
// Main_hall_netgame_started = 1;
// main_hall_do_multi_ready();
//} DTP commented out to keep original source
if ( (Cmdline_start_netgame || (Cmdline_connect_addr != NULL)) && (!Main_hall_netgame_started) /*&& (Game_mode == GM_MULTIPLAYER)*/) { // DTP added "&& (game_mode == GM_multiplayer)" so that ppl don't get thrown into Multiplayer with a Singleplayer Pilot.
if ( (Cmdline_start_netgame || (!Cmdline_connect_addr.empty())) && (!Main_hall_netgame_started) /*&& (Game_mode == GM_MULTIPLAYER)*/) { // DTP added "&& (game_mode == GM_multiplayer)" so that ppl don't get thrown into Multiplayer with a Singleplayer Pilot.
Main_hall_netgame_started = 1;
main_hall_do_multi_ready();
}
if(Cmdline_start_mission) {
strcpy_s(Game_current_mission_filename, Cmdline_start_mission);
if(!Cmdline_start_mission.empty()) {
strcpy_s(Game_current_mission_filename, Cmdline_start_mission.c_str());
mprintf(( "Straight to mission '%s'\n", Game_current_mission_filename ));
gameseq_post_event(GS_EVENT_START_GAME);
// This stops the mission from loading again when you go back to the hall
Cmdline_start_mission = NULL;
Cmdline_start_mission.clear();
}
break;
@@ -6738,7 +6732,6 @@ int game_main(int argc, char *argv[])
tmp_mem = NULL;
#endif // _WIN32
if ( !parse_cmdline(argc, argv) ) {
return 1;
}
@@ -6757,10 +6750,10 @@ int game_main(int argc, char *argv[])
game_stop_time();
if (Cmdline_spew_mission_crcs) {
if (!Cmdline_spew_mission_crcs.empty()) {
multi_spew_pxo_checksums(1024, "mission_crcs.csv");
if (Cmdline_spew_table_crcs) {
if (!Cmdline_spew_table_crcs.empty()) {
fs2netd_spew_table_checksums("table_crcs.csv");
}
@@ -6768,7 +6761,7 @@ int game_main(int argc, char *argv[])
return 0;
}
if (Cmdline_spew_table_crcs) {
if (!Cmdline_spew_table_crcs.empty()) {
fs2netd_spew_table_checksums("table_crcs.csv");
game_shutdown();
return 0;
@@ -6965,13 +6958,6 @@ void game_shutdown(void)
cfile_close();
// although the comment in cmdline.cpp said this isn't needed,
// Valgrind disagrees (quite possibly incorrectly), but this is just cleaner
if (Cmdline_mod != NULL) {
delete[] Cmdline_mod;
Cmdline_mod = NULL;
}
lcl_xstr_close();
#if 0 // don't have an updater for fs2_open
+1 -5
View File
@@ -81,12 +81,8 @@ initialize(const std::string& cfilepath, int argc, char* argv[], Editor* editor,
cmdline_debug_print_cmdline();
#endif
// d'oh
// cfile needs a file path...
auto file_path = cfilepath + DIR_SEPARATOR_STR + "qtfred.exe";
listener(SubSystem::CFile);
if (cfile_init(file_path.c_str())) {
if (cfile_init(cfilepath.c_str())) {
return false;
}
-6
View File
@@ -24,8 +24,6 @@ class CFileInitTest : public test::FSTestFixture {
TEST_F(CFileInitTest, wrong_data_case) {
SCP_string cfile_dir(TEST_DATA_PATH);
cfile_dir += DIR_SEPARATOR_CHAR;
cfile_dir += "test"; // Cfile expects something after the path
ASSERT_FALSE(cfile_init(cfile_dir.c_str()));
@@ -34,8 +32,6 @@ TEST_F(CFileInitTest, wrong_data_case) {
TEST_F(CFileInitTest, right_data_case) {
SCP_string cfile_dir(TEST_DATA_PATH);
cfile_dir += DIR_SEPARATOR_CHAR;
cfile_dir += "test"; // Cfile expects something after the path
ASSERT_FALSE(cfile_init(cfile_dir.c_str()));
@@ -129,8 +125,6 @@ TEST(CFileStandalone, test_check_location_flags) {
TEST_F(CFileTest, test_get_path_type)
{
SCP_string cfile_dir(TEST_DATA_PATH);
cfile_dir += DIR_SEPARATOR_CHAR;
cfile_dir += "test"; // Cfile expects something after the path
ASSERT_FALSE(cfile_init(cfile_dir.c_str()));
-2
View File
@@ -33,8 +33,6 @@ void test::FSTestFixture::SetUp() {
if (_initFlags & INIT_CFILE) {
SCP_string cfile_dir(TEST_DATA_PATH);
cfile_dir += DIR_SEPARATOR_CHAR;
cfile_dir += "test"; // Cfile expects something after the path
if (cfile_init(cfile_dir.c_str())) {
FAIL() << "Cfile init failed!";