From 31eec46c4de9674d0147f7c1f856d8da09a598cd Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Mon, 8 Sep 2014 19:58:15 +0100 Subject: [PATCH 1/2] allow scenarios from any location to be started via command line --- src/rct2.c | 3 +++ src/scenario.c | 26 ++++++++++++++++---------- src/scenario.h | 5 +++-- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/rct2.c b/src/rct2.c index 29572477a3..4c9c416eb3 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -307,6 +307,9 @@ void check_cmdline_arg() else if (!_stricmp(processed_arg + last_period, "sc6")) { //TODO: scenario install + rct_scenario_basic scenarioBasic; + strcpy(scenarioBasic.path, processed_arg); + scenario_load_and_play_from_path(scenarioBasic.path); } else if (!_stricmp(processed_arg + last_period, "td6") || !_stricmp(processed_arg + last_period, "td4")) { diff --git a/src/scenario.c b/src/scenario.c index 9154ce9e81..c83c136f8b 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -83,7 +83,7 @@ int scenario_load_basic(const char *path) * rct2: 0x00676053 * scenario (ebx) */ -void scenario_load(const char *path) +int scenario_load(const char *path) { FILE *file; int i, j; @@ -96,7 +96,7 @@ void scenario_load(const char *path) fclose(file); RCT2_GLOBAL(0x009AC31B, uint8) = 255; RCT2_GLOBAL(0x009AC31C, uint16) = STR_FILE_CONTAINS_INVALID_DATA; - return; + return 0; } // Read first chunk @@ -158,7 +158,7 @@ void scenario_load(const char *path) RCT2_CALLPROC_EBPSAFE(0x006A9FC0); map_update_tile_pointers(); reset_0x69EBE4();// RCT2_CALLPROC_EBPSAFE(0x0069EBE4); - return; + return 1; } fclose(file); @@ -166,6 +166,7 @@ void scenario_load(const char *path) RCT2_GLOBAL(0x009AC31B, uint8) = 255; RCT2_GLOBAL(0x009AC31C, uint16) = STR_FILE_CONTAINS_INVALID_DATA; + return 0; } /** @@ -173,7 +174,15 @@ void scenario_load(const char *path) * rct2: 0x00678282 * scenario (ebx) */ -void scenario_load_and_play(const rct_scenario_basic *scenario) +int scenario_load_and_play(const rct_scenario_basic *scenario) +{ + char path[MAX_PATH]; + + subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), scenario->path); + return scenario_load_and_play_from_path(path); +} + +int scenario_load_and_play_from_path(const char *path) { rct_window *mainWindow; rct_s6_info *s6Info = (rct_s6_info*)0x0141F570; @@ -185,12 +194,9 @@ void scenario_load_and_play(const rct_scenario_basic *scenario) RCT2_CALLPROC_EBPSAFE(0x006CBCC3); - subsitute_path( - RCT2_ADDRESS(0x0141EF68, char), - RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), - scenario->path - ); - scenario_load((char*)0x0141EF68); + if (!scenario_load(path)) + return 0; + RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_PLAYING; viewport_init_all(); game_create_windows(); diff --git a/src/scenario.h b/src/scenario.h index cbd5b5d764..7d061cc061 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -402,8 +402,9 @@ extern rct_scenario_basic *gScenarioList; int scenario_scores_save(); void scenario_load_list(); int scenario_load_basic(const char *path); -void scenario_load(const char *path); -void scenario_load_and_play(const rct_scenario_basic *scenario); +int scenario_load(const char *path); +int scenario_load_and_play(const rct_scenario_basic *scenario); +int scenario_load_and_play_from_path(const char *path); void scenario_update(); int scenario_rand(); From 645b8fbb46eafc9b38852442c4f878faa6cdd8f0 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Wed, 10 Sep 2014 19:36:11 +0100 Subject: [PATCH 2/2] add edit command line function --- src/editor.c | 10 ++++ src/editor.h | 1 + src/game.c | 7 +-- src/game.h | 2 +- src/rct2.c | 160 ++++++++++++++++++++++++++++++++++++++------------- 5 files changed, 134 insertions(+), 46 deletions(-) diff --git a/src/editor.c b/src/editor.c index db3ead3c26..d9f7be568e 100644 --- a/src/editor.c +++ b/src/editor.c @@ -165,6 +165,16 @@ void trackmanager_load() rct2_endupdate(); } +/** + * + * rct2: 0x006758C0 + */ +void editor_load_landscape(const char *path) +{ + strcpy((char *)0x0141EF68, path); + RCT2_CALLPROC_EBPSAFE(0x006758C0); +} + /** * * rct2: 0x0068ABEC diff --git a/src/editor.h b/src/editor.h index 9022a6cd4d..c544bf3a16 100644 --- a/src/editor.h +++ b/src/editor.h @@ -25,6 +25,7 @@ void editor_load(); void editor_convert_save_to_scenario(); void trackdesigner_load(); void trackmanager_load(); +void editor_load_landscape(const char *path); void sub_6BD3A4(); diff --git a/src/game.c b/src/game.c index 621ba79b3c..91b057fa4b 100644 --- a/src/game.c +++ b/src/game.c @@ -693,14 +693,13 @@ static void load_landscape() * * rct2: 0x00675E1B */ -int game_load_save() +int game_load_save(const char *path) { rct_window *mainWindow; FILE *file; - char *path; int i, j; - path = (char*)0x0141EF68; + strcpy((char*)0x0141EF68, path); file = fopen(path, "rb"); if (file == NULL) { RCT2_GLOBAL(0x009AC31B, uint8) = 255; @@ -825,7 +824,7 @@ static void load_game() } strcpy((char*)RCT2_ADDRESS_SAVED_GAMES_PATH_2, (char*)0x0141EF68); - if (game_load_save()) { + if (game_load_save((char *)0x0141EF68)) { gfx_invalidate_screen(); rct2_endupdate(); } else { diff --git a/src/game.h b/src/game.h index b3d4f15adb..72e3f63ccf 100644 --- a/src/game.h +++ b/src/game.h @@ -100,7 +100,7 @@ void game_increase_game_speed(); void game_reduce_game_speed(); void game_load_or_quit_no_save_prompt(); -int game_load_save(); +int game_load_save(const char *path); void game_pause_toggle(); char save_game(); void rct2_exit(); diff --git a/src/rct2.c b/src/rct2.c index 4c9c416eb3..98c82e7bfd 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -65,6 +65,8 @@ static void rct2_loop(); static void rct2_update(); static void rct2_update_2(); +PCHAR *CommandLineToArgvA(PCHAR CmdLine, int *_argc); + static int _finished; static jmp_buf _end_update_jump; @@ -267,54 +269,47 @@ void rct2_update() rct2_update_2(); } +int rct2_open_file(const char *path) +{ + char *extension = strrchr(path, '.'); + if (extension == NULL) + return 0; + extension++; + + if (_stricmp(extension, "sv6")) { + game_load_save(path); + } else if (!_stricmp(extension, "sc6")) { + // TODO scenario install + rct_scenario_basic scenarioBasic; + strcpy(scenarioBasic.path, path); + scenario_load_and_play_from_path(scenarioBasic.path); + } else if (!_stricmp(extension, "td6") || !_stricmp(extension, "td4")) { + // TODO track design install + } +} + void check_cmdline_arg() { - if(RCT2_GLOBAL(0x009AC310, uint32) == 0xFFFFFFFF) + int argc; + char **argv; + char *args; + + args = RCT2_GLOBAL(0x009AC310, char*); + if (args == (char*)0xFFFFFFFF) return; + RCT2_GLOBAL(0x009AC310, char*) = (char*)0xFFFFFFFF; - char *arg = RCT2_GLOBAL(0x009AC310, char *); - char processed_arg[255]; - int len, i, j; - int quote = 0; - int last_period = 0; - - RCT2_GLOBAL(0x009AC310, uint32) = 0xFFFFFFFF; - len = strlen(arg); - - for(i = 0, j = 0; i < len; i ++) - { - if(arg[i] == '\"') - { - if(quote) - quote = 0; - else - quote = 1; - continue; + argv = CommandLineToArgvA(args, &argc); + if (argc > 0) { + if (_stricmp(argv[0], "edit") == 0) { + if (argc >= 1) + editor_load_landscape(argv[1]); + } else { + rct2_open_file(argv[0]); } - if(arg[i] == ' ' && !quote) - break; - if(arg[i] == '.') - last_period = i; - processed_arg[j ++] = arg[i]; } - processed_arg[j ++] = 0; - if (!_stricmp(processed_arg + last_period, "sv6")) - { - strcpy((char*)0x00141EF68, processed_arg); - game_load_save(); - } - else if (!_stricmp(processed_arg + last_period, "sc6")) - { - //TODO: scenario install - rct_scenario_basic scenarioBasic; - strcpy(scenarioBasic.path, processed_arg); - scenario_load_and_play_from_path(scenarioBasic.path); - } - else if (!_stricmp(processed_arg + last_period, "td6") || !_stricmp(processed_arg + last_period, "td4")) - { - //TODO: track design install - } + LocalFree(argv); } // rct2: 0x00407DB0 @@ -606,3 +601,86 @@ void rct2_free(void *block) { RCT2_CALLPROC_1(0x004068DE, void*, block); } + +/** + * http://alter.org.ua/en/docs/win/args/ + */ +PCHAR *CommandLineToArgvA(PCHAR CmdLine, int *_argc) +{ + PCHAR* argv; + PCHAR _argv; + ULONG len; + ULONG argc; + CHAR a; + ULONG i, j; + + BOOLEAN in_QM; + BOOLEAN in_TEXT; + BOOLEAN in_SPACE; + + len = strlen(CmdLine); + i = ((len + 2) / 2)*sizeof(PVOID) + sizeof(PVOID); + + argv = (PCHAR*)GlobalAlloc(GMEM_FIXED, + i + (len + 2)*sizeof(CHAR)); + + _argv = (PCHAR)(((PUCHAR)argv) + i); + + argc = 0; + argv[argc] = _argv; + in_QM = FALSE; + in_TEXT = FALSE; + in_SPACE = TRUE; + i = 0; + j = 0; + + while (a = CmdLine[i]) { + if (in_QM) { + if (a == '\"') { + in_QM = FALSE; + } else { + _argv[j] = a; + j++; + } + } else { + switch (a) { + case '\"': + in_QM = TRUE; + in_TEXT = TRUE; + if (in_SPACE) { + argv[argc] = _argv + j; + argc++; + } + in_SPACE = FALSE; + break; + case ' ': + case '\t': + case '\n': + case '\r': + if (in_TEXT) { + _argv[j] = '\0'; + j++; + } + in_TEXT = FALSE; + in_SPACE = TRUE; + break; + default: + in_TEXT = TRUE; + if (in_SPACE) { + argv[argc] = _argv + j; + argc++; + } + _argv[j] = a; + j++; + in_SPACE = FALSE; + break; + } + } + i++; + } + _argv[j] = '\0'; + argv[argc] = NULL; + + (*_argc) = argc; + return argv; +} \ No newline at end of file