mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
ef384e85dd
## Link to GitHub Issue or related Pull Request, if one exists N/A ## Description of change Adds GITADORA Arena windowed monitor layout options for the GITADORA, LEFT, RIGHT, and SMALL windows. This also applies the selected window border style to all four GITADORA Arena windows, and allows the SMALL touch window to be resized in windowed mode while keeping touch coordinates updated. ## Testing - Manually tested GITADORA Arena windowed mode: - default, resizable, and borderless window styles - per-window monitor placement - SMALL resize - SMALL touch coordinate mapping after resize
2814 lines
100 KiB
C++
2814 lines
100 KiB
C++
#include <condition_variable>
|
|
#include <iostream>
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
#include <assert.h>
|
|
#include <shlwapi.h>
|
|
#include <windows.h>
|
|
#include <cfg/configurator.h>
|
|
|
|
#include "api/modules/capture.h"
|
|
#include "acio/acio.h"
|
|
#include "acio/icca/icca.h"
|
|
#include "acio/mdxf/mdxf.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"
|
|
#ifndef NO_SCARD
|
|
#include "external/scard/scard.h"
|
|
#endif
|
|
#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/nost/poke.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/mfg/mfg.h"
|
|
#include "games/pc/pc.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/graphics/nvenc_hook.h"
|
|
#include "hooks/input/dinput8/hook.h"
|
|
#include "hooks/graphics/graphics.h"
|
|
#include "hooks/lang.h"
|
|
#include "hooks/networkhook.h"
|
|
#include "hooks/icmphook_net.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 "misc/bt5api.h"
|
|
#include "misc/device.h"
|
|
#include "misc/eamuse.h"
|
|
#include "misc/extdev.h"
|
|
#include "misc/ami2000.h"
|
|
#include "misc/sciunit.h"
|
|
#include "misc/sde.h"
|
|
#include "misc/wintouchemu.h"
|
|
#include "overlay/overlay.h"
|
|
#include "overlay/notifications.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 "sdk/sdk.h"
|
|
#include "stubs/stubs.h"
|
|
#include "touch/touch.h"
|
|
#include "util/cpuutils.h"
|
|
#include "util/crypt.h"
|
|
#include "util/deferlog.h"
|
|
#include "util/fileutils.h"
|
|
#include "util/libutils.h"
|
|
#include "util/logging.h"
|
|
#include "util/peb.h"
|
|
#include "util/precise_timer.h"
|
|
#include "util/socd_cleaner.h"
|
|
#include "util/sysutils.h"
|
|
#include "util/tapeled.h"
|
|
#include "util/time.h"
|
|
#include "util/utils.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<std::string> game_hooks;
|
|
static std::vector<std::string> early_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<std::vector<Option>> LAUNCHER_OPTIONS;
|
|
|
|
std::mutex CARD_OVERRIDES_LOCK;
|
|
std::string CARD_OVERRIDES[2];
|
|
|
|
// sub-systems
|
|
std::unique_ptr<api::Controller> API_CONTROLLER;
|
|
std::unique_ptr<rawinput::RawInputManager> 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);
|
|
}
|
|
}
|
|
|
|
void update_msvcrt_args(int argc, char *argv[]);
|
|
|
|
void dump_button_bindings(std::vector<Button> *buttons);
|
|
void dump_analog_bindings();
|
|
|
|
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<std::string> api_serial_port;
|
|
std::vector<DWORD> 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_ami2000 = 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_mfg = false;
|
|
bool attach_pc = false;
|
|
bool attach_museca = false;
|
|
bool show_cursor_if_no_touch = 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 icmphook_enable = 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;
|
|
bool dump_sysinfo = true;
|
|
std::vector<std::string> sextet_devices;
|
|
std::optional<rawinput::MidiNoteAlgorithm> midi_algo;
|
|
|
|
// parse arguments
|
|
LAUNCHER_OPTIONS = launcher::parse_options(argc, argv);
|
|
|
|
// command line override (must be done before merging options with cfg)
|
|
if (LAUNCHER_OPTIONS->at(launcher::Options::OptionConflictResolution).value_bool()) {
|
|
launcher::USE_CMD_OVERRIDE = true;
|
|
}
|
|
|
|
// 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,
|
|
LAUNCHER_OPTIONS->at(launcher::Options::PathToBootstrap).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;
|
|
|
|
#if !SPICE_XP
|
|
|
|
{
|
|
// skip elevation only if AutoElevate is explicitly set to "user"
|
|
const bool skip_elevation = options[launcher::Options::AutoElevate].is_active() &&
|
|
options[launcher::Options::AutoElevate].value_text() == "user";
|
|
if (!skip_elevation && !sysutils::is_running_as_admin()) {
|
|
log_info("launcher", "relaunching with administrator privileges");
|
|
if (sysutils::relaunch_as_admin()) {
|
|
exit(0);
|
|
} else {
|
|
// elevation failed or was denied by the user
|
|
log_fatal("launcher", "failed to launch with administrator privileges");
|
|
exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif // !SPICE_XP
|
|
|
|
// 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;
|
|
}
|
|
|
|
// -ea, but ignored if -url is set
|
|
if (options[launcher::Options::EAmusementEmulation].value_bool() &&
|
|
!options[launcher::Options::ServiceURL].is_active()) {
|
|
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::FullscreenSubRefreshRate].is_active()) {
|
|
GRAPHICS_FORCE_REFRESH_SUB =
|
|
options[launcher::Options::FullscreenSubRefreshRate].value_uint32();
|
|
}
|
|
if (options[launcher::Options::GraphicsForceSingleAdapter].value_bool()) {
|
|
GRAPHICS_FORCE_SINGLE_ADAPTER = true;
|
|
}
|
|
if (options[launcher::Options::ForceBackBufferCount].is_active()) {
|
|
const auto n = options[launcher::Options::ForceBackBufferCount].value_uint32();
|
|
if (n == 2 || n == 3) {
|
|
// user provided 2 => double buffering => 1 back buffer
|
|
// user provided 3 => triple buffering => 2 back buffers
|
|
GRAPHICS_FORCE_VSYNC_BUFFER = n - 1;
|
|
} else {
|
|
log_warning("graphics", "invalid parameter specified for -vsyncbuffer: {}", n);
|
|
}
|
|
}
|
|
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_WINDOWS = true;
|
|
}
|
|
if (options[launcher::Options::DXDisplayAdapter].is_active() &&
|
|
options[launcher::Options::DXDisplayAdapter].value_uint32() != D3DADAPTER_DEFAULT) {
|
|
D3D9_ADAPTER = options[launcher::Options::DXDisplayAdapter].value_uint32();
|
|
|
|
// when we fix up adapter numbers, we only fix the first adapter, and not any subsequent
|
|
// adapters, so we can't deal with multi-monitor games
|
|
GRAPHICS_FORCE_SINGLE_ADAPTER = true;
|
|
}
|
|
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::AllowEA3Verbose].value_bool()) {
|
|
avs::ea3::EA3_DEBUG_VERBOSE = true;
|
|
}
|
|
|
|
std::optional<graphics_orientation> monitor_orientation;
|
|
if (options[launcher::Options::spice2x_AutoOrientation].is_active()) {
|
|
monitor_orientation =
|
|
(graphics_orientation)options[launcher::Options::spice2x_AutoOrientation].value_uint32();
|
|
} else if (options[launcher::Options::AdjustOrientation].value_bool()) {
|
|
monitor_orientation = ORIENTATION_CW;
|
|
}
|
|
|
|
std::optional<std::pair<uint32_t, uint32_t>> monitor_resolution;
|
|
if (options[launcher::Options::ChangeResolution].is_active()) {
|
|
std::pair<uint32_t, uint32_t> result;
|
|
if (parse_width_height(options[launcher::Options::ChangeResolution].value_text(), result)) {
|
|
monitor_resolution = result;
|
|
} else if (!cfg_run && !cfg::CONFIGURATOR_STANDALONE) {
|
|
log_fatal("launcher", "failed to parse -changeres");
|
|
}
|
|
}
|
|
|
|
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<std::string> tokens;
|
|
while (stream >> buffer) {
|
|
game_hooks.push_back(buffer);
|
|
}
|
|
}
|
|
for (auto &hook : options[launcher::Options::EarlyInjectHook].values_text()) {
|
|
std::string buffer;
|
|
std::stringstream stream(hook);
|
|
std::vector<std::string> tokens;
|
|
while (stream >> buffer) {
|
|
early_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::EnableAMI2000Module].value_bool()) {
|
|
attach_ami2000 = 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::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;
|
|
} else if (txt == "bottomleft") {
|
|
games::sdvx::OVERLAY_POS = games::sdvx::SDVX_OVERLAY_BOTTOM_LEFT;
|
|
} else if (txt == "bottomright") {
|
|
games::sdvx::OVERLAY_POS = games::sdvx::SDVX_OVERLAY_BOTTOM_RIGHT;
|
|
}
|
|
// else - bottom
|
|
}
|
|
if (options[launcher::Options::spice2x_SDVXSubRedraw].value_bool()) {
|
|
SUBSCREEN_FORCE_REDRAW = true;
|
|
}
|
|
if (options[launcher::Options::SDVXSubMonitorOverride].is_active()) {
|
|
sysutils::SECOND_MONITOR_OVERRIDE = options[launcher::Options::SDVXSubMonitorOverride].value_text();
|
|
}
|
|
if (options[launcher::Options::LoadIIDXModule].value_bool()) {
|
|
attach_iidx = true;
|
|
}
|
|
if (options[launcher::Options::IIDXCameraOrderFlip].value_bool()) {
|
|
games::iidx::FLIP_CAMS = true;
|
|
}
|
|
|
|
// IIDX CONNECT_CAMERA logic here for cases where user is running without -iidx module
|
|
// for now, we assume that user may be running on a cab
|
|
// (games::iidx::DISABLE_CAMS starts out as false unless user overrides)
|
|
// we will check again in IIDX module with a different default
|
|
assert(!games::iidx::DISABLE_CAMS.has_value());
|
|
if (options[launcher::Options::IIDXDisableCameras].value_bool()) {
|
|
games::iidx::DISABLE_CAMS = true;
|
|
}
|
|
if (options[launcher::Options::IIDXCabCamAccess].is_active() &&
|
|
options[launcher::Options::IIDXCabCamAccess].value_text() == "off") {
|
|
games::iidx::DISABLE_CAMS = true;
|
|
}
|
|
if (options[launcher::Options::IIDXCamHook].value_bool()) {
|
|
games::iidx::TDJ_CAMERA = true;
|
|
// Disable legacy behaviour to avoid conflict
|
|
games::iidx::DISABLE_CAMS = true;
|
|
}
|
|
// CONNECT_CAMERA env var will be set once logging is enabled
|
|
|
|
if (options[launcher::Options::IIDXCamHookOverride].is_active()) {
|
|
games::iidx::TDJ_CAMERA_OVERRIDE = options[launcher::Options::IIDXCamHookOverride].value_text();
|
|
}
|
|
if (options[launcher::Options::IIDXCamHookRatio].is_active() &&
|
|
options[launcher::Options::IIDXCamHookRatio].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::IIDXLEDBorderless].value_bool()) {
|
|
overlay::windows::IIDX_SEGMENT_BORDERLESS = true;
|
|
}
|
|
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";
|
|
}
|
|
#ifdef SPICE64
|
|
if (options[launcher::Options::IIDXRecQuality].is_active()) {
|
|
nvenc_hook::VIDEO_CQP_STRING_OVERRIDE = options[launcher::Options::IIDXRecQuality].value_text();
|
|
}
|
|
if (options[launcher::Options::IIDXRecDisable].value_bool()) {
|
|
nvenc_hook::FORCE_DISABLE = true;
|
|
}
|
|
#endif
|
|
if (options[launcher::Options::OtocaCamHook].value_bool()) {
|
|
games::otoca::BYPASS_CAMERA = true;
|
|
}
|
|
|
|
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::PopnNoSub].value_bool()) {
|
|
GRAPHICS_FORCE_SINGLE_ADAPTER = true;
|
|
GRAPHICS_PREVENT_SECONDARY_WINDOWS = true;
|
|
}
|
|
if (options[launcher::Options::PopnSubMonitorOverride].is_active()) {
|
|
sysutils::SECOND_MONITOR_OVERRIDE = options[launcher::Options::PopnSubMonitorOverride].value_text();
|
|
}
|
|
if (options[launcher::Options::PopnNativeTouch].value_bool()) {
|
|
games::popn::NATIVE_TOUCH = true;
|
|
}
|
|
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();
|
|
}
|
|
|
|
// gitadora arena layout
|
|
if (options[launcher::Options::GitaDoraArenaSingleWindow].value_bool()) {
|
|
games::gitadora::ARENA_WINDOW_COUNT = 1;
|
|
}
|
|
if (options[launcher::Options::GitaDoraArenaWindowLayout].is_active()) {
|
|
const auto window_count = options[launcher::Options::GitaDoraArenaWindowLayout].value_text();
|
|
if (window_count == "1") {
|
|
games::gitadora::ARENA_WINDOW_COUNT = 1;
|
|
} else if (window_count == "2") {
|
|
games::gitadora::ARENA_WINDOW_COUNT = 2;
|
|
} else if (window_count == "4") {
|
|
games::gitadora::ARENA_WINDOW_COUNT = 4;
|
|
}
|
|
}
|
|
|
|
if (options[launcher::Options::GitaDoraWailHold].is_active()) {
|
|
socd::TILT_HOLD_MS = options[launcher::Options::GitaDoraWailHold].value_uint32();
|
|
}
|
|
if (options[launcher::Options::GitaDoraPickAlgo].is_active()) {
|
|
const auto text = options[launcher::Options::GitaDoraPickAlgo].value_text();
|
|
if (text == "legacy") {
|
|
games::gitadora::PICK_ALGO.reset();
|
|
} else if (text == "neutral") {
|
|
games::gitadora::PICK_ALGO = socd::SocdAlgorithm::Neutral;
|
|
} else if (text == "raw") {
|
|
games::gitadora::PICK_ALGO = socd::SocdAlgorithm::None;
|
|
}
|
|
}
|
|
if (options[launcher::Options::GitaDoraSubOverlaySize].is_active()) {
|
|
games::gitadora::SUBSCREEN_OVERLAY_SIZE = options[launcher::Options::GitaDoraSubOverlaySize].value_text();
|
|
}
|
|
if (options[launcher::Options::GitaDoraArenaAsioDriver].is_active()) {
|
|
games::gitadora::ASIO_DRIVER = options[launcher::Options::GitaDoraArenaAsioDriver].value_text();
|
|
}
|
|
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::GitaDoraLefty].is_active()) {
|
|
const auto text = options[launcher::Options::GitaDoraLefty].value_text();
|
|
if (text == "p1") {
|
|
games::gitadora::P1_LEFTY = true;
|
|
} else if (text == "p2") {
|
|
games::gitadora::P2_LEFTY = true;
|
|
} else if (text == "both") {
|
|
games::gitadora::P1_LEFTY = true;
|
|
games::gitadora::P2_LEFTY = 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::LoadMFGModule].value_bool()) {
|
|
attach_mfg = true;
|
|
}
|
|
if (options[launcher::Options::LoadPCModule].value_bool()) {
|
|
attach_pc = 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::DDRSkipCodecRegisteration].value_bool()) {
|
|
games::ddr::NO_CODEC_REGISTRATION = 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::EnableICMPHook].value_bool()) {
|
|
icmphook_enable = 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::DumpSystemInfo].is_active()) {
|
|
if (options[launcher::Options::DumpSystemInfo].value_text() == "all") {
|
|
rawinput::DUMP_HID_DEVICES_TO_LOG = true;
|
|
} else if (options[launcher::Options::DumpSystemInfo].value_text() == "basic") {
|
|
dump_sysinfo = true;
|
|
} else {
|
|
dump_sysinfo = false;
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
|
|
// printer overwrite
|
|
if (options[launcher::Options::SDVXPrinterOutputOverwrite].value_bool() ||
|
|
options[launcher::Options::LovePlusPrinterOutputOverwrite].value_bool()) {
|
|
games::shared::PRINTER_OVERWRITE_FILE = true;
|
|
}
|
|
|
|
// printer output path
|
|
for (auto &path : options[launcher::Options::SDVXPrinterOutputPath].values_text()) {
|
|
games::shared::PRINTER_PATH.push_back(path);
|
|
}
|
|
for (auto &path : options[launcher::Options::LovePlusPrinterOutputPath].values_text()) {
|
|
games::shared::PRINTER_PATH.push_back(path);
|
|
}
|
|
|
|
// printer file format
|
|
for (auto &path : options[launcher::Options::SDVXPrinterOutputFormat].values_text()) {
|
|
games::shared::PRINTER_FORMAT.push_back(path);
|
|
}
|
|
for (auto &path : options[launcher::Options::LovePlusPrinterOutputFormat].values_text()) {
|
|
games::shared::PRINTER_FORMAT.push_back(path);
|
|
}
|
|
|
|
// printer JPG quality
|
|
if (options[launcher::Options::SDVXPrinterJPGQuality].is_active()) {
|
|
games::shared::PRINTER_JPG_QUALITY = options[launcher::Options::SDVXPrinterJPGQuality].value_uint32();
|
|
} else if (options[launcher::Options::LovePlusPrinterJPGQuality].is_active()) {
|
|
games::shared::PRINTER_JPG_QUALITY = options[launcher::Options::LovePlusPrinterJPGQuality].value_uint32();
|
|
}
|
|
|
|
// printer output clear
|
|
if (options[launcher::Options::SDVXPrinterOutputClear].value_bool() ||
|
|
options[launcher::Options::LovePlusPrinterOutputClear].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::DisableAvsCache].is_active()) {
|
|
hooks::avs::config::DISABLE_CACHE = true;
|
|
}
|
|
if (options[launcher::Options::ScreenResizeConfigPath].is_active()) {
|
|
cfg::SCREEN_RESIZE_CFG_PATH_OVERRIDE =
|
|
options[launcher::Options::ScreenResizeConfigPath].value_text();
|
|
}
|
|
if (options[launcher::Options::PatchManagerConfigPath].is_active()) {
|
|
overlay::windows::PATCH_MANAGER_CFG_PATH_OVERRIDE =
|
|
options[launcher::Options::PatchManagerConfigPath].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()) {
|
|
std::lock_guard<std::mutex> lock(CARD_OVERRIDES_LOCK);
|
|
CARD_OVERRIDES[0] = options[launcher::Options::Player1Card].value_text();
|
|
}
|
|
if (options[launcher::Options::Player2Card].is_active()) {
|
|
std::lock_guard<std::mutex> lock(CARD_OVERRIDES_LOCK);
|
|
CARD_OVERRIDES[1] = options[launcher::Options::Player2Card].value_text();
|
|
}
|
|
if (options[launcher::Options::Player1PinMacro].is_active()) {
|
|
PIN_MACRO_ENABLED = true;
|
|
PIN_MACRO_VALUES[0] = options[launcher::Options::Player1PinMacro].value_text();
|
|
}
|
|
if (options[launcher::Options::Player2PinMacro].is_active()) {
|
|
PIN_MACRO_ENABLED = true;
|
|
PIN_MACRO_VALUES[1] = options[launcher::Options::Player2PinMacro].value_text();
|
|
}
|
|
if (options[launcher::Options::AutoPinMacroTrigger0].is_active()) {
|
|
AUTO_PIN_MACRO_TRIGGER[0] = options[launcher::Options::AutoPinMacroTrigger0].value_text();
|
|
}
|
|
if (options[launcher::Options::AutoPinMacroTrigger1].is_active()) {
|
|
AUTO_PIN_MACRO_TRIGGER[1] = options[launcher::Options::AutoPinMacroTrigger1].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);
|
|
}
|
|
#ifndef NO_SCARD
|
|
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::HIDSmartCardIdConvert].is_active()) {
|
|
const auto text = options[launcher::Options::HIDSmartCardIdConvert].value_text();
|
|
if (text == "fix") {
|
|
WINSCARD_CONFIG.add_padding_to_old_cards = true;
|
|
} else if (text == "all") {
|
|
WINSCARD_CONFIG.add_padding_to_old_cards = true;
|
|
WINSCARD_CONFIG.add_padding_to_felica = true;
|
|
}
|
|
}
|
|
#endif
|
|
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::APIScreenMirrorQuality].is_active()) {
|
|
api::modules::CAPTURE_QUALITY = options[launcher::Options::APIScreenMirrorQuality].value_uint32();
|
|
}
|
|
if (options[launcher::Options::APIScreenMirrorDivide].is_active()) {
|
|
api::modules::CAPTURE_DIVIDE = options[launcher::Options::APIScreenMirrorDivide].value_uint32();
|
|
}
|
|
|
|
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_run) {
|
|
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::OverlayScaling].is_active() && !cfg::CONFIGURATOR_STANDALONE && !cfg_run) {
|
|
const auto val = options[launcher::Options::OverlayScaling].value_uint32();
|
|
if (10 <= val && val <= 400 && val != 100) {
|
|
overlay::UI_SCALE_PERCENT = options[launcher::Options::OverlayScaling].value_uint32();
|
|
}
|
|
}
|
|
if (options[launcher::Options::DisableAudioHooks].value_bool()) {
|
|
hooks::audio::ENABLED = false;
|
|
deferredlogs::defer_error_messages({
|
|
"audio hooks are forcibly disabled by user (-audiohookdisable)",
|
|
" having hooks disabled means some required audio fixes are not being applied",
|
|
" if you have audio-related crashes, you should try again after clearing this option"
|
|
});
|
|
}
|
|
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::AsioDriverName].is_active()) {
|
|
hooks::audio::BACKEND = hooks::audio::name_to_backend("asio");
|
|
hooks::audio::ASIO_DRIVER_NAME = options[launcher::Options::AsioDriverName].value_text();
|
|
// this new option overrides the old one
|
|
hooks::audio::ASIO_DRIVER_ID.reset();
|
|
}
|
|
|
|
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_FpsOpposite].value_bool()) {
|
|
overlay::FPS_SHOULD_FLIP = 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()) {
|
|
std::pair<uint32_t, uint32_t> result;
|
|
if (parse_width_height(options[launcher::Options::spice2x_WindowSize].value_text(), result)) {
|
|
GRAPHICS_WINDOW_SIZE = result;
|
|
} else if (!cfg_run && !cfg::CONFIGURATOR_STANDALONE) {
|
|
log_fatal("launcher", "failed to parse -windowsize");
|
|
}
|
|
}
|
|
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();
|
|
GRAPHICS_WINDOW_BACKBUFFER_SCALE = options[launcher::Options::WindowForceScaling].value_bool();
|
|
GRAPHICS_WINDOW_DISABLE_ROUNDED_CORNERS = options[launcher::Options::WindowDisableRoundedCorners].value_bool();
|
|
if (options[launcher::Options::GitaDoraWindowedMainMonitor].is_active()) {
|
|
GRAPHICS_GITADORA_MAIN_MONITOR =
|
|
options[launcher::Options::GitaDoraWindowedMainMonitor].value_text();
|
|
}
|
|
if (options[launcher::Options::GitaDoraWindowedLeftMonitor].is_active()) {
|
|
GRAPHICS_GITADORA_LEFT_MONITOR =
|
|
options[launcher::Options::GitaDoraWindowedLeftMonitor].value_text();
|
|
}
|
|
if (options[launcher::Options::GitaDoraWindowedRightMonitor].is_active()) {
|
|
GRAPHICS_GITADORA_RIGHT_MONITOR =
|
|
options[launcher::Options::GitaDoraWindowedRightMonitor].value_text();
|
|
}
|
|
if (options[launcher::Options::GitaDoraWindowedSmallMonitor].is_active()) {
|
|
GRAPHICS_GITADORA_SMALL_MONITOR =
|
|
options[launcher::Options::GitaDoraWindowedSmallMonitor].value_text();
|
|
}
|
|
|
|
// IIDX/SDVX Windowed Subscreen
|
|
if (options[launcher::Options::spice2x_IIDXWindowedSubscreenSize].is_active()) {
|
|
GRAPHICS_WSUB_SIZE = options[launcher::Options::spice2x_IIDXWindowedSubscreenSize].value_text();
|
|
} else if (options[launcher::Options::SDVXWindowedSubscreenSize].is_active()) {
|
|
GRAPHICS_WSUB_SIZE = options[launcher::Options::SDVXWindowedSubscreenSize].value_text();
|
|
}
|
|
if (options[launcher::Options::spice2x_IIDXWindowedSubscreenPosition].is_active()) {
|
|
GRAPHICS_WSUB_POS = options[launcher::Options::spice2x_IIDXWindowedSubscreenPosition].value_text();
|
|
} else if (options[launcher::Options::SDVXWindowedSubscreenPosition].is_active()) {
|
|
GRAPHICS_WSUB_POS = options[launcher::Options::SDVXWindowedSubscreenPosition].value_text();
|
|
}
|
|
if (options[launcher::Options::IIDXWindowedSubscreenBorderless].value_bool() ||
|
|
options[launcher::Options::SDVXWindowedSubscreenBorderless].value_bool()) {
|
|
GRAPHICS_WSUB_BORDERLESS = true;
|
|
}
|
|
if (options[launcher::Options::IIDXWindowedSubscreenAlwaysOnTop].value_bool() ||
|
|
options[launcher::Options::SDVXWindowedSubscreenAlwaysOnTop].value_bool()) {
|
|
GRAPHICS_WSUB_ALWAYS_ON_TOP = true;
|
|
}
|
|
if (options[launcher::Options::IIDXSubMonitorOverride].is_active()) {
|
|
sysutils::SECOND_MONITOR_OVERRIDE = options[launcher::Options::IIDXSubMonitorOverride].value_text();
|
|
}
|
|
|
|
if (options[launcher::Options::spice2x_JubeatLegacyTouch].value_bool()) {
|
|
games::jb::TOUCH_ALGORITHM = games::jb::JubeatTouchAlgorithm::Legacy;
|
|
}
|
|
if (options[launcher::Options::JubeatTouchAlgo].is_active()) {
|
|
if (options[launcher::Options::JubeatTouchAlgo].value_text() == "accurate") {
|
|
games::jb::TOUCH_ALGORITHM = games::jb::JubeatTouchAlgorithm::AcAccurate;
|
|
} else if (options[launcher::Options::JubeatTouchAlgo].value_text() == "legacy") {
|
|
games::jb::TOUCH_ALGORITHM = games::jb::JubeatTouchAlgorithm::Legacy;
|
|
} else {
|
|
games::jb::TOUCH_ALGORITHM = games::jb::JubeatTouchAlgorithm::Improved;
|
|
}
|
|
}
|
|
|
|
// reflec beat touch emulation
|
|
if (options[launcher::Options::spice2x_RBTouchScale].is_active()) {
|
|
games::rb::TOUCH_SCALING = options[launcher::Options::spice2x_RBTouchScale].value_uint32();
|
|
}
|
|
if (options[launcher::Options::RBTouchSize].is_active()) {
|
|
const auto text = options[launcher::Options::RBTouchSize].value_text();
|
|
if (text == "3") {
|
|
games::rb::TOUCH_SIZE = 3;
|
|
}
|
|
}
|
|
if (options[launcher::Options::RBTouchPollRate].is_active()) {
|
|
games::rb::TOUCH_POLL_RATE = options[launcher::Options::RBTouchPollRate].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::DRSRGBCameraHook].value_bool()) {
|
|
games::drs::RGB_CAMERA_HOOK = 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::MFGArgs].is_active()) {
|
|
games::mfg::MFG_INJECT_ARGS = options[launcher::Options::MFGArgs].value_text();
|
|
}
|
|
if (options[launcher::Options::MFGCabType].is_active()) {
|
|
games::mfg::MFG_CABINET_TYPE = options[launcher::Options::MFGCabType].value_text();
|
|
}
|
|
if (options[launcher::Options::MFGNoIO].is_active()) {
|
|
games::mfg::MFG_NO_IO = options[launcher::Options::MFGNoIO].value_bool();
|
|
}
|
|
if (options[launcher::Options::PCArgs].is_active()) {
|
|
games::pc::PC_INJECT_ARGS = options[launcher::Options::PCArgs].value_text();
|
|
}
|
|
if (options[launcher::Options::PCNoIO].is_active()) {
|
|
games::pc::PC_NO_IO = options[launcher::Options::PCNoIO].value_bool();
|
|
}
|
|
if (options[launcher::Options::PCKnobMode].value_bool()) {
|
|
games::pc::PC_KNOB_MODE = true;
|
|
}
|
|
if (options[launcher::Options::spice2x_EnableSMXStage].value_bool()) {
|
|
rawinput::ENABLE_SMX_STAGE = true;
|
|
}
|
|
if (options[launcher::Options::spice2x_EnableSMXDedicab].value_bool()) {
|
|
rawinput::ENABLE_SMX_DEDICAB = true;
|
|
}
|
|
if (options[launcher::Options::InputRequiresFocus].is_active()) {
|
|
const auto &text = options[launcher::Options::InputRequiresFocus].value_text();
|
|
if (text == "always") {
|
|
rawinput::NAIVE_REQUIRE_FOCUS = true;
|
|
rawinput::RAWINPUT_REQUIRE_FOCUS = true;
|
|
} else if (text == "never") {
|
|
rawinput::NAIVE_REQUIRE_FOCUS = false;
|
|
rawinput::RAWINPUT_REQUIRE_FOCUS = false;
|
|
}
|
|
}
|
|
if (options[launcher::Options::DDRP4IOBufferMode].is_active()) {
|
|
if (options[launcher::Options::DDRP4IOBufferMode].value_text() == "thread") {
|
|
acio::MDXF_BUFFER_FILL_MODE = acio::MDXFBufferFillMode::THREAD_MODE;
|
|
} else if (options[launcher::Options::DDRP4IOBufferMode].value_text() == "backfill") {
|
|
acio::MDXF_BUFFER_FILL_MODE = acio::MDXFBufferFillMode::BACKFILL_MODE;
|
|
}
|
|
}
|
|
|
|
if (options[launcher::Options::MidiAlgoVer].is_active()) {
|
|
if (options[launcher::Options::MidiAlgoVer].value_text() == "legacy") {
|
|
midi_algo = rawinput::MidiNoteAlgorithm::LEGACY;
|
|
} else if (options[launcher::Options::MidiAlgoVer].value_text() == "v2") {
|
|
midi_algo = rawinput::MidiNoteAlgorithm::V2;
|
|
} else if (options[launcher::Options::MidiAlgoVer].value_text() == "v2_drum") {
|
|
midi_algo = rawinput::MidiNoteAlgorithm::V2_DRUM;
|
|
}
|
|
// else - automatic (no value)
|
|
}
|
|
if (cfg::CONFIGURATOR_STANDALONE) {
|
|
// three reasons for this hardcoded value
|
|
// 1) poll rate is tied to framerate in spicecfg, and the software ImGui renderer has
|
|
// inconsistent framerate, often failing to meet 60fps
|
|
// 2) the default is 20ms which is 1 frame, which is too quick for the user to see
|
|
// 3) to help with binding process
|
|
rawinput::MIDI_NOTE_SUSTAIN = 100;
|
|
} else if (options[launcher::Options::MidiNoteSustain].is_active()) {
|
|
rawinput::MIDI_NOTE_SUSTAIN = options[launcher::Options::MidiNoteSustain].value_uint32();
|
|
}
|
|
|
|
if (options[launcher::Options::LovePlusCamEnable].value_bool()) {
|
|
games::loveplus::CAMERA_ENABLE = true;
|
|
}
|
|
|
|
if (options[launcher::Options::DisableHighResTimer].value_bool()) {
|
|
timeutils::TIMER_HACKS_DISABLE = true;
|
|
}
|
|
|
|
if (options[launcher::Options::CfgForceSoftwareRender].value_bool()) {
|
|
cfg::CONFIGURATOR_FORCE_SOFTWARE_RENDER = true;
|
|
}
|
|
|
|
// API debugging
|
|
if (api_debug && !cfg::CONFIGURATOR_STANDALONE) {
|
|
API_CONTROLLER = std::make_unique<api::Controller>(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
|
|
#if SPICE_LINUX
|
|
#ifdef SPICE64
|
|
log_info("launcher", "SpiceTools Bootstrap (x64) (spice2x) for Linux");
|
|
#else
|
|
log_info("launcher", "SpiceTools Bootstrap (x32) (spice2x) for Linux");
|
|
#endif
|
|
#elif SPICE_XP
|
|
#ifdef SPICE64
|
|
log_info("launcher", "SpiceTools Bootstrap (x64) (spice2x) for WinXP");
|
|
#else
|
|
log_info("launcher", "SpiceTools Bootstrap (x32) (spice2x) for WinXP");
|
|
#endif
|
|
#else
|
|
#ifdef SPICE64
|
|
log_info("launcher", "SpiceTools Bootstrap (x64) (spice2x)");
|
|
#elif SPICE32_LARGE_ADDRESS_AWARE
|
|
log_info("launcher", "SpiceTools Bootstrap (x32 - Large Address Aware) (spice2x)");
|
|
#else
|
|
log_info("launcher", "SpiceTools Bootstrap (x32) (spice2x)");
|
|
#endif
|
|
#endif
|
|
|
|
log_info("launcher", "{}", VERSION_STRING);
|
|
|
|
// note: distribution of modified version of this software without providing source is GPLv3 license violation.
|
|
log_info("launcher", "spice2x is free & open source; if you paid money for it, you got scammed");
|
|
log_info("launcher", "visit https://spice2x.github.io to download the latest version for free");
|
|
|
|
// log command line arguments
|
|
std::ostringstream arguments;
|
|
for (auto &root_option : options) {
|
|
std::vector<Option> options_all { root_option };
|
|
|
|
options_all.insert(options_all.end(),
|
|
root_option.alternatives.begin(),
|
|
root_option.alternatives.end());
|
|
|
|
for (const auto &option : options_all) {
|
|
if (option.is_active()) {
|
|
auto &definition = option.get_definition();
|
|
|
|
arguments << " ";
|
|
arguments << "-";
|
|
|
|
if (definition.display_name.empty()) {
|
|
arguments << definition.name;
|
|
} else {
|
|
arguments << definition.display_name;
|
|
}
|
|
|
|
if (definition.type != OptionType::Bool) {
|
|
arguments << " ";
|
|
|
|
if (definition.sensitive) {
|
|
arguments << std::string(5, '*');
|
|
} else {
|
|
arguments << option.value;
|
|
}
|
|
}
|
|
|
|
arguments << "\n";
|
|
}
|
|
}
|
|
}
|
|
log_info("launcher", "arguments:\n{}", arguments.str());
|
|
|
|
// print out conflicts
|
|
size_t conflicts = 0;
|
|
for (const auto &option : options) {
|
|
if (option.conflicting && option.get_definition().type != OptionType::Bool) {
|
|
conflicts += 1;
|
|
const auto& value = option.get_definition().sensitive ? "*****" : option.value;
|
|
if (launcher::USE_CMD_OVERRIDE) {
|
|
log_warning(
|
|
"launcher",
|
|
"multiple values for -{}, command line args take precedence: {}",
|
|
option.get_definition().name,
|
|
value);
|
|
} else {
|
|
log_warning(
|
|
"launcher",
|
|
"multiple values for -{}, spicecfg values take precedence: {}",
|
|
option.get_definition().name,
|
|
value);
|
|
}
|
|
}
|
|
}
|
|
if (conflicts) {
|
|
if (launcher::USE_CMD_OVERRIDE) {
|
|
log_info(
|
|
"launcher",
|
|
"user specified -cmdoverride, therefore command line args took precedence over spicecfg");
|
|
} else {
|
|
log_warning(
|
|
"launcher",
|
|
"spicecfg values take precedence over command line args; to change this behavior, use -cmdoverride");
|
|
}
|
|
}
|
|
|
|
if (options[launcher::Options::GameExecutable].is_active() && !cfg::CONFIGURATOR_STANDALONE) {
|
|
log_warning(
|
|
"launcher",
|
|
"WARNING - user specified -exec option\n\n\n"
|
|
"!!! !!!\n"
|
|
"!!! Using -exec option disables all game-specific hooks! !!!\n"
|
|
"!!! Unless you know exactly what you are doing, clear -exec !!!\n"
|
|
"!!! and try again. Using -exec by itself will result in weird !!!\n"
|
|
"!!! errors and loss of functionality. !!!\n"
|
|
"!!! !!!\n"
|
|
);
|
|
}
|
|
|
|
if (launcher::signal::DISABLE && !cfg::CONFIGURATOR_STANDALONE) {
|
|
log_warning(
|
|
"launcher",
|
|
"WARNING - user specified -signaldisable option\n\n\n"
|
|
"!!! !!!\n"
|
|
"!!! Using -signaldisable option disables all exception handling, !!!\n"
|
|
"!!! which means when the game crashes it will likely just vanish !!!\n"
|
|
"!!! without troubleshooting information in the logs. !!!\n"
|
|
"!!! !!!\n"
|
|
);
|
|
}
|
|
|
|
if (options[launcher::Options::FullscreenResolution].is_active()) {
|
|
std::pair<uint32_t, uint32_t> result;
|
|
if (parse_width_height(options[launcher::Options::FullscreenResolution].value_text(), result)) {
|
|
GRAPHICS_FS_CUSTOM_RESOLUTION = result;
|
|
} else if (!cfg_run && !cfg::CONFIGURATOR_STANDALONE) {
|
|
log_fatal("launcher", "failed to parse -forceres");
|
|
}
|
|
}
|
|
|
|
if (options[launcher::Options::FullscreenSubResolution].is_active()) {
|
|
std::pair<uint32_t, uint32_t> result;
|
|
if (parse_width_height(options[launcher::Options::FullscreenSubResolution].value_text(), result)) {
|
|
GRAPHICS_FS_CUSTOM_RESOLUTION_SUB = result;
|
|
} else if (!cfg_run && !cfg::CONFIGURATOR_STANDALONE) {
|
|
log_fatal("launcher", "failed to parse -forceressub");
|
|
}
|
|
}
|
|
|
|
// SDVXFullscreenLandscape disabled due to it messing with in-game camera angle
|
|
// FullscreenOrientationFlip continues to live on, however.
|
|
if (options[launcher::Options::SDVXFullscreenLandscape].value_bool() && !cfg::CONFIGURATOR_STANDALONE) {
|
|
log_fatal("launcher", "-sdvxlandscape removed due to a camera bug in SDVX!");
|
|
}
|
|
// if (options[launcher::Options::SDVXFullscreenLandscape].value_bool() && !GRAPHICS_WINDOWED) {
|
|
// #if SPICE64
|
|
// GRAPHICS_FS_ORIENTATION_SWAP = true;
|
|
// #else
|
|
// log_warning("launcher", "-sdvxlandscape is not supported in 32-bit SDVX, ignoring...");
|
|
// #endif
|
|
// }
|
|
|
|
if (options[launcher::Options::FullscreenOrientationFlip].value_bool() && !GRAPHICS_WINDOWED) {
|
|
GRAPHICS_FS_ORIENTATION_SWAP = true;
|
|
}
|
|
|
|
if (games::iidx::DISABLE_CAMS.has_value() &&
|
|
games::iidx::DISABLE_CAMS.value() &&
|
|
!cfg::CONFIGURATOR_STANDALONE) {
|
|
log_misc("launcher", "CONNECT_CAMERA env var set to 0");
|
|
SetEnvironmentVariable("CONNECT_CAMERA", "0");
|
|
}
|
|
|
|
// deleted options
|
|
if (options[launcher::Options::OpenKFControl].value_bool() && !cfg::CONFIGURATOR_STANDALONE) {
|
|
log_fatal("launcher", "KFControl has been removed from spice2x; please use an older version.");
|
|
}
|
|
if (options[launcher::Options::VREnable].value_bool()) {
|
|
log_warning("launcher", "-vr has been removed from spice2x; ignoring");
|
|
}
|
|
if (options[launcher::Options::ExecuteScript].is_active()) {
|
|
log_warning("launcher", "-script has been removed from spice2x; ignoring");
|
|
}
|
|
|
|
// disable automatic system/monitor sleep
|
|
if (!SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED)) {
|
|
log_warning("launcher", "could not set thread execution state: {}", GetLastError());
|
|
}
|
|
|
|
if (!cfg::CONFIGURATOR_STANDALONE) {
|
|
|
|
// set process priority
|
|
cpuutils::set_processor_priority(process_priority_str);
|
|
|
|
// set process affinity
|
|
if (options[launcher::Options::spice2x_ProcessAffinity].is_active()) {
|
|
uint64_t affinity = options[launcher::Options::spice2x_ProcessAffinity].value_hex64();
|
|
cpuutils::set_processor_affinity(affinity, true);
|
|
|
|
// efficiency class (but only if no affinity is set)
|
|
} else if (options[launcher::Options::spice2x_ProcessorEfficiencyClass].is_active()) {
|
|
const auto eff_class_str =
|
|
options[launcher::Options::spice2x_ProcessorEfficiencyClass].value_text();
|
|
if (eff_class_str == "ecores") {
|
|
cpuutils::set_processor_affinity(cpuutils::CpuEfficiencyClass::PreferECores);
|
|
} else if (eff_class_str == "pcores") {
|
|
cpuutils::set_processor_affinity(cpuutils::CpuEfficiencyClass::PreferPCores);
|
|
}
|
|
}
|
|
|
|
// initialize nvapi if available
|
|
nvapi::initialize();
|
|
// add application profile to nvcp
|
|
nvapi::set_profile_settings();
|
|
// enable super exit
|
|
superexit::enable();
|
|
|
|
// enable subscreen touch emulation
|
|
if (options[launcher::Options::spice2x_IIDXEmulateSubscreenKeypadTouch].is_active()) {
|
|
games::iidx::poke::enable();
|
|
}
|
|
if (options[launcher::Options::NostalgiaPoke].is_active()) {
|
|
games::nost::ENABLE_POKE = TRUE;
|
|
}
|
|
}
|
|
|
|
// early hooks
|
|
if (!cfg_run) {
|
|
for (auto &hook : early_hooks) {
|
|
log_info("launcher", "loading early hook DLL {}", hook);
|
|
libutils::print_dll_info(hook);
|
|
HMODULE module;
|
|
if (!(module = libutils::try_library(hook))) {
|
|
log_warning("launcher", "failed to load early hook {}: {}", hook, get_last_error_string());
|
|
deferredlogs::defer_error_messages({
|
|
fmt::format("failed to load early hook {}:", hook),
|
|
fmt::format(" {}", get_last_error_string())
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
// auto detect game if not specified
|
|
if (avs::game::DLL_NAME.empty()) {
|
|
bool module_path_tried = false;
|
|
do {
|
|
|
|
// IIDX
|
|
if (check_dll("bm2dx.dll")) {
|
|
avs::game::DLL_NAME = "bm2dx.dll";
|
|
attach_io = true;
|
|
attach_iidx = true;
|
|
// automatically show cursor in windowed mode to interact with second window (sub)
|
|
if (GRAPHICS_WINDOWED) {
|
|
GRAPHICS_SHOW_CURSOR = true;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// SDVX
|
|
if (check_dll("soundvoltex.dll")) {
|
|
avs::game::DLL_NAME = "soundvoltex.dll";
|
|
attach_io = true;
|
|
attach_sdvx = true;
|
|
#ifdef SPICE64
|
|
debughook::DEBUGHOOK_LOGGING = false;
|
|
#endif
|
|
// automatically show cursor in windowed mode to interact with second window (sub)
|
|
if (GRAPHICS_WINDOWED) {
|
|
GRAPHICS_SHOW_CURSOR = true;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// JB
|
|
if (check_dll("jubeat.dll")) {
|
|
avs::game::DLL_NAME = "jubeat.dll";
|
|
attach_io = true;
|
|
attach_jb = true;
|
|
break;
|
|
}
|
|
|
|
// RB
|
|
if (check_dll("reflecbeat.dll")) {
|
|
avs::game::DLL_NAME = "reflecbeat.dll";
|
|
attach_io = true;
|
|
attach_rb = true;
|
|
break;
|
|
}
|
|
|
|
// Shogikai
|
|
if (check_dll("shogi_engine.dll")) {
|
|
avs::game::DLL_NAME = "system.dll";
|
|
attach_io = true;
|
|
attach_shogikai = true;
|
|
show_cursor_if_no_touch = true;
|
|
break;
|
|
}
|
|
|
|
// PCM & MGA
|
|
if (check_dll("launch.dll")) {
|
|
avs::game::DLL_NAME = "launch.dll";
|
|
attach_io = true;
|
|
|
|
// MGA uses ESS while PCM does not
|
|
if (check_dll("ess.dll")) {
|
|
attach_mga = true;
|
|
} else {
|
|
attach_pcm = true;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
// DEA
|
|
if (check_dll("arkkdm.dll")) {
|
|
avs::game::DLL_NAME = "arkkdm.dll";
|
|
attach_io = true;
|
|
attach_dea = true;
|
|
|
|
// the game is windowed by default unless we set the env
|
|
if (GRAPHICS_WINDOWED) {
|
|
GRAPHICS_WINDOWED = false;
|
|
} else {
|
|
SetEnvironmentVariable("DAMAC_VIEWER_FULLSCREEN", "0");
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
// BS
|
|
if (check_dll("beatstream.dll")) {
|
|
avs::game::DLL_NAME = "beatstream.dll";
|
|
attach_io = true;
|
|
attach_bs = true;
|
|
|
|
// game crash fix
|
|
easrv_maint = false;
|
|
show_cursor_if_no_touch = true;
|
|
break;
|
|
}
|
|
|
|
// RF3D
|
|
if (check_dll("jgt.dll")) {
|
|
avs::game::DLL_NAME = "jgt.dll";
|
|
attach_io = true;
|
|
attach_rf3d = true;
|
|
break;
|
|
}
|
|
|
|
// MUSECA
|
|
if (check_dll("museca.dll")) {
|
|
avs::game::DLL_NAME = "museca.dll";
|
|
attach_io = true;
|
|
attach_museca = true;
|
|
break;
|
|
}
|
|
|
|
// pop'n Lapistoria/eclale/UsaNeko/peace
|
|
if (check_dll("popn22.dll")) {
|
|
avs::game::DLL_NAME = "popn22.dll";
|
|
attach_io = true;
|
|
attach_popn = true;
|
|
break;
|
|
}
|
|
|
|
// pop'n Sunny Park
|
|
if (check_dll("popn21.dll")) {
|
|
avs::game::DLL_NAME = "popn21.dll";
|
|
attach_io = true;
|
|
attach_popn = true;
|
|
break;
|
|
}
|
|
|
|
// pop'n Fantasia
|
|
if (check_dll("popn20.dll")) {
|
|
avs::game::DLL_NAME = "popn20.dll";
|
|
attach_io = true;
|
|
attach_popn = true;
|
|
break;
|
|
}
|
|
|
|
// pop'n Tune Street
|
|
if (check_dll("popn19.dll")) {
|
|
avs::game::DLL_NAME = "popn19.dll";
|
|
attach_io = true;
|
|
attach_popn = true;
|
|
break;
|
|
}
|
|
|
|
// DDR Ace/A20 (bio2)
|
|
if (check_dll("arkmdxbio2.dll")) {
|
|
avs::game::DLL_NAME = "arkmdxbio2.dll";
|
|
attach_io = true;
|
|
attach_ddr = true;
|
|
break;
|
|
}
|
|
|
|
// DDR Ace/A20 (p3io)
|
|
if (check_dll("arkmdxp3.dll")) {
|
|
avs::game::DLL_NAME = "arkmdxp3.dll";
|
|
attach_io = true;
|
|
attach_ddr = true;
|
|
break;
|
|
}
|
|
|
|
// DDR Ace/A20 (p4io)
|
|
if (check_dll("arkmdxp4.dll")) {
|
|
avs::game::DLL_NAME = "arkmdxp4.dll";
|
|
attach_io = true;
|
|
attach_ddr = true;
|
|
break;
|
|
}
|
|
|
|
// DDR 2013/2014 (old cabinets)
|
|
if (check_dll("mdxja_945.dll")) {
|
|
avs::game::DLL_NAME = "mdxja_945.dll";
|
|
attach_io = true;
|
|
attach_ddr = true;
|
|
break;
|
|
}
|
|
|
|
// DDR 2013/2014 (white cabinet)
|
|
if (check_dll("mdxja_hm65.dll")) {
|
|
avs::game::DLL_NAME = "mdxja_hm65.dll";
|
|
attach_io = true;
|
|
attach_ddr = true;
|
|
break;
|
|
}
|
|
|
|
// DDR X2/X3
|
|
if (check_dll("ddr.dll")) {
|
|
avs::game::DLL_NAME = "ddr.dll";
|
|
attach_io = true;
|
|
attach_ddr = true;
|
|
break;
|
|
}
|
|
|
|
// GitaDora
|
|
if (check_dll("gdxg.dll")) {
|
|
avs::game::DLL_NAME = "gdxg.dll";
|
|
attach_io = true;
|
|
attach_device = true;
|
|
attach_extdev = true;
|
|
attach_ami2000 = true;
|
|
attach_gitadora = true;
|
|
break;
|
|
}
|
|
|
|
// Nostalgia
|
|
if (check_dll("nostalgia.dll")) {
|
|
avs::game::DLL_NAME = "nostalgia.dll";
|
|
attach_io = true;
|
|
attach_nostalgia = true;
|
|
show_cursor_if_no_touch = true;
|
|
break;
|
|
}
|
|
|
|
// Bishi Bashi Channel
|
|
if (check_dll("bsch.dll")) {
|
|
avs::game::DLL_NAME = "bsch.dll";
|
|
attach_io = true;
|
|
attach_bbc = true;
|
|
break;
|
|
}
|
|
|
|
if (check_dll("popn.dll")) {
|
|
avs::game::DLL_NAME = "popn.dll";
|
|
attach_io = true;
|
|
|
|
if (check_dll("libaio-iob2_video.dll")) {
|
|
// pop'n music (pika cabinet)
|
|
attach_popn = true;
|
|
// automatically show cursor in windowed mode to interact with second window (sub)
|
|
if (GRAPHICS_WINDOWED) {
|
|
GRAPHICS_SHOW_CURSOR = true;
|
|
}
|
|
} else {
|
|
// HELLO! Pop'n Music
|
|
attach_hpm = true;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Quiz Magic Academy
|
|
if (check_dll("client.dll")) {
|
|
avs::game::DLL_NAME = "client.dll";
|
|
attach_io = true;
|
|
attach_qma = true;
|
|
break;
|
|
}
|
|
|
|
// LovePlus
|
|
if (check_dll("arkklp.dll")) {
|
|
avs::game::DLL_NAME = "arkklp.dll";
|
|
attach_io = true;
|
|
attach_loveplus = true;
|
|
attach_cpusbxpkm_printer = true;
|
|
break;
|
|
}
|
|
|
|
// Steel Chronicle
|
|
if (check_dll("arkkgg.dll")) {
|
|
avs::game::DLL_NAME = "arkkgg.dll";
|
|
attach_io = true;
|
|
attach_sc = true;
|
|
easrv_maint = false;
|
|
break;
|
|
}
|
|
|
|
// Mahjong Fight Club
|
|
if (check_dll("allinone.dll")) {
|
|
avs::game::DLL_NAME = "system.dll";
|
|
attach_io = true;
|
|
attach_mfc = true;
|
|
break;
|
|
|
|
// Mahjong Fight Club - 2025?
|
|
// they removed allinone.dll and moved i/o into system.dll
|
|
} else if (check_dll("system.dll") && fileutils::file_exists("data/mfc.ini")) {
|
|
avs::game::DLL_NAME = "system.dll";
|
|
attach_io = true;
|
|
attach_mfc = true;
|
|
break;
|
|
}
|
|
|
|
// FutureTomTom
|
|
if (check_dll("arkmmd.dll")) {
|
|
avs::game::DLL_NAME = "arkmmd.dll";
|
|
attach_io = true;
|
|
attach_ftt = true;
|
|
|
|
// the game is windowed by default unless we set the env
|
|
if (!GRAPHICS_WINDOWED) {
|
|
SetEnvironmentVariable("DAMAC_VIEWER_FULLSCREEN", "0");
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
// Scotto
|
|
if (check_dll("scotto.dll")) {
|
|
avs::game::DLL_NAME = "scotto.dll";
|
|
attach_io = true;
|
|
attach_scotto = true;
|
|
break;
|
|
}
|
|
|
|
// TsumTsum
|
|
if (check_dll("arko26.dll")) {
|
|
avs::game::DLL_NAME = "arko26.dll";
|
|
attach_io = true;
|
|
break;
|
|
}
|
|
|
|
// DANCERUSH
|
|
if (check_dll("superstep.dll")) {
|
|
avs::game::DLL_NAME = "superstep.dll";
|
|
attach_io = true;
|
|
attach_drs = true;
|
|
break;
|
|
}
|
|
|
|
// Winning Eleven 2012
|
|
if (check_dll("weac12_bootstrap_release.dll")) {
|
|
avs::game::DLL_NAME = "weac12_bootstrap_release.dll";
|
|
attach_io = true;
|
|
attach_we = true;
|
|
break;
|
|
}
|
|
|
|
// Winning Eleven 2014
|
|
if (check_dll("arknck.dll")) {
|
|
avs::game::DLL_NAME = "arknck.dll";
|
|
attach_io = true;
|
|
attach_we = true;
|
|
show_cursor_if_no_touch = true;
|
|
break;
|
|
}
|
|
|
|
// Otoca D'or
|
|
if (check_dll("arkkep.dll")) {
|
|
avs::game::DLL_NAME = "arkkep.dll";
|
|
attach_io = true;
|
|
attach_otoca = true;
|
|
break;
|
|
}
|
|
|
|
// Silent Scope: Bone Eater
|
|
if (check_dll("arkndd.dll")) {
|
|
avs::game::DLL_NAME = "arkndd.dll";
|
|
attach_io = true;
|
|
attach_silentscope = true;
|
|
break;
|
|
}
|
|
|
|
// Ongaku Paradise
|
|
if (check_dll("arkjc9.dll")) {
|
|
avs::game::DLL_NAME = "arkjc9.dll";
|
|
attach_io = true;
|
|
attach_onpara = true;
|
|
break;
|
|
}
|
|
|
|
// Chase Chase Jokers
|
|
if (check_dll("kamunity.dll") && fileutils::file_exists("game/chaseproject.exe")) {
|
|
avs::game::DLL_NAME = "kamunity.dll";
|
|
attach_io = true;
|
|
attach_ccj = true;
|
|
show_cursor_if_no_touch = true;
|
|
break;
|
|
}
|
|
|
|
// QuizKnock STADIUM
|
|
if (check_dll("kamunity.dll") && fileutils::file_exists("game/uks.exe")) {
|
|
avs::game::DLL_NAME = "kamunity.dll";
|
|
attach_io = true;
|
|
attach_qks = true;
|
|
show_cursor_if_no_touch = true;
|
|
break;
|
|
}
|
|
|
|
// Mahjong Fight Girl
|
|
if (check_dll("kamunity.dll") && fileutils::dir_exists("game/MFGClient_Data")) {
|
|
avs::game::DLL_NAME = "kamunity.dll";
|
|
attach_io = true;
|
|
attach_mfg = true;
|
|
launcher::signal::USE_VEH_WORKAROUND = true;
|
|
show_cursor_if_no_touch = true;
|
|
break;
|
|
}
|
|
|
|
// Polaris Chord
|
|
if (check_dll("kamunity.dll") && fileutils::file_exists("game/svm.exe")) {
|
|
avs::game::DLL_NAME = "kamunity.dll";
|
|
attach_io = true;
|
|
attach_pc = true;
|
|
launcher::signal::USE_VEH_WORKAROUND = true;
|
|
show_cursor_if_no_touch = true;
|
|
break;
|
|
}
|
|
|
|
// Busou Shinki: Armored Princess Battle Conductor
|
|
if (check_dll("kamunity.dll") && fileutils::file_exists("game/bsac_app.exe")) {
|
|
avs::game::DLL_NAME = "kamunity.dll";
|
|
attach_io = true;
|
|
attach_bc = true;
|
|
show_cursor_if_no_touch = true;
|
|
break;
|
|
}
|
|
|
|
// try module path
|
|
if (!module_path_tried) {
|
|
module_path_tried = true;
|
|
|
|
MODULE_PATH /= "modules";
|
|
SetDllDirectoryW(MODULE_PATH.c_str());
|
|
|
|
MODULE_PATH /= "";
|
|
|
|
continue;
|
|
}
|
|
|
|
// usage error
|
|
if (!cfg::CONFIGURATOR_STANDALONE
|
|
&& (!CHECK_DLL_IGNORE_ARCH)) {
|
|
log_warning(
|
|
"launcher",
|
|
"module auto detection failed!\n\n"
|
|
"This usually means one of the following:\n\n"
|
|
" 1. You put spice executables in the wrong place, or\n"
|
|
" 2. XML files in prop directory are malformed or missing, or\n"
|
|
" 3. You passed in invalid options (do not specify -exec or -modules if you don't know what you're doing)\n\n"
|
|
);
|
|
|
|
log_fatal("launcher", "module auto detection failed, see log.txt for troubleshooting");
|
|
}
|
|
break;
|
|
|
|
} while (true);
|
|
}
|
|
|
|
// set error mode to show all errors
|
|
SetErrorMode(0);
|
|
|
|
// set the AVS heap size to a default value varying by game
|
|
avs::core::set_default_heap_size(avs::game::DLL_NAME);
|
|
|
|
// load the games
|
|
std::vector<games::Game *> games;
|
|
if (attach_popn) {
|
|
games.push_back(new games::popn::POPNGame());
|
|
}
|
|
if (attach_bbc) {
|
|
avs::core::set_default_heap_size("bsch.dll");
|
|
games.push_back(new games::bbc::BBCGame());
|
|
}
|
|
if (attach_ddr) {
|
|
avs::core::set_default_heap_size("arkmdxp3.dll");
|
|
games.push_back(new games::ddr::DDRGame());
|
|
}
|
|
if (attach_iidx) {
|
|
avs::core::set_default_heap_size("bm2dx.dll");
|
|
games.push_back(new games::iidx::IIDXGame());
|
|
}
|
|
if (attach_sdvx) {
|
|
avs::core::set_default_heap_size("soundvoltex.dll");
|
|
games.push_back(new games::sdvx::SDVXGame());
|
|
}
|
|
if (attach_jb) {
|
|
avs::core::set_default_heap_size("jubeat.dll");
|
|
games.push_back(new games::jb::JBGame());
|
|
}
|
|
if (attach_nostalgia) {
|
|
avs::core::set_default_heap_size("nostalgia.dll");
|
|
games.push_back(new games::nost::NostGame());
|
|
}
|
|
if (attach_gitadora) {
|
|
games.push_back(new games::gitadora::GitaDoraGame());
|
|
}
|
|
if (attach_hpm) {
|
|
avs::core::set_default_heap_size("popn.dll");
|
|
games.push_back(new games::hpm::HPMGame());
|
|
}
|
|
if (attach_mga) {
|
|
games.push_back(new games::mga::MGAGame());
|
|
}
|
|
if (attach_sc) {
|
|
games.push_back(new games::sc::SCGame());
|
|
}
|
|
if (attach_rb) {
|
|
games.push_back(new games::rb::RBGame());
|
|
}
|
|
if (attach_shogikai) {
|
|
games.push_back(new games::shogikai::ShogikaiGame());
|
|
}
|
|
if (attach_qma) {
|
|
avs::core::set_default_heap_size("client.dll");
|
|
games.push_back(new games::qma::QMAGame());
|
|
}
|
|
if (attach_dea) {
|
|
games.push_back(new games::dea::DEAGame());
|
|
}
|
|
if (attach_mfc) {
|
|
avs::core::set_default_heap_size("system.dll");
|
|
games.push_back(new games::mfc::MFCGame());
|
|
}
|
|
if (attach_ftt) {
|
|
avs::core::set_default_heap_size("arkmmd.dll");
|
|
games.push_back(new games::ftt::FTTGame());
|
|
}
|
|
if (attach_bs) {
|
|
games.push_back(new games::bs::BSGame());
|
|
}
|
|
if (attach_loveplus) {
|
|
games.push_back(new games::loveplus::LovePlusGame());
|
|
}
|
|
if (attach_scotto) {
|
|
avs::core::set_default_heap_size("scotto.dll");
|
|
games.push_back(new games::scotto::ScottoGame());
|
|
}
|
|
if (attach_rf3d) {
|
|
games.push_back(new games::rf3d::RF3DGame());
|
|
}
|
|
if (attach_museca) {
|
|
games.push_back(new games::museca::MusecaGame());
|
|
}
|
|
if (attach_drs) {
|
|
avs::core::set_default_heap_size("superstep.dll");
|
|
games.push_back(new games::drs::DRSGame());
|
|
}
|
|
if (attach_we) {
|
|
games.push_back(new games::we::WEGame());
|
|
}
|
|
if (attach_otoca) {
|
|
games.push_back(new games::otoca::OtocaGame());
|
|
}
|
|
if (attach_silentscope) {
|
|
games.push_back(new games::silentscope::SilentScopeGame());
|
|
}
|
|
if (attach_pcm) {
|
|
games.push_back(new games::pcm::PCMGame());
|
|
}
|
|
if (attach_onpara) {
|
|
avs::core::set_default_heap_size("arkjc9.dll");
|
|
games.push_back(new games::onpara::OnparaGame());
|
|
}
|
|
if (attach_bc) {
|
|
avs::core::set_default_heap_size("kamunity.dll");
|
|
games.push_back(new games::bc::BCGame());
|
|
}
|
|
if (attach_ccj) {
|
|
avs::core::set_default_heap_size("kamunity.dll");
|
|
games.push_back(new games::ccj::CCJGame());
|
|
}
|
|
if (attach_qks) {
|
|
avs::core::set_default_heap_size("kamunity.dll");
|
|
games.push_back(new games::qks::QKSGame());
|
|
}
|
|
if (attach_mfg) {
|
|
avs::core::set_default_heap_size("kamunity.dll");
|
|
games.push_back(new games::mfg::MFGGame());
|
|
}
|
|
if (attach_pc) {
|
|
avs::core::HEAP_SIZE = 536870912; // 512MB
|
|
games.push_back(new games::pc::PCGame());
|
|
}
|
|
|
|
// apply user heap size, if defined
|
|
if (user_heap_size > 0) {
|
|
avs::core::HEAP_SIZE = user_heap_size;
|
|
}
|
|
|
|
// call pre-attach
|
|
for (auto game : games) {
|
|
game->pre_attach();
|
|
}
|
|
|
|
// run configuration utility
|
|
if (cfg_run || cfg::CONFIGURATOR_STANDALONE) {
|
|
// cardio thread for cfg
|
|
if (cardio_enabled) {
|
|
cardio_runner_start(true);
|
|
}
|
|
|
|
if (!midi_algo.has_value()) {
|
|
midi_algo = rawinput::MidiNoteAlgorithm::V2;
|
|
}
|
|
rawinput::set_midi_algorithm(midi_algo.value());
|
|
|
|
if (api_enable || api_debug) {
|
|
API_CONTROLLER = std::make_unique<api::Controller>(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]);
|
|
}
|
|
}
|
|
exit(spicecfg_run(sextet_devices));
|
|
}
|
|
|
|
// log some DLLs found in path (purely for troubleshooting purposes to detect
|
|
// dxvk, ForceD3D9On12, ifs_layeredfs, etc)
|
|
libutils::warn_if_dll_exists("d3d8.dll");
|
|
libutils::warn_if_dll_exists("d3d9.dll");
|
|
libutils::warn_if_dll_exists("d3d10core.dll");
|
|
libutils::warn_if_dll_exists("d3d11.dll");
|
|
libutils::warn_if_dll_exists("d3d12.dll");
|
|
libutils::warn_if_dll_exists("dxgi.dll");
|
|
libutils::warn_if_dll_exists("opengl32.dll");
|
|
libutils::warn_if_dll_exists("nvcuda.dll");
|
|
libutils::warn_if_dll_exists("nvcuvid.dll");
|
|
libutils::warn_if_dll_exists("nvEncodeAPI64.dll");
|
|
libutils::warn_if_dll_exists("msvcr100.dll");
|
|
libutils::warn_if_dll_exists("dsound.dll");
|
|
|
|
// complain loudly & early about dll load ordering issue
|
|
libutils::check_duplicate_dlls();
|
|
|
|
// print cpu features
|
|
if (!cfg::CONFIGURATOR_STANDALONE && dump_sysinfo) {
|
|
cpuutils::print_cpu_features();
|
|
sysutils::print_os();
|
|
sysutils::print_smbios();
|
|
sysutils::print_gpus();
|
|
}
|
|
|
|
// fix up monitor
|
|
if (options[launcher::Options::PrimaryMonitor].is_active()) {
|
|
change_primary_monitor(options[launcher::Options::PrimaryMonitor].value_text());
|
|
}
|
|
update_monitor_on_boot(monitor_orientation, GRAPHICS_FORCE_REFRESH, monitor_resolution);
|
|
|
|
// initialize raw input
|
|
RI_MGR = std::make_unique<rawinput::RawInputManager>();
|
|
for (const auto &device : sextet_devices) {
|
|
RI_MGR->sextet_register(device);
|
|
}
|
|
|
|
// print devices
|
|
RI_MGR->devices_print();
|
|
|
|
auto buttons = games::get_buttons(eamuse_get_game());
|
|
log_misc("rawinput", "Button mappings:");
|
|
dump_button_bindings(buttons);
|
|
|
|
log_misc("rawinput", "Keypad button mappings:");
|
|
auto keypads = games::get_buttons_keypads(eamuse_get_game());
|
|
dump_button_bindings(keypads);
|
|
|
|
log_misc("rawinput", "Overlay button mappings:");
|
|
auto overlay_buttons = games::get_buttons_overlay(eamuse_get_game());
|
|
dump_button_bindings(overlay_buttons);
|
|
|
|
log_misc("rawinput", "Analog mappings:");
|
|
dump_analog_bindings();
|
|
|
|
// for certain games, show cursor if no touch is available (must be called after RI_MGR is available)
|
|
if (show_cursor_if_no_touch && !is_touch_available("launcher::main_implementation")) {
|
|
GRAPHICS_SHOW_CURSOR = true;
|
|
}
|
|
|
|
// cardio
|
|
if (cardio_enabled) {
|
|
cardio_runner_start(true);
|
|
}
|
|
|
|
// load stubs
|
|
if (load_stubs) {
|
|
for (const auto &stub : STUBS) {
|
|
if (fileutils::verify_header_pe(MODULE_PATH / stub)) {
|
|
libutils::load_library(MODULE_PATH / stub);
|
|
} else {
|
|
log_warning("launcher", "failed to load stubs!");
|
|
load_stubs = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// locale hook
|
|
if (!lang_disable) {
|
|
hooks::lang::early_init();
|
|
}
|
|
|
|
// use high resolution timer for this process
|
|
timeutils::set_timer_resolution();
|
|
|
|
// load DLLs
|
|
avs::core::load_dll();
|
|
avs::ea3::load_dll();
|
|
|
|
// ICMP emulation (opt-in; before games open raw ICMP sockets)
|
|
if (icmphook_enable) {
|
|
icmphook_net_init();
|
|
}
|
|
|
|
// net fix
|
|
if (!netfix_disable) {
|
|
networkhook_init();
|
|
}
|
|
|
|
// boot AVS
|
|
avs::core::boot();
|
|
|
|
// initialize SSL
|
|
if (!ssl_disable) {
|
|
avs::ssl::init();
|
|
}
|
|
|
|
// copy defaults to nvram
|
|
avs::core::copy_defaults();
|
|
|
|
// prepare patches
|
|
{
|
|
overlay::windows::PatchManager patch_manager(nullptr, false);
|
|
}
|
|
|
|
// load game
|
|
avs::game::load_dll();
|
|
|
|
// attach games
|
|
for (auto game : games) {
|
|
game->attach();
|
|
}
|
|
|
|
#if SPICE64 && !SPICE_XP
|
|
if (!cfg::CONFIGURATOR_STANDALONE) {
|
|
if (games::iidx::TDJ_CAMERA) {
|
|
games::iidx::init_camera_hooks();
|
|
}
|
|
if (!D3D9_DEVICE_HOOK_DISABLE) {
|
|
nvenc_hook::initialize();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// attach stub functions
|
|
if (!load_stubs) {
|
|
stubs::attach();
|
|
}
|
|
|
|
// locale hook
|
|
if (!lang_disable) {
|
|
hooks::lang::init();
|
|
}
|
|
|
|
// exception/signal hook
|
|
launcher::signal::attach();
|
|
|
|
// audio hook
|
|
hooks::audio::init();
|
|
|
|
// DirectInput 8 hook
|
|
hooks::input::dinput8::init();
|
|
|
|
// D3D9 hook
|
|
graphics_init();
|
|
|
|
// debug hook
|
|
debughook::attach();
|
|
|
|
// device debug
|
|
if (DEVICE_CREATEFILE_DEBUG) {
|
|
devicehook_init();
|
|
}
|
|
|
|
// server
|
|
if (easrv_port != 0u && !easrv_smart) {
|
|
easrv_start(easrv_port, easrv_maint, 4, 8);
|
|
}
|
|
|
|
// acio attach
|
|
if (attach_io || attach_acio) {
|
|
acio::attach();
|
|
}
|
|
|
|
// acio icca attach
|
|
if (attach_icca) {
|
|
acio::attach_icca();
|
|
}
|
|
|
|
// device attach
|
|
if (attach_io || attach_device) {
|
|
spicedevice_attach();
|
|
}
|
|
|
|
// ext dev attach
|
|
if (attach_io || attach_extdev) {
|
|
extdev_attach();
|
|
}
|
|
|
|
// ami 2000 card reader attach
|
|
if (attach_io || attach_ami2000) {
|
|
ami2000_attach();
|
|
}
|
|
|
|
// sci unit attach
|
|
if (attach_io || attach_sciunit) {
|
|
sciunit_attach();
|
|
}
|
|
|
|
// SDVX printer attach
|
|
if (attach_cpusbxpkm_printer) {
|
|
games::shared::printer_attach();
|
|
}
|
|
|
|
// net fix
|
|
if (!netfix_disable) {
|
|
networkhook_init();
|
|
}
|
|
|
|
update_msvcrt_args(argc, argv);
|
|
|
|
// load hooks
|
|
for (auto &hook : game_hooks) {
|
|
log_info("launcher", "loading hook DLL {}", hook);
|
|
libutils::print_dll_info(hook);
|
|
HMODULE module;
|
|
if (!(module = libutils::try_library(hook))) {
|
|
log_warning("launcher", "failed to load hook {}: {}", hook, get_last_error_string());
|
|
deferredlogs::defer_error_messages({
|
|
fmt::format("failed to load hook {}:", hook),
|
|
fmt::format(" {}", get_last_error_string())
|
|
});
|
|
} else {
|
|
bt5api_hook(module);
|
|
sdk::register_sdk_hooks(hook, module);
|
|
}
|
|
}
|
|
|
|
// layeredfs
|
|
if (fileutils::dir_exists("data_mods") &&
|
|
GetModuleHandleA("ifs_hook.dll") == nullptr) {
|
|
log_warning("launcher", "data_mods directory found, but ifs_hook.dll is not loaded; mods will not load");
|
|
deferredlogs::defer_error_messages({
|
|
"data_mods directory was found, but ifs_hook.dll is not loaded",
|
|
" your mods will not load",
|
|
" to fix this, download ifs_layeredfs and add it as a DLL hook (-k)",
|
|
" https://github.com/mon/ifs_layeredfs"
|
|
});
|
|
}
|
|
|
|
// apply patches
|
|
{
|
|
overlay::windows::PatchManager patch_manager(nullptr, true);
|
|
}
|
|
|
|
// load AVS-EA3
|
|
avs::ea3::boot(easrv_port, easrv_maint, easrv_smart);
|
|
|
|
// eamuse init
|
|
eamuse_autodetect_game();
|
|
|
|
// notification position: apply per-game default first, then the explicit
|
|
// user option (if set) wins over the default.
|
|
overlay::notifications::apply_game_default_position(eamuse_get_game());
|
|
if (options[launcher::Options::NotificationPosition].is_active()) {
|
|
const auto txt = options[launcher::Options::NotificationPosition].value_text();
|
|
if (txt == "topleft") {
|
|
overlay::notifications::POSITION = overlay::notifications::Position::TopLeft;
|
|
} else if (txt == "topright") {
|
|
overlay::notifications::POSITION = overlay::notifications::Position::TopRight;
|
|
} else if (txt == "bottomleft") {
|
|
overlay::notifications::POSITION = overlay::notifications::Position::BottomLeft;
|
|
} else if (txt == "bottomright") {
|
|
overlay::notifications::POSITION = overlay::notifications::Position::BottomRight;
|
|
} else if (txt == "off") {
|
|
overlay::notifications::ENABLED = false;
|
|
}
|
|
}
|
|
|
|
// unis device hook
|
|
unisintrhook_init();
|
|
|
|
// BT5API
|
|
if (BT5API_ENABLED) {
|
|
bt5api_init();
|
|
}
|
|
|
|
// init SDK
|
|
sdk::init_sdk_modules();
|
|
|
|
// API
|
|
if (api_enable || std::min(api_serial_port.size(), api_serial_baud.size()) > 0) {
|
|
API_CONTROLLER = std::make_unique<api::Controller>(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]);
|
|
}
|
|
|
|
// start coin input thread
|
|
eamuse_coin_start_thread();
|
|
|
|
// pin macro
|
|
if (!cfg::CONFIGURATOR_STANDALONE && PIN_MACRO_ENABLED) {
|
|
eamuse_pin_macro_start_thread();
|
|
}
|
|
|
|
// print PEB
|
|
if (peb_print) {
|
|
peb::peb_print();
|
|
}
|
|
|
|
// enable automap
|
|
if (automap) {
|
|
avs::automap::enable();
|
|
}
|
|
|
|
// initialize rich presence
|
|
if (rich_presence) {
|
|
richpresence::init();
|
|
}
|
|
|
|
// turn off controlled game lights
|
|
auto lights = games::get_lights(eamuse_get_game());
|
|
if (lights) {
|
|
for (auto &light : *lights) {
|
|
GameAPI::Lights::writeLight(RI_MGR, light, 0.f);
|
|
}
|
|
RI_MGR->devices_flush_output();
|
|
}
|
|
|
|
// update rawinput midi algorithm, which is game-dependent
|
|
if (!midi_algo.has_value()) {
|
|
if (games::gitadora::is_drum() || avs::game::is_model("MMD")) {
|
|
// GITADORA DrumMania, FutureTomTom
|
|
midi_algo = rawinput::MidiNoteAlgorithm::V2_DRUM;
|
|
} else {
|
|
midi_algo = rawinput::MidiNoteAlgorithm::V2;
|
|
}
|
|
}
|
|
rawinput::set_midi_algorithm(midi_algo.value());
|
|
|
|
// attach games
|
|
for (auto game : games) {
|
|
game->post_attach();
|
|
}
|
|
|
|
// game start
|
|
log_info("launcher", "calling game entry");
|
|
avs::game::entry_main();
|
|
|
|
// clear presence
|
|
richpresence::shutdown();
|
|
|
|
// detach games
|
|
for (auto game : games) {
|
|
game->detach();
|
|
}
|
|
|
|
// sci unit detach
|
|
if (attach_io || attach_sciunit) {
|
|
sciunit_detach();
|
|
}
|
|
|
|
// ext dev detach
|
|
if (attach_io || attach_extdev) {
|
|
extdev_detach();
|
|
}
|
|
|
|
// device detach
|
|
if (attach_io || attach_device) {
|
|
spicedevice_detach();
|
|
}
|
|
|
|
// acio detach
|
|
if (attach_io || attach_acio) {
|
|
acio::detach();
|
|
}
|
|
|
|
// delete games
|
|
while (!games.empty()) {
|
|
delete games.back();
|
|
games.pop_back();
|
|
}
|
|
|
|
// free api controller
|
|
API_CONTROLLER.reset();
|
|
|
|
// stop coin input thread
|
|
eamuse_coin_stop_thread();
|
|
|
|
eamuse_pin_macro_stop_thread();
|
|
|
|
// BT5API
|
|
if (BT5API_ENABLED) {
|
|
bt5api_dispose();
|
|
}
|
|
|
|
sdk::fini_sdk_modules();
|
|
|
|
// stop raw input
|
|
RI_MGR.reset();
|
|
|
|
// debug hook
|
|
debughook::detach();
|
|
|
|
#ifndef NO_SCARD
|
|
// scard
|
|
scard_fini();
|
|
#endif
|
|
|
|
// stop reader thread in case it was running
|
|
stop_reader_thread();
|
|
|
|
// cardio
|
|
if (cardio_enabled) {
|
|
cardio_runner_stop();
|
|
}
|
|
|
|
// server
|
|
if (easrv_port != 0u) {
|
|
easrv_shutdown();
|
|
}
|
|
|
|
// AVS EA3 shutdown
|
|
avs::ea3::shutdown();
|
|
|
|
// AVS cleanup
|
|
avs::core::shutdown();
|
|
|
|
// dispose crypt
|
|
crypt::dispose();
|
|
|
|
// disable super exit
|
|
superexit::disable();
|
|
|
|
// disable poke
|
|
games::iidx::poke::disable();
|
|
|
|
#if SPICE64 && !SPICE_XP
|
|
games::iidx::camera_release();
|
|
#endif
|
|
|
|
// shutdown
|
|
log_warning("launcher", "end");
|
|
launcher::stop_subsystems();
|
|
|
|
return 0;
|
|
}
|
|
|
|
// https://github.com/spice2x/spice2x.github.io/issues/264
|
|
// huge ugly hack to work around things that broke when MinGW switched from msvcrt to ucrt
|
|
// this is done to ensure that any DLL hooks that rely on msvcrt continue to work
|
|
void update_msvcrt_args(int argc, char *argv[]) {
|
|
#if defined(_UCRT)
|
|
auto msvc = LoadLibraryA("msvcrt.dll");
|
|
if (!msvc) {
|
|
log_warning("launcher", "failed to load msvcrt.dll");
|
|
return;
|
|
}
|
|
|
|
// get __argc
|
|
PINT32 argc_addr = (PINT32)GetProcAddress(msvc, "__argc");
|
|
if (!argc_addr) {
|
|
log_warning("launcher", "failed to find msvcrt!__argc");
|
|
return;
|
|
}
|
|
try {
|
|
if (*argc_addr == argc) {
|
|
log_warning("launcher", "msvcrt!__argc is already set");
|
|
return;
|
|
}
|
|
} catch (const std::exception &e) {
|
|
log_warning("launcher", "exception while reading msvcrt!_argc: {}", e.what());
|
|
}
|
|
|
|
// get __argv
|
|
PCHAR **argv_addr = (PCHAR **)GetProcAddress(msvc, "__argv");
|
|
if (!argv_addr) {
|
|
log_warning("launcher", "failed to find msvcrt!__argv");
|
|
return;
|
|
}
|
|
|
|
// update them
|
|
try {
|
|
log_info("launcher", "msvcrt!__argc value before: {}", *argc_addr);
|
|
*argc_addr = argc;
|
|
log_info("launcher", "msvcrt!__argc value after: {}", *argc_addr);
|
|
*argv_addr = argv;
|
|
} catch (const std::exception &e) {
|
|
log_warning("launcher", "exception while messing with msvcrt!_argc and _argv: {}", e.what());
|
|
}
|
|
|
|
#else
|
|
log_misc("launcher", "not UCRT, skipping msvcrt!_argc / _argv hacks");
|
|
#endif
|
|
}
|
|
|
|
void dump_button_bindings(std::vector<Button> *buttons) {
|
|
if (!buttons) {
|
|
return;
|
|
}
|
|
|
|
for (auto button = buttons->begin(); button != buttons->end(); ++button) {
|
|
if (!button->isSet()) {
|
|
continue;
|
|
}
|
|
|
|
if (button->isNaive()) {
|
|
log_misc(
|
|
"rawinput", " [{}] dev=Naive, vkey={} ({})",
|
|
button->getName(),
|
|
button->getVKey(),
|
|
button->getVKeyString()
|
|
);
|
|
} else {
|
|
log_misc(
|
|
"rawinput", " [{}] dev={}, vkey={}, analogtype={}",
|
|
button->getName(),
|
|
button->getDeviceIdentifier(),
|
|
button->getVKey(),
|
|
static_cast<uint32_t>(button->getAnalogType())
|
|
);
|
|
}
|
|
|
|
for (auto& alt : button->getAlternatives()) {
|
|
if (!alt.isValid()) {
|
|
continue;
|
|
}
|
|
if (alt.isNaive()) {
|
|
log_misc(
|
|
"rawinput", " [{}] (alt) dev=Naive, vkey={} ({})",
|
|
alt.getName(),
|
|
alt.getVKey(),
|
|
alt.getVKeyString()
|
|
);
|
|
} else {
|
|
log_misc(
|
|
"rawinput", " [{}] (alt) dev={}, vkey={}, analogtype={}",
|
|
alt.getName(),
|
|
alt.getDeviceIdentifier(),
|
|
alt.getVKey(),
|
|
static_cast<uint32_t>(alt.getAnalogType())
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void dump_analog_bindings() {
|
|
auto analogs = games::get_analogs(eamuse_get_game());
|
|
if (!analogs) {
|
|
return;
|
|
}
|
|
for (auto& analog : *analogs) {
|
|
if (!analog.isSet()) {
|
|
continue;
|
|
}
|
|
log_misc(
|
|
"rawinput", " [{}] dev={}, index={}",
|
|
analog.getName(),
|
|
analog.getDeviceIdentifier(),
|
|
analog.getIndex()
|
|
);
|
|
}
|
|
}
|
|
|
|
#ifndef SPICETOOLS_SPICECFG_STANDALONE
|
|
int main(int argc, char *argv[]) {
|
|
return main_implementation(argc, argv);
|
|
}
|
|
#endif
|