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:
Michał Janiszewski 2015-12-17 22:49:39 +01:00
parent 859c35574a
commit ea6fa2c82a
10 changed files with 125 additions and 10 deletions

View File

@ -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;
char *server = NULL;
char *userDataPath = NULL;
char *openrctDataPath = NULL;
argparse_option_t options[] = {
OPT_HELP(),
@ -84,8 +85,9 @@ int cmdline_run(const char **argv, int argc)
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_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, "openrct-data-path", &openrctDataPath, "path to the OpenRCT2 data directory (containing languages)"),
OPT_END()
};
@ -117,6 +119,10 @@ int cmdline_run(const char **argv, int argc)
safe_strncpy(gCustomUserDataPath, userDataPath, sizeof(gCustomUserDataPath));
}
if (openrctDataPath != NULL) {
safe_strncpy(gCustomOpenrctDataPath, openrctDataPath, sizeof(gCustomOpenrctDataPath));
}
#ifndef DISABLE_NETWORK
if (port != 0) {
gNetworkStart = NETWORK_MODE_SERVER;

View File

@ -1359,6 +1359,7 @@ static void title_sequence_open(const char *path, const char *customName);
void title_sequences_set_default()
{
char path[MAX_PATH];
char dataPath[MAX_PATH];
char sep = platform_get_path_separator();
platform_get_user_directory(path, "title sequences");
@ -1367,12 +1368,14 @@ void title_sequences_set_default()
gConfigTitleSequences.presets = malloc(0);
gConfigTitleSequences.num_presets = 0;
platform_get_openrct_data_path(dataPath);
// 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));
// 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));
}

View File

@ -82,7 +82,10 @@ int gfx_load_g2()
unsigned int i;
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");
if (file != NULL) {
if (SDL_RWread(file, &g2.header, 8, 1) == 1) {

View File

@ -146,19 +146,21 @@ const char *language_get_string(rct_string_id 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 dataPath[MAX_PATH];
language_close_all();
if (id == LANGUAGE_UNDEFINED)
return 1;
platform_get_openrct_data_path(dataPath);
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);
}
sprintf(filename, languagePath, gExePath, LanguagesDescriptors[id].path);
sprintf(filename, languagePath, dataPath, LanguagesDescriptors[id].path);
_languageCurrent = LanguagePack::FromFile(id, filename);
if (_languageCurrent != nullptr) {
gCurrentLanguage = id;

View File

@ -53,6 +53,7 @@ int gOpenRCT2StartupAction = STARTUP_ACTION_TITLE;
utf8 gOpenRCT2StartupActionPath[512] = { 0 };
utf8 gExePath[MAX_PATH];
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
bool gOpenRCT2Headless = false;
@ -148,7 +149,6 @@ static void openrct2_copy_files_over(const utf8 *originalDirectory, const utf8 *
platform_enumerate_directories_end(fileEnumHandle);
}
// TODO move to platform
static void openrct2_set_exe_path()
{
platform_get_exe_path(gExePath);
@ -173,6 +173,7 @@ bool openrct2_initialise()
{
utf8 userPath[MAX_PATH];
platform_resolve_openrct_data_path();
platform_resolve_user_data_path();
platform_get_user_directory(userPath, NULL);
if (!platform_ensure_directory_exists(userPath)) {

View File

@ -34,6 +34,7 @@ extern int gOpenRCT2StartupAction;
extern utf8 gOpenRCT2StartupActionPath[512];
extern utf8 gExePath[MAX_PATH];
extern utf8 gCustomUserDataPath[MAX_PATH];
extern utf8 gCustomOpenrctDataPath[MAX_PATH];
extern bool gOpenRCT2Headless;
extern bool gOpenRCT2ShowChangelog;

View File

@ -147,6 +147,8 @@ void platform_get_cursor_position(int *x, int *y);
void platform_set_cursor_position(int x, int y);
unsigned int platform_get_ticks();
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_show_messagebox(utf8 *message);
int platform_open_common_file_dialog(int type, utf8 *title, utf8 *filename, utf8 *filterPattern, utf8 *filterName);

View File

@ -42,6 +42,7 @@
#define SINGLE_INSTANCE_MUTEX_NAME "RollerCoaster Tycoon 2_GSKMUTEX"
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
@ -568,6 +569,54 @@ void platform_resolve_user_data_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)
{
const char separator[2] = { platform_get_path_separator(), 0 };

View File

@ -38,6 +38,7 @@
#define SINGLE_INSTANCE_MUTEX_NAME "RollerCoaster Tycoon 2_GSKMUTEX"
utf8 _userDataDirectoryPath[MAX_PATH] = { 0 };
utf8 _openrctDataDirectoryPath[MAX_PATH] = { 0 };
utf8 **windows_get_command_line_args(int *outNumArgs);
@ -407,6 +408,51 @@ bool platform_file_delete(const utf8 *path)
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:
* - (command line argument)

View File

@ -602,9 +602,11 @@ static uint8 *title_script_load()
char parts[3 * 128], *token, *part1, *part2, *src;
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);
file = SDL_RWFromFile(path, "r");
if (file == NULL) {