diff --git a/src/Launcher.c b/src/Launcher.c index fcb6d3988..5973d25ab 100644 --- a/src/Launcher.c +++ b/src/Launcher.c @@ -86,7 +86,7 @@ static CC_NOINLINE void InitFramebuffer(void) { *#########################################################################################################################*/ static cc_uint64 lastJoin; cc_bool Launcher_StartGame(const cc_string* user, const cc_string* mppass, const cc_string* ip, const cc_string* port, const cc_string* server) { - cc_string args; char argsBuffer[512]; + cc_string args[4]; int numArgs; TimeMS now; cc_result res; @@ -106,11 +106,16 @@ cc_bool Launcher_StartGame(const cc_string* user, const cc_string* mppass, const /* Otherwise can get 'file already in use' errors on startup */ Options_SaveIfChanged(); - String_InitArray(args, argsBuffer); - String_AppendString(&args, user); - if (mppass->length) String_Format3(&args, " %s %s %s", mppass, ip, port); + args[0] = *user; + numArgs = 1; + if (mppass->length) { + args[1] = *mppass; + args[2] = *ip; + args[3] = *port; + numArgs = 4; + } - res = Process_StartGame(&args); + res = Process_StartGame2(args, numArgs); if (res) { Logger_SysWarn(res, "starting game"); return false; } #ifdef CC_BUILD_MOBILE diff --git a/src/Platform.h b/src/Platform.h index dd24043d5..ddb40918b 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -63,7 +63,7 @@ describe exists (e.g. Http_DescribeError), that should be preferred. */ cc_bool Platform_DescribeError(cc_result res, cc_string* dst); /* Starts the game with the given arguments. */ -CC_API cc_result Process_StartGame(const cc_string* args); +CC_API cc_result Process_StartGame2(const cc_string* args, int numArgs); /* Terminates the process with the given return code. */ CC_API void Process_Exit(cc_result code); /* Starts the platform-specific program to open the given url or filename. */ diff --git a/src/Platform_Android.c b/src/Platform_Android.c index 690419a88..482ca64ff 100644 --- a/src/Platform_Android.c +++ b/src/Platform_Android.c @@ -27,11 +27,15 @@ void Platform_Log(const char* msg, int len) { /*########################################################################################################################* *-----------------------------------------------------Process/Module------------------------------------------------------* *#########################################################################################################################*/ -static char gameArgsBuffer[512]; -static cc_string gameArgs = String_FromArray(gameArgsBuffer); +static char gameArgs[GAME_MAX_CMDARGS][STRING_SIZE]; +static int gameNumArgs; -cc_result Process_StartGame(const cc_string* args) { - String_Copy(&gameArgs, args); +cc_result Process_StartGame2(const cc_string* args, int numArgs) { + for (int i = 0; i < numArgs; i++) { + String_CopyToRawArray(gameArgs[i], &args[i]); + } + + gameNumArgs = numArgs; return 0; } @@ -94,13 +98,14 @@ void Platform_ShareScreenshot(const cc_string* filename) { *-----------------------------------------------------Configuration-------------------------------------------------------* *#########################################################################################################################*/ int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, cc_string* args) { - int count = 0; - if (gameArgs.length) { - count = String_UNSAFE_Split(&gameArgs, ' ', args, GAME_MAX_CMDARGS); - /* clear arguments so after game is closed, launcher is started */ - gameArgs.length = 0; + int count = gameNumArgs; + for (int i = 0; i < count; i++) { + args[i] = String_FromRawArray(gameArgs[i]); } - return count; + + // clear arguments so after game is closed, launcher is started + gameNumArgs = 0; + return count; } cc_result Platform_SetDefaultCurrentDirectory(int argc, char **argv) { diff --git a/src/Platform_Posix.c b/src/Platform_Posix.c index 66eaf599f..ff13cf217 100644 --- a/src/Platform_Posix.c +++ b/src/Platform_Posix.c @@ -622,25 +622,20 @@ static cc_result Process_RawStart(const char* path, char** argv) { static cc_result Process_RawGetExePath(char* path, int* len); -cc_result Process_StartGame(const cc_string* args) { - char path[NATIVE_STR_LEN], raw[NATIVE_STR_LEN]; +cc_result Process_StartGame2(const cc_string* args, int numArgs) { + char raw[GAME_MAX_CMDARGS][NATIVE_STR_LEN]; + char path[NATIVE_STR_LEN]; int i, j, len = 0; char* argv[15]; cc_result res = Process_RawGetExePath(path, &len); if (res) return res; path[len] = '\0'; + argv[0] = path; - Platform_EncodeUtf8(raw, args); - argv[0] = path; argv[1] = raw; - - /* need to null-terminate multiple arguments */ - for (i = 0, j = 2; raw[i] && i < Array_Elems(raw); i++) { - if (raw[i] != ' ') continue; - - /* null terminate previous argument */ - raw[i] = '\0'; - argv[j++] = &raw[i + 1]; + for (i = 0, j = 1; i < numArgs; i++, j++) { + Platform_EncodeUtf8(raw[i], &args[i]); + argv[j] = raw[i]; } if (defaultDirectory) { argv[j++] = defaultDirectory; } diff --git a/src/Platform_Web.c b/src/Platform_Web.c index 1b6bb7eb1..7ab0a3abd 100644 --- a/src/Platform_Web.c +++ b/src/Platform_Web.c @@ -357,7 +357,9 @@ cc_result Socket_Poll(cc_socket s, int mode, cc_bool* success) { /*########################################################################################################################* *-----------------------------------------------------Process/Module------------------------------------------------------* *#########################################################################################################################*/ -cc_result Process_StartGame(const cc_string* args) { return ERR_NOT_SUPPORTED; } +cc_result Process_StartGame(const cc_string* args, int numArgs) { + return ERR_NOT_SUPPORTED; +} void Process_Exit(cc_result code) { /* Window isn't implicitly closed when process is exited */ if (code) Window_Close(); diff --git a/src/Platform_WinApi.c b/src/Platform_WinApi.c index bf9b1da07..1d08b34ae 100644 --- a/src/Platform_WinApi.c +++ b/src/Platform_WinApi.c @@ -547,13 +547,13 @@ static cc_result Process_RawGetExePath(WCHAR* path, int* len) { return *len ? 0 : GetLastError(); } -cc_result Process_StartGame(const cc_string* args) { +cc_result Process_StartGame2(const cc_string* args, int numArgs) { WCHAR path[NATIVE_STR_LEN + 1], raw[NATIVE_STR_LEN]; cc_string argv; char argvBuffer[NATIVE_STR_LEN]; STARTUPINFOW si = { 0 }; PROCESS_INFORMATION pi = { 0 }; cc_result res; - int len; + int len, i; Process_RawGetExePath(path, &len); path[len] = '\0'; @@ -561,8 +561,15 @@ cc_result Process_StartGame(const cc_string* args) { String_InitArray(argv, argvBuffer); /* Game doesn't actually care about argv[0] */ - String_Format1(&argv, "cc %s", args); - String_UNSAFE_TrimEnd(&argv); + String_AppendConst(&argv, "cc"); + for (i = 0; i < numArgs; i++) + { + if (String_IndexOf(&args[i], ' ') >= 0) { + String_Format1(&argv, " \"%s\"", &args[i]); + } else { + String_Format1(&argv, " %s", &args[i]); + } + } Platform_EncodeUtf16(raw, &argv); if (CreateProcessW(path, raw, NULL, NULL, @@ -636,7 +643,7 @@ cc_result Updater_Start(const char** action) { if (!MoveFileExW(UPDATE_SRC, path, MOVEFILE_REPLACE_EXISTING)) return GetLastError(); *action = "Restarting game"; - return Process_StartGame(&String_Empty); + return Process_StartGame2(NULL, 0); } cc_result Updater_GetBuildTime(cc_uint64* timestamp) { diff --git a/src/_GraphicsBase.h b/src/_GraphicsBase.h index b5ec63987..7923dac1a 100644 --- a/src/_GraphicsBase.h +++ b/src/_GraphicsBase.h @@ -85,7 +85,7 @@ static void LimitFPS(void) { float cooldown = gfx_targetTime - gfx_actualTime; Thread_Sleep((int)(cooldown + 0.5f)); - /* also accumulate Thread_Sleep duration, as actual sleep + /* also accumulate Thread_Sleep duration, as actual sleep */ /* duration can significantly deviate from requested time */ /* (e.g. requested 4ms, but actually slept for 8ms) */ cc_uint64 sleepEnd = Stopwatch_Measure(); diff --git a/src/interop_ios.m b/src/interop_ios.m index f14cea482..c8f86679b 100644 --- a/src/interop_ios.m +++ b/src/interop_ios.m @@ -406,6 +406,9 @@ cc_result Updater_SetNewBuildTime(cc_uint64 t) { return ERR_NOT_SUPPORTED; } /*########################################################################################################################* *--------------------------------------------------------Platform--------------------------------------------------------* *#########################################################################################################################*/ +static char gameArgs[GAME_MAX_CMDARGS][STRING_SIZE]; +static int gameNumArgs; + cc_result Process_StartOpen(const cc_string* args) { char raw[NATIVE_STR_LEN]; NSURL* url; @@ -418,19 +421,23 @@ cc_result Process_StartOpen(const cc_string* args) { return 0; } -static char gameArgsBuffer[512]; -static cc_string gameArgs = String_FromArray(gameArgsBuffer); -cc_result Process_StartGame(const cc_string* args) { - String_Copy(&gameArgs, args); +cc_result Process_StartGame2(const cc_string* args, int numArgs) { + for (int i = 0; i < numArgs; i++) { + String_CopyToRawArray(gameArgs[i], &args[i]); + } + + gameNumArgs = numArgs; return 0; } int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, cc_string* args) { - if (!gameArgs.length) return 0; - - int count = String_UNSAFE_Split(&gameArgs, ' ', args, GAME_MAX_CMDARGS); - // clear arguments so after game is closed, launcher is started again - gameArgs.length = 0; + int count = gameNumArgs; + for (int i = 0; i < count; i++) { + args[i] = String_FromRawArray(gameArgs[i]); + } + + // clear arguments so after game is closed, launcher is started + gameNumArgs = 0; return count; }