From 8dc835bf52c9f248e08e5924c7de9aee49ed7250 Mon Sep 17 00:00:00 2001 From: bicarus-dev <202771338+bicarus-dev@users.noreply.github.com> Date: Sun, 23 Mar 2025 18:05:38 -0700 Subject: [PATCH] Auto PIN entry (#272) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Link to GitHub Issue, if one exists Fixes https://github.com/spice2x/spice2x.github.io/issues/193 ## Description of change Merges guardianblue's changes plus some code review feedback. Adds the ability to automatically type out the digits of a PIN when an overlay shortcut is pressed. ## Compiling 💯 ## Testing Tested: * 32 bit popn * TDJ, 1p/2p * KFC, UFC --- src/spice2x/games/io.cpp | 4 ++ src/spice2x/games/io.h | 2 + src/spice2x/launcher/launcher.cpp | 16 +++++ src/spice2x/launcher/options.cpp | 20 +++++++ src/spice2x/launcher/options.h | 2 + src/spice2x/misc/eamuse.cpp | 98 +++++++++++++++++++++++++++++++ src/spice2x/misc/eamuse.h | 6 ++ 7 files changed, 148 insertions(+) diff --git a/src/spice2x/games/io.cpp b/src/spice2x/games/io.cpp index f1b1c94..ad91129 100644 --- a/src/spice2x/games/io.cpp +++ b/src/spice2x/games/io.cpp @@ -437,6 +437,10 @@ namespace games { vkey_defaults.push_back(VK_F12); names.emplace_back("Toggle Camera Control"); vkey_defaults.push_back(0xFF); + names.emplace_back("Player 1 PIN Macro"); + vkey_defaults.push_back(0xFF); + names.emplace_back("Player 2 PIN Macro"); + vkey_defaults.push_back(0xFF); names.emplace_back("Screen Resize"); vkey_defaults.push_back(0xFF); names.emplace_back("Screen Resize Scene 1"); diff --git a/src/spice2x/games/io.h b/src/spice2x/games/io.h index b399b08..81790ee 100644 --- a/src/spice2x/games/io.h +++ b/src/spice2x/games/io.h @@ -22,6 +22,8 @@ namespace games { ToggleScreenResize, ToggleOverlay, ToggleCameraControl, + TriggerPinMacroP1, + TriggerPinMacroP2, ScreenResize, ScreenResizeScene1, ScreenResizeScene2, diff --git a/src/spice2x/launcher/launcher.cpp b/src/spice2x/launcher/launcher.cpp index 53b6ca3..eabc1ab 100644 --- a/src/spice2x/launcher/launcher.cpp +++ b/src/spice2x/launcher/launcher.cpp @@ -737,6 +737,15 @@ int main_implementation(int argc, char *argv[]) { if (options[launcher::Options::Player2Card].is_active()) { CARD_OVERRIDES[1] = options[launcher::Options::Player2Card].value_text(); } + if (options[launcher::Options::Player1PinMacro].is_active()) { + PIN_MACRO_ENABLED = true; + PIN_MACRO_VALUES[0] = options[launcher::Options::Player1PinMacro].value_text(); + } + if (options[launcher::Options::Player2PinMacro].is_active()) { + PIN_MACRO_ENABLED = true; + PIN_MACRO_VALUES[1] = options[launcher::Options::Player2PinMacro].value_text(); + } + for (auto &reader : options[launcher::Options::ICCAReaderPort].values_text()) { static int reader_id = 0; if (reader_id < 2) { @@ -1968,6 +1977,11 @@ int main_implementation(int argc, char *argv[]) { // start coin input thread eamuse_coin_start_thread(); + // pin macro + if (!cfg::CONFIGURATOR_STANDALONE && PIN_MACRO_ENABLED) { + eamuse_pin_macro_start_thread(); + } + // print PEB if (peb_print) { peb::peb_print(); @@ -2052,6 +2066,8 @@ int main_implementation(int argc, char *argv[]) { // stop coin input thread eamuse_coin_stop_thread(); + eamuse_pin_macro_stop_thread(); + // BT5API if (BT5API_ENABLED) { bt5api_dispose(); diff --git a/src/spice2x/launcher/options.cpp b/src/spice2x/launcher/options.cpp index 54fc362..4e8af97 100644 --- a/src/spice2x/launcher/options.cpp +++ b/src/spice2x/launcher/options.cpp @@ -113,6 +113,26 @@ static const std::vector OPTION_DEFINITIONS = { .category = "Network", .sensitive = true, }, + { + // Player1PinMacro + .title = "Player 1 PIN Macro", + .name = "pinmacro0", + .desc = "Set a PIN for Player 1 that will cause the PIN to be automatically typed when Player 1 PIN Macro overlay key is pressed", + .type = OptionType::Text, + .setting_name = "1234", + .category = "Network (Advanced)", + .sensitive = true, + }, + { + // Player2PinMacro + .title = "Player 2 PIN Macro", + .name = "pinmacro1", + .desc = "Set a PIN for Player 2 that will cause the PIN to be automatically typed when Player 2 PIN Macro overlay key is pressed", + .type = OptionType::Text, + .setting_name = "5678", + .category = "Network (Advanced)", + .sensitive = true, + }, { .title = "Windowed Mode", .name = "w", diff --git a/src/spice2x/launcher/options.h b/src/spice2x/launcher/options.h index 0a1b2b0..6a2fc23 100644 --- a/src/spice2x/launcher/options.h +++ b/src/spice2x/launcher/options.h @@ -18,6 +18,8 @@ namespace launcher { PCBID, Player1Card, Player2Card, + Player1PinMacro, + Player2PinMacro, WindowedMode, InjectHook, EarlyInjectHook, diff --git a/src/spice2x/misc/eamuse.cpp b/src/spice2x/misc/eamuse.cpp index 702dfb1..ed30174 100644 --- a/src/spice2x/misc/eamuse.cpp +++ b/src/spice2x/misc/eamuse.cpp @@ -11,6 +11,7 @@ #include "util/logging.h" #include "util/time.h" #include "util/utils.h" +#include "overlay/overlay.h" #include "bt5api.h" @@ -39,6 +40,16 @@ static std::optional 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 @@ -295,6 +306,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 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 diff --git a/src/spice2x/misc/eamuse.h b/src/spice2x/misc/eamuse.h index 65ed07c..09941c0 100644 --- a/src/spice2x/misc/eamuse.h +++ b/src/spice2x/misc/eamuse.h @@ -34,6 +34,9 @@ extern std::string CARD_OVERRIDES[2]; extern bool AUTO_INSERT_CARD[2]; extern float AUTO_INSERT_CARD_COOLDOWN; +extern bool PIN_MACRO_ENABLED; +extern std::string PIN_MACRO_VALUES[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); bool eamuse_get_card_from_file(const std::filesystem::path &path, uint8_t *card, int index); @@ -56,6 +59,9 @@ int eamuse_coin_add(); void eamuse_coin_start_thread(); void eamuse_coin_stop_thread(); +void eamuse_pin_macro_start_thread(); +void eamuse_pin_macro_stop_thread(); + void eamuse_set_keypad_overrides(size_t unit, uint16_t keypad_state); void eamuse_set_keypad_overrides_bt5(size_t unit, uint16_t keypad_state); void eamuse_set_keypad_overrides_reader(size_t unit, uint16_t keypad_state);