/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program 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 "ags/shared/core/platform.h" #include "common/std/set.h" #include "ags/lib/allegro.h" // allegro_exit #include "ags/shared/ac/common.h" #include "ags/engine/ac/game_setup.h" #include "ags/engine/ac/game_state.h" #include "ags/shared/core/def_version.h" #include "ags/engine/debugging/debugger.h" #include "ags/engine/debugging/debug_log.h" #include "ags/shared/debugging/out.h" #include "ags/engine/main/config.h" #include "ags/engine/main/engine.h" #include "ags/engine/main/main.h" #include "ags/engine/platform/base/ags_platform_driver.h" #include "ags/engine/platform/base/sys_main.h" #include "ags/engine/ac/route_finder.h" #include "ags/shared/core/asset_manager.h" #include "ags/shared/util/directory.h" #include "ags/shared/util/path.h" #include "ags/shared/util/string_compat.h" #include "ags/shared/util/string_utils.h" #include "ags/globals.h" namespace AGS3 { using namespace AGS::Shared; using namespace AGS::Engine; void main_init(int argc, const char *argv[]) { set_our_eip(-999); // Init libraries: set text encoding set_uformat(U_UTF8); set_filename_encoding(U_UNICODE); _G(EngineVersion) = Version(ACI_VERSION_STR " " SPECIAL_VERSION); #if defined (BUILD_STR) _G(EngineVersion).BuildInfo = BUILD_STR; #endif _G(platform) = AGSPlatformDriver::GetDriver(); _G(platform)->SetCommandArgs(argv, argc); _G(platform)->MainInit(); _GP(AssetMgr).reset(new AssetManager()); _GP(AssetMgr)->SetSearchPriority(Shared::kAssetPriorityDir); } String get_engine_string() { return String::FromFormat("Adventure Game Studio v%s Interpreter\n" "Copyright (c) 1999-2011 Chris Jones and " ACI_COPYRIGHT_YEARS " others\n" "Engine version %s\n", _G(EngineVersion).ShortString.GetCStr(), get_engine_version_and_build().GetCStr()); } void main_print_help() { _G(platform)->WriteStdOut("%s", "Usage: ags [OPTIONS] [GAMEFILE or DIRECTORY]\n\n" //--------------------------------------------------------------------------------| "Options:\n" " --background Keeps game running in background\n" " (this does not work in exclusive fullscreen)\n" " --clear-cache-on-room-change Clears sprite cache on every room change\n" " --conf FILEPATH Specify explicit config file to read on startup\n" #if AGS_PLATFORM_OS_WINDOWS " --console-attach Write output to the parent process's console\n" #endif " --fps Display fps counter\n" " --fullscreen Force display mode to fullscreen\n" " --gfxdriver Request graphics driver. Available options:\n" #if AGS_PLATFORM_OS_WINDOWS " d3d9, ogl, software\n" #else " ogl, software\n" #endif " --gfxfilter FILTER [SCALING]\n" " Request graphics filter. Available options:\n" " stdscale, linear\n" " (support may differ between graphic drivers);\n" " Scaling is specified as:\n" " proportional, round, stretch,\n" " or an explicit integer multiplier.\n" " --help Print this help message and stop\n" " --loadsavedgame FILEPATH Load savegame on startup\n" " --localuserconf Read and write user config in the game's \n" " directory rather than using standard system path.\n" " Game directory must be writeable.\n" " --log-OUTPUT=GROUP[:LEVEL][,GROUP[:LEVEL]][,...]\n" " --log-OUTPUT=+GROUPLIST[:LEVEL]\n" " Setup logging to the chosen OUTPUT with given\n" " log groups and verbosity levels. Groups may\n" " be also defined by a LIST of one-letter IDs,\n" " preceded by '+', e.g. +ABCD:LEVEL. Verbosity may\n" " be also defined by a numberic ID.\n" " OUTPUTs are\n" " stdout, file, console\n" " (where \"console\" is internal engine's console)\n" " GROUPs are:\n" " all, main (m), game (g), manobj (o),\n" " sprcache (c)\n" " LEVELs are:\n" " all, alert (1), fatal (2), error (3), warn (4),\n" " info (5), debug (6)\n" " Examples:\n" " --log-stdout=+mg:debug\n" " --log-file=all:warn\n" " --log-file-path=PATH Define custom path for the log file\n" //--------------------------------------------------------------------------------| " --no-message-box Disable alerts as modal message boxes\n" " --no-translation Use default game language on start\n" " --noiface Don't draw game GUI\n" " --noscript Don't run room scripts; *WARNING:* unreliable\n" " --nospr Don't draw room objects and characters\n" " --noupdate Don't run game update\n" " --novideo Don't play game videos\n" " --rotation Screen rotation preferences. MODEs are:\n" " unlocked (0), portrait (1), landscape (2)\n" #if AGS_PLATFORM_OS_WINDOWS " --setup Run setup application\n" #endif " --shared-data-dir DIR Set the shared game data directory\n" " --startr Start game by loading certain room.\n" " --tell Print various information concerning engine\n" " and the game; for selected output use:\n" " --tell-config Print contents of merged game config\n" " --tell-configpath Print paths to available config files\n" " --tell-data Print information on game data and its location\n" " --tell-gameproperties Print information on game general settings\n" " --tell-engine Print engine name and version\n" " --tell-filepath Print all filepaths engine uses for the game\n" " --tell-graphicdriver Print list of supported graphic drivers\n" "\n" " --test Run game in the test mode\n" " --translation Select the given translation on start\n" " --version Print engine's version and stop\n" " --user-data-dir DIR Set the save game directory\n" " --windowed Force display mode to windowed\n" "\n" "Gamefile options:\n" " /dir/path/game/ Launch the game in specified directory\n" " /dir/path/game/penguin.exe Launch penguin.exe\n" " [nothing] Launch the game in the current directory\n" //--------------------------------------------------------------------------------| ); } int main_process_cmdline(ConfigTree &cfg, int argc, const char *argv[]) { int datafile_argv = 0; for (int ee = 1; ee < argc; ++ee) { const char *arg = argv[ee]; // // Startup options // if (ags_stricmp(arg, "--help") == 0 || ags_stricmp(arg, "/?") == 0 || ags_stricmp(arg, "-?") == 0) { _G(justDisplayHelp) = true; } if (ags_stricmp(arg, "-v") == 0 || ags_stricmp(arg, "--version") == 0) { _G(justDisplayVersion) = true; } else if (ags_stricmp(arg, "--updatereg") == 0) _G(debug_flags) |= DBG_REGONLY; else if ((ags_stricmp(arg, "--startr") == 0) && (ee < argc - 1)) { _G(override_start_room) = atoi(argv[ee + 1]); ee++; } else if (ags_stricmp(arg, "--noexceptionhandler") == 0) _GP(usetup).disable_exception_handling = true; else if (ags_stricmp(arg, "--setup") == 0) { _G(justRunSetup) = true; } else if ((ags_stricmp(arg, "--loadsavedgame") == 0) && (argc > ee + 1)) { _G(loadSaveGameOnStartup) = atoi(argv[ee + 1]); ee++; } else if ((ags_stricmp(arg, "--enabledebugger") == 0) && (argc > ee + 1)) { snprintf(_G(editor_debugger_instance_token), sizeof(_G(editor_debugger_instance_token)), "%s", argv[ee + 1]); _G(editor_debugging_enabled) = 1; ee++; } else if (ags_stricmp(arg, "--conf") == 0 && (argc > ee + 1)) { _GP(usetup).conf_path = argv[++ee]; } else if (ags_stricmp(arg, "--localuserconf") == 0) { _GP(usetup).local_user_conf = true; } else if (ags_stricmp(arg, "--localuserconf") == 0) { _GP(usetup).user_conf_dir = "."; } else if ((ags_stricmp(arg, "--user-conf-dir") == 0) && (argc > ee + 1)) { _GP(usetup).user_conf_dir = argv[++ee]; } else if (ags_stricmp(arg, "--runfromide") == 0 && (argc > ee + 4)) { _GP(usetup).install_dir = argv[ee + 1]; _GP(usetup).opt_data_dir = argv[ee + 2]; _GP(usetup).opt_audio_dir = argv[ee + 3]; _GP(usetup).opt_voice_dir = argv[ee + 4]; ee += 4; } else if (ags_stricmp(arg, "--takeover") == 0) { if (argc < ee + 2) break; _GP(play).takeover_data = atoi(argv[ee + 1]); snprintf(_GP(play).takeover_from, sizeof(_GP(play).takeover_from), "%s", argv[ee + 2]); ee += 2; } else if (ags_stricmp(arg, "--clear-cache-on-room-change") == 0) { cfg["misc"]["clear_cache_on_room_change"] = "1"; } else if (ags_strnicmp(arg, "--tell", 6) == 0) { if (arg[6] == 0) _G(tellInfoKeys).insert(String("all")); else if (arg[6] == '-' && arg[7] != 0) _G(tellInfoKeys).insert(String(arg + 7)); } // // Config overrides // else if ((ags_stricmp(arg, "--user-data-dir") == 0) && (argc > ee + 1)) cfg["misc"]["user_data_dir"] = argv[++ee]; else if ((ags_stricmp(arg, "--shared-data-dir") == 0) && (argc > ee + 1)) cfg["misc"]["shared_data_dir"] = argv[++ee]; else if (ags_stricmp(arg, "--windowed") == 0) cfg["graphics"]["windowed"] = "1"; else if (ags_stricmp(arg, "--fullscreen") == 0) cfg["graphics"]["windowed"] = "0"; else if ((ags_stricmp(arg, "--gfxdriver") == 0) && (argc > ee + 1)) { cfg["graphics"]["driver"] = argv[++ee]; } else if ((ags_stricmp(arg, "--gfxfilter") == 0) && (argc > ee + 1)) { cfg["graphics"]["filter"] = argv[++ee]; if (argc > ee + 1 && argv[ee + 1][0] != '-') { // NOTE: we make an assumption here that if user provides scaling // multiplier, then it's meant to be applied to windowed mode only; // Otherwise the scaling style is applied to both. String scale_value = argv[++ee]; int scale_mul = StrUtil::StringToInt(scale_value); if (scale_mul > 0) { cfg["graphics"]["window"] = String::FromFormat("x%d", scale_mul); cfg["graphics"]["game_scale_win"] = "round"; } else { cfg["graphics"]["game_scale_fs"] = scale_value; cfg["graphics"]["game_scale_win"] = scale_value; } } } else if ((ags_stricmp(arg, "--translation") == 0) && (argc > ee + 1)) { cfg["language"]["translation"] = argv[++ee]; } else if (ags_stricmp(arg, "--no-translation") == 0) { cfg["language"]["translation"] = ""; } else if (ags_stricmp(arg, "--background") == 0) { cfg["override"]["multitasking"] = "1"; } else if (ags_stricmp(arg, "--fps") == 0) cfg["misc"]["show_fps"] = "1"; else if (ags_stricmp(arg, "--test") == 0) _G(debug_flags) |= DBG_DEBUGMODE; else if (ags_stricmp(arg, "--noiface") == 0) _G(debug_flags) |= DBG_NOIFACE; else if (ags_stricmp(arg, "--nosprdisp") == 0) _G(debug_flags) |= DBG_NODRAWSPRITES; else if (ags_stricmp(arg, "--nospr") == 0) _G(debug_flags) |= DBG_NOOBJECTS; else if (ags_stricmp(arg, "--noupdate") == 0) _G(debug_flags) |= DBG_NOUPDATE; else if (ags_stricmp(arg, "--nosound") == 0) _G(debug_flags) |= DBG_NOSFX; else if (ags_stricmp(arg, "--nomusic") == 0) _G(debug_flags) |= DBG_NOMUSIC; else if (ags_stricmp(arg, "--noscript") == 0) _G(debug_flags) |= DBG_NOSCRIPT; else if (ags_stricmp(arg, "--novideo") == 0) _G(debug_flags) |= DBG_NOVIDEO; else if (ags_stricmp(arg, "--rotation") == 0 && (argc > ee + 1)) { cfg["graphics"]["rotation"] = argv[++ee]; } else if (ags_strnicmp(arg, "--log-", 6) == 0 && arg[6] != 0) { String logarg = arg + 6; size_t split_at = logarg.FindChar('='); if (split_at != String::NoIndex) cfg["log"][logarg.Left(split_at)] = logarg.Mid(split_at + 1); else cfg["log"][logarg] = ""; } else if (arg[0] != '-') datafile_argv = ee; } if (datafile_argv > 0) { _G(cmdGameDataPath) = _G(platform)->GetCommandArg(datafile_argv); } if (_G(tellInfoKeys).size() > 0) _G(justTellInfo) = true; return 0; } void main_set_gamedir(int argc, const char *argv[]) { _G(appPath) = Path::MakeAbsolutePath(_G(platform)->GetCommandArg(0)); _G(appDirectory) = Path::GetDirectoryPath(_G(appPath)); // TODO: remove following when supporting unicode paths { // It looks like Allegro library does not like ANSI (ACP) paths. // When *not* working in U_UNICODE filepath mode, whenever it gets // current directory for its own operations, it "fixes" it by // substituting non-ASCII symbols with '^'. // Here we explicitly set current directory to ASCII path. String cur_dir = Directory::GetCurrentDirectory(); String path = Path::GetPathInASCII(cur_dir); if (!path.IsEmpty()) Directory::SetCurrentDirectory(Path::MakeAbsolutePath(path)); else Debug::Printf(kDbgMsg_Error, "Unable to determine current directory: GetPathInASCII failed.\nArg: %s", cur_dir.GetCStr()); } } } // namespace AGS3