1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-04 13:42:55 +01:00

Merge pull request #2709 from OpenRCT2/set-rct2-path

Add ability to set RCT2 path by command line.
This commit is contained in:
Ted John
2016-01-13 00:04:49 +00:00
13 changed files with 245 additions and 46 deletions

View File

@@ -22,6 +22,7 @@
D4B63B951C43028200367A37 /* Console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4B63B931C43028200367A37 /* Console.cpp */; };
D4B63B981C43028F00367A37 /* String.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4B63B961C43028F00367A37 /* String.cpp */; };
D4B85B5B1C41C7F3005C568A /* cable_lift.c in Sources */ = {isa = PBXBuildFile; fileRef = D4B85B591C41C7F3005C568A /* cable_lift.c */; };
D4D35E2C1C45BD9B00AAFCB4 /* Path.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4D35E2A1C45BD9B00AAFCB4 /* Path.cpp */; };
D4D4DF141C34697B0048BE43 /* image_io.c in Sources */ = {isa = PBXBuildFile; fileRef = D4D4DF121C34697B0048BE43 /* image_io.c */; };
D4EC47DF1C26342F0024B507 /* addresses.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC46D61C26342F0024B507 /* addresses.c */; };
D4EC47E01C26342F0024B507 /* audio.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC46D91C26342F0024B507 /* audio.c */; };
@@ -237,6 +238,8 @@
D4B63B971C43028F00367A37 /* String.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = String.hpp; sourceTree = "<group>"; };
D4B85B591C41C7F3005C568A /* cable_lift.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cable_lift.c; sourceTree = "<group>"; };
D4B85B5A1C41C7F3005C568A /* cable_lift.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cable_lift.h; sourceTree = "<group>"; };
D4D35E2A1C45BD9B00AAFCB4 /* Path.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Path.cpp; sourceTree = "<group>"; };
D4D35E2B1C45BD9B00AAFCB4 /* Path.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Path.hpp; sourceTree = "<group>"; };
D4D4DF121C34697B0048BE43 /* image_io.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = image_io.c; path = src/image_io.c; sourceTree = "<group>"; };
D4D4DF131C34697B0048BE43 /* image_io.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = image_io.h; path = src/image_io.h; sourceTree = "<group>"; };
D4EC46D61C26342F0024B507 /* addresses.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = addresses.c; path = src/addresses.c; sourceTree = "<group>"; };
@@ -726,6 +729,8 @@
D4EC46E91C26342F0024B507 /* IStream.hpp */,
D4EC46EA1C26342F0024B507 /* Math.hpp */,
D4EC46EB1C26342F0024B507 /* Memory.hpp */,
D4D35E2A1C45BD9B00AAFCB4 /* Path.cpp */,
D4D35E2B1C45BD9B00AAFCB4 /* Path.hpp */,
D4B63B961C43028F00367A37 /* String.cpp */,
D4B63B971C43028F00367A37 /* String.hpp */,
D4EC46EC1C26342F0024B507 /* StringBuilder.hpp */,
@@ -1354,6 +1359,7 @@
D4EC484F1C26342F0024B507 /* options.c in Sources */,
D4EC485C1C26342F0024B507 /* shortcut_keys.c in Sources */,
D4EC481A1C26342F0024B507 /* posix.c in Sources */,
D4D35E2C1C45BD9B00AAFCB4 /* Path.cpp in Sources */,
D4B63B981C43028F00367A37 /* String.cpp in Sources */,
D4EC47E31C26342F0024B507 /* cmdline_sprite.c in Sources */,
D4EC48611C26342F0024B507 /* text_input.c in Sources */,

View File

@@ -30,6 +30,7 @@
<ClCompile Include="src\cmdline_sprite.c" />
<ClCompile Include="src\config.c" />
<ClCompile Include="src\core\Console.cpp" />
<ClCompile Include="src\core\Path.cpp" />
<ClCompile Include="src\core\Stopwatch.cpp" />
<ClCompile Include="src\core\String.cpp" />
<ClCompile Include="src\cursors.c" />
@@ -203,6 +204,7 @@
<ClInclude Include="src\core\IStream.hpp" />
<ClInclude Include="src\core\Math.hpp" />
<ClInclude Include="src\core\Memory.hpp" />
<ClInclude Include="src\core\Path.hpp" />
<ClInclude Include="src\core\stopwatch.h" />
<ClInclude Include="src\core\Stopwatch.hpp" />
<ClInclude Include="src\core\String.hpp" />
@@ -377,4 +379,4 @@
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
</Project>
</Project>

View File

@@ -576,6 +576,9 @@
<ClCompile Include="src\core\String.cpp">
<Filter>Source\Core</Filter>
</ClCompile>
<ClCompile Include="src\core\Path.cpp">
<Filter>Source\Core</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\management\award.h">
@@ -875,5 +878,8 @@
<ClInclude Include="src\core\String.hpp">
<Filter>Source\Core</Filter>
</ClInclude>
<ClInclude Include="src\core\Path.hpp">
<Filter>Source\Core</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@@ -350,7 +350,7 @@ namespace CommandLine
}
else if (!firstOption)
{
Console::WriteLineError("All options must be passed at the end of the command line.");
Console::Error::WriteLine("All options must be passed at the end of the command line.");
return false;
}
else
@@ -383,8 +383,8 @@ namespace CommandLine
const CommandLineOptionDefinition * option = FindOption(options, optionName);
if (option == nullptr)
{
Console::WriteError("Unknown option: --");
Console::WriteLineError(optionName);
Console::Error::Write("Unknown option: --");
Console::Error::WriteLine(optionName);
return false;
}
@@ -399,8 +399,8 @@ namespace CommandLine
const char * valueString = nullptr;
if (!argEnumerator->TryPopString(&valueString))
{
Console::WriteError("Expected value for option: ");
Console::WriteLineError(optionName);
Console::Error::Write("Expected value for option: ");
Console::Error::WriteLine(optionName);
return false;
}
@@ -414,8 +414,8 @@ namespace CommandLine
{
if (option->Type == CMDLINE_TYPE_SWITCH)
{
Console::WriteError("Option is a switch: ");
Console::WriteLineError(optionName);
Console::Error::Write("Option is a switch: ");
Console::Error::WriteLine(optionName);
return false;
}
else
@@ -442,9 +442,9 @@ namespace CommandLine
option = FindOption(options, shortOption[0]);
if (option == nullptr)
{
Console::WriteError("Unknown option: -");
Console::WriteError(shortOption[0]);
Console::WriteLineError();
Console::Error::Write("Unknown option: -");
Console::Error::Write(shortOption[0]);
Console::Error::WriteLine();
return false;
}
if (option->Type == CMDLINE_TYPE_SWITCH)
@@ -469,9 +469,9 @@ namespace CommandLine
const char * valueString = nullptr;
if (!argEnumerator->TryPopString(&valueString))
{
Console::WriteError("Expected value for option: ");
Console::WriteError(option->ShortName);
Console::WriteLineError();
Console::Error::Write("Expected value for option: ");
Console::Error::Write(option->ShortName);
Console::Error::WriteLine();
return false;
}
@@ -502,8 +502,8 @@ namespace CommandLine
*((utf8 * *)option->OutAddress) = String::Duplicate(valueString);
return true;
default:
Console::WriteError("Unknown CMDLINE_TYPE for: ");
Console::WriteLineError(option->LongName);
Console::Error::Write("Unknown CMDLINE_TYPE for: ");
Console::Error::WriteLine(option->LongName);
return false;
}
}

View File

@@ -2,11 +2,13 @@
extern "C"
{
#include "../config.h"
#include "../openrct2.h"
}
#include "../core/Console.hpp"
#include "../core/Memory.hpp"
#include "../core/Path.hpp"
#include "../core/String.hpp"
#include "../network/network.h"
#include "CommandLine.hpp"
@@ -52,6 +54,7 @@ static exitcode_t HandleCommandEdit(CommandLineArgEnumerator * enumerator);
static exitcode_t HandleCommandIntro(CommandLineArgEnumerator * enumerator);
static exitcode_t HandleCommandHost(CommandLineArgEnumerator * enumerator);
static exitcode_t HandleCommandJoin(CommandLineArgEnumerator * enumerator);
static exitcode_t HandleCommandSetRCT2(CommandLineArgEnumerator * enumerator);
static void PrintAbout();
static void PrintVersion();
@@ -60,13 +63,14 @@ static void PrintLaunchInformation();
const CommandLineCommand CommandLine::RootCommands[]
{
// Main commands
DefineCommand("", "<uri>", StandardOptions, HandleNoCommand ),
DefineCommand("edit", "<uri>", StandardOptions, HandleCommandEdit ),
DefineCommand("intro", "", StandardOptions, HandleCommandIntro),
#ifndef DISABLE_NETWORK
DefineCommand("host", "<uri>", StandardOptions, HandleCommandHost ),
DefineCommand("join", "<hostname>", StandardOptions, HandleCommandJoin ),
DefineCommand("", "<uri>", StandardOptions, HandleNoCommand ),
DefineCommand("edit", "<uri>", StandardOptions, HandleCommandEdit ),
DefineCommand("intro", "", StandardOptions, HandleCommandIntro ),
#ifndef DISABLE_NETWORK
DefineCommand("host", "<uri>", StandardOptions, HandleCommandHost ),
DefineCommand("join", "<hostname>", StandardOptions, HandleCommandJoin ),
#endif
DefineCommand("set-rct2", "<path>", StandardOptions, HandleCommandSetRCT2),
// Sub-commands
DefineSubCommand("screenshot", CommandLine::ScreenshotCommands),
@@ -163,7 +167,7 @@ exitcode_t HandleCommandEdit(CommandLineArgEnumerator * enumerator)
const char * parkUri;
if (!enumerator->TryPopString(&parkUri))
{
Console::WriteLineError("Expected path or URL to a saved park.");
Console::Error::WriteLine("Expected path or URL to a saved park.");
return EXITCODE_FAIL;
}
String::Set(gOpenRCT2StartupActionPath, sizeof(gOpenRCT2StartupActionPath), parkUri);
@@ -197,7 +201,7 @@ exitcode_t HandleCommandHost(CommandLineArgEnumerator * enumerator)
const char * parkUri;
if (!enumerator->TryPopString(&parkUri))
{
Console::WriteLineError("Expected path or URL to a saved park.");
Console::Error::WriteLine("Expected path or URL to a saved park.");
return EXITCODE_FAIL;
}
@@ -220,7 +224,7 @@ exitcode_t HandleCommandJoin(CommandLineArgEnumerator * enumerator)
const char * hostname;
if (!enumerator->TryPopString(&hostname))
{
Console::WriteLineError("Expected a hostname or IP address to the server to connect to.");
Console::Error::WriteLine("Expected a hostname or IP address to the server to connect to.");
return EXITCODE_FAIL;
}
@@ -232,6 +236,84 @@ exitcode_t HandleCommandJoin(CommandLineArgEnumerator * enumerator)
#endif // DISABLE_NETWORK
static exitcode_t HandleCommandSetRCT2(CommandLineArgEnumerator * enumerator)
{
exitcode_t result = CommandLine::HandleCommandDefault();
if (result != EXITCODE_CONTINUE)
{
return result;
}
// Get the path that was passed
const utf8 * rawPath;
if (!enumerator->TryPopString(&rawPath))
{
Console::Error::WriteLine("Expected a path.");
return EXITCODE_FAIL;
}
utf8 path[MAX_PATH];
Path::GetAbsolute(path, sizeof(path), rawPath);
// Check if path exists
Console::WriteLine("Checking path...");
if (!platform_directory_exists(path))
{
Console::Error::WriteFormat("The path '%s' does not exist", path);
Console::Error::WriteLine();
return EXITCODE_FAIL;
}
// Check if g1.dat exists (naive but good check)
Console::WriteLine("Checking g1.dat...");
utf8 pathG1Check[MAX_PATH];
String::Set(pathG1Check, sizeof(pathG1Check), path);
Path::Append(pathG1Check, sizeof(pathG1Check), "Data");
Path::Append(pathG1Check, sizeof(pathG1Check), "g1.dat");
if (!platform_file_exists(pathG1Check))
{
Console::Error::WriteLine("RCT2 path not valid.");
Console::Error::WriteFormat("Unable to find %s.", pathG1Check);
Console::Error::WriteLine();
return EXITCODE_FAIL;
}
// Check user path that will contain the config
utf8 userPath[MAX_PATH];
platform_resolve_user_data_path();
platform_get_user_directory(userPath, NULL);
if (!platform_ensure_directory_exists(userPath)) {
Console::Error::WriteFormat("Unable to access or create directory '%s'.", userPath);
Console::Error::WriteLine();
return EXITCODE_FAIL;
}
// Update RCT2 path in config
// TODO remove this when we get rid of config_apply_to_old_addresses
if (!openrct2_setup_rct2_segment()) {
Console::Error::WriteLine("Unable to load RCT2 data sector");
return EXITCODE_FAIL;
}
config_set_defaults();
config_open_default();
String::DiscardDuplicate(&gConfigGeneral.game_path, path);
if (config_save_default())
{
Console::WriteFormat("Updating RCT2 path to '%s'.", path);
Console::WriteLine();
Console::WriteLine("Updated config.ini");
return EXITCODE_OK;
}
else
{
Console::Error::WriteLine("Unable to update config.ini");
return EXITCODE_FAIL;
}
}
static void PrintAbout()
{
PrintVersion();

View File

@@ -44,24 +44,36 @@ namespace Console
puts(str);
}
void WriteError(char c)
namespace Error
{
fputc(c, stderr);
}
void Write(char c)
{
fputc(c, stderr);
}
void WriteError(const utf8 * str)
{
fputs(str, stderr);
}
void Write(const utf8 * str)
{
fputs(str, stderr);
}
void WriteLineError()
{
fputs(platform_get_new_line(), stderr);
}
void WriteFormat(const utf8 * format, ...)
{
va_list args;
void WriteLineError(const utf8 * str)
{
fputs(str, stderr);
WriteLineError();
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
}
void WriteLine()
{
fputs(platform_get_new_line(), stderr);
}
void WriteLine(const utf8 * str)
{
fputs(str, stderr);
WriteLine();
}
}
}

View File

@@ -13,8 +13,13 @@ namespace Console
void WriteFormat(const utf8 * format, ...);
void WriteLine();
void WriteLine(const utf8 * str);
void WriteError(char c);
void WriteError(const utf8 * str);
void WriteLineError();
void WriteLineError(const utf8 * str);
namespace Error
{
void Write(char c);
void Write(const utf8 * str);
void WriteFormat(const utf8 * format, ...);
void WriteLine();
void WriteLine(const utf8 * str);
}
}

52
src/core/Path.cpp Normal file
View File

@@ -0,0 +1,52 @@
extern "C"
{
#include "../platform/platform.h"
#include "../localisation/localisation.h"
#include "../util/util.h"
}
#include "Memory.hpp"
#include "Path.hpp"
#include "String.hpp"
#include "Util.hpp"
namespace Path
{
utf8 * Append(utf8 * buffer, size_t bufferSize, const utf8 * src)
{
return safe_strcat_path(buffer, src, bufferSize);
}
utf8 * GetAbsolute(utf8 *buffer, size_t bufferSize, const utf8 * relativePath)
{
#if _WIN32
wchar_t * relativePathW = utf8_to_widechar(relativePath);
wchar_t absolutePathW[MAX_PATH];
DWORD length = GetFullPathNameW(relativePathW, Util::CountOf(absolutePathW), absolutePathW, NULL);
Memory::Free(relativePathW);
if (length == 0)
{
return String::Set(buffer, bufferSize, relativePath);
}
else
{
utf8 * absolutePath = widechar_to_utf8(absolutePathW);
String::Set(buffer, bufferSize, absolutePath);
Memory::Free(absolutePath);
return buffer;
}
#else
utf8 * absolutePath = realpath(relativePath, NULL);
if (absolutePath == nullptr)
{
return String::Set(buffer, bufferSize, relativePath);
}
else
{
String::Set(buffer, bufferSize, absolutePath);
Memory::Free(absolutePath);
return buffer;
}
#endif
}
}

12
src/core/Path.hpp Normal file
View File

@@ -0,0 +1,12 @@
#pragma once
extern "C"
{
#include "../common.h"
}
namespace Path
{
utf8 * Append(utf8 * buffer, size_t bufferSize, const utf8 * src);
utf8 * GetAbsolute(utf8 *buffer, size_t bufferSize, const utf8 * relativePath);
}

View File

@@ -129,4 +129,16 @@ namespace String
size_t srcSize = SizeOf(src);
return Memory::DuplicateArray(src, srcSize + 1);
}
utf8 * DiscardUse(utf8 * * ptr, utf8 * replacement)
{
Memory::Free(*ptr);
*ptr = replacement;
return replacement;
}
utf8 * DiscardDuplicate(utf8 * * ptr, utf8 * replacement)
{
return DiscardUse(ptr, String::Duplicate(replacement));
}
}

View File

@@ -17,4 +17,14 @@ namespace String
utf8 * Format(utf8 * buffer, size_t bufferSize, const utf8 * format, ...);
utf8 * AppendFormat(utf8 * buffer, size_t bufferSize, const utf8 * format, ...);
utf8 * Duplicate(const utf8 * src);
/**
* Helper method to free the string a string pointer points to and set it to a replacement string.
*/
utf8 * DiscardUse(utf8 * * ptr, utf8 * replacement);
/**
* Helper method to free the string a string pointer points to and set it to a copy of a replacement string.
*/
utf8 * DiscardDuplicate(utf8 * * ptr, utf8 * replacement);
}

View File

@@ -68,7 +68,6 @@ int _finished;
static struct { sint16 x, y, z; } _spritelocations1[MAX_SPRITES], _spritelocations2[MAX_SPRITES];
static void openrct2_loop();
static bool openrct2_setup_rct2_segment();
static void openrct2_setup_rct2_hooks();
void openrct2_write_full_version_info(utf8 *buffer, size_t bufferSize)
@@ -475,7 +474,7 @@ void openrct2_reset_object_tween_locations()
* Loads RCT2's data model and remaps the addresses.
* @returns true if the data integrity check succeeded, otherwise false.
*/
static bool openrct2_setup_rct2_segment()
bool openrct2_setup_rct2_segment()
{
// OpenRCT2 on Linux and OS X is wired to have the original Windows PE sections loaded
// necessary. Windows does not need to do this as OpenRCT2 runs as a DLL loaded from the Windows PE.

View File

@@ -54,6 +54,7 @@ void openrct2_launch();
void openrct2_dispose();
void openrct2_finish();
void openrct2_reset_object_tween_locations();
bool openrct2_setup_rct2_segment();
int cmdline_run(const char **argv, int argc);