diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj index 5d856b42d7..dc4b8b876c 100644 --- a/projects/openrct2.vcxproj +++ b/projects/openrct2.vcxproj @@ -42,6 +42,7 @@ + @@ -71,6 +72,7 @@ + @@ -139,6 +141,7 @@ + @@ -165,6 +168,7 @@ + diff --git a/projects/openrct2.vcxproj.filters b/projects/openrct2.vcxproj.filters index e1b4435a08..f70267d16a 100644 --- a/projects/openrct2.vcxproj.filters +++ b/projects/openrct2.vcxproj.filters @@ -367,7 +367,6 @@ - Source\Windows @@ -377,9 +376,6 @@ - - Libraries\libspeex - @@ -415,6 +411,14 @@ Libraries\lodepng + + + + Source + + + Source + @@ -600,5 +604,11 @@ Source\Management + + Source + + + Source + \ No newline at end of file diff --git a/projects/openrct2.vcxproj.user b/projects/openrct2.vcxproj.user index 80981e45c6..3695926811 100644 --- a/projects/openrct2.vcxproj.user +++ b/projects/openrct2.vcxproj.user @@ -12,5 +12,6 @@ $(TargetDir)\openrct2.exe $(TargetDir) WindowsLocalDebugger + "C:\Users\Ted\Documents\OpenRCT2\scenarios\RCT Forest Frontiers.SC6" \ No newline at end of file diff --git a/src/cmdline.c b/src/cmdline.c new file mode 100644 index 0000000000..fca9191417 --- /dev/null +++ b/src/cmdline.c @@ -0,0 +1,99 @@ +/***************************************************************************** + * Copyright (c) 2014 Ted John + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * This file is part of OpenRCT2. + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *****************************************************************************/ + +#include +#ifdef _MSC_VER +#include +#endif +#include "cmdline.h" +#include "openrct2.h" + +typedef struct tm tm_t; + +int gExitCode = 0; + +static void print_launch_information(); + +/** + * A shared entry point to OpenRCT2. The command lines must be parsed before any further action is done. Invalid command lines + * will then terminate before any initialisation has even been done. + * @returns 1 if the game should run, otherwise 0. + */ +int cmdline_run(char *argv[], int argc) +{ + print_launch_information(); + + if (argc > 0) { + if (_stricmp(argv[0], "edit") == 0) { + gOpenRCT2StartupAction = STARTUP_ACTION_EDIT; + if (argc >= 2) + strcpy(gOpenRCT2StartupActionPath, argv[1]); + } else { + gOpenRCT2StartupAction = STARTUP_ACTION_OPEN; + strcpy(gOpenRCT2StartupActionPath, argv[0]); + } + } + + return 1; +} + +static void print_launch_information() +{ + char buffer[32]; + time_t timer; + tm_t* tmInfo; + + // Print version information + printf("Starting %s v%s\n", OPENRCT2_NAME, OPENRCT2_VERSION); + printf(" %s (%s)\n", OPENRCT2_PLATFORM, OPENRCT2_ARCHITECTURE); + printf(" %s\n\n", OPENRCT2_TIMESTAMP); + + // Print current time + time(&timer); + tmInfo = localtime(&timer); + strftime(buffer, sizeof(buffer), "%Y/%m/%d %H:%M:%S", tmInfo); + printf("Time: %s\n", buffer); + + // TODO Print other potential information (e.g. user, hardware) +} + +//void check_cmdline_arg() +//{ +// int argc; +// char **argv; +// char *args; +// +// args = RCT2_GLOBAL(0x009AC310, char*); +// if (args == (char*)0xFFFFFFFF) +// return; +// RCT2_GLOBAL(0x009AC310, char*) = (char*)0xFFFFFFFF; +// +// 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]); +// } +// } +// +// LocalFree(argv); +//} \ No newline at end of file diff --git a/src/cmdline.h b/src/cmdline.h new file mode 100644 index 0000000000..09baea261b --- /dev/null +++ b/src/cmdline.h @@ -0,0 +1,31 @@ +/***************************************************************************** + * Copyright (c) 2014 Ted John + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * This file is part of OpenRCT2. + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *****************************************************************************/ + +#ifndef _CMDLINE_H_ +#define _CMDLINE_H_ + +#include "common.h" + +/** The exit code for OpenRCT2 when it exits. */ +extern int gExitCode; + +int cmdline_run(char *argv[], int argc); + +#endif \ No newline at end of file diff --git a/src/editor.c b/src/editor.c index dd79fb9723..30fc1f4785 100644 --- a/src/editor.c +++ b/src/editor.c @@ -78,7 +78,7 @@ void editor_load() RCT2_CALLPROC_EBPSAFE(0x006837E3); gfx_invalidate_screen(); RCT2_GLOBAL(0x009DEA66, sint16) = 0; - rct2_endupdate(); + // rct2_endupdate(); } /** diff --git a/src/openrct2.c b/src/openrct2.c new file mode 100644 index 0000000000..b6227145de --- /dev/null +++ b/src/openrct2.c @@ -0,0 +1,78 @@ +/***************************************************************************** + * Copyright (c) 2014 Ted John + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * This file is part of OpenRCT2. + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *****************************************************************************/ + +#include "addresses.h" +#include "audio/audio.h" +#include "audio/mixer.h" +#include "cmdline.h" +#include "config.h" +#include "editor.h" +#include "localisation/localisation.h" +#include "openrct2.h" +#include "platform/osinterface.h" + +int gOpenRCT2StartupAction = STARTUP_ACTION_TITLE; +char gOpenRCT2StartupActionPath[512] = { 0 }; + +/** + * Launches the game, after command line arguments have been parsed and processed. + */ +void openrct2_launch() +{ + get_system_info(); + audio_init(); + audio_get_devices(); + get_dsound_devices(); + config_init(); + language_open(gGeneral_config.language); + rct2_init(); + Mixer_Init(NULL); + + switch (gOpenRCT2StartupAction) { + case STARTUP_ACTION_INTRO: + RCT2_GLOBAL(RCT2_ADDRESS_RUN_INTRO_TICK_PART, uint8) = 8; + break; + case STARTUP_ACTION_TITLE: + RCT2_GLOBAL(RCT2_ADDRESS_RUN_INTRO_TICK_PART, uint8) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_TITLE_DEMO; + break; + case STARTUP_ACTION_OPEN: + assert(gOpenRCT2StartupActionPath != NULL); + rct2_open_file(gOpenRCT2StartupActionPath); + + RCT2_GLOBAL(RCT2_ADDRESS_RUN_INTRO_TICK_PART, uint8) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_PLAYING; + + // TODO fix, crashes on first game logic update + break; + case STARTUP_ACTION_EDIT: + if (strlen(gOpenRCT2StartupActionPath) == 0) + editor_load(); + else + editor_load_landscape(gOpenRCT2StartupActionPath); + break; + } + + rct2_loop(); + osinterface_free(); + + // HACK Some threads are still running which causes the game to not terminate. Investigation required! + exit(gExitCode); +} \ No newline at end of file diff --git a/src/openrct2.h b/src/openrct2.h new file mode 100644 index 0000000000..055fb7f245 --- /dev/null +++ b/src/openrct2.h @@ -0,0 +1,38 @@ +/***************************************************************************** + * Copyright (c) 2014 Ted John + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * This file is part of OpenRCT2. + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *****************************************************************************/ + +#ifndef _OPENRCT2_H_ +#define _OPENRCT2_H_ + +#include "common.h" + +enum { + STARTUP_ACTION_INTRO, + STARTUP_ACTION_TITLE, + STARTUP_ACTION_OPEN, + STARTUP_ACTION_EDIT +}; + +extern int gOpenRCT2StartupAction; +extern char gOpenRCT2StartupActionPath[512]; + +void openrct2_launch(); + +#endif \ No newline at end of file diff --git a/src/platform/unix.c b/src/platform/unix.c index 47aecde2d2..e5151df42d 100644 --- a/src/platform/unix.c +++ b/src/platform/unix.c @@ -21,12 +21,18 @@ #ifndef _WIN32 #ifndef __APPLE__ +#include "../cmdline.h" +#include "../openrct2.h" + /** * Unix, linux and fallback entry point to OpenRCT2. */ // int main(char *argv[], int argc) // { -// return 0; +// if (cmdline_run(argv, argc)) +// openrct2_launch(); +// +// return gExitCode; // } char platform_get_path_separator() diff --git a/src/platform/windows.c b/src/platform/windows.c index 1d683f9e8b..1de14e0272 100644 --- a/src/platform/windows.c +++ b/src/platform/windows.c @@ -21,6 +21,11 @@ #ifdef _WIN32 #include +#include "../addresses.h" +#include "../cmdline.h" +#include "../openrct2.h" + +LPSTR *CommandLineToArgvA(LPSTR lpCmdLine, int *argc); /** * Windows entry point to OpenRCT2 without a console window. @@ -50,9 +55,24 @@ BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved) * The function that is called directly from the host application (rct2.exe)'s WinMain. This will be removed when OpenRCT2 can * be built as a stand alone application. */ -// __declspec(dllexport) int StartOpenRCT(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) -// { -// } +__declspec(dllexport) int StartOpenRCT(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) +{ + int argc, runGame; + char **argv; + + RCT2_GLOBAL(RCT2_ADDRESS_HINSTANCE, HINSTANCE) = hInstance; + RCT2_GLOBAL(RCT2_ADDRESS_CMDLINE, LPSTR) = lpCmdLine; + + // Get command line arguments in standard form + argv = CommandLineToArgvA(lpCmdLine, &argc); + runGame = cmdline_run(argv, argc); + LocalFree(argv); + + if (runGame) + openrct2_launch(); + + return gExitCode; +} char platform_get_path_separator() { @@ -73,4 +93,87 @@ int platform_ensure_directory_exists(const char *path) return CreateDirectory(path, NULL); } +/** + * 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; +} + #endif \ No newline at end of file diff --git a/src/rct2.c b/src/rct2.c index 9e6a05190b..9a2e00ded7 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -58,60 +58,12 @@ void print_launch_information(); void rct2_init_directories(); void rct2_startup_checks(); - -static void rct2_init(); -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; -__declspec(dllexport) int StartOpenRCT(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) -{ - print_launch_information(); - - // Begin RCT2 - RCT2_GLOBAL(RCT2_ADDRESS_HINSTANCE, HINSTANCE) = hInstance; - RCT2_GLOBAL(RCT2_ADDRESS_CMDLINE, LPSTR) = lpCmdLine; - get_system_info(); - - audio_init(); - audio_get_devices(); - get_dsound_devices(); - config_init(); - language_open(gGeneral_config.language); - rct2_init(); - Mixer_Init(NULL); - rct2_loop(); - osinterface_free(); - exit(0); - - return 0; -} - -void print_launch_information() -{ - char buffer[32]; - time_t timer; - tm_t* tmInfo; - - // Print version information - printf("Starting %s v%s\n", OPENRCT2_NAME, OPENRCT2_VERSION); - printf(" %s (%s)\n", OPENRCT2_PLATFORM, OPENRCT2_ARCHITECTURE); - printf(" %s\n\n", OPENRCT2_TIMESTAMP); - - // Print current time - time(&timer); - tmInfo = localtime(&timer); - strftime(buffer, sizeof(buffer), "%Y/%m/%d %H:%M:%S", tmInfo); - printf("Time: %s\n", buffer); - - // TODO Print other potential information (e.g. user, hardware) -} - void rct2_loop() { int last_tick = 0; @@ -286,30 +238,6 @@ int rct2_open_file(const char *path) } } -void check_cmdline_arg() -{ - int argc; - char **argv; - char *args; - - args = RCT2_GLOBAL(0x009AC310, char*); - if (args == (char*)0xFFFFFFFF) - return; - RCT2_GLOBAL(0x009AC310, char*) = (char*)0xFFFFFFFF; - - 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]); - } - } - - LocalFree(argv); -} - // rct2: 0x00407DB0 int check_mutex() { @@ -425,7 +353,7 @@ void rct2_update_2() // TODO: screenshot countdown process - check_cmdline_arg(); + // check_cmdline_arg(); // Screens if (RCT2_GLOBAL(RCT2_ADDRESS_RUN_INTRO_TICK_PART, uint8) != 0) intro_update(); @@ -598,87 +526,4 @@ void *rct2_realloc(void *block, size_t numBytes) 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 diff --git a/src/rct2.h b/src/rct2.h index 51f982c4ed..85d13baf0e 100644 --- a/src/rct2.h +++ b/src/rct2.h @@ -21,6 +21,7 @@ #ifndef _RCT2_H_ #define _RCT2_H_ +#include #include #include #include @@ -268,6 +269,8 @@ static const struct file_to_check { PATH_ID_END, 0 } }; +void rct2_init(); +void rct2_loop(); void rct2_endupdate(); void subsitute_path(char *dest, const char *path, const char *filename); int check_mutex(); @@ -283,4 +286,6 @@ void *rct2_realloc(void *block, size_t numBytes); void rct2_free(void *block); void rct2_quit(); +int rct2_open_file(const char *path); + #endif