diff --git a/.gitignore b/.gitignore
index 07a2a7a..8dfb3a6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,4 +17,9 @@ dist/*
external/cv2pdb/*
-.ccache/*
\ No newline at end of file
+.ccache/*
+
+# Visual Studio
+.vs
+out
+CMakeSettings.json
diff --git a/.idea/.gitignore b/.idea/.gitignore
index 13566b8..3588def 100644
--- a/.idea/.gitignore
+++ b/.idea/.gitignore
@@ -6,3 +6,5 @@
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
+# Unnecessary plugin data
+/markdown-navigator.xml
diff --git a/.idea/runConfigurations/Deploy_Extra_x86_.xml b/.idea/runConfigurations/Deploy_Extra_x86_.xml
index bca6430..dd7d022 100644
--- a/.idea/runConfigurations/Deploy_Extra_x86_.xml
+++ b/.idea/runConfigurations/Deploy_Extra_x86_.xml
@@ -16,6 +16,7 @@
+
diff --git a/.idea/runConfigurations/spicetools_stubs_cpusbxpkm.xml b/.idea/runConfigurations/spicetools_stubs_cpusbxpkm.xml
new file mode 100644
index 0000000..167d0da
--- /dev/null
+++ b/.idea/runConfigurations/spicetools_stubs_cpusbxpkm.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bc12575..5d0d8f2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -80,6 +80,25 @@ if(MSVC)
# enable COMDAT folding for even smaller release builds
add_link_options("$<$:/OPT:ICF>")
+
+ # always use UTF-8 (fix 4819)
+ add_compile_options("/utf-8")
+
+ # spectre mitigation warning
+ add_compile_options("/wd5045")
+
+ # implicit type convert warnings
+ add_compile_options("/wd4244")
+ add_compile_options("/wd4267")
+ add_compile_options("/wd4305")
+
+ # unreferenced local variable
+ add_compile_options("/wd4101")
+
+ # warning in winbase.h??
+ add_compile_options("/wd5039")
+
+
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# disable warnings about using non _s variants like strncpy
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
@@ -124,8 +143,8 @@ else()
# https://github.com/msys2/MINGW-packages/pull/6880
# some games crash if some DLLS load above 4GB VA, so manually set base address to standard 32-bit VA,
# and might as well double make sure ASLR is disabled here
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections,--disable-dynamicbase,--image-base=0x400000")
- set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections,--disable-dynamicbase,--image-base=0x400000")
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections,--disable-dynamicbase,--image-base=0x400000,--enable-stdcall-fixup")
+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections,--disable-dynamicbase,--image-base=0x400000,--enable-stdcall-fixup")
# set visibility to hidden
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fvisibility=hidden")
@@ -160,8 +179,8 @@ else()
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-fno-ident -ffunction-sections -fdata-sections")
# linker fix to load below 4GB
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections,--disable-dynamicbase,--image-base=0x400000")
- set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections,--disable-dynamicbase,--image-base=0x400000")
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections,--disable-dynamicbase,--image-base=0x400000,--enable-stdcall-fixup")
+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections,--disable-dynamicbase,--image-base=0x400000,--enable-stdcall-fixup")
# set visibility to hidden
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fvisibility=hidden")
@@ -184,8 +203,8 @@ else()
set(CMAKE_CXX_FLAGS_DEBUG "-gdwarf")
# linker fix to load below 4GB
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--disable-dynamicbase,--image-base=0x400000")
- set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--disable-dynamicbase,--image-base=0x400000")
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--disable-dynamicbase,--image-base=0x400000,--enable-stdcall-fixup")
+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--disable-dynamicbase,--image-base=0x400000,--enable-stdcall-fixup")
# enable debug symbols on level 3 and keep frame pointers
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g3 -fno-omit-frame-pointer")
@@ -443,6 +462,9 @@ set(SOURCE_FILES ${SOURCE_FILES}
games/mfg/mfg.cpp
games/mfg/io.cpp
games/mfg/bi2a_hook.cpp
+ games/pc/pc.cpp
+ games/pc/io.cpp
+ games/pc/bi2x_hook.cpp
# hooks
hooks/audio/audio.cpp
@@ -592,6 +614,8 @@ set(SOURCE_FILES ${SOURCE_FILES}
util/lz77.cpp
util/tapeled.cpp
util/execexe.cpp
+ util/dependencies.cpp
+ util/deferlog.cpp
)
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "Source Files" FILES ${SOURCE_FILES})
@@ -742,6 +766,16 @@ if(NOT MSVC)
set_target_properties(spicetools_stubs_nvEncodeAPI64 PROPERTIES COMPILE_FLAGS "-m64" LINK_FLAGS "-m64")
endif()
+# cpusbxpkm.dll (32 bit)
+set(SOURCE_FILES stubs/cpusbxpkm.cpp)
+add_library(spicetools_stubs_cpusbxpkm SHARED ${SOURCE_FILES} stubs/cpusbxpkm.def)
+set_target_properties(spicetools_stubs_cpusbxpkm PROPERTIES PREFIX "")
+set_target_properties(spicetools_stubs_cpusbxpkm PROPERTIES OUTPUT_NAME "cpusbxpkm")
+
+if(NOT MSVC)
+ set_target_properties(spicetools_stubs_cpusbxpkm PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
+endif()
+
# output directories
####################
@@ -751,7 +785,7 @@ set_target_properties(spicetools_cfg
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools")
# output 32bit
-set_target_properties(spicetools_spice spicetools_spice_laa spicetools_stubs_kbt spicetools_stubs_kld
+set_target_properties(spicetools_spice spicetools_spice_laa spicetools_stubs_kbt spicetools_stubs_kld spicetools_stubs_cpusbxpkm
PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/archive32"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools/32"
diff --git a/README.md b/README.md
index e7c754d..f224037 100644
--- a/README.md
+++ b/README.md
@@ -247,6 +247,25 @@ which also means that your hex edits are applicable directly.
- sets the contents of the 16 segment display and disables writes from game
- ticker_reset()
- re-enables writes from game
+- tapeled_get(name: str, ...)
+ - returns a list containing a dict of the current tape LED states. The dict keys are:
+ - `Stage Left`
+ - `Stage Right`
+ - `Cabinet Left`
+ - `Cabinet Right`
+ - `Control Panel Under`
+ - `Ceiling Left`
+ - `Title Left`
+ - `Title Right`
+ - `Ceiling Right`
+ - `Touch Panel Left`
+ - `Touch Panel Right`
+ - `Side Panel Left Inner`
+ - `Side Panel Left Outer`
+ - `Side Panel Left`
+ - `Side Panel Right Outer`
+ - `Side Panel Right Inner`
+ - `Side Panel Right`
#### LCD
- info()
diff --git a/acio/acio.cpp b/acio/acio.cpp
index 2ae28f4..be8546f 100644
--- a/acio/acio.cpp
+++ b/acio/acio.cpp
@@ -41,6 +41,7 @@
namespace acio {
HINSTANCE DLL_INSTANCE = nullptr;
std::vector MODULES;
+ std::atomic IO_INIT_IN_PROGRESS = false;
}
/*
@@ -58,6 +59,7 @@ static inline acio::HookMode get_hookmode() {
void acio::attach() {
log_info("acio", "SpiceTools ACIO");
+ IO_INIT_IN_PROGRESS = true;
// load settings and instance
acio::DLL_INSTANCE = LoadLibraryA("libacio.dll");
@@ -111,6 +113,8 @@ void acio::attach() {
for (auto &module : MODULES) {
module->attach();
}
+
+ IO_INIT_IN_PROGRESS = false;
}
void acio::attach_icca() {
diff --git a/acio/acio.h b/acio/acio.h
index b2f1838..e9497a2 100644
--- a/acio/acio.h
+++ b/acio/acio.h
@@ -1,5 +1,6 @@
#pragma once
+#include
#include
#include
@@ -11,6 +12,7 @@ namespace acio {
// globals
extern HINSTANCE DLL_INSTANCE;
extern std::vector MODULES;
+ extern std::atomic IO_INIT_IN_PROGRESS;
void attach();
void attach_icca();
diff --git a/acio2emu/handle.cpp b/acio2emu/handle.cpp
index 2e6a86e..155ac73 100644
--- a/acio2emu/handle.cpp
+++ b/acio2emu/handle.cpp
@@ -31,7 +31,7 @@ namespace acio2emu {
}
};
- IOBHandle::IOBHandle(std::wstring device) : device_(device) {
+ IOBHandle::IOBHandle(LPCWSTR device) : device_(device) {
nodes_[0] = std::make_unique(this);
}
diff --git a/acio2emu/handle.h b/acio2emu/handle.h
index 5939d54..d24bb22 100644
--- a/acio2emu/handle.h
+++ b/acio2emu/handle.h
@@ -26,7 +26,7 @@ namespace acio2emu {
void forward_packet_(const Packet &packet);
public:
- IOBHandle(std::wstring device);
+ IOBHandle(LPCWSTR device);
bool register_node(std::unique_ptr node);
int number_of_nodes() const;
diff --git a/acioemu/icca.cpp b/acioemu/icca.cpp
index 2733aa7..56fce06 100644
--- a/acioemu/icca.cpp
+++ b/acioemu/icca.cpp
@@ -102,7 +102,7 @@ bool ICCADevice::parse_msg(MessageData *msg_in,
// send version data
auto msg = this->create_msg(msg_in, MSG_VERSION_SIZE);
if (
- avs::game::is_model({"LDJ", "TBS", "UJK"}) ||
+ avs::game::is_model({"LDJ", "TBS", "UJK", "XIF"}) ||
// SDVX Valkyrie cabinet mode
(avs::game::is_model("KFC") && (avs::game::SPEC[0] == 'G' || avs::game::SPEC[0] == 'H'))
) {
@@ -373,7 +373,7 @@ void ICCADevice::update_card(int unit) {
bool kb_insert_press = false;
// eamio keypress
- kb_insert_press |= eamuse_get_keypad_state((size_t) unit) & (1 << EAM_IO_INSERT);
+ kb_insert_press |= static_cast(eamuse_get_keypad_state((size_t) unit) & (1 << EAM_IO_INSERT));
// check for card
if (this->cards[unit] == nullptr && (eamuse_card_insert_consume(this->node_count, unit) || kb_insert_press)) {
@@ -521,7 +521,7 @@ void ICCADevice::update_status(int unit) {
buffer[10] = felica ? 0x01 : 0x00;
} else if (
- avs::game::is_model({"LDJ", "TBS"}) ||
+ avs::game::is_model({"LDJ", "TBS", "XIF"}) ||
// SDVX Valkyrie cabinet mode
(avs::game::is_model("KFC") && (avs::game::SPEC[0] == 'G' || avs::game::SPEC[0] == 'H'))) {
diff --git a/api/modules/capture.cpp b/api/modules/capture.cpp
index 9cab7e7..5bef6a3 100644
--- a/api/modules/capture.cpp
+++ b/api/modules/capture.cpp
@@ -9,6 +9,9 @@ using namespace rapidjson;
namespace api::modules {
+ std::optional CAPTURE_QUALITY;
+ std::optional CAPTURE_DIVIDE;
+
static thread_local std::vector CAPTURE_BUFFER;
Capture::Capture() : Module("capture") {
@@ -44,12 +47,21 @@ namespace api::modules {
int screen = 0;
int quality = 70;
int divide = 1;
- if (req.params.Size() > 0 && req.params[0].IsUint())
+ if (req.params.Size() > 0 && req.params[0].IsUint()) {
screen = req.params[0].GetUint();
- if (req.params.Size() > 1 && req.params[1].IsUint())
+ }
+
+ if (CAPTURE_QUALITY.has_value()) {
+ quality = CAPTURE_QUALITY.value();
+ } else if (req.params.Size() > 1 && req.params[1].IsUint()) {
quality = req.params[1].GetUint();
- if (req.params.Size() > 2 && req.params[2].IsUint())
+ }
+
+ if (CAPTURE_DIVIDE.has_value()) {
+ divide = CAPTURE_DIVIDE.value();
+ } else if (req.params.Size() > 2 && req.params[2].IsUint()) {
divide = req.params[2].GetUint();
+ }
// receive JPEG data
uint64_t timestamp = 0;
diff --git a/api/modules/capture.h b/api/modules/capture.h
index 8b02b02..fb8c55d 100644
--- a/api/modules/capture.h
+++ b/api/modules/capture.h
@@ -1,10 +1,15 @@
#pragma once
+#include
+
#include "api/module.h"
#include "api/request.h"
namespace api::modules {
+ extern std::optional CAPTURE_QUALITY;
+ extern std::optional CAPTURE_DIVIDE;
+
class Capture : public Module {
public:
Capture();
diff --git a/api/modules/iidx.cpp b/api/modules/iidx.cpp
index 43860b2..b65423f 100644
--- a/api/modules/iidx.cpp
+++ b/api/modules/iidx.cpp
@@ -1,13 +1,9 @@
#include "iidx.h"
#include
-#include
-#include "games/iidx/iidx.h"
-#include "external/rapidjson/document.h"
using namespace std::placeholders;
using namespace rapidjson;
-
namespace api::modules {
// settings
@@ -17,6 +13,11 @@ namespace api::modules {
functions["ticker_get"] = std::bind(&IIDX::ticker_get, this, _1, _2);
functions["ticker_set"] = std::bind(&IIDX::ticker_set, this, _1, _2);
functions["ticker_reset"] = std::bind(&IIDX::ticker_reset, this, _1, _2);
+ functions["tapeled_get"] = std::bind(&IIDX::tapeled_get, this, _1, _2);
+
+ for (auto &light : games::iidx::TAPELED_MAPPING) {
+ this->lights_by_names.emplace(light.lightName, light);
+ }
}
/**
@@ -69,4 +70,51 @@ namespace api::modules {
// disable read only
games::iidx::IIDXIO_LED_TICKER_READONLY = false;
}
+
+ /**
+ * tapeled_get()
+ * tapeled_get(name: str, ...)
+ */
+ void IIDX::tapeled_get(Request &req, Response &res) {
+ Value response_object(kObjectType);
+
+ // all tape leds
+ if (req.params.Size() == 0) {
+ // Iterate through each device and dump its lights data into the response
+ for (const auto &mapping : games::iidx::TAPELED_MAPPING) {
+ copy_tapeled_data(res, response_object, mapping);
+ }
+ } else {
+ // specified light names
+ for (Value ¶m : req.params.GetArray()) {
+ // check params
+ if (!param.IsString()) {
+ error_type(res, "name", "string");
+ return;
+ }
+ const auto name = param.GetString();
+ if (const auto &it = lights_by_names.find(name); it != lights_by_names.end()) {
+ const auto mapping = it->second.get();
+ copy_tapeled_data(res, response_object, mapping);
+ }
+ }
+ }
+
+ res.add_data(response_object);
+ }
+
+ void IIDX::copy_tapeled_data(Response &res, Value &response_object, const tapeledutils::tape_led &mapping) {
+ // Create an array for the light state
+ Value light_state(kArrayType);
+ light_state.Reserve(mapping.data.capacity() * 3, res.doc()->GetAllocator());
+ for (const auto [r, g, b] : mapping.data) {
+ light_state.PushBack(r, res.doc()->GetAllocator());
+ light_state.PushBack(g, res.doc()->GetAllocator());
+ light_state.PushBack(b, res.doc()->GetAllocator());
+ }
+
+ // Can't use StringRef here, turns some strings partially into null bytes for some reason
+ Value light_name(mapping.lightName.c_str(), res.doc()->GetAllocator());
+ response_object.AddMember(light_name, light_state, res.doc()->GetAllocator());
+ }
}
diff --git a/api/modules/iidx.h b/api/modules/iidx.h
index 50fea1e..41ae20e 100644
--- a/api/modules/iidx.h
+++ b/api/modules/iidx.h
@@ -2,6 +2,7 @@
#include "api/module.h"
#include "api/request.h"
+#include "games/iidx/iidx.h"
namespace api::modules {
@@ -10,10 +11,16 @@ namespace api::modules {
IIDX();
private:
+ // state
+ robin_hood::unordered_map> lights_by_names;
// function definitions
void ticker_get(Request &req, Response &res);
void ticker_set(Request &req, Response &res);
void ticker_reset(Request &req, Response &res);
+ void tapeled_get(Request &req, Response &res);
+
+ // helper
+ void copy_tapeled_data(Response &res, rapidjson::Value &response_object, const tapeledutils::tape_led &mapping);
};
}
diff --git a/api/resources/python/spiceapi/iidx.py b/api/resources/python/spiceapi/iidx.py
index b2736e1..79050a5 100644
--- a/api/resources/python/spiceapi/iidx.py
+++ b/api/resources/python/spiceapi/iidx.py
@@ -16,3 +16,13 @@ def iidx_ticker_set(con: Connection, text: str):
def iidx_ticker_reset(con: Connection):
req = Request("iidx", "ticker_reset")
con.request(req)
+
+
+def iidx_tapeled_get(con: Connection, *light_names):
+ req = Request("iidx", "tapeled_get")
+
+ for light_name in light_names:
+ req.add_param(light_name)
+
+ res = con.request(req)
+ return res.get_data()
diff --git a/avs/core.cpp b/avs/core.cpp
index e46b549..59b648f 100644
--- a/avs/core.cpp
+++ b/avs/core.cpp
@@ -8,6 +8,8 @@
#include "external/robin_hood.h"
#include "launcher/logger.h"
+#include "launcher/signal.h"
+#include "util/deferlog.h"
#include "util/detour.h"
#include "util/fileutils.h"
#include "util/libutils.h"
@@ -1741,7 +1743,17 @@ namespace avs {
return;
}
- static void create_dir(
+ static void avs_dir_err(const std::filesystem::path &src_path)
+ {
+ deferredlogs::defer_error_messages({
+ "AVS filesystem initialization failure was previously detected during boot!",
+ fmt::format(" ERROR: directory could not be created: {}", src_path.string().c_str()),
+ fmt::format(" if you see a crash, it may have been caused by bad contents in {}", avs::core::CFG_PATH.c_str()),
+ " fix the XML file and try again"
+ });
+ }
+
+ static void create_avs_dir(
const std::string_view &avs_path,
const std::string_view &src_path)
{
@@ -1750,6 +1762,7 @@ namespace avs {
auto real_path = std::filesystem::absolute(src_path, err);
if (err) {
+ avs_dir_err(real_path);
log_warning("avs-core", "failed to resolve '{}' path: {}", avs_path, err.message());
return;
}
@@ -1759,7 +1772,9 @@ namespace avs {
if (created) {
log_info("avs-core", "created '{}' at '{}'", avs_path, real_path.string());
}
+
if (err) {
+ avs_dir_err(real_path);
log_warning("avs-core", "failed to create '{}' folder at '{}': {}",
avs_path,
real_path.string(),
@@ -1820,7 +1835,7 @@ namespace avs {
return;
}
- create_dir(avs_path, device_path);
+ create_avs_dir(avs_path, device_path);
}
static void create_avs_config_fs_table(
@@ -1875,7 +1890,7 @@ namespace avs {
continue;
}
- create_dir(dst_path, src_path);
+ create_avs_dir(dst_path, src_path);
} while ((vfs_node = property_node_traversal(vfs_node, TRAVERSE_NEXT_SEARCH_RESULT)));
}
@@ -1929,6 +1944,7 @@ namespace avs {
static const char *LOG_LEVELS[] = { "disable", "fatal", "warning", "info", "misc", "all" };
char current_log_level_buffer[32] { 0 };
uint32_t current_log_level = 0;
+ std::string log_level_as_str;
if (VERSION == AVSLEGACY || VERSION == AVS21360) {
auto level_node = property_search(config, config_node, "/log/level");
@@ -1944,6 +1960,7 @@ namespace avs {
{
if (current_log_level < std::size(LOG_LEVELS)) {
log_info("avs-core", "log level: {}", LOG_LEVELS[current_log_level]);
+ log_level_as_str = LOG_LEVELS[current_log_level];
} else {
log_fatal("avs-core", "log level ({}) is invalid!", current_log_level);
}
@@ -1963,7 +1980,7 @@ namespace avs {
level_node = property_node_create(config, config_node, NODE_TYPE_str, "/log/level",
LOG_LEVELS[current_log_level]);
} else {
- log_fatal("avs-core", "log level ({}) is invalid!", current_log_level);
+ log_fatal("avs-core", "log level ({}) is invalid! *", current_log_level);
}
}
@@ -1976,12 +1993,27 @@ namespace avs {
if (property_node_refer(config, config_node, "/log/level",
NODE_TYPE_str, current_log_level_buffer, sizeof(current_log_level_buffer)) > 0)
{
- log_info("avs-core", "log level: {}", current_log_level_buffer);
+ log_info("avs-core", "log level: {} *", current_log_level_buffer);
+ log_level_as_str = current_log_level_buffer;
} else {
- log_warning("avs-core", "log level: unknown");
+ log_warning("avs-core", "log level: unknown *");
}
}
+ if (log_level_as_str == "disable" ||
+ log_level_as_str == "fatal" ||
+ log_level_as_str == "warning" ||
+ log_level_as_str == "info") {
+
+ deferredlogs::defer_error_messages({
+ fmt::format(
+ "log level is set to `{}` (either in avs-config.xml or using -loglevel)", log_level_as_str),
+ " this log file may have omitted important error messages from the game",
+ " if you are troubleshooting crashes or failures, it is recommended that you",
+ " set AVS Log Level (-loglevel) option to `all`",
+ });
+ }
+
// fix time offset
auto t_now = std::time(nullptr);
auto tm_now = *std::gmtime(&t_now);
diff --git a/avs/core.h b/avs/core.h
index 779f25d..a99c238 100644
--- a/avs/core.h
+++ b/avs/core.h
@@ -4,6 +4,7 @@
#include
#include
#include
+#include
namespace avs {
namespace core {
diff --git a/avs/ea3.cpp b/avs/ea3.cpp
index 58598b4..2c804c5 100644
--- a/avs/ea3.cpp
+++ b/avs/ea3.cpp
@@ -41,6 +41,7 @@ namespace avs {
int HTTP11 = -1;
int URL_SLASH = -1;
int PCB_TYPE = -1;
+ bool EA3_DEBUG_VERBOSE = false;
// handle
std::string VERSION_STR = "unknown";
@@ -356,6 +357,12 @@ namespace avs {
}
}
+ // fall back to default PCBID if node is not found
+ if (!EA3_PCBID[0] && PCBID_CUSTOM.empty()) {
+ log_warning("avs-ea3", "no PCBID set, falling back to default PCBID value (04040000000000000000)");
+ PCBID_CUSTOM = "04040000000000000000";
+ }
+
// custom PCBID
if (!PCBID_CUSTOM.empty()) {
@@ -399,13 +406,18 @@ namespace avs {
avs::core::NODE_TYPE_str, "/ea3/id/accountid", &EA3_ACCOUNTID);
}
- // check if PCBID is defined
+ // check if PCBID is defined - should never hit, left for sanity check only
if (avs::core::property_search(ea3_config, nullptr, "/ea3/id/pcbid") == nullptr) {
log_fatal("avs-ea3", "node not found: /ea3/id/pcbid (try using -p to specify PCBID)");
} else if (strlen(EA3_PCBID) == 0) {
log_fatal("avs-ea3", "no PCBID set (try using -p to specify PCBID)");
}
+ // remove since it can expose pcbid in logged requests
+ if (!EA3_DEBUG_VERBOSE) {
+ avs::core::property_search_remove_safe(ea3_config, nullptr, "/ea3/debug/verbose");
+ }
+
// remember IDs
char pcbid_buffer[256] { 0 };
char accountid_buffer[256] { 0 };
diff --git a/avs/ea3.h b/avs/ea3.h
index 267daf8..d4a8d1a 100644
--- a/avs/ea3.h
+++ b/avs/ea3.h
@@ -28,6 +28,7 @@ namespace avs {
extern int HTTP11;
extern int URL_SLASH;
extern int PCB_TYPE;
+ extern bool EA3_DEBUG_VERBOSE;
// handle
extern std::string VERSION_STR;
diff --git a/avs/game.cpp b/avs/game.cpp
index ca5c1a2..adefa8f 100644
--- a/avs/game.cpp
+++ b/avs/game.cpp
@@ -80,7 +80,7 @@ namespace avs {
if (130 <= dll_path_s.length()) {
log_warning(
"avs-game",
- "PATH TOO LONG WARNING\n\n\n"
+ "PATH TOO LONG WARNING\n\n"
"-------------------------------------------------------------------\n"
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
"WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING\n"
@@ -95,10 +95,26 @@ namespace avs {
"-------------------------------------------------------------------\n\n",
dll_path_s, dll_path_s.length());
}
+
+ // ddr gamemdx.dll user error
+ if (avs::game::is_model("MDX") && DLL_NAME == "gamemdx.dll") {
+ log_fatal(
+ "ddr",
+ "BAD GAME DLL ERROR\n\n"
+ "!!! !!!\n"
+ "!!! -exec gamemdx.dll was specified !!!\n"
+ "!!! this is the wrong DLL; the game will not load !!!\n"
+ "!!! remove -exec argument and try again. !!!\n"
+ "!!! !!!\n"
+ );
+ }
+
+ // file not found on disk
if (!fileutils::file_exists(dll_path)) {
log_warning("avs-game", "game DLL could not be found on disk: {}", dll_path.string().c_str());
log_warning("avs-game", "double check -exec and -modules parameters; unless you know what you're doing, leave them blank");
}
+
if (fileutils::verify_header_pe(dll_path)) {
DLL_INSTANCE = libutils::load_library(dll_path);
}
@@ -106,7 +122,7 @@ namespace avs {
// load entry points
dll_entry_init = (ENTRY_INIT_T) libutils::get_proc(DLL_INSTANCE, ENTRY_INIT_NAME);
dll_entry_main = (ENTRY_MAIN_T) libutils::get_proc(DLL_INSTANCE, ENTRY_MAIN_NAME);
- log_info("avs-game", "loaded successfully ({})", fmt::ptr(DLL_INSTANCE));
+ log_info("avs-game", "loaded {} successfully ({})", DLL_NAME, fmt::ptr(DLL_INSTANCE));
}
bool entry_init(char *sid_code, void *app_param) {
diff --git a/build/resource.h b/build/resource.h
index c356936..62f4372 100644
--- a/build/resource.h
+++ b/build/resource.h
@@ -2,7 +2,6 @@
#define IDC_STATIC -1
#define IDD_DIALOG1 129
-#define IDR_CHANGELOG 130
#define IDR_LICENSES 131
#define IDR_PATCHES 132
#define IDR_README 133
diff --git a/build_all.sh b/build_all.sh
index 713512a..4283280 100755
--- a/build_all.sh
+++ b/build_all.sh
@@ -60,7 +60,7 @@ DIST_ENABLE=1
DIST_FOLDER="./dist"
DIST_NAME="spice2x-$(date +%y)-$(date +%m)-$(date +%d).zip"
DIST_COMMENT=${DIST_NAME}$'\n'"$GIT_BRANCH - $GIT_HEAD"$'\nThank you for playing.'
-TARGETS_32="spicetools_stubs_kbt spicetools_stubs_kld spicetools_cfg spicetools_spice spicetools_spice_laa"
+TARGETS_32="spicetools_stubs_kbt spicetools_stubs_kld spicetools_cfg spicetools_spice spicetools_spice_laa spicetools_stubs_cpusbxpkm"
TARGETS_64="spicetools_stubs_kbt64 spicetools_stubs_kld64 spicetools_stubs_nvEncodeAPI64 spicetools_stubs_nvcuvid spicetools_stubs_nvcuda spicetools_spice64"
# determine build type
@@ -181,7 +181,7 @@ fi
echo "Copy files to output directory..."
rm -rf ${OUTDIR}
mkdir -p ${OUTDIR}
-#mkdir -p ${OUTDIR}/stubs/32
+mkdir -p ${OUTDIR}/stubs/32
mkdir -p ${OUTDIR}/stubs/64
mkdir -p ${OUTDIR}/extras/largeaddressaware
if false # ((DEBUG > 0))
@@ -200,6 +200,7 @@ then
#cp ${BUILDDIR_64}/spicetools/64/nvEncodeAPI64.dll ${OUTDIR}/stubs/64 2>/dev/null
#cp ${BUILDDIR_64}/spicetools/64/nvcuda.dll ${OUTDIR}/stubs/64 2>/dev/null
#cp ${BUILDDIR_64}/spicetools/64/nvcuvid.dll ${OUTDIR}/stubs/64 2>/dev/null
+ #cp ${BUILDDIR_32}/spicetools/32/cpusbxpkm.dll ${OUTDIR}/stubs/32 2>/dev/null
else
# release files
cp ${BUILDDIR_32}/spicetools/spicecfg.exe ${OUTDIR} 2>/dev/null
@@ -213,6 +214,7 @@ else
cp ${BUILDDIR_64}/spicetools/64/nvEncodeAPI64.dll ${OUTDIR}/stubs/64 2>/dev/null
cp ${BUILDDIR_64}/spicetools/64/nvcuda.dll ${OUTDIR}/stubs/64 2>/dev/null
cp ${BUILDDIR_64}/spicetools/64/nvcuvid.dll ${OUTDIR}/stubs/64 2>/dev/null
+ cp ${BUILDDIR_32}/spicetools/32/cpusbxpkm.dll ${OUTDIR}/stubs/32 2>/dev/null
fi
# pack source files to output directory
diff --git a/cfg/Win32D.rc b/cfg/Win32D.rc
index ed201c0..cec5bfd 100644
--- a/cfg/Win32D.rc
+++ b/cfg/Win32D.rc
@@ -9,7 +9,6 @@
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-IDR_CHANGELOG RCDATA "../changelog.txt"
IDR_LICENSES RCDATA "../licenses.txt"
IDR_PATCHES RCDATA "../build/patches.json"
IDR_README RCDATA "../readme.txt"
diff --git a/cfg/api.cpp b/cfg/api.cpp
index ace41c4..461c9d1 100644
--- a/cfg/api.cpp
+++ b/cfg/api.cpp
@@ -1,5 +1,8 @@
#include "api.h"
+#include
+
+#include "launcher/superexit.h"
#include "rawinput/rawinput.h"
#include "rawinput/piuio.h"
#include "util/time.h"
@@ -64,18 +67,29 @@ GameAPI::Buttons::State GameAPI::Buttons::getState(rawinput::RawInputManager *ma
auto current_button = &_button;
auto alternatives = check_alts ? ¤t_button->getAlternatives() : nullptr;
unsigned int button_count = 0;
+ std::optional window_has_focus;
while (true) {
// naive behavior
if (current_button->isNaive()) {
+ GameAPI::Buttons::State state;
+ auto vkey = current_button->getVKey();
+
+ // check for focus
+ if (vkey != INVALID_VKEY && rawinput::NAIVE_REQUIRE_FOCUS) {
+ if (!window_has_focus.has_value()) {
+ window_has_focus = superexit::has_focus();
+ }
+ if (!window_has_focus.value()) {
+ vkey = INVALID_VKEY;
+ }
+ }
// read
- auto vkey = current_button->getVKey();
- GameAPI::Buttons::State state;
- if (vkey == 0xFF) {
+ if (vkey == INVALID_VKEY) {
state = BUTTON_NOT_PRESSED;
} else {
- state = (GetAsyncKeyState(current_button->getVKey()) & 0x8000) ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
+ state = (GetAsyncKeyState(vkey) & 0x8000) ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
}
// invert
@@ -106,6 +120,16 @@ GameAPI::Buttons::State GameAPI::Buttons::getState(rawinput::RawInputManager *ma
auto &devid = current_button->getDeviceIdentifier();
auto device = manager->devices_get(devid, false); // TODO: fix to update only
+ // check for focus
+ if (device && rawinput::RAWINPUT_REQUIRE_FOCUS) {
+ if (!window_has_focus.has_value()) {
+ window_has_focus = superexit::has_focus();
+ }
+ if (!window_has_focus.value()) {
+ device = nullptr;
+ }
+ }
+
// get state if device was marked as updated
GameAPI::Buttons::State state = current_button->getLastState();
double *last_up = nullptr;
@@ -571,6 +595,12 @@ float GameAPI::Analogs::getState(rawinput::Device *device, Analog &analog) {
switch (device->type) {
case rawinput::MOUSE: {
+ // check for focus
+ if (rawinput::NAIVE_REQUIRE_FOCUS && !superexit::has_focus()) {
+ value = analog.getLastState();
+ break;
+ }
+
// get mouse position
auto mouse = device->mouseInfo;
long pos;
diff --git a/cfg/button.cpp b/cfg/button.cpp
index 439f9b3..134439f 100644
--- a/cfg/button.cpp
+++ b/cfg/button.cpp
@@ -284,7 +284,7 @@ std::string Button::getDisplayString(rawinput::RawInputManager* manager) {
std::string vKeyString = fmt::format("{:#x}", vKey);
// device must be existing
- if (this->device_identifier.empty() && vKey == 0xFF) {
+ if (this->device_identifier.empty() && vKey == INVALID_VKEY) {
return "";
}
diff --git a/cfg/button.h b/cfg/button.h
index 4043047..b320b11 100644
--- a/cfg/button.h
+++ b/cfg/button.h
@@ -33,12 +33,14 @@ enum ButtonAnalogType {
extern const char *ButtonAnalogTypeStr[];
+constexpr unsigned short INVALID_VKEY = UINT16_C(0xFF);
+
class Button {
private:
std::vector