Update to spice2x-25-04-25 (pre-apply)

> broken commit
This commit is contained in:
[ ]
2025-05-07 00:25:31 +09:00
parent 04dee88276
commit c94de456b5
543 changed files with 78491 additions and 91698 deletions
+182 -20
View File
@@ -11,6 +11,7 @@
#include "util/logging.h"
#include "util/time.h"
#include "util/utils.h"
#include "overlay/overlay.h"
#include "bt5api.h"
@@ -32,16 +33,40 @@ static uint16_t KEYPAD_STATE_OVERRIDES_OVERLAY[] = {0, 0};
static std::string EAMUSE_GAME_NAME;
static ConfigKeypadBindings KEYPAD_BINDINGS {};
// auto card
bool AUTO_INSERT_CARD[2] = {false, false};
float AUTO_INSERT_CARD_COOLDOWN = 8.f; // seconds
static std::optional<double> AUTO_INSERT_CARD_FIRST_CONSUME_TIME;
static bool AUTO_INSERT_CARD_CACHED[2];
static uint8_t AUTO_INSERT_CARD_CACHED_DATA[2][8];
// pin macro
bool PIN_MACRO_ENABLED = false;
std::string PIN_MACRO_VALUES[2] = {"", ""};
static std::thread *PIN_MACRO_THREAD = nullptr;
static bool PIN_MACRO_THREAD_ACTIVE = false;
static uint16_t PIN_MACRO_TRIGGER_KEYS[2] = {
games::OverlayButtons::TriggerPinMacroP1,
games::OverlayButtons::TriggerPinMacroP2
};
bool eamuse_get_card(int active_count, int unit_id, uint8_t *card) {
// get unit index
int index = unit_id > 0 && active_count > 1 ? 1 : 0;
// check cards cached for auto-insert
// explicitly not logging anything in this path to avoid log spam
if (AUTO_INSERT_CARD[index] && AUTO_INSERT_CARD_CACHED[index]) {
memcpy(card, AUTO_INSERT_CARD_CACHED_DATA[index], 8);
return true;
}
// reader card input
if (CARD_INSERT_UID_ENABLE[index]) {
CARD_INSERT_UID_ENABLE[index] = false;
memcpy(card, CARD_INSERT_UID[index], 8);
log_info("eamuse", "Inserted card from reader {}: {}", index, bin2hex(card, 8));
log_info("eamuse", "[P{}] Inserted card from reader: {}", index+1, bin2hex(card, 8));
return true;
}
@@ -58,38 +83,50 @@ 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 index) {
// do a quick copy under lock
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_OVERRIDES[index].empty()) {
if (!card_override.empty()) {
// Override is present
for (int n = 0; n < 16; n++) {
char c = CARD_OVERRIDES[index].c_str()[n];
char c = card_override.c_str()[n];
bool digit = c >= '0' && c <= '9';
bool character_big = c >= 'A' && c <= 'F';
bool character_small = c >= 'a' && c <= 'f';
if (!digit && !character_big && !character_small) {
log_warning("eamuse",
"{} card override contains an invalid character sequence at byte {} (16 characters, 0-9/A-F only)",
CARD_OVERRIDES[index], n);
card_override, n);
return false;
}
}
// Log info
log_info("eamuse", "Inserted card override: {}", CARD_OVERRIDES[index]);
log_info("eamuse", "[P{}] Inserted card override: {}", index+1, card_override);
// Card is valid, convert and set it.
hex2bin(CARD_OVERRIDES[index].c_str(), card);
hex2bin(card_override.c_str(), card);
// cache it for auto-insert
// always overwrite from overrides since override may have changed by user in card manager
if (AUTO_INSERT_CARD[index]) {
memcpy(AUTO_INSERT_CARD_CACHED_DATA[index], card, 8);
AUTO_INSERT_CARD_CACHED[index] = true;
log_info("eamuse", "[P{}] Auto card insert - caching this card override in memory: {}", index+1, card_override);
}
// success
return true;
}
// Overrides are not present. Use the standard file reading method.
return eamuse_get_card(path, card);
return eamuse_get_card_from_file(path, card, index);
}
bool eamuse_get_card(const std::filesystem::path &path, uint8_t *card) {
bool eamuse_get_card_from_file(const std::filesystem::path &path, uint8_t *card, int index) {
// open file
std::ifstream f(path);
@@ -130,11 +167,18 @@ bool eamuse_get_card(const std::filesystem::path &path, uint8_t *card) {
}
// info
log_info("eamuse", "Inserted {}: {}", path.string(), buffer);
log_info("eamuse", "[P{}] Inserted {}: {}", index+1, path.string(), buffer);
// convert hex to bytes
hex2bin(buffer, card);
// cache it for auto-insert
if (AUTO_INSERT_CARD[index] && !AUTO_INSERT_CARD_CACHED[index]) {
memcpy(AUTO_INSERT_CARD_CACHED_DATA[index], card, 8);
AUTO_INSERT_CARD_CACHED[index] = true;
log_info("eamuse", "[P{}] Auto card insert - caching this card from file in memory: {}", index+1, buffer);
}
// success
return true;
}
@@ -161,12 +205,29 @@ bool eamuse_card_insert_consume(int active_count, int unit_id) {
bt5api_poll_reader_card((uint8_t) index);
}
// auto insert card
if (AUTO_INSERT_CARD[index]) {
// reset timer if enough time has passed since last insert
if (CARD_INSERT[index] &&
AUTO_INSERT_CARD_COOLDOWN < (get_performance_seconds() - CARD_INSERT_TIME[index])) {
CARD_INSERT[index] = false;
}
if (!CARD_INSERT[index]) {
eamuse_card_insert(index);
// not logging anything here to prevent spam
return true;
} else {
return false;
}
}
// check for card insert
auto keypad_buttons = games::get_buttons_keypads(eamuse_get_game());
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", "Card insert on {}/{}", unit_id + 1, active_count);
|| 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;
return true;
}
@@ -249,6 +310,93 @@ void eamuse_coin_stop_thread() {
COIN_INPUT_THREAD = nullptr;
}
void eamuse_pin_macro_start_thread() {
// set active
PIN_MACRO_THREAD_ACTIVE = true;
// create thread
PIN_MACRO_THREAD = new std::thread([]() {
uint16_t keypad_overrides[] = {
1 << EAM_IO_KEYPAD_0,
1 << EAM_IO_KEYPAD_1,
1 << EAM_IO_KEYPAD_2,
1 << EAM_IO_KEYPAD_3,
1 << EAM_IO_KEYPAD_4,
1 << EAM_IO_KEYPAD_5,
1 << EAM_IO_KEYPAD_6,
1 << EAM_IO_KEYPAD_7,
1 << EAM_IO_KEYPAD_8,
1 << EAM_IO_KEYPAD_9,
};
auto overlay_buttons = games::get_buttons_overlay(eamuse_get_game());
size_t pin_index[2] = {PIN_MACRO_VALUES[0].length(), PIN_MACRO_VALUES[1].length()};
std::optional<uint8_t> active_unit = std::nullopt;
while (PIN_MACRO_THREAD_ACTIVE) {
// wait for key press
if (!active_unit.has_value()) {
for (int unit = 0; unit < 2; unit++) {
if (PIN_MACRO_VALUES[unit].empty()) {
continue;
}
if (overlay_buttons &&
(!overlay::OVERLAY || overlay::OVERLAY->hotkeys_triggered()) &&
GameAPI::Buttons::getState(RI_MGR, overlay_buttons->at(PIN_MACRO_TRIGGER_KEYS[unit]))) {
active_unit = unit;
// Reset key index
pin_index[unit] = 0;
break;
}
}
if (!active_unit.has_value()) {
Sleep(20);
continue;
}
}
const auto unit = active_unit.value();
// get character from config
if (pin_index[unit] < PIN_MACRO_VALUES[unit].length()) {
// insert character
char pin_char = PIN_MACRO_VALUES[unit].at(pin_index[unit]);
if (pin_char >= '0' && pin_char <= '9') {
int char_index = pin_char - '0';
eamuse_set_keypad_overrides(unit, keypad_overrides[char_index]);
}
pin_index[unit]++;
Sleep(100);
// clear
eamuse_set_keypad_overrides(unit, 0);
Sleep(50);
// end of PIN
if (pin_index[unit] == PIN_MACRO_VALUES[unit].length()) {
active_unit = std::nullopt;
Sleep(120);
}
continue;
}
Sleep(200);
}
});
}
void eamuse_pin_macro_stop_thread() {
PIN_MACRO_THREAD_ACTIVE = false;
if (PIN_MACRO_THREAD != nullptr) {
PIN_MACRO_THREAD->join();
delete PIN_MACRO_THREAD;
PIN_MACRO_THREAD = nullptr;
}
}
void eamuse_set_keypad_overrides(size_t unit, uint16_t keypad_state) {
// check unit
@@ -300,13 +448,6 @@ uint16_t eamuse_get_keypad_state(size_t unit) {
return 0;
}
// keypad disabled for KFC in BI2X mode, since the game won't handle it correctly
// this check for IO is necessary (as opposed to just doing a check for Valkyrie cab mode)
// because there are hex edits that allow you to use legacy (KFC/BIO2) IO while in Valk mode.
if (avs::game::is_model("KFC") && games::sdvx::BI2X_INITIALIZED) {
return 0;
}
// reset
KEYPAD_STATE[unit] = KEYPAD_STATE_OVERRIDES[unit];
KEYPAD_STATE[unit] |= KEYPAD_STATE_OVERRIDES_BT5[unit];
@@ -512,6 +653,12 @@ void eamuse_autodetect_game() {
eamuse_set_game("Ongaku Paradise");
else if (avs::game::is_model("TBS"))
eamuse_set_game("Busou Shinki: Armored Princess Battle Conductor");
else if (avs::game::is_model("UJK"))
eamuse_set_game("Chase Chase Jokers");
else if (avs::game::is_model("UKS"))
eamuse_set_game("QuizKnock STADIUM");
else if (avs::game::is_model("VFG"))
eamuse_set_game("Mahjong Fight Girl");
else {
log_warning("eamuse", "unknown game model: {}", avs::game::MODEL);
eamuse_set_game("unknown");
@@ -519,7 +666,22 @@ void eamuse_autodetect_game() {
}
void eamuse_scard_callback(uint8_t slot_no, card_info_t *cardinfo) {
log_misc("scard", "eamuse_scard_callback: slot_no={}, card_type={}", slot_no, cardinfo->card_type);
if (cardinfo->card_type > 0) {
eamuse_card_insert(slot_no, cardinfo->uid);
eamuse_card_insert(slot_no & 1, cardinfo->uid);
}
}
bool eamuse_scanned_card_peek_noninvasive(size_t unit, char card_uid[8]) {
const int unit_index = unit > 0 ? 1 : 0;
if (!CARD_INSERT_UID_ENABLE[unit_index]) {
return false;
}
memcpy(card_uid, CARD_INSERT_UID[unit_index], 8);
return true;
}
void eamuse_scanned_card_clear(size_t unit) {
const int unit_index = unit > 0 ? 1 : 0;
CARD_INSERT_UID_ENABLE[unit_index] = false;
}