mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-08 07:28:22 -10:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1111dcf0a8 |
No files matched your search
+2
-68
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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();
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 == '"') {
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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()));
|
||||
|
||||
|
||||
@@ -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!";
|
||||
|
||||
Reference in new issue
Block a user