#include #include #include #include #include #include #include "acio/acio.h" #include "acio/icca/icca.h" #include "api/controller.h" #include "avs/automap.h" #include "avs/core.h" #include "avs/ea3.h" #include "avs/game.h" #include "build/defs.h" #include "cfg/spicecfg.h" #include "cfg/config.h" #include "cfg/screen_resize.h" #include "easrv/easrv.h" #include "external/cardio/cardio_runner.h" #include "external/scard/scard.h" #include "external/layeredfs/hook.h" #include "games/game.h" #include "games/io.h" #include "games/bbc/bbc.h" #include "games/bs/bs.h" #include "games/ddr/ddr.h" #include "games/dea/dea.h" #include "games/drs/drs.h" #include "games/gitadora/gitadora.h" #include "games/hpm/hpm.h" #include "games/iidx/iidx.h" #ifdef SPICE64 #include "games/iidx/camera.h" #endif #include "games/iidx/poke.h" #include "games/jb/jb.h" #include "games/mga/mga.h" #include "games/nost/nost.h" #include "games/popn/popn.h" #include "games/qma/qma.h" #include "games/rb/rb.h" #include "games/rf3d/rf3d.h" #include "games/sc/sc.h" #include "games/scotto/scotto.h" #include "games/sdvx/sdvx.h" #include "games/shared/printer.h" #include "games/silentscope/silentscope.h" #include "games/mfc/mfc.h" #include "games/ftt/ftt.h" #include "games/loveplus/loveplus.h" #include "games/we/we.h" #include "games/otoca/otoca.h" #include "games/shogikai/shogikai.h" #include "games/pcm/pcm.h" #include "games/onpara/onpara.h" #include "games/bc/bc.h" #include "games/ccj/ccj.h" #include "games/ccj/trackball.h" #include "games/qks/qks.h" #include "games/museca/museca.h" #include "hooks/avshook.h" #include "hooks/audio/audio.h" #include "hooks/debughook.h" #include "hooks/devicehook.h" #include "hooks/input/dinput8/hook.h" #include "hooks/graphics/graphics.h" #include "hooks/lang.h" #include "hooks/networkhook.h" #include "hooks/unisintrhook.h" #include "launcher/launcher.h" #include "launcher/logger.h" #include "launcher/signal.h" #include "launcher/superexit.h" #include "launcher/richpresence.h" #include "launcher/shutdown.h" #include "launcher/options.h" #include "script/manager.h" #include "misc/bt5api.h" #include "misc/device.h" #include "misc/eamuse.h" #include "misc/extdev.h" #include "misc/sciunit.h" #include "misc/sde.h" #include "misc/vrutil.h" #include "misc/wintouchemu.h" #include "overlay/overlay.h" #include "overlay/windows/patch_manager.h" #include "overlay/windows/iidx_seg.h" #include "rawinput/rawinput.h" #include "rawinput/touch.h" #include "reader/reader.h" #include "stubs/stubs.h" #include "touch/touch.h" #include "util/cpuutils.h" #include "util/crypt.h" #include "util/fileutils.h" #include "util/libutils.h" #include "util/logging.h" #include "util/peb.h" #include "util/tapeled.h" #include "util/time.h" #include "avs/ssl.h" #include "nvapi/nvapi.h" #include "hooks/graphics/nvapi_hook.h" // std::max #ifdef max #undef max #endif // constants static const char *STUBS[] = {"kbt.dll", "kld.dll"}; // general settings static std::vector game_hooks; std::filesystem::path MODULE_PATH; HANDLE LOG_FILE = INVALID_HANDLE_VALUE; std::string LOG_FILE_PATH = ""; int LAUNCHER_ARGC = 0; char **LAUNCHER_ARGV = nullptr; std::unique_ptr> LAUNCHER_OPTIONS; games::Game *GAME_INSTANCE = nullptr; std::string CARD_OVERRIDES[2]; // sub-systems std::unique_ptr API_CONTROLLER; std::unique_ptr RI_MGR; // trigger NVIDIA Optimus & AMD Enduro High Performance Graphics extern "C" { __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; } static bool CHECK_DLL_IGNORE_ARCH = false; static bool check_dll(const std::string &model) { if (cfg::CONFIGURATOR_STANDALONE || CHECK_DLL_IGNORE_ARCH) { return fileutils::file_exists(MODULE_PATH / model); } else { return fileutils::verify_header_pe(MODULE_PATH / model); } } int main_implementation(int argc, char *argv[]) { // remember argv, argv LAUNCHER_ARGC = argc; LAUNCHER_ARGV = argv; // register exception handler and control handler launcher::signal::init(); // start logger logger::start(); // get module path MODULE_PATH = libutils::module_file_name(nullptr).parent_path(); // initialize crypt crypt::init(); // initialize timer init_performance_counter(); // api settings bool api_enable = false; bool api_pretty = false; bool api_debug = false; unsigned short api_port = 1337; std::string api_pass = ""; std::vector api_serial_port; std::vector api_serial_baud; // attach settings bool attach_io = false; bool attach_acio = false; bool attach_icca = false; bool attach_device = false; bool attach_extdev = false; bool attach_sciunit = false; bool attach_cpusbxpkm_printer = false; bool attach_iidx = false; bool attach_sdvx = false; bool attach_jb = false; bool attach_rb = false; bool attach_shogikai = false; bool attach_mga = false; bool attach_sc = false; bool attach_popn = false; bool attach_ddr = false; bool attach_gitadora = false; bool attach_nostalgia = false; bool attach_bbc = false; bool attach_hpm = false; bool attach_qma = false; bool attach_dea = false; bool attach_mfc = false; bool attach_ftt = false; bool attach_bs = false; bool attach_loveplus = false; bool attach_scotto = false; bool attach_rf3d = false; bool attach_drs = false; bool attach_we = false; bool attach_otoca = false; bool attach_silentscope = false; bool attach_pcm = false; bool attach_onpara = false; bool attach_bc = false; bool attach_ccj = false; bool attach_qks = false; bool attach_museca = false; // misc settings size_t user_heap_size = 0; unsigned short easrv_port = 0; bool easrv_maint = true; bool easrv_smart = false; bool load_stubs = false; bool netfix_disable = false; bool lang_disable = false; std::string process_priority_str = "high"; bool cardio_enabled = false; bool peb_print = false; bool cfg_run = false; bool rich_presence = false; bool automap = false; bool ssl_disable = false; std::vector sextet_devices; // parse arguments LAUNCHER_OPTIONS = launcher::parse_options(argc, argv); // determine config file path - must be done before anything else const auto &cfg_path = LAUNCHER_OPTIONS->at(launcher::Options::ConfigurationPath); if (cfg_path.is_active()) { CONFIG_PATH_OVERRIDE = cfg_path.value_text(); } // detect model used to load option overrides auto options_version = launcher::detect_gameversion( LAUNCHER_OPTIONS->at(launcher::Options::PathToEa3Config).value ); if (!options_version.model.empty() && options_version.model.size() < 4) { if (options_version.dest.size() == 1) { avs::game::DEST[0] = options_version.dest[0]; } if (options_version.spec.size() == 1) { avs::game::SPEC[0] = options_version.spec[0]; } if (options_version.rev.size() == 1) { avs::game::REV[0] = options_version.rev[0]; } if (options_version.ext.size() == 10) { strcpy(avs::game::EXT, options_version.ext.c_str()); } strcpy(avs::game::MODEL, options_version.model.c_str()); eamuse_autodetect_game(); } // grab merged game options auto options_ptr = games::get_options(eamuse_get_game()); if (!options_ptr) { options_ptr = LAUNCHER_OPTIONS.get(); } auto &options = *options_ptr; // check options // TODO: get rid of some booleans here and make use of the options directly if (options[launcher::Options::OpenConfigurator].value_bool()) { CHECK_DLL_IGNORE_ARCH = true; cfg::CONFIGURATOR_TYPE = cfg::ConfigType::Config; cfg_run = true; } if (options[launcher::Options::OpenKFControl].value_bool()) { CHECK_DLL_IGNORE_ARCH = true; cfg::CONFIGURATOR_TYPE = cfg::ConfigType::KFControl; cfg_run = true; } if (options[launcher::Options::EAmusementEmulation].value_bool() && options[launcher::Options::ServiceURL].is_active() && !cfg::CONFIGURATOR_STANDALONE) { log_fatal( "launcher", "BAD EAMUSE SETTINGS ERROR\n\n\n" "-------------------------------------------------------------------\n" "WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING\n" "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" "A service URL is set **AND** E-Amusement emulation is enabled.\n" "Either remove the service URL, or disable E-Amusement emulation.\n" "Otherwise you may experience problems logging in.\n" "-------------------------------------------------------------------\n\n\n" ); } if (options[launcher::Options::EAmusementEmulation].value_bool()) { avs::ea3::URL_SLASH = 1; easrv_port = 8080; } if (options[launcher::Options::SmartEAmusement].value_bool()) { easrv_smart = true; } if (options[launcher::Options::EAmusementMaintenance].is_active()) { easrv_maint = options[launcher::Options::EAmusementMaintenance].value_uint32() > 0; } if (options[launcher::Options::spice2x_EAmusementMaintenance].value_bool()) { easrv_maint = true; } if (options[launcher::Options::WindowedMode].value_bool()) { GRAPHICS_WINDOWED = true; } if (options[launcher::Options::GraphicsForceRefresh].is_active()) { GRAPHICS_FORCE_REFRESH = options[launcher::Options::GraphicsForceRefresh].value_uint32(); } if (options[launcher::Options::GraphicsForceSingleAdapter].value_bool()) { GRAPHICS_FORCE_SINGLE_ADAPTER = true; } if (options[launcher::Options::spice2x_IIDXNoSub].value_bool()) { GRAPHICS_FORCE_SINGLE_ADAPTER = true; } if (options[launcher::Options::spice2x_SDVXNoSub].value_bool()) { GRAPHICS_FORCE_SINGLE_ADAPTER = true; GRAPHICS_PREVENT_SECONDARY_WINDOW = true; } if (options[launcher::Options::DisplayAdapter].is_active()) { D3D9_ADAPTER = options[launcher::Options::DisplayAdapter].value_uint32(); } if (options[launcher::Options::CaptureCursor].value_bool()) { GRAPHICS_CAPTURE_CURSOR = true; } if (options[launcher::Options::ShowCursor].value_bool()) { GRAPHICS_SHOW_CURSOR = true; } if (options[launcher::Options::VerboseGraphicsLogging].value_bool()) { GRAPHICS_LOG_HRESULT = true; } if (options[launcher::Options::VerboseAVSLogging].value_bool()) { hooks::avs::config::LOG = true; } if (options[launcher::Options::spice2x_AutoOrientation].is_active()) { GRAPHICS_ADJUST_ORIENTATION = (graphics_orientation)options[launcher::Options::spice2x_AutoOrientation].value_uint32(); } else if (options[launcher::Options::AdjustOrientation].value_bool()) { GRAPHICS_ADJUST_ORIENTATION = ORIENTATION_CW; } if (options[launcher::Options::spice2x_NoD3D9DeviceHook].value_bool()) { D3D9_DEVICE_HOOK_DISABLE = true; // touch emulation gets disabled, might as well turn these on games::iidx::NATIVE_TOUCH = true; games::sdvx::NATIVETOUCH = true; // not strictly necessary as it will fail to init anyway, but cleaner to just disable it now overlay::ENABLED = false; // leaving these on without dx9hooks result in torn state and therefore failure to draw GRAPHICS_FORCE_SINGLE_ADAPTER = false; } if (options[launcher::Options::spice2x_NvapiProfile].value_bool() && !cfg::CONFIGURATOR_STANDALONE) { nvapi::ADD_PROFILE = true; } if (options[launcher::Options::spice2x_NoNVAPI].value_bool()) { nvapi_hook::BYPASS_NVAPI = true; } if (options[launcher::Options::LogLevel].is_active()) { avs::core::LOG_LEVEL_CUSTOM = options[launcher::Options::LogLevel].value_text(); } for (auto &hook : options[launcher::Options::InjectHook].values_text()) { std::string buffer; std::stringstream stream(hook); std::vector tokens; while (stream >> buffer) { game_hooks.push_back(buffer); } } if (options[launcher::Options::LoadStubs].value_bool()) { load_stubs = true; } if (options[launcher::Options::EnableAllIOModules].value_bool()) { attach_io = true; } if (options[launcher::Options::EnableACIOModule].value_bool()) { attach_acio = true; } if (options[launcher::Options::EnableICCAModule].value_bool()) { attach_icca = true; } if (options[launcher::Options::EnableDEVICEModule].value_bool()) { attach_device = true; } if (options[launcher::Options::EnableEXTDEVModule].value_bool()) { attach_extdev = true; } if (options[launcher::Options::EnableSCIUNITModule].value_bool()) { attach_sciunit = true; } if (options[launcher::Options::EnableDevicePassthrough].value_bool()) { hooks::device::ENABLE = false; } if (options[launcher::Options::LoadSoundVoltexModule].value_bool()) { attach_sdvx = true; } if (options[launcher::Options::SDVXDisableCameras].value_bool()) { games::sdvx::DISABLECAMS = true; } if (options[launcher::Options::SDVXNativeTouch].value_bool()) { games::sdvx::NATIVETOUCH = true; } if (options[launcher::Options::spice2x_SDVXDigitalKnobSensitivity].is_active()) { games::sdvx::DIGITAL_KNOB_SENS = (uint8_t) options[launcher::Options::spice2x_SDVXDigitalKnobSensitivity].value_uint32(); } if (options[launcher::Options::spice2x_SDVXAsioDriver].is_active()) { games::sdvx::ASIO_DRIVER = options[launcher::Options::spice2x_SDVXAsioDriver].value_text(); } if (options[launcher::Options::spice2x_SDVXSubPos].is_active()) { auto txt = options[launcher::Options::spice2x_SDVXSubPos].value_text(); if (txt == "top") { games::sdvx::OVERLAY_POS = games::sdvx::SDVX_OVERLAY_TOP; } else if (txt == "center") { games::sdvx::OVERLAY_POS = games::sdvx::SDVX_OVERLAY_MIDDLE; } } if (options[launcher::Options::spice2x_SDVXSubRedraw].value_bool()) { SUBSCREEN_FORCE_REDRAW = true; } if (options[launcher::Options::LoadIIDXModule].value_bool()) { attach_iidx = true; } if (options[launcher::Options::IIDXCameraOrderFlip].value_bool()) { games::iidx::FLIP_CAMS = true; } if (options[launcher::Options::IIDXDisableCameras].value_bool()) { games::iidx::DISABLE_CAMS = true; } if (options[launcher::Options::IIDXTDJCamera].value_bool()) { games::iidx::TDJ_CAMERA = true; // Disable legacy behaviour to avoid conflict games::iidx::DISABLE_CAMS = true; } if (options[launcher::Options::IIDXTDJCameraOverride].is_active()) { games::iidx::TDJ_CAMERA_OVERRIDE = options[launcher::Options::IIDXTDJCameraOverride].value_text(); } if (options[launcher::Options::IIDXTDJCameraRatio].is_active() && options[launcher::Options::IIDXTDJCameraRatio].value_text() == "169") { games::iidx::TDJ_CAMERA_PREFER_16_9 = true; } if (options[launcher::Options::IIDXSoundOutputDevice].is_active()) { games::iidx::SOUND_OUTPUT_DEVICE = options[launcher::Options::IIDXSoundOutputDevice].value_text(); } if (options[launcher::Options::IIDXAsioDriver].is_active()) { games::iidx::ASIO_DRIVER = options[launcher::Options::IIDXAsioDriver].value_text(); } if (options[launcher::Options::IIDXTDJMode].value_bool()) { games::iidx::TDJ_MODE = true; } if (options[launcher::Options::spice2x_IIDXDigitalTTSensitivity].is_active()) { games::iidx::DIGITAL_TT_SENS = (uint8_t) options[launcher::Options::spice2x_IIDXDigitalTTSensitivity].value_uint32(); } if (options[launcher::Options::spice2x_IIDXLDJForce720p].value_bool()) { games::iidx::FORCE_720P = true; } if (options[launcher::Options::spice2x_IIDXTDJSubSize].is_active()) { games::iidx::SUBSCREEN_OVERLAY_SIZE = options[launcher::Options::spice2x_IIDXTDJSubSize].value_text(); } if (options[launcher::Options::spice2x_IIDXLEDFontSize].is_active()) { overlay::windows::IIDX_SEGMENT_FONT_SIZE = options[launcher::Options::spice2x_IIDXLEDFontSize].value_uint32(); } if (options[launcher::Options::spice2x_IIDXLEDColor].is_active()) { overlay::windows::IIDX_SEGMENT_FONT_COLOR = options[launcher::Options::spice2x_IIDXLEDColor].value_hex64(); } if (options[launcher::Options::spice2x_IIDXLEDPos].is_active()) { overlay::windows::IIDX_SEGMENT_LOCATION = options[launcher::Options::spice2x_IIDXLEDPos].value_text(); } if (options[launcher::Options::spice2x_IIDXNoESpec].value_bool()) { games::iidx::DISABLE_ESPEC_IO = true; } if (options[launcher::Options::spice2x_IIDXNativeTouch].value_bool()) { games::iidx::NATIVE_TOUCH = true; } // should come later since this will override a few settings if (options[launcher::Options::spice2x_IIDXWindowedTDJ].value_bool() || (options[launcher::Options::IIDXTDJMode].value_bool() && GRAPHICS_WINDOWED)) { games::iidx::TDJ_MODE = true; GRAPHICS_WINDOWED = true; games::iidx::SCREEN_MODE = "2"; } if (options[launcher::Options::LoadJubeatModule].value_bool()) { attach_jb = true; } if (options[launcher::Options::LoadBeatstreamModule].value_bool()) { attach_bs = true; } if (options[launcher::Options::LoadReflecBeatModule].value_bool()) { attach_rb = true; } if (options[launcher::Options::LoadShogikaiModule].value_bool()) { attach_shogikai = true; } if (options[launcher::Options::LoadPopnMusicModule].value_bool()) { attach_popn = true; } if (options[launcher::Options::PopnMusicForceHDMode].value_bool()) { avs::ea3::PCB_TYPE = 1; } if (options[launcher::Options::PopnMusicForceSDMode].value_bool()) { avs::ea3::PCB_TYPE = 0; } if (options[launcher::Options::LoadMetalGearArcadeModule].value_bool()) { attach_mga = true; } if (options[launcher::Options::LoadGitaDoraModule].value_bool()) { attach_gitadora = true; } if (options[launcher::Options::GitaDoraCabinetType].is_active()) { games::gitadora::CAB_TYPE = options[launcher::Options::GitaDoraCabinetType].value_uint32(); } if (options[launcher::Options::LoadNostalgiaModule].value_bool()) { attach_nostalgia = true; } if (options[launcher::Options::LoadBBCModule].value_bool()) { attach_bbc = true; } if (options[launcher::Options::LoadHelloPopnMusicModule].value_bool()) { attach_hpm = true; } if (options[launcher::Options::LoadQuizMagicAcademyModule].value_bool()) { attach_qma = true; } if (options[launcher::Options::LoadDanceEvolutionModule].value_bool()) { attach_dea = true; } if (options[launcher::Options::LoadLovePlusModule].value_bool()) { attach_loveplus = true; } if (options[launcher::Options::GitaDoraTwoChannelAudio].value_bool()) { games::gitadora::TWOCHANNEL = true; } if (options[launcher::Options::LoadDDRModule].value_bool()) { attach_ddr = true; } if (options[launcher::Options::LoadMahjongFightClubModule].value_bool()) { attach_mfc = true; } if (options[launcher::Options::LoadFutureTomTomModule].value_bool()) { attach_ftt = true; } if (options[launcher::Options::LoadScottoModule].value_bool()) { attach_scotto = true; } if (options[launcher::Options::LoadRoadFighters3DModule].value_bool()) { attach_rf3d = true; } if (options[launcher::Options::LoadDanceRushModule].value_bool()) { attach_drs = true; } if (options[launcher::Options::LoadWinningElevenModule].value_bool()) { attach_we = true; } if (options[launcher::Options::LoadOtocaModule].value_bool()) { attach_otoca = true; } if (options[launcher::Options::LoadChargeMachineModule].value_bool()) { attach_pcm = true; } if (options[launcher::Options::LoadOngakuParadiseModule].value_bool()) { attach_onpara = true; } if (options[launcher::Options::LoadBusouShinkiModule].value_bool()) { attach_bc = true; } if (options[launcher::Options::LoadCCJModule].value_bool()) { attach_ccj = true; } if (options[launcher::Options::LoadQKSModule].value_bool()) { attach_qks = true; } if (options[launcher::Options::LoadMusecaModule].value_bool()) { attach_museca = true; } if (options[launcher::Options::DDR43Mode].value_bool()) { games::ddr::SDMODE = true; } if (options[launcher::Options::LoadSteelChronicleModule].value_bool()) { attach_sc = true; } if (options[launcher::Options::DisableNetworkFixes].value_bool()) { netfix_disable = true; } if (options[launcher::Options::DisableACPHook].value_bool()) { lang_disable = true; } if (options[launcher::Options::DisableSignalHandling].value_bool()) { launcher::signal::DISABLE = true; } if (options[launcher::Options::DebugCreateFile].value_bool()) { DEVICE_CREATEFILE_DEBUG = true; } if (options[launcher::Options::BlockingLogger].value_bool()) { logger::BLOCKING = true; } if (options[launcher::Options::OutputPEB].value_bool()) { peb_print = true; } if (options[launcher::Options::EnableBemaniTools5API].value_bool()) { BT5API_ENABLED = true; } if (options[launcher::Options::CardIOHIDReaderSupport].value_bool()) { cardio_enabled = true; } if (options[launcher::Options::SDVXPrinterEmulation].value_bool()) { attach_cpusbxpkm_printer = true; } if (options[launcher::Options::SDVXPrinterOutputOverwrite].value_bool()) { games::shared::PRINTER_OVERWRITE_FILE = true; } for (auto &path : options[launcher::Options::SDVXPrinterOutputPath].values_text()) { games::shared::PRINTER_PATH.push_back(path); } for (auto &path : options[launcher::Options::SDVXPrinterOutputFormat].values_text()) { games::shared::PRINTER_FORMAT.push_back(path); } if (options[launcher::Options::SDVXPrinterJPGQuality].is_active()) { games::shared::PRINTER_JPG_QUALITY = options[launcher::Options::SDVXPrinterJPGQuality].value_uint32(); } if (options[launcher::Options::SDVXPrinterOutputClear].value_bool()) { games::shared::PRINTER_CLEAR = true; } if (options[launcher::Options::HTTP11].is_active()) { avs::ea3::HTTP11 = options[launcher::Options::HTTP11].value_uint32(); } if (options[launcher::Options::DisableSSL].value_bool()) { ssl_disable = true; } if (options[launcher::Options::URLSlash].is_active()) { avs::ea3::URL_SLASH = options[launcher::Options::URLSlash].value_uint32(); } if (options[launcher::Options::spice2x_ProcessPriority].is_active()) { process_priority_str = options[launcher::Options::spice2x_ProcessPriority].value_text(); } else if (options[launcher::Options::RealtimeProcessPriority].value_bool()) { process_priority_str = "realtime"; } if (options[launcher::Options::HeapSize].is_active()) { user_heap_size = options[launcher::Options::HeapSize].value_uint32(); } if (options[launcher::Options::DisableAvsVfsDriveMountRedirection].is_active()) { hooks::avs::config::DISABLE_VFS_DRIVE_REDIRECTION = true; } if (options[launcher::Options::ScreenResizeConfigPath].is_active()) { cfg::SCREEN_RESIZE_CFG_PATH_OVERRIDE = options[launcher::Options::ScreenResizeConfigPath].value_text(); } if (options[launcher::Options::PathToAppConfig].is_active()) { avs::ea3::APP_PATH = options[launcher::Options::PathToAppConfig].value_text(); } if (options[launcher::Options::PathToAvsConfig].is_active()) { avs::core::CFG_PATH = options[launcher::Options::PathToAvsConfig].value_text(); } if (options[launcher::Options::PathToEa3Config].is_active()) { avs::ea3::CFG_PATH = options[launcher::Options::PathToEa3Config].value_text(); } if (options[launcher::Options::PathToBootstrap].is_active()) { avs::ea3::BOOTSTRAP_PATH = options[launcher::Options::PathToBootstrap].value_text(); } if (options[launcher::Options::PathToLog].is_active()) { avs::core::LOG_PATH = options[launcher::Options::PathToLog].value_text(); } if (options[launcher::Options::PCBID].is_active()) { avs::ea3::PCBID_CUSTOM = options[launcher::Options::PCBID].value_text(); } if (options[launcher::Options::SOFTID].is_active()) { avs::ea3::SOFTID_CUSTOM = options[launcher::Options::SOFTID].value_text(); } if (options[launcher::Options::ServiceURL].is_active()) { avs::ea3::URL_CUSTOM = options[launcher::Options::ServiceURL].value_text(); } if (options[launcher::Options::PathToModules].is_active()) { std::error_code err; auto &path = options[launcher::Options::PathToModules].value_text(); auto module_path = std::filesystem::absolute(path, err); if (err) { if (cfg::CONFIGURATOR_STANDALONE) { log_warning("launcher", "failed to resolve module path '{}': {}", path, err.message()); } else { log_fatal("launcher", "failed to resolve module path '{}': {}", path, err.message()); } } MODULE_PATH = std::move(module_path); SetDllDirectoryW(MODULE_PATH.c_str()); } if (options[launcher::Options::Player1Card].is_active()) { CARD_OVERRIDES[0] = options[launcher::Options::Player1Card].value_text(); } if (options[launcher::Options::Player2Card].is_active()) { CARD_OVERRIDES[1] = options[launcher::Options::Player2Card].value_text(); } for (auto &reader : options[launcher::Options::ICCAReaderPort].values_text()) { static int reader_id = 0; if (reader_id < 2) { start_reader_thread(reader, reader_id++); } else { if (!cfg::CONFIGURATOR_STANDALONE) { log_fatal("launcher", "too many readers specified (maximum is 2)"); } break; } } for (auto &sextet : options[launcher::Options::SextetStreamPort].values_text()) { sextet_devices.emplace_back(sextet); } if (options[launcher::Options::HIDSmartCard].value_bool()) { WINSCARD_CONFIG.cardinfo_callback = eamuse_scard_callback; scard_threadstart(); } if (options[launcher::Options::HIDSmartCardOrderFlip].value_bool()) { WINSCARD_CONFIG.flip_order = true; } if (options[launcher::Options::HIDSmartCardOrderToggle].value_bool()) { WINSCARD_CONFIG.toggle_order = true; } if (options[launcher::Options::CardIOHIDReaderOrderFlip].value_bool()) { CARDIO_RUNNER_FLIP = true; } if (options[launcher::Options::CardIOHIDReaderOrderToggle].value_bool()) { CARDIO_RUNNER_TOGGLE = true; } if (options[launcher::Options::ICCAReaderPortToggle].is_active()) { start_reader_thread(options[launcher::Options::ICCAReaderPortToggle].value_text(), -1); } if (options[launcher::Options::IntelSDEFolder].is_active()) { sde_init(options[launcher::Options::IntelSDEFolder].value_text()); } if (options[launcher::Options::AdapterNetwork].is_active()) { NETWORK_ADDRESS = options[launcher::Options::AdapterNetwork].value_text(); } if (options[launcher::Options::AdapterSubnet].is_active()) { NETWORK_SUBNET = options[launcher::Options::AdapterSubnet].value_text(); } if (options[launcher::Options::APITCPPort].is_active()) { api_enable = true; api_port = options[launcher::Options::APITCPPort].value_uint32(); } if (options[launcher::Options::APIPassword].is_active()) { api_pass = options[launcher::Options::APIPassword].value_text(); } if (options[launcher::Options::APISerialPort].is_active()) { api_serial_port.push_back(options[launcher::Options::APISerialPort].value_text()); } if (options[launcher::Options::APISerialBaud].is_active()) { api_serial_baud.push_back(options[launcher::Options::APISerialBaud].value_uint32()); } if (options[launcher::Options::APIPretty].value_bool()) { api_pretty = true; } if (options[launcher::Options::APIVerboseLogging].value_bool()) { api::LOGGING = true; } if (options[launcher::Options::APIDebugMode].value_bool()) { api_debug = true; } if (options[launcher::Options::DisableDebugHooks].value_bool()) { debughook::DEBUGHOOK_LOGGING = false; } if (options[launcher::Options::ForceWinTouch].value_bool()) { rawinput::touch::DISABLED = true; } if (options[launcher::Options::SDVXForce720p].value_bool()) { GRAPHICS_SDVX_FORCE_720 = true; } if (options[launcher::Options::InvertTouchCoordinates].value_bool()) { rawinput::touch::INVERTED = true; } // DisableTouchCardInsert is no longer honored in spice2x // if (options[launcher::Options::DisableTouchCardInsert].value_bool()) { // SPICETOUCH_CARD_DISABLE = true; // } if (options[launcher::Options::spice2x_TouchCardInsert].value_bool()) { SPICETOUCH_CARD_DISABLE = false; } if (options[launcher::Options::ForceTouchEmulation].value_bool()) { wintouchemu::FORCE = true; } if (options[launcher::Options::Graphics9On12].value_bool()) { GRAPHICS_9_ON_12_STATE = DX9ON12_FORCE_ON; } if (options[launcher::Options::spice2x_Dx9On12].is_active()) { auto &name = options[launcher::Options::spice2x_Dx9On12].value_text(); if (name == "0") { GRAPHICS_9_ON_12_STATE = DX9ON12_FORCE_OFF; } else if (name == "1") { GRAPHICS_9_ON_12_STATE = DX9ON12_FORCE_ON; } // do not explicitly set GRAPHICS_9_ON_12_STATE to default here; must respect // legacy Graphics9On12 option from above if set } if (options[launcher::Options::NoLegacy].value_bool() && !cfg::CONFIGURATOR_STANDALONE) { rawinput::NOLEGACY = true; } if (options[launcher::Options::RichPresence].value_bool()) { rich_presence = true; } if (options[launcher::Options::DiscordAppID].is_active()) { richpresence::discord::APPID_OVERRIDE = options[launcher::Options::DiscordAppID].value_text(); } if (options[launcher::Options::ScreenshotFolder].is_active()) { GRAPHICS_SCREENSHOT_DIR = options[launcher::Options::ScreenshotFolder].value_text(); } if (options[launcher::Options::DisableColoredOutput].value_bool()) { logger::COLOR = false; } if (options[launcher::Options::DisableOverlay].value_bool()) { overlay::ENABLED = false; } if (options[launcher::Options::DisableAudioHooks].value_bool()) { hooks::audio::ENABLED = false; } if (options[launcher::Options::spice2x_DisableVolumeHook].value_bool()) { hooks::audio::VOLUME_HOOK_ENABLED = false; } if (options[launcher::Options::AudioBackend].is_active()) { auto &name = options[launcher::Options::AudioBackend].value_text(); auto backend = hooks::audio::name_to_backend(name.c_str()); if (!backend.has_value() && !cfg::CONFIGURATOR_STANDALONE) { log_fatal("launcher", "invalid audio backend: {}", name); } hooks::audio::BACKEND = backend; } if (options[launcher::Options::AsioDriverId].is_active()) { hooks::audio::ASIO_DRIVER_ID = options[launcher::Options::AsioDriverId].value_uint32(); } if (options[launcher::Options::AudioDummy].value_bool()) { hooks::audio::USE_DUMMY = true; } if (options[launcher::Options::EAAutomap].value_bool()) { easrv_maint = false; automap = true; avs::automap::ENABLED = true; avs::automap::PATCH = true; avs::automap::RESTRICT_NETWORK = true; avs::automap::DUMP = true; } if (options[launcher::Options::EANetdump].value_bool()) { easrv_maint = false; automap = true; avs::automap::ENABLED = true; avs::automap::PATCH = false; avs::automap::RESTRICT_NETWORK = true; avs::automap::DUMP = true; } if (options[launcher::Options::GameExecutable].is_active()) { avs::game::DLL_NAME = options[launcher::Options::GameExecutable].value_text(); } if (options[launcher::Options::spice2x_LightsOverallBrightness].is_active()) { rawinput::HID_LIGHT_BRIGHTNESS = (uint8_t)options[launcher::Options::spice2x_LightsOverallBrightness].value_uint32(); } if (options[launcher::Options::spice2x_FpsAutoShow].value_bool()) { overlay::AUTO_SHOW_FPS = true; } if (options[launcher::Options::spice2x_SubScreenAutoShow].value_bool()) { overlay::AUTO_SHOW_SUBSCREEN = true; } if (options[launcher::Options::spice2x_IOPanelAutoShow].value_bool()) { overlay::AUTO_SHOW_IOPANEL = true; } if (options[launcher::Options::spice2x_KeypadAutoShow].is_active()) { auto s = options[launcher::Options::spice2x_KeypadAutoShow].value_uint32(); switch (s) { case 1: overlay::AUTO_SHOW_KEYPAD_P1 = true; break; case 2: overlay::AUTO_SHOW_KEYPAD_P2 = true; break; case 3: overlay::AUTO_SHOW_KEYPAD_P1 = true; overlay::AUTO_SHOW_KEYPAD_P2 = true; break; } } if (options[launcher::Options::spice2x_WindowBorder].is_active()) { GRAPHICS_WINDOW_STYLE = options[launcher::Options::spice2x_WindowBorder].value_uint32(); } if (options[launcher::Options::spice2x_WindowSize].is_active()) { GRAPHICS_WINDOW_SIZE = options[launcher::Options::spice2x_WindowSize].value_text(); } if (options[launcher::Options::spice2x_WindowPosition].is_active()) { GRAPHICS_WINDOW_POS = options[launcher::Options::spice2x_WindowPosition].value_text(); } GRAPHICS_WINDOW_ALWAYS_ON_TOP = options[launcher::Options::spice2x_WindowAlwaysOnTop].value_bool(); // IIDX Windowed Subscreen if (options[launcher::Options::spice2x_IIDXWindowedSubscreenSize].is_active()) { GRAPHICS_IIDX_WSUB_SIZE = options[launcher::Options::spice2x_IIDXWindowedSubscreenSize].value_text(); } if (options[launcher::Options::spice2x_IIDXWindowedSubscreenPosition].is_active()) { GRAPHICS_IIDX_WSUB_POS = options[launcher::Options::spice2x_IIDXWindowedSubscreenPosition].value_text(); } if (options[launcher::Options::spice2x_JubeatLegacyTouch].value_bool()) { games::jb::TOUCH_LEGACY_BOX = true; } if (options[launcher::Options::spice2x_RBTouchScale].is_active()) { games::rb::TOUCH_SCALING = options[launcher::Options::spice2x_RBTouchScale].value_uint32(); } if (options[launcher::Options::spice2x_AsioForceUnload].value_bool()) { hooks::audio::ASIO_FORCE_UNLOAD_ON_STOP = true; } if (options[launcher::Options::spice2x_DRSDisableTouch].value_bool()) { games::drs::DISABLE_TOUCH = true; } if (options[launcher::Options::spice2x_DRSTransposeTouch].value_bool()) { games::drs::TRANSPOSE_TOUCH = true; } if (options[launcher::Options::spice2x_AutoCard].is_active()) { const auto text = options[launcher::Options::spice2x_AutoCard].value_text(); if (text == "p1") { AUTO_INSERT_CARD[0] = true; } else if (text == "p2") { AUTO_INSERT_CARD[1] = true; } else if (text == "both") { AUTO_INSERT_CARD[0] = true; AUTO_INSERT_CARD[1] = true; } } if (options[launcher::Options::spice2x_LowLatencySharedAudio].value_bool()) { hooks::audio::LOW_LATENCY_SHARED_WASAPI = true; } if (options[launcher::Options::spice2x_TapeLedAlgorithm].is_active()) { const auto text = options[launcher::Options::spice2x_TapeLedAlgorithm].value_text(); if (text == "off") { tapeledutils::TAPE_LED_ALGORITHM = tapeledutils::TAPE_LED_USE_NONE; } else if (text == "avg") { tapeledutils::TAPE_LED_ALGORITHM = tapeledutils::TAPE_LED_USE_AVERAGE; } else if (text == "first") { tapeledutils::TAPE_LED_ALGORITHM = tapeledutils::TAPE_LED_USE_FIRST; } else if (text == "last") { tapeledutils::TAPE_LED_ALGORITHM = tapeledutils::TAPE_LED_USE_LAST; } } if (options[launcher::Options::CCJTrackballSensitivity].is_active()) { games::ccj::TRACKBALL_SENSITIVITY = (uint8_t) options[launcher::Options::CCJTrackballSensitivity].value_uint32(); } if (options[launcher::Options::CCJMouseTrackball].value_bool()) { games::ccj::MOUSE_TRACKBALL = true; } if (options[launcher::Options::CCJMouseTrackballWithToggle].value_bool()) { games::ccj::MOUSE_TRACKBALL_USE_TOGGLE = true; } if (options[launcher::Options::CCJArgs].is_active()) { games::ccj::CCJ_INJECT_ARGS = options[launcher::Options::CCJArgs].value_text(); } if (options[launcher::Options::QKSArgs].is_active()) { games::qks::QKS_INJECT_ARGS = options[launcher::Options::QKSArgs].value_text(); } if (options[launcher::Options::spice2x_EnableSMXStage].value_bool()) { rawinput::ENABLE_SMX_STAGE = true; } // API debugging if (api_debug && !cfg::CONFIGURATOR_STANDALONE) { API_CONTROLLER = std::make_unique(api_port, api_pass, api_pretty); for (size_t i = 0; i < std::min(api_serial_port.size(), api_serial_baud.size()); i++) { API_CONTROLLER->listen_serial(api_serial_port[i], api_serial_baud[i]); } if (cfg_run) { exit(spicecfg_run(sextet_devices)); } else { while (API_CONTROLLER->server_running) { Sleep(100); } } log_fatal("launcher", "API server stopped"); } // delay if (!cfg::CONFIGURATOR_STANDALONE) { DWORD delayInSeconds = 0; if (options[launcher::Options::spice2x_DelayByNSeconds].is_active()) { delayInSeconds = (DWORD)options[launcher::Options::spice2x_DelayByNSeconds].value_uint32(); } else if (options[launcher::Options::DelayBy5Seconds].value_bool()) { delayInSeconds = 5; } if (0 < delayInSeconds) { log_info("launcher", "delay by {}ms...", delayInSeconds * 1000); Sleep(delayInSeconds * 1000); } } // create log file // configurator does not write a log file because it tends to cause the // config file to be corrupt... if (!cfg::CONFIGURATOR_STANDALONE) { avs::core::create_log(); } // log #ifdef SPICE64 log_info("launcher", "SpiceTools Bootstrap (x64) (spice2x)"); #else log_info("launcher", "SpiceTools Bootstrap (x32) (spice2x)"); #endif log_info("launcher", "{}", VERSION_STRING); // log command line arguments std::ostringstream arguments; for (auto &root_option : options) { std::vector