Merge branch 'spice2x' into spice22x
This commit is contained in:
+270
-20
@@ -6,6 +6,7 @@
|
||||
#include <shlwapi.h>
|
||||
#include <cfg/configurator.h>
|
||||
|
||||
#include "api/modules/capture.h"
|
||||
#include "acio/acio.h"
|
||||
#include "acio/icca/icca.h"
|
||||
#include "api/controller.h"
|
||||
@@ -60,6 +61,7 @@
|
||||
#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/develhook.h"
|
||||
#include "hooks/avshook.h"
|
||||
@@ -96,6 +98,7 @@
|
||||
#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"
|
||||
@@ -150,6 +153,9 @@ static bool check_dll(const std::string &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
|
||||
@@ -219,6 +225,7 @@ int main_implementation(int argc, char *argv[]) {
|
||||
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;
|
||||
|
||||
@@ -244,6 +251,11 @@ int main_implementation(int argc, char *argv[]) {
|
||||
// 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()) {
|
||||
@@ -285,6 +297,7 @@ int main_implementation(int argc, char *argv[]) {
|
||||
cfg::CONFIGURATOR_TYPE = cfg::ConfigType::Config;
|
||||
cfg_run = true;
|
||||
}
|
||||
|
||||
if (options[launcher::Options::EAmusementEmulation].value_bool() &&
|
||||
options[launcher::Options::ServiceURL].is_active() &&
|
||||
!cfg::CONFIGURATOR_STANDALONE) {
|
||||
@@ -354,6 +367,9 @@ int main_implementation(int argc, char *argv[]) {
|
||||
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;
|
||||
}
|
||||
if (options[launcher::Options::spice2x_AutoOrientation].is_active()) {
|
||||
GRAPHICS_ADJUST_ORIENTATION =
|
||||
(graphics_orientation)options[launcher::Options::spice2x_AutoOrientation].value_uint32();
|
||||
@@ -424,9 +440,6 @@ int main_implementation(int argc, char *argv[]) {
|
||||
if (options[launcher::Options::LoadSoundVoltexModule].value_bool()) {
|
||||
attach_sdvx = true;
|
||||
}
|
||||
if (options[launcher::Options::SDVXDisableCameras].value_bool()) {
|
||||
games::sdvx::DISABLECAMS = true;
|
||||
}
|
||||
if (options[launcher::Options::SDVXNativeTouch].value_bool()) {
|
||||
games::sdvx::NATIVETOUCH = true;
|
||||
}
|
||||
@@ -617,12 +630,18 @@ int main_implementation(int argc, char *argv[]) {
|
||||
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;
|
||||
}
|
||||
@@ -662,21 +681,42 @@ int main_implementation(int argc, char *argv[]) {
|
||||
if (options[launcher::Options::SDVXPrinterEmulation].value_bool()) {
|
||||
attach_cpusbxpkm_printer = true;
|
||||
}
|
||||
if (options[launcher::Options::SDVXPrinterOutputOverwrite].value_bool()) {
|
||||
|
||||
// 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();
|
||||
}
|
||||
if (options[launcher::Options::SDVXPrinterOutputClear].value_bool()) {
|
||||
|
||||
// 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();
|
||||
}
|
||||
@@ -814,6 +854,7 @@ int main_implementation(int argc, char *argv[]) {
|
||||
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();
|
||||
@@ -836,6 +877,13 @@ int main_implementation(int argc, char *argv[]) {
|
||||
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;
|
||||
}
|
||||
@@ -977,12 +1025,24 @@ int main_implementation(int argc, char *argv[]) {
|
||||
GRAPHICS_WINDOW_ALWAYS_ON_TOP = options[launcher::Options::spice2x_WindowAlwaysOnTop].value_bool();
|
||||
GRAPHICS_WINDOW_BACKBUFFER_SCALE = options[launcher::Options::WindowForceScaling].value_bool();
|
||||
|
||||
// IIDX Windowed Subscreen
|
||||
// IIDX/SDVX Windowed Subscreen
|
||||
if (options[launcher::Options::spice2x_IIDXWindowedSubscreenSize].is_active()) {
|
||||
GRAPHICS_IIDX_WSUB_SIZE = options[launcher::Options::spice2x_IIDXWindowedSubscreenSize].value_text();
|
||||
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_IIDX_WSUB_POS = options[launcher::Options::spice2x_IIDXWindowedSubscreenPosition].value_text();
|
||||
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::spice2x_JubeatLegacyTouch].value_bool()) {
|
||||
@@ -1051,12 +1111,32 @@ int main_implementation(int argc, char *argv[]) {
|
||||
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::MidiAlgoVer].is_active()) {
|
||||
if (options[launcher::Options::MidiAlgoVer].value_text() == "legacy") {
|
||||
midi_algo = rawinput::MidiNoteAlgorithm::LEGACY;
|
||||
@@ -1078,6 +1158,10 @@ int main_implementation(int argc, char *argv[]) {
|
||||
rawinput::MIDI_NOTE_SUSTAIN = options[launcher::Options::MidiNoteSustain].value_uint32();
|
||||
}
|
||||
|
||||
if (options[launcher::Options::LovePlusCamEnable].value_bool()) {
|
||||
games::loveplus::CAMERA_ENABLE = true;
|
||||
}
|
||||
|
||||
// API debugging
|
||||
if (api_debug && !cfg::CONFIGURATOR_STANDALONE) {
|
||||
API_CONTROLLER = std::make_unique<api::Controller>(api_port, api_pass, api_pretty);
|
||||
@@ -1164,6 +1248,51 @@ int main_implementation(int argc, char *argv[]) {
|
||||
}
|
||||
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;
|
||||
if (launcher::USE_CMD_OVERRIDE) {
|
||||
log_warning(
|
||||
"launcher",
|
||||
"multiple values for -{}, command line args take precedence: {}",
|
||||
option.get_definition().name,
|
||||
option.value);
|
||||
} else {
|
||||
log_warning(
|
||||
"launcher",
|
||||
"multiple values for -{}, spicecfg values take precedence: {}",
|
||||
option.get_definition().name,
|
||||
option.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 (options[launcher::Options::FullscreenResolution].is_active()) {
|
||||
std::pair<uint32_t, uint32_t> result;
|
||||
if (parse_width_height(options[launcher::Options::FullscreenResolution].value_text(), result)) {
|
||||
@@ -1248,7 +1377,11 @@ int main_implementation(int argc, char *argv[]) {
|
||||
log_info("launcher", "loading early hook DLL {}", hook);
|
||||
HMODULE module;
|
||||
if (!(module = libutils::try_library(hook))) {
|
||||
log_warning("launcher", "failed to load early hook {}", 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())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1625,6 +1758,16 @@ int main_implementation(int argc, char *argv[]) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Polaris Chord
|
||||
if (check_dll("kamunity.dll") && fileutils::dir_exists("game/svm_Data")) {
|
||||
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";
|
||||
@@ -1649,7 +1792,14 @@ int main_implementation(int argc, char *argv[]) {
|
||||
// usage error
|
||||
if (!cfg::CONFIGURATOR_STANDALONE
|
||||
&& (!CHECK_DLL_IGNORE_ARCH)) {
|
||||
log_fatal("launcher", "module auto detection failed.");
|
||||
log_fatal(
|
||||
"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 (usually, path overrides like -exec)\n\n"
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1777,6 +1927,10 @@ int main_implementation(int argc, char *argv[]) {
|
||||
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());
|
||||
}
|
||||
GAME_INSTANCE = games.back();
|
||||
|
||||
// apply user heap size, if defined
|
||||
@@ -1810,6 +1964,21 @@ int main_implementation(int argc, char *argv[]) {
|
||||
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();
|
||||
|
||||
@@ -1830,6 +1999,21 @@ int main_implementation(int argc, char *argv[]) {
|
||||
// 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;
|
||||
@@ -1971,15 +2155,6 @@ int main_implementation(int argc, char *argv[]) {
|
||||
networkhook_init();
|
||||
}
|
||||
|
||||
// layeredfs
|
||||
if (fileutils::dir_exists("data_mods") &&
|
||||
!fileutils::file_exists("ifs_hook.dll") &&
|
||||
!fileutils::file_exists(MODULE_PATH / "ifs_hook.dll")) {
|
||||
log_warning("launcher", "data_mods directory was found, but ifs_hook.dll is not present; your mods will not load");
|
||||
log_warning("launcher", "to fix this, download ifs_layeredfs and add it as a DLL hook (-k)");
|
||||
log_warning("launcher", "https://github.com/mon/ifs_layeredfs");
|
||||
}
|
||||
|
||||
update_msvcrt_args(argc, argv);
|
||||
|
||||
// load hooks
|
||||
@@ -1987,12 +2162,28 @@ int main_implementation(int argc, char *argv[]) {
|
||||
log_info("launcher", "loading hook DLL {}", hook);
|
||||
HMODULE module;
|
||||
if (!(module = libutils::try_library(hook))) {
|
||||
log_warning("launcher", "failed to load hook {}", 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);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 present; mods will not load");
|
||||
deferredlogs::defer_error_messages({
|
||||
"data_mods directory was found, but ifs_hook.dll is not present",
|
||||
" 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);
|
||||
@@ -2222,6 +2413,65 @@ void update_msvcrt_args(int argc, char *argv[]) {
|
||||
#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()
|
||||
);
|
||||
} else {
|
||||
log_misc(
|
||||
"rawinput", " [{}] dev={}, vkey={}, analogtype={}",
|
||||
button->getName(),
|
||||
button->getDeviceIdentifier(),
|
||||
button->getVKey(),
|
||||
button->getAnalogType()
|
||||
);
|
||||
}
|
||||
|
||||
for (auto& alt : button->getAlternatives()) {
|
||||
if (alt.getVKey() == INVALID_VKEY) {
|
||||
continue;
|
||||
}
|
||||
log_misc(
|
||||
"rawinput", " [{}] (alt) dev={}, vkey={}, analogtype={}",
|
||||
button->getName(),
|
||||
alt.isNaive() ? "Naive" : alt.getDeviceIdentifier(),
|
||||
alt.getVKey(),
|
||||
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);
|
||||
|
||||
+320
-70
@@ -17,7 +17,6 @@ static const std::vector<std::string> CATEGORY_ORDER_BASIC = {
|
||||
"Game Options",
|
||||
"Common",
|
||||
"Network",
|
||||
"Overlay",
|
||||
"Graphics (Common)",
|
||||
"Graphics (Full Screen)",
|
||||
"Graphics (Windowed)",
|
||||
@@ -26,35 +25,42 @@ static const std::vector<std::string> CATEGORY_ORDER_BASIC = {
|
||||
|
||||
static const std::vector<std::string> CATEGORY_ORDER_ADVANCED = {
|
||||
"Game Options (Advanced)",
|
||||
"Overlay",
|
||||
"Network (Advanced)",
|
||||
"Performance",
|
||||
"Miscellaneous",
|
||||
"Paths",
|
||||
"Touch Parameters",
|
||||
"I/O Options",
|
||||
"NFC Card Readers",
|
||||
};
|
||||
static const std::vector<std::string> CATEGORY_ORDER_DEV = {
|
||||
"Network Adapters",
|
||||
"Path Overrides",
|
||||
"Network (Development)",
|
||||
"Audio (Hacks)",
|
||||
"I/O Modules",
|
||||
"Development",
|
||||
"Debug Log",
|
||||
};
|
||||
static const std::vector<std::string> CATEGORY_ORDER_NONE = {
|
||||
""
|
||||
};
|
||||
|
||||
bool launcher::USE_CMD_OVERRIDE = false;
|
||||
|
||||
/*
|
||||
* Option Definitions
|
||||
* Be aware that the order must be the same as in the enum launcher::Options!
|
||||
*/
|
||||
static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
{
|
||||
.title = "Game Executable",
|
||||
.title = "Override Game Executable & Disable Hooks",
|
||||
.name = "exec",
|
||||
.desc = "Path to the game DLL file",
|
||||
.desc = "Path to the game DLL file.\n\n"
|
||||
"This option is typically not needed; leave it empty to allow spice to auto-detect your game.\n\n"
|
||||
"WARNING: this option also disables all game-specific hooks and turns off most I/O modules!",
|
||||
.type = OptionType::Text,
|
||||
.setting_name = "*.dll",
|
||||
.category = "Paths",
|
||||
.category = "Path Overrides",
|
||||
},
|
||||
{
|
||||
.title = "Open Configurator",
|
||||
@@ -81,6 +87,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.category = "Network",
|
||||
},
|
||||
{
|
||||
// ServiceURL
|
||||
.title = "EA Service URL",
|
||||
.name = "url",
|
||||
.desc = "Sets a custom service URL override",
|
||||
@@ -142,6 +149,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.category = "Graphics (Windowed)",
|
||||
},
|
||||
{
|
||||
// InjectHook
|
||||
.title = "Inject DLL Hooks",
|
||||
.name = "k",
|
||||
.desc = "Multiple files are allowed; use multiple -k flags, or in SpiceCfg, separate by "
|
||||
@@ -152,6 +160,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.category = "Common",
|
||||
},
|
||||
{
|
||||
// EarlyInjectHook
|
||||
.title = "Inject Early DLL Hooks",
|
||||
.name = "z",
|
||||
.desc = "Equivalent to 'Inject DLL Hooks' option, but ensures hooks are injected before "
|
||||
@@ -263,7 +272,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.name = "nolegacy",
|
||||
.desc = "Disables legacy key activation in-game.",
|
||||
.type = OptionType::Bool,
|
||||
.category = "Miscellaneous",
|
||||
.category = "I/O Options",
|
||||
},
|
||||
{
|
||||
.title = "Discord Rich Presence",
|
||||
@@ -305,28 +314,29 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.desc = "This is NOT the EA service URL; use -url for that. "
|
||||
"Force the use of an adapter with the specified network. Must also provide -subnet",
|
||||
.type = OptionType::Text,
|
||||
.category = "Network Adapters",
|
||||
.category = "Network (Development)",
|
||||
.sensitive = true,
|
||||
},
|
||||
{
|
||||
.title = "Preferred NetAdapter Subnet",
|
||||
.name = "subnet",
|
||||
.desc = "Force the use of an adapter with the specified subnet. Must also provide -network",
|
||||
.type = OptionType::Text,
|
||||
.category = "Network Adapters",
|
||||
.category = "Network (Development)",
|
||||
},
|
||||
{
|
||||
.title = "Disable Network Fixes",
|
||||
.name = "netfixdisable",
|
||||
.desc = "Force disables network fixes",
|
||||
.type = OptionType::Bool,
|
||||
.category = "Network Adapters",
|
||||
.category = "Network (Development)",
|
||||
},
|
||||
{
|
||||
.title = "HTTP/1.1",
|
||||
.name = "http11",
|
||||
.desc = "Sets EA3 http11 value",
|
||||
.type = OptionType::Enum,
|
||||
.category = "Network (Advanced)",
|
||||
.category = "Network (Development)",
|
||||
.elements = {{"0", "Off"}, {"1", "On"}},
|
||||
},
|
||||
{
|
||||
@@ -334,7 +344,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.name = "ssldisable",
|
||||
.desc = "Prevents the SSL protocol from being registered",
|
||||
.type = OptionType::Bool,
|
||||
.category = "Network (Advanced)",
|
||||
.category = "Network (Development)",
|
||||
},
|
||||
{
|
||||
.title = "URL Slash",
|
||||
@@ -349,7 +359,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.name = "r",
|
||||
.desc = "Set custom SOFTID override",
|
||||
.type = OptionType::Text,
|
||||
.category = "Network (Advanced)",
|
||||
.category = "Development",
|
||||
.sensitive = true,
|
||||
},
|
||||
{
|
||||
@@ -544,10 +554,11 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.category = "Game Options",
|
||||
},
|
||||
{
|
||||
.title = "IIDX BIO2 Firmware",
|
||||
.title = "IIDX BIO2 Firmware Update",
|
||||
.name = "iidxbio2fw",
|
||||
.desc = "Enables BIO2 firmware updates",
|
||||
.desc = "Enables BIO2 firmware updates. WARNING - can cause semi-permanent change to your I/O board",
|
||||
.type = OptionType::Bool,
|
||||
.hidden = true,
|
||||
.game_name = "Beatmania IIDX",
|
||||
.category = "Game Options (Advanced)",
|
||||
},
|
||||
@@ -667,6 +678,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.category = "Game Options (Advanced)",
|
||||
},
|
||||
{
|
||||
// SDVXPrinterOutputPath
|
||||
.title = "SDVX Printer Output Path",
|
||||
.name = "printerpath",
|
||||
.desc = "Path to folder where images will be stored",
|
||||
@@ -691,9 +703,10 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.category = "Game Options (Advanced)",
|
||||
},
|
||||
{
|
||||
// SDVXPrinterOutputFormat
|
||||
.title = "SDVX Printer Output Format",
|
||||
.name = "printerformat",
|
||||
.desc = "Path to folder where images will be stored",
|
||||
.desc = "File format for printer output",
|
||||
.type = OptionType::Text,
|
||||
.setting_name = "(png/bmp/tga/jpg)",
|
||||
.game_name = "Sound Voltex",
|
||||
@@ -709,10 +722,13 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.category = "Game Options (Advanced)",
|
||||
},
|
||||
{
|
||||
.title = "SDVX Disable Cameras",
|
||||
.title = "SDVX Disable Cameras (DEPRECATED - no longer needed)",
|
||||
.name = "sdvxdisablecams",
|
||||
.desc = "Disables cameras",
|
||||
.desc = "This option does nothing.\n\n"
|
||||
"This option was used in the past to fix cameras in SDVX5 but this is no longer "
|
||||
"needed as camera check will always be skipped with a built-in patch.",
|
||||
.type = OptionType::Bool,
|
||||
.hidden = true,
|
||||
.game_name = "Sound Voltex",
|
||||
.category = "Game Options",
|
||||
},
|
||||
@@ -798,6 +814,15 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.game_name = "Dance Dance Revolution",
|
||||
.category = "Game Options",
|
||||
},
|
||||
{
|
||||
// DDRSkipCodecRegisteration
|
||||
.title = "DDR Skip Codec Registration",
|
||||
.name = "ddrnocodec",
|
||||
.desc = "Prevent automatic registration of codecs in the com folder",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "Dance Dance Revolution",
|
||||
.category = "Game Options (Advanced)",
|
||||
},
|
||||
{
|
||||
.title = "Force Load Pop'n Music Module",
|
||||
.name = "pnm",
|
||||
@@ -1025,7 +1050,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
},
|
||||
{
|
||||
// LoadCCJModule
|
||||
.title = "Force Load Chase Chase Jokers",
|
||||
.title = "Force Load Chase Chase Jokers Module",
|
||||
.name = "ccj",
|
||||
.desc = "manually enable Chase Chase Jokers module",
|
||||
.type = OptionType::Bool,
|
||||
@@ -1034,7 +1059,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
},
|
||||
{
|
||||
// LoadQKSModule
|
||||
.title = "Force Load QuizKnock STADIUM",
|
||||
.title = "Force Load QuizKnock STADIUM Module",
|
||||
.name = "qks",
|
||||
.desc = "manually enable QuizKnock STADIUM module",
|
||||
.type = OptionType::Bool,
|
||||
@@ -1043,16 +1068,25 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
},
|
||||
{
|
||||
// LoadMFGModule
|
||||
.title = "Force Load Mahjong Fight Girl",
|
||||
.title = "Force Load Mahjong Fight Girl Module",
|
||||
.name = "mfg",
|
||||
.desc = "manually enable Mahjong Fight Girl module",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "Mahjong Fight Girl",
|
||||
.category = "Game Options (Advanced)",
|
||||
},
|
||||
{
|
||||
// LoadPCModule
|
||||
.title = "Force Load Polaris Chord Module",
|
||||
.name = "pc",
|
||||
.desc = "manually enable Polaris Chord module",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "Polaris Chord",
|
||||
.category = "Game Options (Advanced)",
|
||||
},
|
||||
{
|
||||
// LoadMusecaModule
|
||||
.title = "Force Load Museca",
|
||||
.title = "Force Load Museca Module",
|
||||
.name = "museca",
|
||||
.desc = "manually enable Museca module",
|
||||
.type = OptionType::Bool,
|
||||
@@ -1060,88 +1094,88 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.category = "Game Options (Advanced)",
|
||||
},
|
||||
{
|
||||
.title = "Modules Folder Path",
|
||||
.title = "Modules Folder Override",
|
||||
.name = "modules",
|
||||
.desc = "Sets a custom path to the modules folder",
|
||||
.type = OptionType::Text,
|
||||
.category = "Paths",
|
||||
.category = "Path Overrides",
|
||||
},
|
||||
{
|
||||
.title = "Screenshot Folder Path",
|
||||
.title = "Screenshot Folder Override",
|
||||
.name = "screenshotpath",
|
||||
.desc = "Sets a custom path to the screenshots folder",
|
||||
.type = OptionType::Text,
|
||||
.category = "Paths",
|
||||
.category = "Path Overrides",
|
||||
},
|
||||
{
|
||||
.title = "Configuration Path",
|
||||
.title = "Configuration Path Override",
|
||||
.name = "cfgpath",
|
||||
.desc = "Sets a custom file path for config file. Must be passed via the command line. "
|
||||
"If left empty, %appdata%\\spicetools.xml will be used",
|
||||
.type = OptionType::Text,
|
||||
.setting_name = "(default)",
|
||||
.category = "Paths",
|
||||
.category = "Path Overrides",
|
||||
.disabled = true,
|
||||
},
|
||||
{
|
||||
// ScreenResizeConfigPath
|
||||
.title = "Screen Resize Config Path",
|
||||
.title = "Screen Resize Config Path Override",
|
||||
.name = "resizecfgpath",
|
||||
.desc = "Sets a custom file path for screen resize config file. "
|
||||
"If left empty, %appdata%\\spice2x\\spicetools_screen_resize.json will be used",
|
||||
.type = OptionType::Text,
|
||||
.category = "Paths",
|
||||
.category = "Path Overrides",
|
||||
},
|
||||
{
|
||||
// PatchManagerConfigPath
|
||||
.title = "Patch Manager Config Path",
|
||||
.title = "Patch Manager Config Path Override",
|
||||
.name = "patchcfgpath",
|
||||
.desc = "Sets a custom file path for patch manager config file. Can be used to manage 'profiles' for auto-patches. "
|
||||
"If left empty, %appdata%\\spice2x\\spicetools_patch_manager.json will be used",
|
||||
.type = OptionType::Text,
|
||||
.category = "Paths",
|
||||
.category = "Path Overrides",
|
||||
},
|
||||
{
|
||||
.title = "Intel SDE Folder Path",
|
||||
.title = "Intel SDE",
|
||||
.name = "sde",
|
||||
.desc = "Path to Intel SDE kit path for automatic attaching",
|
||||
.type = OptionType::Text,
|
||||
.category = "Paths",
|
||||
.category = "Development",
|
||||
},
|
||||
{
|
||||
.title = "Path to ea3-config.xml",
|
||||
.title = "ea3-config.xml Override",
|
||||
.name = "e",
|
||||
.desc = "Sets a custom path to ea3-config.xml",
|
||||
.type = OptionType::Text,
|
||||
.category = "Paths",
|
||||
.category = "Path Overrides",
|
||||
},
|
||||
{
|
||||
.title = "Path to app-config.xml",
|
||||
.title = "app-config.xml Override",
|
||||
.name = "a",
|
||||
.desc = "Sets a custom path to app-config.xml",
|
||||
.type = OptionType::Text,
|
||||
.category = "Paths",
|
||||
.category = "Path Overrides",
|
||||
},
|
||||
{
|
||||
.title = "Path to avs-config.xml",
|
||||
.title = "avs-config.xml Override",
|
||||
.name = "v",
|
||||
.desc = "Sets a custom path to avs-config.xml",
|
||||
.type = OptionType::Text,
|
||||
.category = "Paths",
|
||||
.category = "Path Overrides",
|
||||
},
|
||||
{
|
||||
.title = "Path to bootstrap.xml",
|
||||
.title = "bootstrap.xml Override",
|
||||
.name = "b",
|
||||
.desc = "Sets a custom path to bootstrap.xml",
|
||||
.type = OptionType::Text,
|
||||
.category = "Paths",
|
||||
.category = "Path Overrides",
|
||||
},
|
||||
{
|
||||
.title = "Path to log.txt",
|
||||
.title = "log.txt Override",
|
||||
.name = "y",
|
||||
.desc = "Sets a custom path to log.txt",
|
||||
.type = OptionType::Text,
|
||||
.category = "Paths",
|
||||
.category = "Path Overrides",
|
||||
},
|
||||
{
|
||||
.title = "API TCP Port",
|
||||
@@ -1193,6 +1227,28 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.type = OptionType::Bool,
|
||||
.category = "API (Dev)",
|
||||
},
|
||||
{
|
||||
// APIScreenMirrorQuality
|
||||
.title = "API Screen Mirror Quality Override",
|
||||
.name = "apiscreenq",
|
||||
.desc = "JPEG compression level of mirrored images, overriding any client request. "
|
||||
"Value must be between 0 (poor quality) and 100 (best quality), inclusive. Default: 70",
|
||||
.type = OptionType::Integer,
|
||||
.setting_name = "(0-100)",
|
||||
.category = "SpiceCompanion and API",
|
||||
},
|
||||
{
|
||||
// APIScreenMirrorDivide
|
||||
.title = "API Screen Mirror Divide Override",
|
||||
.name = "apiscreendiv",
|
||||
.desc = "Divide value of mirrored images, overriding any client request. "
|
||||
"Divide of 1 means send every pixel, 2 means every other pixel, 3 means every third pixel, and so on; "
|
||||
"increasing the value drastically reduces transfer size at the cost of image quality. "
|
||||
"Value must be 1 or greater. Default: 1",
|
||||
.type = OptionType::Integer,
|
||||
.setting_name = "1",
|
||||
.category = "SpiceCompanion and API",
|
||||
},
|
||||
{
|
||||
.title = "Enable All IO Modules",
|
||||
.name = "io",
|
||||
@@ -1288,6 +1344,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.category = "Touch Parameters",
|
||||
},
|
||||
{
|
||||
// ICCAReaderPort
|
||||
.title = "ICCA Reader Port",
|
||||
.name = "reader",
|
||||
.desc = "Connects to and uses a ICCA on a given COM port",
|
||||
@@ -1364,11 +1421,12 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
},
|
||||
},
|
||||
{
|
||||
// SextetStreamPort
|
||||
.title = "SextetStream Port",
|
||||
.name = "sextet",
|
||||
.desc = "Use a SextetStream device on a given COM port",
|
||||
.type = OptionType::Text,
|
||||
.category = "Miscellaneous",
|
||||
.category = "I/O Options",
|
||||
},
|
||||
{
|
||||
.title = "Enable BemaniTools 5 API",
|
||||
@@ -1469,7 +1527,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
"you use a different backend instead of exclusive WASAPI).\n\n"
|
||||
"Check this if you want games to natively access your audio device",
|
||||
.type = OptionType::Bool,
|
||||
.category = "Audio",
|
||||
.category = "Audio (Hacks)",
|
||||
},
|
||||
{
|
||||
// spice2x_DisableVolumeHook
|
||||
@@ -1481,16 +1539,21 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
"Default: off (prevent games from changing audio volume by hooking IAudioEndpointVolume).\n\n"
|
||||
"Check this if you want games to freely change your volume",
|
||||
.type = OptionType::Bool,
|
||||
.category = "Audio",
|
||||
.category = "Audio (Hacks)",
|
||||
},
|
||||
{
|
||||
.title = "Spice Audio Hook Backend",
|
||||
.name = "audiobackend",
|
||||
.desc = "Selects the audio backend to use when spice audio hook is enabled, overriding exclusive WASAPI. "
|
||||
" Does nothing for games that do not output to exclusive WASAPI",
|
||||
"Does nothing for games that do not output to exclusive WASAPI",
|
||||
.type = OptionType::Enum,
|
||||
.category = "Audio",
|
||||
.elements = {{"asio", "ASIO"}, {"waveout", "waveOut"},{"pipewire", "Pipewire (Linux)"},{"none", "None"}},
|
||||
.elements = {
|
||||
{"asio", "ASIO"},
|
||||
{"waveout", "broken, do not use"},
|
||||
{"pipewire", "Pipewire (Linux)"},
|
||||
{"none", "None"}
|
||||
},
|
||||
},
|
||||
{
|
||||
.title = "Spice Audio Hook ASIO Driver ID",
|
||||
@@ -1506,7 +1569,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
"This is automatically enabled when required and not normally needed",
|
||||
.type = OptionType::Bool,
|
||||
.hidden = true,
|
||||
.category = "Audio",
|
||||
.category = "Audio (Hacks)",
|
||||
},
|
||||
{
|
||||
// DelayBy5Seconds
|
||||
@@ -1559,11 +1622,11 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.elements = {{"0", "90 (CW)"}, {"1", "270 (CCW)"}},
|
||||
},
|
||||
{
|
||||
.title = "Log Level",
|
||||
.title = "AVS Log Level",
|
||||
.name = "loglevel",
|
||||
.desc = "Set the level of detail that gets written to the log",
|
||||
.desc = "Set the level of detail for AVS log messages written to the log. Does not affect logging from spice",
|
||||
.type = OptionType::Enum,
|
||||
.category = "Performance",
|
||||
.category = "Debug Log",
|
||||
.elements = {{"fatal", ""}, {"warning", ""}, {"info", ""}, {"misc", ""}, {"all", ""}, {"disable", ""}},
|
||||
},
|
||||
{
|
||||
@@ -1571,14 +1634,14 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.name = "automap",
|
||||
.desc = "Enable automap in patch configuration",
|
||||
.type = OptionType::Bool,
|
||||
.category = "Development",
|
||||
.category = "Network (Development)",
|
||||
},
|
||||
{
|
||||
.title = "EA Netdump",
|
||||
.name = "netdump",
|
||||
.desc = "Enable automap in network dumping configuration",
|
||||
.type = OptionType::Bool,
|
||||
.category = "Development",
|
||||
.category = "Network (Development)",
|
||||
},
|
||||
{
|
||||
.title = "Discord RPC AppID Override",
|
||||
@@ -1592,35 +1655,45 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.name = "logblock",
|
||||
.desc = "Slower but safer logging used for debugging",
|
||||
.type = OptionType::Bool,
|
||||
.category = "Development",
|
||||
.category = "Debug Log",
|
||||
},
|
||||
{
|
||||
.title = "Debug CreateFile",
|
||||
.name = "createfiledebug",
|
||||
.desc = "Outputs CreateFile debug prints",
|
||||
.type = OptionType::Bool,
|
||||
.category = "Development",
|
||||
.category = "Debug Log",
|
||||
},
|
||||
{
|
||||
.title = "Verbose Graphics Logging",
|
||||
.name = "graphicsverbose",
|
||||
.desc = "Enable the verbose logging of graphics hook code",
|
||||
.type = OptionType::Bool,
|
||||
.category = "Development",
|
||||
.category = "Debug Log",
|
||||
},
|
||||
{
|
||||
.title = "Verbose AVS Logging",
|
||||
.name = "avsverbose",
|
||||
.desc = "Enable the verbose logging of AVS filesystem functions",
|
||||
.type = OptionType::Bool,
|
||||
.category = "Development",
|
||||
.category = "Debug Log",
|
||||
},
|
||||
{
|
||||
// AllowEA3Verbose
|
||||
.title = "Allow EA3 Verbose Debug Logging",
|
||||
.name = "ea3verbose",
|
||||
.desc = "This option is only useful for network developers; leave this OFF.\n\n"
|
||||
"By default, ea3/debug/verbose node is removed by spice to prevent exposing PCBID in the logs. "
|
||||
"When this is enabled, ea3/debug/verbose node in the XML will be kept and exposed to the game",
|
||||
.type = OptionType::Bool,
|
||||
.category = "Debug Log",
|
||||
},
|
||||
{
|
||||
.title = "Disable Colored Output",
|
||||
.name = "nocolor",
|
||||
.desc = "Disable terminal colors for log outputs to console",
|
||||
.type = OptionType::Bool,
|
||||
.category = "Development",
|
||||
.category = "Debug Log",
|
||||
},
|
||||
{
|
||||
.title = "Disable ACP Hook",
|
||||
@@ -1655,7 +1728,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.name = "pebprint",
|
||||
.desc = "Prints PEB on startup to console",
|
||||
.type = OptionType::Bool,
|
||||
.category = "Development",
|
||||
.category = "Debug Log",
|
||||
},
|
||||
{
|
||||
// DumpSystemInfo
|
||||
@@ -1663,7 +1736,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.name = "sysdump",
|
||||
.desc = "Print system information to the log on startup. Default: basic",
|
||||
.type = OptionType::Enum,
|
||||
.category = "Development",
|
||||
.category = "Debug Log",
|
||||
.elements = {
|
||||
{"none", "Nothing"},
|
||||
{"basic", "OS, CPU, SMBIOS, GPU"},
|
||||
@@ -1748,6 +1821,35 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.game_name = "Mahjong Fight Girl",
|
||||
.category = "Game Options (Advanced)"
|
||||
},
|
||||
{
|
||||
// PCArgs
|
||||
.title = "PC Arguments Override",
|
||||
.name = "pcargs",
|
||||
.desc = "Command line arguments passed to the game.",
|
||||
.type = OptionType::Text,
|
||||
.setting_name = "",
|
||||
.game_name = "Polaris Chord",
|
||||
.category = "Game Options (Advanced)",
|
||||
},
|
||||
{
|
||||
// PCNoIO
|
||||
.title = "PC Disable IO Emulation",
|
||||
.name = "pcnoio",
|
||||
.desc = "Disables BI2X hooks for PC",
|
||||
.type = OptionType::Bool,
|
||||
.setting_name = "",
|
||||
.game_name = "Polaris Chord",
|
||||
.category = "Game Options (Advanced)"
|
||||
},
|
||||
{
|
||||
// PCKnobMode
|
||||
.title = "PC Fader Knobs Mode",
|
||||
.name = "pcknobs",
|
||||
.desc = "Allows SDVX knobs and IIDX turntables to be bound as Polaris Chord faders",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "Polaris Chord",
|
||||
.category = "Game Options",
|
||||
},
|
||||
{
|
||||
// spice2x_LightsOverallBrightness
|
||||
.title = "Lights Brightness Adjustment",
|
||||
@@ -1842,6 +1944,24 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.game_name = "Beatmania IIDX",
|
||||
.category = "Graphics (Windowed)",
|
||||
},
|
||||
{
|
||||
// IIDXWindowedSubscreenBorderless
|
||||
.title = "IIDX Windowed Subscreen Borderless",
|
||||
.name = "iidxwsubborderless",
|
||||
.desc = "Remove window decoration from windowed subscreen",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "Beatmania IIDX",
|
||||
.category = "Graphics (Windowed)",
|
||||
},
|
||||
{
|
||||
// IIDXWindowedSubscreenAlwaysOnTop
|
||||
.title = "IIDX Windowed Subscreen Always On Top",
|
||||
.name = "iidxwsubtop",
|
||||
.desc = "Keep windowed subscreen on top",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "Beatmania IIDX",
|
||||
.category = "Graphics (Windowed)",
|
||||
},
|
||||
{
|
||||
// spice2x_JubeatLegacyTouch
|
||||
.title = "JB Legacy Touch Targets",
|
||||
@@ -1875,7 +1995,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.desc = "For certain buggy ASIO drivers, force unload of ASIO driver when audio stream stops. "
|
||||
"Used for working around ASIO drivers that lock up after force quitting games",
|
||||
.type = OptionType::Bool,
|
||||
.category = "Audio",
|
||||
.category = "Audio (Hacks)",
|
||||
},
|
||||
{
|
||||
// spice2x_IIDXNoESpec
|
||||
@@ -2129,6 +2249,23 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.setting_name = "20",
|
||||
.category = "I/O Options",
|
||||
},
|
||||
{
|
||||
// InputRequiresFocus
|
||||
.title = "Input Requires Focus",
|
||||
.name = "inputfocus",
|
||||
.desc =
|
||||
"Determine input behavior when game window is not in focus.\n\n"
|
||||
"never: allow input regardless of focus\n"
|
||||
"naive (default): only naive bindings check for window focus, rawinput binds are always allowed\n"
|
||||
"always: only process input when window is in focus",
|
||||
.type = OptionType::Enum,
|
||||
.category = "I/O Options",
|
||||
.elements = {
|
||||
{"never", ""},
|
||||
{"naive", ""},
|
||||
{"always", ""},
|
||||
},
|
||||
},
|
||||
{
|
||||
// NostalgiaPoke
|
||||
.title = "Nost Screen Poke",
|
||||
@@ -2153,6 +2290,107 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
{"2", "double buffer"},
|
||||
{"3", "triple buffer"},
|
||||
},
|
||||
},
|
||||
{
|
||||
// SDVXWindowedSubscreenSize
|
||||
.title = "SDVX Windowed Subscreen Size",
|
||||
.name = "sdvxwsubsize",
|
||||
.desc = "Size of the subscreen window. Defaults to (1920,1080)",
|
||||
.type = OptionType::Text,
|
||||
.setting_name = "1920,1080",
|
||||
.game_name = "Sound Voltex",
|
||||
.category = "Graphics (Windowed)",
|
||||
},
|
||||
{
|
||||
// SDVXWindowedSubscreenPosition
|
||||
.title = "SDVX Windowed Subscreen Position",
|
||||
.name = "sdvxwsubpos",
|
||||
.desc = "Initial position of the subscreen window. Defaults to (0,0)",
|
||||
.type = OptionType::Text,
|
||||
.setting_name = "0,0",
|
||||
.game_name = "Sound Voltex",
|
||||
.category = "Graphics (Windowed)",
|
||||
},
|
||||
{
|
||||
// SDVXWindowedSubscreenBorderless
|
||||
.title = "SDVX Windowed Subscreen Borderless",
|
||||
.name = "sdvxwsubborderless",
|
||||
.desc = "Remove window decoration from windowed subscreen",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "Sound Voltex",
|
||||
.category = "Graphics (Windowed)",
|
||||
},
|
||||
{
|
||||
// SDVXWindowedSubscreenAlwaysOnTop
|
||||
.title = "SDVX Windowed Subscreen Always On Top",
|
||||
.name = "sdvxwsubtop",
|
||||
.desc = "Keep windowed subscreen on top",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "Sound Voltex",
|
||||
.category = "Graphics (Windowed)",
|
||||
},
|
||||
{
|
||||
// LovePlusCamEnable
|
||||
.title = "LovePlus Camera Enable",
|
||||
.name = "lovepluscam",
|
||||
.desc = "Allow game to access camera; camera must be compatible with game",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "LovePlus",
|
||||
.category = "Game Options",
|
||||
},
|
||||
{
|
||||
// LovePlusPrinterOutputPath
|
||||
.title = "LovePlus Printer Output Path",
|
||||
.name = "lpprinterpath",
|
||||
.desc = "Path to folder where images will be stored",
|
||||
.type = OptionType::Text,
|
||||
.game_name = "LovePlus",
|
||||
.category = "Game Options (Advanced)",
|
||||
},
|
||||
{
|
||||
.title = "LovePlus Printer Output Clear",
|
||||
.name = "lpprinterclear",
|
||||
.desc = "Clean up saved images in the output directory on startup",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "LovePlus",
|
||||
.category = "Game Options (Advanced)",
|
||||
},
|
||||
{
|
||||
.title = "LovePlus Printer Output Overwrite",
|
||||
.name = "lpprinteroverwrite",
|
||||
.desc = "Always overwrite the same file in output directory",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "LovePlus",
|
||||
.category = "Game Options (Advanced)",
|
||||
},
|
||||
{
|
||||
// LovePlusPrinterOutputFormat
|
||||
.title = "LovePlus Printer Output Format",
|
||||
.name = "lpprinterformat",
|
||||
.desc = "File format for printer output",
|
||||
.type = OptionType::Text,
|
||||
.setting_name = "(png/bmp/tga/jpg)",
|
||||
.game_name = "LovePlus",
|
||||
.category = "Game Options (Advanced)",
|
||||
},
|
||||
{
|
||||
.title = "LovePlus Printer JPG Quality",
|
||||
.name = "lpprinterjpgquality",
|
||||
.desc = "Quality setting in percent if JPG format is used",
|
||||
.type = OptionType::Integer,
|
||||
.setting_name = "(0-100)",
|
||||
.game_name = "LovePlus",
|
||||
.category = "Game Options (Advanced)",
|
||||
},
|
||||
{
|
||||
// OptionConflictResolution
|
||||
.title = "Command Line Args Override",
|
||||
.name = "cmdoverride",
|
||||
.desc = "By default, option values in spicecfg take precedence over command-line args, for legacy compat.\n"
|
||||
"When this is specified in command line, command-line args take precedence instead",
|
||||
.type = OptionType::Bool,
|
||||
.category = "Development",
|
||||
.disabled = true,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2234,7 +2472,7 @@ std::unique_ptr<std::vector<Option>> launcher::parse_options(int argc, char *arg
|
||||
} else {
|
||||
// validate it is an integer
|
||||
try {
|
||||
std::stoull(argv[i], nullptr, 16);
|
||||
auto _ = std::stoull(argv[i], nullptr, 16);
|
||||
} catch (const std::exception &ex) {
|
||||
log_fatal("options", "parameter for -{} is not a hex number: {}", alias, argv[i]);
|
||||
}
|
||||
@@ -2335,12 +2573,25 @@ std::vector<Option> launcher::merge_options(
|
||||
auto &new_option = merged.emplace_back(option.get_definition(), "");
|
||||
new_option.disabled = true;
|
||||
|
||||
for (auto &value : option.values()) {
|
||||
new_option.value_add(value);
|
||||
}
|
||||
for (auto &value : override.values()) {
|
||||
new_option.value_add(value);
|
||||
if (USE_CMD_OVERRIDE) {
|
||||
// command-line arguments take precedence (opt-in)
|
||||
for (auto &value : override.values()) {
|
||||
new_option.value_add(value);
|
||||
}
|
||||
for (auto &value : option.values()) {
|
||||
new_option.value_add(value);
|
||||
}
|
||||
} else {
|
||||
// spicecfg options take precedence (default)
|
||||
// this sucks, but it's the default for legacy spicetools compat
|
||||
for (auto &value : option.values()) {
|
||||
new_option.value_add(value);
|
||||
}
|
||||
for (auto &value : override.values()) {
|
||||
new_option.value_add(value);
|
||||
}
|
||||
}
|
||||
new_option.conflicting = true;
|
||||
} else {
|
||||
auto &new_option = merged.emplace_back(override.get_definition(), "");
|
||||
new_option.disabled = true;
|
||||
@@ -2356,7 +2607,6 @@ std::vector<Option> launcher::merge_options(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return merged;
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +86,7 @@ namespace launcher {
|
||||
spice2x_SDVXSubRedraw,
|
||||
LoadDDRModule,
|
||||
DDR43Mode,
|
||||
DDRSkipCodecRegisteration,
|
||||
LoadPopnMusicModule,
|
||||
PopnMusicForceHDMode,
|
||||
PopnMusicForceSDMode,
|
||||
@@ -117,6 +118,7 @@ namespace launcher {
|
||||
LoadCCJModule,
|
||||
LoadQKSModule,
|
||||
LoadMFGModule,
|
||||
LoadPCModule,
|
||||
LoadMusecaModule,
|
||||
PathToModules,
|
||||
ScreenshotFolder,
|
||||
@@ -136,6 +138,8 @@ namespace launcher {
|
||||
APISerialBaud,
|
||||
APIPretty,
|
||||
APIDebugMode,
|
||||
APIScreenMirrorQuality,
|
||||
APIScreenMirrorDivide,
|
||||
EnableAllIOModules,
|
||||
EnableACIOModule,
|
||||
EnableICCAModule,
|
||||
@@ -184,6 +188,7 @@ namespace launcher {
|
||||
DebugCreateFile,
|
||||
VerboseGraphicsLogging,
|
||||
VerboseAVSLogging,
|
||||
AllowEA3Verbose,
|
||||
DisableColoredOutput,
|
||||
DisableACPHook,
|
||||
DisableSignalHandling,
|
||||
@@ -199,6 +204,9 @@ namespace launcher {
|
||||
MFGArgs,
|
||||
MFGCabType,
|
||||
MFGNoIO,
|
||||
PCArgs,
|
||||
PCNoIO,
|
||||
PCKnobMode,
|
||||
spice2x_LightsOverallBrightness,
|
||||
spice2x_WindowBorder,
|
||||
spice2x_WindowSize,
|
||||
@@ -207,6 +215,8 @@ namespace launcher {
|
||||
WindowForceScaling,
|
||||
spice2x_IIDXWindowedSubscreenSize,
|
||||
spice2x_IIDXWindowedSubscreenPosition,
|
||||
IIDXWindowedSubscreenBorderless,
|
||||
IIDXWindowedSubscreenAlwaysOnTop,
|
||||
spice2x_JubeatLegacyTouch,
|
||||
spice2x_RBTouchScale,
|
||||
spice2x_AsioForceUnload,
|
||||
@@ -229,8 +239,20 @@ namespace launcher {
|
||||
IIDXRecQuality,
|
||||
MidiAlgoVer,
|
||||
MidiNoteSustain,
|
||||
InputRequiresFocus,
|
||||
NostalgiaPoke,
|
||||
ForceBackBufferCount,
|
||||
SDVXWindowedSubscreenSize,
|
||||
SDVXWindowedSubscreenPosition,
|
||||
SDVXWindowedSubscreenBorderless,
|
||||
SDVXWindowedSubscreenAlwaysOnTop,
|
||||
LovePlusCamEnable,
|
||||
LovePlusPrinterOutputPath,
|
||||
LovePlusPrinterOutputClear,
|
||||
LovePlusPrinterOutputOverwrite,
|
||||
LovePlusPrinterOutputFormat,
|
||||
LovePlusPrinterJPGQuality,
|
||||
OptionConflictResolution,
|
||||
};
|
||||
|
||||
enum class OptionsCategory {
|
||||
@@ -242,6 +264,8 @@ namespace launcher {
|
||||
};
|
||||
}
|
||||
|
||||
extern bool USE_CMD_OVERRIDE;
|
||||
|
||||
const std::vector<std::string> &get_categories(Options::OptionsCategory category);
|
||||
const std::vector<OptionDefinition> &get_option_definitions();
|
||||
std::unique_ptr<std::vector<Option>> parse_options(int argc, char *argv[]);
|
||||
|
||||
@@ -40,6 +40,8 @@ namespace richpresence {
|
||||
{"Busou Shinki: Armored Princess Battle Conductor", "1226739666741366916"},
|
||||
{"Chase Chase Jokers", "1226739863915593770"},
|
||||
{"QuizKnock STADIUM", "1226739930328334478"},
|
||||
{"Mahjong Fight Girl", "1417371188342030468"},
|
||||
{"Polaris Chord", "1417371592224407552"},
|
||||
};
|
||||
|
||||
// state
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "easrv/easrv.h"
|
||||
#include "rawinput/rawinput.h"
|
||||
#include "hooks/audio/audio.h"
|
||||
#include "util/deferlog.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
#include "launcher.h"
|
||||
@@ -23,6 +24,9 @@ namespace launcher {
|
||||
// therefore, subsystems need to be guarded against multiple unload attempts
|
||||
log_info("launcher", "stopping subsystems");
|
||||
|
||||
// before shutting down logger, dump any deferred log messages
|
||||
deferredlogs::dump_to_logger();
|
||||
|
||||
// stop ea server
|
||||
easrv_shutdown();
|
||||
|
||||
|
||||
+30
-1
@@ -1,14 +1,15 @@
|
||||
#include "signal.h"
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
#include <windows.h>
|
||||
#include <dbghelp.h>
|
||||
|
||||
#include "acio/acio.h"
|
||||
#include "external/stackwalker/stackwalker.h"
|
||||
#include "hooks/libraryhook.h"
|
||||
#include "launcher/shutdown.h"
|
||||
#include "util/deferlog.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/libutils.h"
|
||||
#include "util/logging.h"
|
||||
@@ -97,6 +98,34 @@ static LONG WINAPI TopLevelExceptionFilter(struct _EXCEPTION_POINTERS *Exception
|
||||
// print signal
|
||||
log_warning("signal", "exception raised: {}", exception_code(ExceptionRecord));
|
||||
|
||||
switch (ExceptionRecord->ExceptionCode) {
|
||||
case EXCEPTION_ILLEGAL_INSTRUCTION:
|
||||
deferredlogs::defer_error_messages({
|
||||
"illegal instruction exception:",
|
||||
" either your CPU is too old (e.g., does not support SSE4.2 or AVX2 ",
|
||||
" but perhaps the game requires it); or, a bad patch was applied."
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// check ACIO init failures
|
||||
if (acio::IO_INIT_IN_PROGRESS) {
|
||||
deferredlogs::defer_error_messages({
|
||||
"exception raised during ACIO init, this usually happens when ",
|
||||
" a third party application interferes with hooks",
|
||||
" please check for the following, disable them, and try launching the game again:",
|
||||
" * RivaTuner Statistics Server (RTSS)",
|
||||
" * MSI Afterburner",
|
||||
" * kernel mode anti-cheat"
|
||||
});
|
||||
}
|
||||
|
||||
// dump deferred logs BEFORE stack trace since some errors cause stack trace logic to hang
|
||||
// (e.g., ACIO init hang due to RTSS)
|
||||
deferredlogs::dump_to_logger(true);
|
||||
|
||||
// walk the exception chain
|
||||
struct _EXCEPTION_RECORD *record_cause = ExceptionRecord->ExceptionRecord;
|
||||
while (record_cause != nullptr) {
|
||||
|
||||
+3
-1
@@ -1,12 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
namespace launcher::signal {
|
||||
|
||||
// settings
|
||||
extern bool DISABLE;
|
||||
extern bool USE_VEH_WORKAROUND;
|
||||
|
||||
//void print_stacktrace();
|
||||
void attach();
|
||||
void init();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user