mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-10 09:32:29 +01:00
Let user specify the data dir as cmdline option.
This adds --openrct-data-dir=<str> option to command line letting user select where he wants OpenRCT2-specific data to be. By default the search locations are: * <exePath>/data (on all platforms) * /var/lib/openrct2 (on Linux) * /usr/share/openrct2 (on Linux)
This commit is contained in:
@@ -76,6 +76,7 @@ int cmdline_run(const char **argv, int argc)
|
|||||||
int version = 0, headless = 0, verbose = 0, width = 0, height = 0, port = 0;
|
int version = 0, headless = 0, verbose = 0, width = 0, height = 0, port = 0;
|
||||||
char *server = NULL;
|
char *server = NULL;
|
||||||
char *userDataPath = NULL;
|
char *userDataPath = NULL;
|
||||||
|
char *openrctDataPath = NULL;
|
||||||
|
|
||||||
argparse_option_t options[] = {
|
argparse_option_t options[] = {
|
||||||
OPT_HELP(),
|
OPT_HELP(),
|
||||||
@@ -84,8 +85,9 @@ int cmdline_run(const char **argv, int argc)
|
|||||||
OPT_BOOLEAN(0, "verbose", &verbose, "log verbose messages"),
|
OPT_BOOLEAN(0, "verbose", &verbose, "log verbose messages"),
|
||||||
OPT_INTEGER('m', "mode", &sprite_mode, "the type of sprite conversion. 0 = default, 1 = simple closest pixel match, 2 = dithering"),
|
OPT_INTEGER('m', "mode", &sprite_mode, "the type of sprite conversion. 0 = default, 1 = simple closest pixel match, 2 = dithering"),
|
||||||
OPT_STRING(0, "server", &server, "server to connect to"),
|
OPT_STRING(0, "server", &server, "server to connect to"),
|
||||||
OPT_INTEGER(0, "port", &port, "port"),
|
OPT_INTEGER(0, "port", &port, "Port to use. If used with --server, it will connect to specified server at this port, otherwise it will start the server"),
|
||||||
OPT_STRING(0, "user-data-path", &userDataPath, "path to the user data directory (containing config.ini)"),
|
OPT_STRING(0, "user-data-path", &userDataPath, "path to the user data directory (containing config.ini)"),
|
||||||
|
OPT_STRING(0, "openrct-data-path", &openrctDataPath, "path to the OpenRCT2 data directory (containing languages)"),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -117,6 +119,10 @@ int cmdline_run(const char **argv, int argc)
|
|||||||
safe_strncpy(gCustomUserDataPath, userDataPath, sizeof(gCustomUserDataPath));
|
safe_strncpy(gCustomUserDataPath, userDataPath, sizeof(gCustomUserDataPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (openrctDataPath != NULL) {
|
||||||
|
safe_strncpy(gCustomOpenrctDataPath, openrctDataPath, sizeof(gCustomOpenrctDataPath));
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef DISABLE_NETWORK
|
#ifndef DISABLE_NETWORK
|
||||||
if (port != 0) {
|
if (port != 0) {
|
||||||
gNetworkStart = NETWORK_MODE_SERVER;
|
gNetworkStart = NETWORK_MODE_SERVER;
|
||||||
|
|||||||
@@ -1359,6 +1359,7 @@ static void title_sequence_open(const char *path, const char *customName);
|
|||||||
void title_sequences_set_default()
|
void title_sequences_set_default()
|
||||||
{
|
{
|
||||||
char path[MAX_PATH];
|
char path[MAX_PATH];
|
||||||
|
char dataPath[MAX_PATH];
|
||||||
char sep = platform_get_path_separator();
|
char sep = platform_get_path_separator();
|
||||||
|
|
||||||
platform_get_user_directory(path, "title sequences");
|
platform_get_user_directory(path, "title sequences");
|
||||||
@@ -1367,12 +1368,14 @@ void title_sequences_set_default()
|
|||||||
gConfigTitleSequences.presets = malloc(0);
|
gConfigTitleSequences.presets = malloc(0);
|
||||||
gConfigTitleSequences.num_presets = 0;
|
gConfigTitleSequences.num_presets = 0;
|
||||||
|
|
||||||
|
platform_get_openrct_data_path(dataPath);
|
||||||
|
|
||||||
// Load OpenRCT2 title sequence
|
// Load OpenRCT2 title sequence
|
||||||
sprintf(path, "%s%c%s%c%s%c%s%c", gExePath, sep, "data", sep, "title", sep, "rct2", sep);
|
sprintf(path, "%s%c%s%c%s%c", dataPath, sep, "title", sep, "rct2", sep);
|
||||||
title_sequence_open(path, language_get_string(5308));
|
title_sequence_open(path, language_get_string(5308));
|
||||||
|
|
||||||
// Load OpenRCT2 title sequence
|
// Load OpenRCT2 title sequence
|
||||||
sprintf(path, "%s%c%s%c%s%c%s%c", gExePath, sep, "data", sep, "title", sep, "openrct2", sep);
|
sprintf(path, "%s%c%s%c%s%c", dataPath, sep, "title", sep, "openrct2", sep);
|
||||||
title_sequence_open(path, language_get_string(5309));
|
title_sequence_open(path, language_get_string(5309));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,10 @@ int gfx_load_g2()
|
|||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
char path[MAX_PATH];
|
char path[MAX_PATH];
|
||||||
sprintf(path, "%s%cdata%cg2.dat", gExePath, platform_get_path_separator(), platform_get_path_separator());
|
char dataPath[MAX_PATH];
|
||||||
|
|
||||||
|
platform_get_openrct_data_path(dataPath);
|
||||||
|
sprintf(path, "%s%cg2.dat", dataPath, platform_get_path_separator());
|
||||||
file = SDL_RWFromFile(path, "rb");
|
file = SDL_RWFromFile(path, "rb");
|
||||||
if (file != NULL) {
|
if (file != NULL) {
|
||||||
if (SDL_RWread(file, &g2.header, 8, 1) == 1) {
|
if (SDL_RWread(file, &g2.header, 8, 1) == 1) {
|
||||||
|
|||||||
@@ -146,19 +146,21 @@ const char *language_get_string(rct_string_id id)
|
|||||||
|
|
||||||
int language_open(int id)
|
int language_open(int id)
|
||||||
{
|
{
|
||||||
static const char *languagePath = "%s/data/language/%s.txt";
|
static const char *languagePath = "%s/language/%s.txt";
|
||||||
char filename[MAX_PATH];
|
char filename[MAX_PATH];
|
||||||
|
char dataPath[MAX_PATH];
|
||||||
|
|
||||||
language_close_all();
|
language_close_all();
|
||||||
if (id == LANGUAGE_UNDEFINED)
|
if (id == LANGUAGE_UNDEFINED)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
platform_get_openrct_data_path(dataPath);
|
||||||
if (id != LANGUAGE_ENGLISH_UK) {
|
if (id != LANGUAGE_ENGLISH_UK) {
|
||||||
sprintf(filename, languagePath, gExePath, LanguagesDescriptors[LANGUAGE_ENGLISH_UK].path);
|
sprintf(filename, languagePath, dataPath, LanguagesDescriptors[LANGUAGE_ENGLISH_UK].path);
|
||||||
_languageFallback = LanguagePack::FromFile(LANGUAGE_ENGLISH_UK, filename);
|
_languageFallback = LanguagePack::FromFile(LANGUAGE_ENGLISH_UK, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(filename, languagePath, gExePath, LanguagesDescriptors[id].path);
|
sprintf(filename, languagePath, dataPath, LanguagesDescriptors[id].path);
|
||||||
_languageCurrent = LanguagePack::FromFile(id, filename);
|
_languageCurrent = LanguagePack::FromFile(id, filename);
|
||||||
if (_languageCurrent != nullptr) {
|
if (_languageCurrent != nullptr) {
|
||||||
gCurrentLanguage = id;
|
gCurrentLanguage = id;
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ int gOpenRCT2StartupAction = STARTUP_ACTION_TITLE;
|
|||||||
utf8 gOpenRCT2StartupActionPath[512] = { 0 };
|
utf8 gOpenRCT2StartupActionPath[512] = { 0 };
|
||||||
utf8 gExePath[MAX_PATH];
|
utf8 gExePath[MAX_PATH];
|
||||||
utf8 gCustomUserDataPath[MAX_PATH] = { 0 };
|
utf8 gCustomUserDataPath[MAX_PATH] = { 0 };
|
||||||
|
utf8 gCustomOpenrctDataPath[MAX_PATH] = { 0 };
|
||||||
|
|
||||||
// This should probably be changed later and allow a custom selection of things to initialise like SDL_INIT
|
// This should probably be changed later and allow a custom selection of things to initialise like SDL_INIT
|
||||||
bool gOpenRCT2Headless = false;
|
bool gOpenRCT2Headless = false;
|
||||||
@@ -148,7 +149,6 @@ static void openrct2_copy_files_over(const utf8 *originalDirectory, const utf8 *
|
|||||||
platform_enumerate_directories_end(fileEnumHandle);
|
platform_enumerate_directories_end(fileEnumHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO move to platform
|
|
||||||
static void openrct2_set_exe_path()
|
static void openrct2_set_exe_path()
|
||||||
{
|
{
|
||||||
platform_get_exe_path(gExePath);
|
platform_get_exe_path(gExePath);
|
||||||
@@ -173,6 +173,7 @@ bool openrct2_initialise()
|
|||||||
{
|
{
|
||||||
utf8 userPath[MAX_PATH];
|
utf8 userPath[MAX_PATH];
|
||||||
|
|
||||||
|
platform_resolve_openrct_data_path();
|
||||||
platform_resolve_user_data_path();
|
platform_resolve_user_data_path();
|
||||||
platform_get_user_directory(userPath, NULL);
|
platform_get_user_directory(userPath, NULL);
|
||||||
if (!platform_ensure_directory_exists(userPath)) {
|
if (!platform_ensure_directory_exists(userPath)) {
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ extern int gOpenRCT2StartupAction;
|
|||||||
extern utf8 gOpenRCT2StartupActionPath[512];
|
extern utf8 gOpenRCT2StartupActionPath[512];
|
||||||
extern utf8 gExePath[MAX_PATH];
|
extern utf8 gExePath[MAX_PATH];
|
||||||
extern utf8 gCustomUserDataPath[MAX_PATH];
|
extern utf8 gCustomUserDataPath[MAX_PATH];
|
||||||
|
extern utf8 gCustomOpenrctDataPath[MAX_PATH];
|
||||||
extern bool gOpenRCT2Headless;
|
extern bool gOpenRCT2Headless;
|
||||||
extern bool gOpenRCT2ShowChangelog;
|
extern bool gOpenRCT2ShowChangelog;
|
||||||
|
|
||||||
|
|||||||
@@ -147,6 +147,8 @@ void platform_get_cursor_position(int *x, int *y);
|
|||||||
void platform_set_cursor_position(int x, int y);
|
void platform_set_cursor_position(int x, int y);
|
||||||
unsigned int platform_get_ticks();
|
unsigned int platform_get_ticks();
|
||||||
void platform_resolve_user_data_path();
|
void platform_resolve_user_data_path();
|
||||||
|
void platform_resolve_openrct_data_path();
|
||||||
|
void platform_get_openrct_data_path(utf8 *outPath);
|
||||||
void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory);
|
void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory);
|
||||||
void platform_show_messagebox(utf8 *message);
|
void platform_show_messagebox(utf8 *message);
|
||||||
int platform_open_common_file_dialog(int type, utf8 *title, utf8 *filename, utf8 *filterPattern, utf8 *filterName);
|
int platform_open_common_file_dialog(int type, utf8 *title, utf8 *filename, utf8 *filterPattern, utf8 *filterName);
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
#define SINGLE_INSTANCE_MUTEX_NAME "RollerCoaster Tycoon 2_GSKMUTEX"
|
#define SINGLE_INSTANCE_MUTEX_NAME "RollerCoaster Tycoon 2_GSKMUTEX"
|
||||||
|
|
||||||
utf8 _userDataDirectoryPath[MAX_PATH] = { 0 };
|
utf8 _userDataDirectoryPath[MAX_PATH] = { 0 };
|
||||||
|
utf8 _openrctDataDirectoryPath[MAX_PATH] = { 0 };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The function that is called directly from the host application (rct2.exe)'s WinMain. This will be removed when OpenRCT2 can
|
* The function that is called directly from the host application (rct2.exe)'s WinMain. This will be removed when OpenRCT2 can
|
||||||
@@ -568,6 +569,54 @@ void platform_resolve_user_data_path()
|
|||||||
free(path);
|
free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void platform_get_openrct_data_path(utf8 *outPath)
|
||||||
|
{
|
||||||
|
safe_strncpy(outPath, _openrctDataDirectoryPath, sizeof(_openrctDataDirectoryPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default directory fallback is:
|
||||||
|
* - (command line argument)
|
||||||
|
* - <platform dependent>
|
||||||
|
*/
|
||||||
|
void platform_resolve_openrct_data_path()
|
||||||
|
{
|
||||||
|
const char separator[2] = { platform_get_path_separator(), 0 };
|
||||||
|
|
||||||
|
if (gCustomOpenrctDataPath[0] != 0) {
|
||||||
|
realpath(gCustomOpenrctDataPath, _openrctDataDirectoryPath);
|
||||||
|
|
||||||
|
// Ensure path ends with separator
|
||||||
|
int len = strlen(_openrctDataDirectoryPath);
|
||||||
|
if (_openrctDataDirectoryPath[len - 1] != separator[0]) {
|
||||||
|
strncat(_openrctDataDirectoryPath, separator, MAX_PATH - 1);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buffer[MAX_PATH] = { 0 };
|
||||||
|
platform_get_exe_path(buffer);
|
||||||
|
|
||||||
|
strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
|
||||||
|
strncat(buffer, "data", MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
|
||||||
|
const utf8 *searchLocations[] = {
|
||||||
|
buffer,
|
||||||
|
#ifdef __linux__
|
||||||
|
"/var/lib/openrct2",
|
||||||
|
"/usr/share/openrct2",
|
||||||
|
#endif // __linux__
|
||||||
|
};
|
||||||
|
for (size_t i = 0; i < countof(searchLocations); i++)
|
||||||
|
{
|
||||||
|
if (platform_directory_exists(searchLocations[i]))
|
||||||
|
{
|
||||||
|
_openrctDataDirectoryPath[0] = '\0';
|
||||||
|
safe_strncpy(_openrctDataDirectoryPath, searchLocations[i], sizeof(_openrctDataDirectoryPath));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory)
|
void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory)
|
||||||
{
|
{
|
||||||
const char separator[2] = { platform_get_path_separator(), 0 };
|
const char separator[2] = { platform_get_path_separator(), 0 };
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
#define SINGLE_INSTANCE_MUTEX_NAME "RollerCoaster Tycoon 2_GSKMUTEX"
|
#define SINGLE_INSTANCE_MUTEX_NAME "RollerCoaster Tycoon 2_GSKMUTEX"
|
||||||
|
|
||||||
utf8 _userDataDirectoryPath[MAX_PATH] = { 0 };
|
utf8 _userDataDirectoryPath[MAX_PATH] = { 0 };
|
||||||
|
utf8 _openrctDataDirectoryPath[MAX_PATH] = { 0 };
|
||||||
|
|
||||||
utf8 **windows_get_command_line_args(int *outNumArgs);
|
utf8 **windows_get_command_line_args(int *outNumArgs);
|
||||||
|
|
||||||
@@ -407,6 +408,51 @@ bool platform_file_delete(const utf8 *path)
|
|||||||
return success == TRUE;
|
return success == TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void platform_resolve_openrct_data_path()
|
||||||
|
{
|
||||||
|
wchar_t wOutPath[MAX_PATH];
|
||||||
|
const char separator[2] = { platform_get_path_separator(), 0 };
|
||||||
|
|
||||||
|
if (gCustomOpenrctDataPath[0] != 0) {
|
||||||
|
wchar_t *customUserDataPathW = utf8_to_widechar(gCustomOpenrctDataPath);
|
||||||
|
if (GetFullPathNameW(customUserDataPathW, countof(wOutPath), wOutPath, NULL) == 0) {
|
||||||
|
log_fatal("Unable to resolve path '%s'.", gCustomOpenrctDataPath);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
utf8 *outPathTemp = widechar_to_utf8(wOutPath);
|
||||||
|
safe_strncpy(_userDataDirectoryPath, outPathTemp, sizeof(_userDataDirectoryPath));
|
||||||
|
free(outPathTemp);
|
||||||
|
free(customUserDataPathW);
|
||||||
|
|
||||||
|
// Ensure path ends with separator
|
||||||
|
int len = strlen(_userDataDirectoryPath);
|
||||||
|
if (_userDataDirectoryPath[len - 1] != separator[0]) {
|
||||||
|
strcat(_userDataDirectoryPath, separator);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char buffer[MAX_PATH] = { 0 };
|
||||||
|
platform_get_exe_path(buffer);
|
||||||
|
|
||||||
|
strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
|
||||||
|
strncat(buffer, "data", MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
|
||||||
|
|
||||||
|
if (platform_directory_exists(buffer))
|
||||||
|
{
|
||||||
|
_openrctDataDirectoryPath[0] = '\0';
|
||||||
|
safe_strncpy(_openrctDataDirectoryPath, buffer, sizeof(_openrctDataDirectoryPath));
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
log_fatal("Unable to resolve openrct data path.");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void platform_get_openrct_data_path(utf8 *outPath)
|
||||||
|
{
|
||||||
|
safe_strncpy(outPath, _openrctDataDirectoryPath, sizeof(_openrctDataDirectoryPath));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default directory fallback is:
|
* Default directory fallback is:
|
||||||
* - (command line argument)
|
* - (command line argument)
|
||||||
|
|||||||
@@ -602,9 +602,11 @@ static uint8 *title_script_load()
|
|||||||
char parts[3 * 128], *token, *part1, *part2, *src;
|
char parts[3 * 128], *token, *part1, *part2, *src;
|
||||||
|
|
||||||
utf8 path[MAX_PATH];
|
utf8 path[MAX_PATH];
|
||||||
utf8 filePath[] = "data/title/script.txt";
|
utf8 dataPath[MAX_PATH];
|
||||||
|
utf8 filePath[] = "title/script.txt";
|
||||||
|
|
||||||
sprintf(path, "%s%c%s", gExePath, platform_get_path_separator(), filePath);
|
platform_get_openrct_data_path(dataPath);
|
||||||
|
sprintf(path, "%s%c%s", dataPath, platform_get_path_separator(), filePath);
|
||||||
log_verbose("loading title script, %s", path);
|
log_verbose("loading title script, %s", path);
|
||||||
file = SDL_RWFromFile(path, "r");
|
file = SDL_RWFromFile(path, "r");
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
|
|||||||
Reference in New Issue
Block a user