Update to spice2x-25-10-07 (pre-apply)

> broken commit
This commit is contained in:
[ ]
2025-11-11 04:57:26 +09:00
parent 359716b850
commit 652ad41845
97 changed files with 3164 additions and 1275 deletions
+270 -20
View File
@@ -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/avshook.h"
#include "hooks/audio/audio.h"
@@ -95,6 +97,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"
@@ -149,6 +152,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
@@ -218,6 +224,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;
@@ -243,6 +250,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()) {
@@ -284,6 +296,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) {
@@ -353,6 +366,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();
@@ -423,9 +439,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;
}
@@ -616,12 +629,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;
}
@@ -661,21 +680,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();
}
@@ -813,6 +853,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();
@@ -835,6 +876,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;
}
@@ -976,12 +1024,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()) {
@@ -1050,12 +1110,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;
@@ -1077,6 +1157,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);
@@ -1163,6 +1247,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)) {
@@ -1247,7 +1376,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())
});
}
}
@@ -1624,6 +1757,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";
@@ -1648,7 +1791,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;
@@ -1776,6 +1926,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());
}
// apply user heap size, if defined
if (user_heap_size > 0) {
@@ -1808,6 +1962,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();
@@ -1828,6 +1997,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;
@@ -1969,15 +2153,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
@@ -1985,12 +2160,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);
@@ -2213,6 +2404,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);
+318 -70
View File
@@ -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,19 @@ 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"}},
.elements = {
{"asio", "ASIO"},
{"waveout", "broken, do not use"}
},
},
{
.title = "Spice Audio Hook ASIO Driver ID",
@@ -1506,7 +1567,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 +1620,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 +1632,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 +1653,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 +1726,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 +1734,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 +1819,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 +1942,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 +1993,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 +2247,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 +2288,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 +2470,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 +2571,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 +2605,6 @@ std::vector<Option> launcher::merge_options(
}
}
}
return merged;
}
+24
View File
@@ -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[]);
+2
View File
@@ -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
+4
View File
@@ -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"
@@ -21,6 +22,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();
// flush/stop logger
logger::stop();
+30 -1
View File
@@ -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
View File
@@ -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();
}