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);