Merge branch 'main' into nac-spice22x

Merge official spice2x 'main', up to b53447b
Notes: dc82c98  is where the nixac fork starts.

- Upstream's OBJECT-library + forbidden-static-DLL-import build refactor
  merged with nixAC's blob/dsdmo resources
- SPICE_XP / runtime large-address-aware detection builds have been
  integrated from upstream
- README.md grabs from upstream; .gitignore keeps nixAC's fork-specific
  entries
This commit is contained in:
2026-08-07 00:21:58 +02:00
359 changed files with 71032 additions and 27946 deletions
+34 -32
View File
@@ -366,6 +366,7 @@ static void __cdecl device_update() {
// update touch
games::jb::touch_update();
auto touched = games::jb::touch_state();
// get buttons
auto &buttons = games::jb::get_buttons();
@@ -382,52 +383,52 @@ static void __cdecl device_update() {
if (Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::CoinMech))) {
DEVICE_INPUT_STATE |= 1 << 29;
}
if (games::jb::TOUCH_STATE[3] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button1))) {
if (touched[3] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button1))) {
DEVICE_INPUT_STATE |= 1 << 13;
}
if (games::jb::TOUCH_STATE[7] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button2))) {
if (touched[7] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button2))) {
DEVICE_INPUT_STATE |= 1 << 9;
}
if (games::jb::TOUCH_STATE[11] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button3))) {
if (touched[11] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button3))) {
DEVICE_INPUT_STATE |= 1 << 21;
}
if (games::jb::TOUCH_STATE[15] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button4))) {
if (touched[15] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button4))) {
DEVICE_INPUT_STATE |= 1 << 17;
}
if (games::jb::TOUCH_STATE[2] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button5))) {
if (touched[2] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button5))) {
DEVICE_INPUT_STATE |= 1 << 14;
}
if (games::jb::TOUCH_STATE[6] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button6))) {
if (touched[6] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button6))) {
DEVICE_INPUT_STATE |= 1 << 10;
}
if (games::jb::TOUCH_STATE[10] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button7))) {
if (touched[10] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button7))) {
DEVICE_INPUT_STATE |= 1 << 22;
}
if (games::jb::TOUCH_STATE[14] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button8))) {
if (touched[14] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button8))) {
DEVICE_INPUT_STATE |= 1 << 18;
}
if (games::jb::TOUCH_STATE[1] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button9))) {
if (touched[1] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button9))) {
DEVICE_INPUT_STATE |= 1 << 15;
}
if (games::jb::TOUCH_STATE[5] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button10))) {
if (touched[5] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button10))) {
DEVICE_INPUT_STATE |= 1 << 11;
}
if (games::jb::TOUCH_STATE[9] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button11))) {
if (touched[9] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button11))) {
DEVICE_INPUT_STATE |= 1 << 23;
}
if (games::jb::TOUCH_STATE[13] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button12))) {
if (touched[13] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button12))) {
DEVICE_INPUT_STATE |= 1 << 19;
}
if (games::jb::TOUCH_STATE[0] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button13))) {
if (touched[0] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button13))) {
DEVICE_INPUT_STATE |= 1 << 24;
}
if (games::jb::TOUCH_STATE[4] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button14))) {
if (touched[4] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button14))) {
DEVICE_INPUT_STATE |= 1 << 12;
}
if (games::jb::TOUCH_STATE[8] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button15))) {
if (touched[8] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button15))) {
DEVICE_INPUT_STATE |= 1 << 26;
}
if (games::jb::TOUCH_STATE[12] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button16))) {
if (touched[12] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button16))) {
DEVICE_INPUT_STATE |= 1 << 20;
}
@@ -439,6 +440,7 @@ static void __cdecl device_update() {
// update touch
games::jb::touch_update();
auto touched = games::jb::touch_state();
// get buttons
auto &buttons = games::jb::get_buttons();
@@ -455,52 +457,52 @@ static void __cdecl device_update() {
if (Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::CoinMech))) {
DEVICE_INPUT_STATE |= 1 << 24;
}
if (games::jb::TOUCH_STATE[0] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button1))) {
if (touched[0] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button1))) {
DEVICE_INPUT_STATE |= 1 << 5;
}
if (games::jb::TOUCH_STATE[1] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button2))) {
if (touched[1] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button2))) {
DEVICE_INPUT_STATE |= 1 << 1;
}
if (games::jb::TOUCH_STATE[2] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button3))) {
if (touched[2] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button3))) {
DEVICE_INPUT_STATE |= 1 << 13;
}
if (games::jb::TOUCH_STATE[3] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button4))) {
if (touched[3] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button4))) {
DEVICE_INPUT_STATE |= 1 << 9;
}
if (games::jb::TOUCH_STATE[4] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button5))) {
if (touched[4] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button5))) {
DEVICE_INPUT_STATE |= 1 << 6;
}
if (games::jb::TOUCH_STATE[5] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button6))) {
if (touched[5] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button6))) {
DEVICE_INPUT_STATE |= 1 << 2;
}
if (games::jb::TOUCH_STATE[6] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button7))) {
if (touched[6] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button7))) {
DEVICE_INPUT_STATE |= 1 << 14;
}
if (games::jb::TOUCH_STATE[7] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button8))) {
if (touched[7] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button8))) {
DEVICE_INPUT_STATE |= 1 << 10;
}
if (games::jb::TOUCH_STATE[8] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button9))) {
if (touched[8] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button9))) {
DEVICE_INPUT_STATE |= 1 << 7;
}
if (games::jb::TOUCH_STATE[9] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button10))) {
if (touched[9] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button10))) {
DEVICE_INPUT_STATE |= 1 << 3;
}
if (games::jb::TOUCH_STATE[10] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button11))) {
if (touched[10] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button11))) {
DEVICE_INPUT_STATE |= 1 << 15;
}
if (games::jb::TOUCH_STATE[11] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button12))) {
if (touched[11] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button12))) {
DEVICE_INPUT_STATE |= 1 << 11;
}
if (games::jb::TOUCH_STATE[12] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button13))) {
if (touched[12] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button13))) {
DEVICE_INPUT_STATE |= 1 << 16;
}
if (games::jb::TOUCH_STATE[13] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button14))) {
if (touched[13] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button14))) {
DEVICE_INPUT_STATE |= 1 << 4;
}
if (games::jb::TOUCH_STATE[14] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button15))) {
if (touched[14] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button15))) {
DEVICE_INPUT_STATE |= 1 << 20;
}
if (games::jb::TOUCH_STATE[15] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button16))) {
if (touched[15] || Buttons::getState(RI_MGR, buttons.at(games::jb::Buttons::Button16))) {
DEVICE_INPUT_STATE |= 1 << 12;
}
}
+99 -18
View File
@@ -1,5 +1,7 @@
#include "eamuse.h"
#include <atomic>
#include <chrono>
#include <fstream>
#include <thread>
@@ -12,14 +14,16 @@
#include "util/time.h"
#include "util/utils.h"
#include "overlay/overlay.h"
#include "overlay/notifications.h"
#include "bt5api.h"
// state
static constexpr double NOTIFICATION_THROTTLE_SECONDS = 3.0;
static bool CARD_INSERT[2] = {false, false};
static double CARD_INSERT_TIME[2] = {0, 0};
static double CARD_INSERT_TIMEOUT = 2.0;
static char CARD_INSERT_UID[2][8];
static char CARD_INSERT_UID[2][8] = {{0}, {0}};
static char CARD_INSERT_UID_ENABLE[2] = {false, false};
static int COIN_STOCK = 0;
static bool COIN_BLOCK = false;
@@ -43,6 +47,9 @@ static uint8_t AUTO_INSERT_CARD_CACHED_DATA[2][8];
// pin macro
bool PIN_MACRO_ENABLED = false;
std::string PIN_MACRO_VALUES[2] = {"", ""};
std::string AUTO_PIN_MACRO_TRIGGER[2];
static std::atomic_bool AUTO_PIN_MACRO_REQUEST[2] {false, false};
static bool AUTO_PIN_MACRO_PLAYER_ACTIVE[2] = {false, false};
static std::thread *PIN_MACRO_THREAD = nullptr;
static bool PIN_MACRO_THREAD_ACTIVE = false;
static uint16_t PIN_MACRO_TRIGGER_KEYS[2] = {
@@ -50,6 +57,18 @@ static uint16_t PIN_MACRO_TRIGGER_KEYS[2] = {
games::OverlayButtons::TriggerPinMacroP2
};
static bool pin_macro_log_hook(void *, const std::string &data, logger::Style, std::string &) {
for (int unit = 0; unit < 2; unit++) {
if (!AUTO_PIN_MACRO_PLAYER_ACTIVE[unit]) {
continue;
}
if (data.find(AUTO_PIN_MACRO_TRIGGER[unit]) != std::string::npos) {
AUTO_PIN_MACRO_REQUEST[unit].store(true);
}
}
return false;
}
bool eamuse_get_card(int active_count, int unit_id, uint8_t *card) {
// get unit index
@@ -87,7 +106,7 @@ bool eamuse_get_card(const std::filesystem::path &path, uint8_t *card, int index
std::unique_lock<std::mutex> lock(CARD_OVERRIDES_LOCK);
const auto card_override = CARD_OVERRIDES[index];
lock.unlock();
// Check if card overrides are present
if (!card_override.empty()) {
@@ -102,6 +121,12 @@ bool eamuse_get_card(const std::filesystem::path &path, uint8_t *card, int index
"{} card override contains an invalid character sequence at byte {} (16 characters, 0-9/A-F only)",
card_override, n);
overlay::notifications::add_throttled(
overlay::notifications::Severity::Error,
fmt::format("eamuse.card_override_error.p{}", index + 1),
NOTIFICATION_THROTTLE_SECONDS,
fmt::format("[P{}] invalid card override", index + 1));
return false;
}
}
@@ -131,7 +156,12 @@ bool eamuse_get_card_from_file(const std::filesystem::path &path, uint8_t *card,
// open file
std::ifstream f(path);
if (!f) {
log_warning("eamuse", "{} can not be opened!", path.string());
log_warning("eamuse", "{} can not be opened!", path);
overlay::notifications::add_throttled(
overlay::notifications::Severity::Error,
fmt::format("eamuse.card_file_error.p{}", index + 1),
NOTIFICATION_THROTTLE_SECONDS,
fmt::format("[P{}] can't open card file", index + 1));
return false;
}
@@ -142,7 +172,13 @@ bool eamuse_get_card_from_file(const std::filesystem::path &path, uint8_t *card,
// check size
if (length < 16) {
log_warning("eamuse", "{} is too small (must be at least 16 characters)", path.string());
log_warning("eamuse", "{} is too small (must be at least 16 characters)", path);
overlay::notifications::add_throttled(
overlay::notifications::Severity::Error,
fmt::format("eamuse.card_file_error.p{}", index + 1),
NOTIFICATION_THROTTLE_SECONDS,
fmt::format("[P{}] card file error", index + 1));
return false;
}
@@ -160,14 +196,19 @@ bool eamuse_get_card_from_file(const std::filesystem::path &path, uint8_t *card,
if (!digit && !character_big && !character_small) {
log_warning("eamuse",
"{} contains an invalid character sequence at byte {} (16 characters, 0-9/A-F only)",
path.string(), n);
path, n);
overlay::notifications::add_throttled(
overlay::notifications::Severity::Error,
fmt::format("eamuse.card_file_error.p{}", index + 1),
NOTIFICATION_THROTTLE_SECONDS,
fmt::format("[P{}] card file error", index + 1));
return false;
}
}
// info
log_info("eamuse", "[P{}] Inserted {}: {}", index+1, path.string(), buffer);
log_info("eamuse", "[P{}] Inserted {}: {}", index+1, path, buffer);
// convert hex to bytes
hex2bin(buffer, card);
@@ -234,8 +275,16 @@ bool eamuse_card_insert_consume(int active_count, int unit_id) {
auto offset = unit_id * games::KeypadButtons::Size;
if ((CARD_INSERT[index] && fabs(get_performance_seconds() - CARD_INSERT_TIME[index]) < CARD_INSERT_TIMEOUT)
|| GameAPI::Buttons::getState(RI_MGR, keypad_buttons->at(games::KeypadButtons::InsertCard + offset))) {
log_info("eamuse", "[P{}] Card insert on reader (total active count: {})", unit_id+1, active_count);
CARD_INSERT[index] = false;
overlay::notifications::add_throttled(
overlay::notifications::Severity::Info,
fmt::format("eamuse.card_inserted.p{}", unit_id + 1),
NOTIFICATION_THROTTLE_SECONDS,
fmt::format("[P{}] card inserted", unit_id + 1));
return true;
}
@@ -305,7 +354,7 @@ void eamuse_coin_start_thread() {
}
// once every two frames
Sleep(1000 / 30);
std::this_thread::sleep_for(std::chrono::milliseconds(1000 / 30));
}
});
}
@@ -322,6 +371,25 @@ void eamuse_pin_macro_start_thread() {
// set active
PIN_MACRO_THREAD_ACTIVE = true;
// a unit is eligible for auto-trigger only if all the static prerequisites are
// satisfied at startup; precomputing this lets the log hook skip per-line checks
// on values that never change at runtime
for (int unit = 0; unit < 2; unit++) {
AUTO_PIN_MACRO_PLAYER_ACTIVE[unit] =
!AUTO_PIN_MACRO_TRIGGER[unit].empty() &&
!PIN_MACRO_VALUES[unit].empty();
if(!AUTO_PIN_MACRO_TRIGGER[unit].empty() && PIN_MACRO_VALUES[unit].empty()) {
log_warning("eamuse", "Configuration error; Pin Macro empty for P{}.", unit+1);
}
}
// register scene log hook so the macro fires on the per-game trigger string,
// but only if at least one player is eligible
if (AUTO_PIN_MACRO_PLAYER_ACTIVE[0] || AUTO_PIN_MACRO_PLAYER_ACTIVE[1]) {
logger::hook_add(pin_macro_log_hook, nullptr);
log_info("eamuse", "AUTO_PIN_MACRO enabled");
}
// create thread
PIN_MACRO_THREAD = new std::thread([]() {
uint16_t keypad_overrides[] = {
@@ -342,15 +410,24 @@ void eamuse_pin_macro_start_thread() {
std::optional<uint8_t> active_unit = std::nullopt;
while (PIN_MACRO_THREAD_ACTIVE) {
// wait for key press
// wait for key press or auto-trigger
if (!active_unit.has_value()) {
for (int unit = 0; unit < 2; unit++) {
if (PIN_MACRO_VALUES[unit].empty()) {
continue;
}
if (overlay_buttons &&
bool key_press = overlay_buttons &&
(!overlay::OVERLAY || overlay::OVERLAY->hotkeys_triggered()) &&
GameAPI::Buttons::getState(RI_MGR, overlay_buttons->at(PIN_MACRO_TRIGGER_KEYS[unit]))) {
GameAPI::Buttons::getState(RI_MGR, overlay_buttons->at(PIN_MACRO_TRIGGER_KEYS[unit]));
bool auto_request = AUTO_PIN_MACRO_REQUEST[unit].exchange(false);
if (auto_request) {
log_info("eamuse", "AUTO_PIN_MACRO_REQUEST detected for P{}", unit+1);
}
if (key_press || auto_request) {
overlay::notifications::add(
overlay::notifications::Severity::Info,
fmt::format("[P{}] PIN macro fired ({})",
unit + 1, auto_request ? "auto" : "manual"));
active_unit = unit;
// Reset key index
pin_index[unit] = 0;
@@ -359,7 +436,7 @@ void eamuse_pin_macro_start_thread() {
}
if (!active_unit.has_value()) {
Sleep(20);
std::this_thread::sleep_for(std::chrono::milliseconds(20));
continue;
}
}
@@ -375,22 +452,22 @@ void eamuse_pin_macro_start_thread() {
eamuse_set_keypad_overrides(unit, keypad_overrides[char_index]);
}
pin_index[unit]++;
Sleep(100);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
// clear
eamuse_set_keypad_overrides(unit, 0);
Sleep(50);
std::this_thread::sleep_for(std::chrono::milliseconds(50));
// end of PIN
if (pin_index[unit] == PIN_MACRO_VALUES[unit].length()) {
active_unit = std::nullopt;
Sleep(120);
std::this_thread::sleep_for(std::chrono::milliseconds(120));
}
continue;
}
Sleep(200);
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
});
}
@@ -402,6 +479,9 @@ void eamuse_pin_macro_stop_thread() {
delete PIN_MACRO_THREAD;
PIN_MACRO_THREAD = nullptr;
}
if (AUTO_PIN_MACRO_PLAYER_ACTIVE[0] || AUTO_PIN_MACRO_PLAYER_ACTIVE[1]) {
logger::hook_remove(pin_macro_log_hook, nullptr);
}
}
void eamuse_set_keypad_overrides(size_t unit, uint16_t keypad_state) {
@@ -454,7 +534,7 @@ uint16_t eamuse_get_keypad_state(size_t unit) {
if (unit >= std::size(KEYPAD_STATE)) {
return 0;
}
// reset
KEYPAD_STATE[unit] = KEYPAD_STATE_OVERRIDES[unit];
KEYPAD_STATE[unit] |= KEYPAD_STATE_OVERRIDES_BT5[unit];
@@ -549,7 +629,7 @@ void eamuse_update_keypad_bindings() {
KEYPAD_BINDINGS = Config::getInstance().getKeypadBindings(EAMUSE_GAME_NAME);
}
std::string eamuse_get_game() {
const std::string &eamuse_get_game() {
return EAMUSE_GAME_NAME;
}
@@ -593,7 +673,8 @@ void eamuse_autodetect_game() {
eamuse_set_game("Beatmania IIDX");
else if (avs::game::is_model("J44") ||
avs::game::is_model("K44") ||
avs::game::is_model("L44"))
avs::game::is_model("L44") ||
avs::game::is_model("T44"))
eamuse_set_game("Jubeat");
else if (avs::game::is_model("KDM"))
eamuse_set_game("Dance Evolution");
+2 -1
View File
@@ -38,6 +38,7 @@ extern float AUTO_INSERT_CARD_COOLDOWN;
extern bool PIN_MACRO_ENABLED;
extern std::string PIN_MACRO_VALUES[2];
extern std::string AUTO_PIN_MACRO_TRIGGER[2];
bool eamuse_get_card(int active_count, int unit_id, uint8_t *card);
bool eamuse_get_card(const std::filesystem::path &path, uint8_t *card, int unit_id);
@@ -77,7 +78,7 @@ bool eamuse_keypad_state_naive();
void eamuse_set_game(std::string game);
std::string eamuse_get_game();
const std::string &eamuse_get_game();
int eamuse_get_game_keypads();
int eamuse_get_game_keypads_name();
+9 -3
View File
@@ -20,6 +20,7 @@ static cardunit_card_cardnumber_t cardunit_card_cardnumber = nullptr;
static HINSTANCE SCIUNIT_INSTANCE;
static std::string SCIUNIT_INSTANCE_NAME = "sciunit.dll";
static bool SCIUNIT_INITIALIZED = false;
static int SCIUNIT_STATUS = 0;
static bool CARD_IN = false;
static bool CARD_PRESSED = false;
static uint8_t CARD_UID[8];
@@ -150,11 +151,11 @@ static int __cdecl sciunit_finalize() {
}
static int __cdecl sciunit_get_errorunit() {
return 0;
return -1;
}
static int __cdecl sciunit_get_stat() {
return 0;
return SCIUNIT_STATUS;
}
static int __cdecl sciunit_get_version(int a1, int a2) {
@@ -163,6 +164,7 @@ static int __cdecl sciunit_get_version(int a1, int a2) {
static int __cdecl sciunit_initialize() {
SCIUNIT_INITIALIZED = true;
SCIUNIT_STATUS = 1;
return 0;
}
@@ -223,8 +225,12 @@ static int __cdecl sciunit_reset() {
}
static int __cdecl sciunit_update() {
if (SCIUNIT_INITIALIZED)
if (SCIUNIT_INITIALIZED) {
if (SCIUNIT_STATUS == 1) {
SCIUNIT_STATUS = 2;
}
update_card();
}
return 0;
}
+42 -3
View File
@@ -12,6 +12,7 @@
#include "cfg/screen_resize.h"
#include "games/gitadora/gitadora.h"
#include "games/iidx/iidx.h"
#include "games/popn/popn.h"
#include "hooks/graphics/graphics.h"
#include "overlay/overlay.h"
#include "overlay/windows/generic_sub.h"
@@ -20,6 +21,7 @@
#include "util/logging.h"
#include "util/time.h"
#include "util/utils.h"
#include "rawinput/touch.h"
#include "avs/game.h"
@@ -36,6 +38,9 @@ namespace wintouchemu {
bool INJECT_MOUSE_AS_WM_TOUCH = false;
bool LOG_FPS = false;
bool ADD_TOUCH_FLAG_PRIMARY = false;
// state
double last_touch_event = 0.0;
static inline bool is_emu_enabled() {
return FORCE || !is_touch_available("wintouchemu::is_emu_enabled") || GRAPHICS_SHOW_CURSOR;
@@ -126,6 +131,11 @@ namespace wintouchemu {
WINDOW_TITLE_END = window_title_end;
}
static void flip_touch_points(PTOUCHINPUT point) {
point->x = rawinput::touch::DISPLAY_SIZE_X * 100 - point->x;
point->y = rawinput::touch::DISPLAY_SIZE_Y * 100 - point->y;
}
static BOOL WINAPI GetTouchInputInfoHook(HANDLE hTouchInput, UINT cInputs, PTOUCHINPUT pInputs, int cbSize) {
// check if original should be called
@@ -220,6 +230,12 @@ namespace wintouchemu {
touch_input->cxContact = 0;
touch_input->cyContact = 0;
if (avs::game::is_model("KFC") &&
rawinput::touch::DISPLAY_INITIALIZED &&
rawinput::touch::DISPLAY_ORIENTATION == DMDO_270) {
flip_touch_points(touch_input);
}
} else if (USE_MOUSE && !mouse_used) {
// disable further mouse inputs this call
@@ -235,7 +251,10 @@ namespace wintouchemu {
touch_input->y -= SPICETOUCH_TOUCH_Y;
}
// log_misc("wintouchemu", "mouse state ({}, {})", to_string(touch_input->x), to_string(touch_input->y));
// log_misc(
// "wintouchemu",
// "mouse state ({}, {}) event={}",
// to_string(touch_input->x), to_string(touch_input->y), mouse_state.touch_event);
auto valid = true;
if (overlay::OVERLAY) {
@@ -393,7 +412,11 @@ namespace wintouchemu {
// use mouse position as ImGui overlay will block the touch window
log_info("wintouchemu", "use mouse cursor API for ldj overlay subscreen");
USE_MOUSE = true;
} else if (games::gitadora::is_arena_model() && games::gitadora::ARENA_SINGLE_WINDOW) {
} else if (games::popn::is_pikapika_model()) {
// same as iidx case above
log_info("wintouchemu", "use mouse cursor API for popn overlay subscreen");
USE_MOUSE = true;
} else if (games::gitadora::is_arena_model() && GRAPHICS_PREVENT_SECONDARY_WINDOWS) {
log_info("wintouchemu", "use mouse cursor API for gitadora overlay subscreen");
USE_MOUSE = true;
} else {
@@ -422,6 +445,8 @@ namespace wintouchemu {
}
}
const auto now = get_performance_milliseconds();
// update touch events
if (hWnd != nullptr) {
@@ -441,6 +466,7 @@ namespace wintouchemu {
// check if new events are available
if (event_count > 0) {
last_touch_event = now;
// send fake event to make the game update it's touch inputs
auto wndProc = (WNDPROC) GetWindowLongPtr(hWnd, GWLP_WNDPROC);
@@ -467,7 +493,20 @@ namespace wintouchemu {
// value from GetTouchInputInfo or fail to read dwFlags for valid events, so it's not OK to
// send empty events when the mouse button is not clicked/released
if (hWnd != nullptr && USE_MOUSE) {
bool button_pressed = ((GetKeyState(VK_LBUTTON) & 0x100) != 0);
bool button_pressed = get_async_primary_mouse();
// while the subscreen overlay cannot accept the mouse, treat the button as
// released; this ends any active touch and prevents new mouse touch contacts
if (overlay::OVERLAY &&
overlay::OVERLAY->has_subscreen_touch_transform() &&
!overlay::OVERLAY->accepts_subscreen_mouse_input()) {
button_pressed = false;
}
// if there was a touch event in the last 500 ms, don't insert new button presses
if (button_pressed && (now - last_touch_event) < 500) {
button_pressed = false;
}
// figure out what kind of touch event to simulate
if (button_pressed && !mouse_state.last_button_pressed) {