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
+42
View File
@@ -15,6 +15,7 @@
#include "util/libutils.h"
#include "util/logging.h"
#include "util/utils.h"
namespace clipboard {
namespace imports {
@@ -140,4 +141,45 @@ namespace clipboard {
handle.detach();
}
void copy_text(const std::string& str) {
if (!OpenClipboard(nullptr)) {
log_warning("clipboard", "Failed to open clipboard");
return;
}
HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, str.length() + 1);
memcpy(GlobalLock(mem), str.c_str(), str.length() + 1);
GlobalUnlock(mem);
EmptyClipboard();
SetClipboardData(CF_TEXT, mem);
CloseClipboard();
}
const std::string paste_text() {
HGLOBAL hglb;
LPSTR str;
std::string text;
// check if clipboard content is text
if (!IsClipboardFormatAvailable(CF_TEXT)) {
return text;
}
if (!OpenClipboard(nullptr)) {
log_warning("clipboard", "Failed to open clipboard");
return text;
}
hglb = GetClipboardData(CF_TEXT);
if (hglb != NULL) {
str = reinterpret_cast<LPSTR>(GlobalLock(hglb));
if (str != NULL) {
text = str;
GlobalUnlock(hglb);
}
}
CloseClipboard();
return text;
}
}
+2
View File
@@ -4,4 +4,6 @@
namespace clipboard {
void copy_image(const std::filesystem::path path);
void copy_text(const std::string& str);
const std::string paste_text();
}
+24 -6
View File
@@ -32,8 +32,9 @@ static int DEVICE_INPUT_STATE;
static int __cdecl device_check_secplug(int a1) {
// check for invalid index
if (a1 > 1)
if (a1 > 1) {
return 0;
}
// J44/K44 has it flipped
if (avs::game::is_model({ "J44", "K44" })) {
@@ -295,6 +296,9 @@ static int __cdecl device_set_coincounter_work() {
return 0;
}
static void __cdecl device_set_coincounter_controllable() {
}
static int __cdecl device_set_panel_mode(int mode) {
return 0;
}
@@ -348,6 +352,10 @@ static int __cdecl device_set_watchdog_timer(int a1) {
return 0;
}
static void __cdecl device_set_watchdog() {
return;
}
static void __cdecl device_update() {
// flush device output
@@ -609,7 +617,9 @@ void spicedevice_attach() {
detour::inline_hook((void *) device_get_coinstock, libutils::try_proc_list(
DEVICE_INSTANCE, {"device_get_coinstock", "?device_get_coinstock@@YAXPEAG0@Z"}));
detour::inline_hook((void *) device_get_coinstock_all, libutils::try_proc_list(
DEVICE_INSTANCE, {"device_get_coinstock_all", "?device_get_coinstock_all@@YAXPEAG0@Z"}));
DEVICE_INSTANCE, {"device_get_coinstock_all",
"?device_get_coinstock_all@@YAXPEAG0@Z",
"?device_get_coinstock_all@@YAXPAG0@Z"}));
detour::inline_hook((void *) device_get_dispw, libutils::try_proc_list(
DEVICE_INSTANCE, {"device_get_dispw", "?device_get_dipsw@@YAEH@Z"}));
detour::inline_hook((void *) device_get_input, libutils::try_proc_list(
@@ -620,7 +630,8 @@ void spicedevice_attach() {
DEVICE_INSTANCE, {"device_get_jamma"}));
detour::inline_hook((void *) device_get_jamma_history, libutils::try_proc_list(
DEVICE_INSTANCE, {"device_get_jamma_history",
"?device_get_jamma_history@@YAHPEAUT_JAMMA_HISTORY_INFO@@H@Z"}));
"?device_get_jamma_history@@YAHPEAUT_JAMMA_HISTORY_INFO@@H@Z",
"?device_get_jamma_history@@YAHPAUT_JAMMA_HISTORY_INFO@@H@Z"}));
detour::inline_hook((void *) device_get_panel_trg_off, libutils::try_proc_list(
DEVICE_INSTANCE, {"device_get_panel_trg_off"}));
detour::inline_hook((void *) device_get_panel_trg_on, libutils::try_proc_list(
@@ -640,11 +651,15 @@ void spicedevice_attach() {
detour::inline_hook((void *) device_get_status, libutils::try_proc_list(
DEVICE_INSTANCE, {"device_get_status", "?device_get_status@@YAHXZ"}));
detour::inline_hook((void *) device_get_subboard_version, libutils::try_proc_list(
DEVICE_INSTANCE, {"device_get_subboard_version", "?device_get_subboard_version@@YAHPEADH@Z"}));
DEVICE_INSTANCE, {"device_get_subboard_version",
"?device_get_subboard_version@@YAHPEADH@Z",
"?device_get_subboard_version@@YAHPADH@Z"}));
detour::inline_hook((void *) device_get_sys_version, libutils::try_proc_list(
DEVICE_INSTANCE, {"device_get_sys_version", "?device_get_sys_version@@YAPEBDXZ"}));
detour::inline_hook((void *) device_initialize, libutils::try_proc_list(
DEVICE_INSTANCE, {"device_initialize", "?device_initialize@@YAHH@Z"}));
DEVICE_INSTANCE, {"device_initialize",
"?device_initialize@@YAHH@Z",
"?device_initialize@@YAHXZ"}));
detour::inline_hook((void *) device_is_initialized, libutils::try_proc_list(
DEVICE_INSTANCE, {"device_is_initialized"}));
detour::inline_hook((void *) device_poweroff, libutils::try_proc_list(
@@ -657,6 +672,8 @@ void spicedevice_attach() {
DEVICE_INSTANCE, {"device_set_coincounter_merge", "?device_set_coincounter_merge@@YAXE@Z"}));
detour::inline_hook((void *) device_set_coincounter_work, libutils::try_proc_list(
DEVICE_INSTANCE, {"device_set_coincounter_work", "?device_set_coincounter_work@@YAXEE@Z"}));
detour::inline_hook((void *) device_set_coincounter_controllable, libutils::try_proc_list(
DEVICE_INSTANCE, {"device_set_coincounter_controllable", "?device_set_coincounter_controllable@@YAXEE@Z"}));
detour::inline_hook((void *) device_set_panel_mode, libutils::try_proc_list(
DEVICE_INSTANCE, {"device_set_panel_mode"}));
detour::inline_hook((void *) device_set_jamma_asyncmode, libutils::try_proc_list(
@@ -671,6 +688,8 @@ void spicedevice_attach() {
DEVICE_INSTANCE, {"device_set_portoutbit", "?device_set_portoutbit@@YAXHH@Z"}));
detour::inline_hook((void *) device_set_watchdog_timer, libutils::try_proc_list(
DEVICE_INSTANCE, {"device_set_watchdog_timer"}));
detour::inline_hook((void *) device_set_watchdog, libutils::try_proc_list(
DEVICE_INSTANCE, {"?device_set_watchdog@@YAXH@Z"}));
detour::inline_hook((void *) device_update, libutils::try_proc_list(
DEVICE_INSTANCE, {"device_update", "?device_update@@YAXXZ"}));
detour::inline_hook((void *) device_update_secplug, libutils::try_proc_list(
@@ -711,7 +730,6 @@ void spicedevice_attach() {
// device_hwinfo_etc_update
// device_hwinfo_get
// device_hwinfo_update
// device_set_coincounter_controllable
// device_set_jamma_interrupt_status
// sci_mng_get_debug_info
// test_device
+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;
}
+15 -1
View File
@@ -3,6 +3,8 @@
#include <cstdint>
#include <filesystem>
#include <string>
#include <optional>
#include <mutex>
#include "external/scard/scard.h"
@@ -29,11 +31,17 @@ enum eam_io_keypad_scan_code {
EAM_IO_INSERT = 13, /* SpiceTools Extension */
};
extern std::mutex CARD_OVERRIDES_LOCK;
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(const std::filesystem::path &path, uint8_t *card);
bool eamuse_get_card_from_file(const std::filesystem::path &path, uint8_t *card, int index);
void eamuse_card_insert(int unit);
void eamuse_card_insert(int unit, const uint8_t *card);
@@ -53,6 +61,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);
@@ -73,3 +84,6 @@ int eamuse_get_game_keypads_name();
void eamuse_autodetect_game();
void eamuse_scard_callback(uint8_t slot_no, card_info_t *cardinfo);
bool eamuse_scanned_card_peek_noninvasive(size_t unit, char card_uid[8]);
void eamuse_scanned_card_clear(size_t unit);
+277 -20
View File
@@ -1,6 +1,7 @@
#include "extdev.h"
#include <cmath>
#include <string>
#include <optional>
#include <windows.h>
#include "util/utils.h"
#include "util/detour.h"
@@ -9,11 +10,18 @@
#include "misc/eamuse.h"
#include "cfg/api.h"
#include "acio/icca/icca.h"
#include "games/gitadora/gitadora.h"
#include "games/gitadora/io.h"
#include "avs/game.h"
using namespace GameAPI;
#if SPICE64
typedef uint64_t LED_INDEX;
#else
typedef uint32_t LED_INDEX;
#endif
// card unit
static size_t EXTDEV_CARDUNIT_COUNT = 0;
static circular_buffer<int> EXTDEV_CARDUNIT_KEY[2] = {
@@ -65,8 +73,14 @@ static std::string EXTDEV_INSTANCE_NAMES[] = {
"libcardunit.dll",
"libledunit.dll",
"libgfdm_unit2.dll",
"libshare-pj.dll",
};
static void set_led_state(games::gitadora::Lights::gitadora_lights_t light, bool led_on);
static void set_led_value(games::gitadora::Lights::gitadora_lights_t light, uint8_t value);
static long __cdecl gitadora_led_common(long index, uint8_t *data);
static void __cdecl cardunit_boot2(int a1, int a2, int a3) {
// default reader count to 1
@@ -326,9 +340,9 @@ static void *__cdecl gfdm_unit_get_button_p(void *a1, int a2, size_t player) {
memset(a1, 0, 64);
// irrelevant for drummania
if (avs::game::is_model({ "J32", "K32", "L32" }) ||
(avs::game::is_model("M32") && avs::game::SPEC[0] == 'B'))
if (games::gitadora::is_drum()) {
return a1;
}
// get buttons
auto &buttons = games::gitadora::get_buttons();
@@ -414,8 +428,7 @@ static long __cdecl gfdm_unit_get_input_p(int device, size_t player) {
auto &analogs = games::gitadora::get_analogs();
// drum mania
if (avs::game::is_model({ "J32", "K32", "L32" }) ||
(avs::game::is_model("M32") && avs::game::SPEC[0] == 'B')) {
if (games::gitadora::is_drum()) {
// we don't want input for this
if (device == 1)
@@ -471,9 +484,7 @@ static long __cdecl gfdm_unit_get_input_p(int device, size_t player) {
}
// guitar freaks
if (avs::game::is_model({ "J33", "K33", "L33" }) ||
(avs::game::is_model("M32") && avs::game::SPEC[0] == 'A'))
{
if (games::gitadora::is_guitar()) {
auto offset = player * 11;
// pick up
@@ -577,8 +588,7 @@ static long __cdecl gfdm_unit2_get_input(int device) {
static long __cdecl gfdm_unit_get_sensor_gf_p(int a1, int a2, size_t player) {
// return if it's actually drum mania
if (avs::game::is_model({ "J32", "K32", "L32" }) ||
(avs::game::is_model("M32") && avs::game::SPEC[0] == 'B'))
if (games::gitadora::is_drum())
return 0;
// get buttons and analogs
@@ -752,15 +762,166 @@ static int __cdecl led_unit_reset() {
return 0;
}
static unsigned int __cdecl led_unit_send_custom1(int a1, unsigned char *a2) {
static void set_led_state(games::gitadora::Lights::gitadora_lights_t light, bool led_on) {
auto &lights = games::gitadora::get_lights();
GameAPI::Lights::writeLight(RI_MGR, lights.at(light), (led_on ? 1.f : 0.f));
}
static void set_led_value(games::gitadora::Lights::gitadora_lights_t light, uint8_t value) {
auto &lights = games::gitadora::get_lights();
GameAPI::Lights::writeLight(RI_MGR, lights.at(light), value / 128.f);
}
static unsigned int __cdecl led_unit_send_custom1(int index, uint8_t *data) {
return 0;
}
static unsigned int __cdecl led_unit_send_custom2(int a1, unsigned char *a2) {
struct ExtDevLight {
int data_index;
games::gitadora::Lights::gitadora_lights_t light;
ExtDevLight(
int data_index, games::gitadora::Lights::gitadora_lights_t light) :
data_index(data_index), light(light) {}
};
// GITADORA series
static unsigned int __cdecl led_unit_send_custom2(int index, uint8_t *data) {
#ifdef SPICE64
return gitadora_led_common(index, data);
#else
return 0;
#endif
}
static long __cdecl led_unit_send_direct(long a1, uint8_t *a2) {
// XG series
static long __cdecl led_unit_send_direct(long index, uint8_t *data) {
#ifdef SPICE64
return 0;
#else
return gitadora_led_common(index, data);
#endif
}
static long __cdecl gitadora_led_common(long index, uint8_t *data) {
// log_info("extdev::led", "gitadora_led_common {}", index);
// for (size_t i = 0; i < 24; i += 3) {
// log_info("extdev::led", "gitadora_led_common ... {} {} {}", data[i], data[i+1], data[i+2]);
// }
if (games::gitadora::is_drum()) {
// Drum: index is always 0, data array has 24 elements, each value ranging [0, 128]
static ExtDevLight mapping_dm[] = {
{0, games::gitadora::Lights::DrumWooferR},
{1, games::gitadora::Lights::DrumWooferG},
{2, games::gitadora::Lights::DrumWooferB},
{3, games::gitadora::Lights::DrumSpotRearLeft},
{7, games::gitadora::Lights::DrumSpotRearRight},
{11, games::gitadora::Lights::SpotFrontLeft},
{12, games::gitadora::Lights::DrumStageR},
{13, games::gitadora::Lights::DrumStageG},
{14, games::gitadora::Lights::DrumStageB},
{15, games::gitadora::Lights::SpotCenterLeft},
{19, games::gitadora::Lights::SpotCenterRight},
{23, games::gitadora::Lights::SpotFrontRight}
};
if (index == 0) {
for (const auto &map : mapping_dm) {
set_led_value(map.light, data[map.data_index]);
}
}
} else {
// Guitar: index is {0,1,2}, data array has 24 elements, each value ranging [0, 128]
static ExtDevLight mapping0[] = {
{0, games::gitadora::Lights::GuitarLowerLeftR},
{1, games::gitadora::Lights::GuitarLowerLeftG},
{2, games::gitadora::Lights::GuitarLowerLeftB},
{3, games::gitadora::Lights::SpotFrontLeft},
{7, games::gitadora::Lights::SpotCenterLeft},
{8, games::gitadora::Lights::GuitarLowerRightR},
{9, games::gitadora::Lights::GuitarLowerRightG},
{10, games::gitadora::Lights::GuitarLowerRightB},
{11, games::gitadora::Lights::SpotCenterRight},
{15, games::gitadora::Lights::SpotFrontRight}
};
static ExtDevLight mapping1[] = {
{0, games::gitadora::Lights::GuitarLeftSpeakerUpperR},
{1, games::gitadora::Lights::GuitarLeftSpeakerUpperG},
{2, games::gitadora::Lights::GuitarLeftSpeakerUpperB},
{4, games::gitadora::Lights::GuitarLeftSpeakerMidUpLeftR},
{5, games::gitadora::Lights::GuitarLeftSpeakerMidUpLeftG},
{6, games::gitadora::Lights::GuitarLeftSpeakerMidUpLeftB},
{8, games::gitadora::Lights::GuitarLeftSpeakerMidUpRightR},
{9, games::gitadora::Lights::GuitarLeftSpeakerMidUpRightG},
{10, games::gitadora::Lights::GuitarLeftSpeakerMidUpRightB},
{12, games::gitadora::Lights::GuitarLeftSpeakerMidLowLeftR},
{13, games::gitadora::Lights::GuitarLeftSpeakerMidLowLeftG},
{14, games::gitadora::Lights::GuitarLeftSpeakerMidLowLeftB},
{16, games::gitadora::Lights::GuitarLeftSpeakerMidLowRightR},
{17, games::gitadora::Lights::GuitarLeftSpeakerMidLowRightG},
{18, games::gitadora::Lights::GuitarLeftSpeakerMidLowRightB},
{20, games::gitadora::Lights::GuitarLeftSpeakerLowerR},
{21, games::gitadora::Lights::GuitarLeftSpeakerLowerG},
{22, games::gitadora::Lights::GuitarLeftSpeakerLowerB}
};
static ExtDevLight mapping2[] = {
{0, games::gitadora::Lights::GuitarRightSpeakerUpperR},
{1, games::gitadora::Lights::GuitarRightSpeakerUpperG},
{2, games::gitadora::Lights::GuitarRightSpeakerUpperB},
{4, games::gitadora::Lights::GuitarRightSpeakerMidUpLeftR},
{5, games::gitadora::Lights::GuitarRightSpeakerMidUpLeftG},
{6, games::gitadora::Lights::GuitarRightSpeakerMidUpLeftB},
{8, games::gitadora::Lights::GuitarRightSpeakerMidUpRightR},
{9, games::gitadora::Lights::GuitarRightSpeakerMidUpRightG},
{10, games::gitadora::Lights::GuitarRightSpeakerMidUpRightB},
{12, games::gitadora::Lights::GuitarRightSpeakerMidLowLeftR},
{13, games::gitadora::Lights::GuitarRightSpeakerMidLowLeftG},
{14, games::gitadora::Lights::GuitarRightSpeakerMidLowLeftB},
{16, games::gitadora::Lights::GuitarRightSpeakerMidLowRightR},
{17, games::gitadora::Lights::GuitarRightSpeakerMidLowRightG},
{18, games::gitadora::Lights::GuitarRightSpeakerMidLowRightB},
{20, games::gitadora::Lights::GuitarRightSpeakerLowerR},
{21, games::gitadora::Lights::GuitarRightSpeakerLowerG},
{22, games::gitadora::Lights::GuitarRightSpeakerLowerB}
};
switch (index) {
case 0:
for (const auto &map : mapping0) {
set_led_value(map.light, data[map.data_index]);
}
break;
case 1:
for (const auto &map : mapping1) {
set_led_value(map.light, data[map.data_index]);
}
break;
case 2:
for (const auto &map : mapping2) {
set_led_value(map.light, data[map.data_index]);
}
break;
default:
break;
}
}
return 0;
}
@@ -814,6 +975,72 @@ static int __cdecl sci_setparam(int a1, int a2, int a3, char a4) {
return 1;
}
static void __cdecl dm_output_set_padled(LED_INDEX index, bool led_on) {
games::gitadora::Lights::gitadora_lights_t lights[] = {
games::gitadora::Lights::DrumHighTom,
games::gitadora::Lights::DrumLowTom,
games::gitadora::Lights::DrumSnare,
games::gitadora::Lights::DrumFloorTom,
games::gitadora::Lights::DrumLeftCymbal,
games::gitadora::Lights::DrumRightCymbal,
games::gitadora::Lights::DrumHiHat
};
// log_info("gitadora", "dm_output_set_padled {} {}", index, led_on);
if (index < std::size(lights)) {
set_led_state(lights[index], led_on);
}
}
static void __cdecl dm_output_set_startled(bool led_on) {
set_led_state(games::gitadora::Lights::P1MenuStart, led_on);
}
static void __cdecl dm_output_set_up_down(bool led_on) {
set_led_state(games::gitadora::Lights::P1MenuUpDown, led_on);
}
static void __cdecl dm_output_set_left_right(bool led_on) {
set_led_state(games::gitadora::Lights::P1MenuLeftRight, led_on);
}
static void __cdecl dm_output_set_help(bool led_on) {
set_led_state(games::gitadora::Lights::P1MenuHelp, led_on);
}
static void __cdecl gf_output_set_startlamp(LED_INDEX index, bool led_on) {
if (index == 0) {
set_led_state(games::gitadora::Lights::P1MenuStart, led_on);
} else if (index == 1) {
set_led_state(games::gitadora::Lights::P2MenuStart, led_on);
}
}
static void __cdecl gf_output_set_up_down(LED_INDEX index, bool led_on) {
if (index == 0) {
set_led_state(games::gitadora::Lights::P1MenuUpDown, led_on);
} else if (index == 1) {
set_led_state(games::gitadora::Lights::P2MenuUpDown, led_on);
}
}
static void __cdecl gf_output_set_left_right(LED_INDEX index, bool led_on) {
if (index == 0) {
set_led_state(games::gitadora::Lights::P1MenuLeftRight, led_on);
} else if (index == 1) {
set_led_state(games::gitadora::Lights::P2MenuLeftRight, led_on);
}
}
static void __cdecl gf_output_set_help(LED_INDEX index, bool led_on) {
if (index == 0) {
set_led_state(games::gitadora::Lights::P1MenuHelp, led_on);
} else if (index == 1) {
set_led_state(games::gitadora::Lights::P2MenuHelp, led_on);
}
}
void extdev_attach() {
// get instance
@@ -902,7 +1129,8 @@ void extdev_attach() {
"?gfdm_unit_get_button_gf@@YAHW4UNIT_NO@@W4GF_BUTTON_DEFINITION@@@Z"}));
detour::inline_hook((void *) gfdm_unit_get_dm_attack_border_value, libutils::try_proc_list(
EXTDEV_INSTANCE, {"gfdm_unit_get_dm_attack_border_value",
"?gfdm_unit_get_dm_attack_border_value@@YAHHPEAH@Z"}));
"?gfdm_unit_get_dm_attack_border_value@@YAHHPEAH@Z",
"?gfdm_unit_get_dm_attack_border_value@@YAHHPAH@Z"}));
detour::inline_hook((void *) gfdm_unit_get_errorcount, libutils::try_proc_list(
EXTDEV_INSTANCE, {"gfdm_unit_get_errorcount",
"?gfdm_unit_get_errorcount@@YAHH@Z"}));
@@ -920,7 +1148,8 @@ void extdev_attach() {
"?gfdm_unit_get_stream_errorcount@@YAHH@Z"}));
detour::inline_hook((void *) gfdm_unit_get_version, libutils::try_proc_list(
EXTDEV_INSTANCE, {"gfdm_unit_get_version",
"?gfdm_unit_get_version@@YAPEBUfirm_version@@H@Z"}));
"?gfdm_unit_get_version@@YAPEBUfirm_version@@H@Z",
"?gfdm_unit_get_version@@YAPBUfirm_version@@H@Z"}));
detour::inline_hook((void *) gfdm_unit_reset, libutils::try_proc_list(
EXTDEV_INSTANCE, {"gfdm_unit_reset",
"?gfdm_unit_reset@@YAHXZ"}));
@@ -932,7 +1161,8 @@ void extdev_attach() {
"?gfdm_unit_send_motor_value@@YAIHE@Z"}));
detour::inline_hook((void *) gfdm_unit_set_dm_attack_border_value, libutils::try_proc_list(
EXTDEV_INSTANCE, {"gfdm_unit_set_dm_attack_border_value",
"?gfdm_unit_set_dm_attack_border_value@@YAXQEAH@Z"}));
"?gfdm_unit_set_dm_attack_border_value@@YAXQEAH@Z",
"?gfdm_unit_set_dm_attack_border_value@@YAXQAH@Z"}));
detour::inline_hook((void *) gfdm_unit_shutdown, libutils::try_proc_list(
EXTDEV_INSTANCE, {"gfdm_unit_shutdown",
"?gfdm_unit_shutdown@@YAXXZ"}));
@@ -976,7 +1206,8 @@ void extdev_attach() {
"?gfdm_unit2_get_stream_errorcount@@YAHH@Z"}));
detour::inline_hook((void *) gfdm_unit2_get_version, libutils::try_proc_list(
EXTDEV_INSTANCE, {"gfdm_unit2_get_version",
"?gfdm_unit2_get_version@@YAPEBUfirm_version@@H@Z"}));
"?gfdm_unit2_get_version@@YAPEBUfirm_version@@H@Z",
"?gfdm_unit2_get_version@@YAPBUfirm_version@@H@Z"}));
detour::inline_hook((void *) gfdm_unit2_reset, libutils::try_proc_list(
EXTDEV_INSTANCE, {"gfdm_unit2_reset",
"?gfdm_unit2_reset@@YAHXZ"}));
@@ -999,7 +1230,8 @@ void extdev_attach() {
// led unit
detour::inline_hook((void *) led_get_version, libutils::try_proc_list(
EXTDEV_INSTANCE, {"led_get_version",
"?led_get_version@@YAPEBUfirm_version@@H@Z"}));
"?led_get_version@@YAPEBUfirm_version@@H@Z",
"?led_get_version@@YAPBUfirm_version@@H@Z"}));
detour::inline_hook((void *) led_unit_boot, libutils::try_proc_list(
EXTDEV_INSTANCE, {"led_unit_boot",
"?led_unit_boot@@YAXHH@Z"}));
@@ -1017,13 +1249,16 @@ void extdev_attach() {
"?led_unit_reset@@YAHXZ"}));
detour::inline_hook((void *) led_unit_send_custom1, libutils::try_proc_list(
EXTDEV_INSTANCE, {"led_unit_send_custom1",
"?led_unit_send_custom1@@YAIHQEAE@Z"}));
"?led_unit_send_custom1@@YAIHQEAE@Z",
"?led_unit_send_custom1@@YAIHQAE@Z"}));
detour::inline_hook((void *) led_unit_send_custom2, libutils::try_proc_list(
EXTDEV_INSTANCE, {"led_unit_send_custom2",
"?led_unit_send_custom2@@YAIHQEAE@Z"}));
"?led_unit_send_custom2@@YAIHQEAE@Z",
"?led_unit_send_custom2@@YAIHQAE@Z"}));
detour::inline_hook((void *) led_unit_send_direct, libutils::try_proc_list(
EXTDEV_INSTANCE, {"led_unit_send_direct",
"?led_unit_send_direct@@YAIHQEAE@Z"}));
"?led_unit_send_direct@@YAIHQEAE@Z",
"?led_unit_send_direct@@YAIHQAE@Z"}));
detour::inline_hook((void *) led_unit_shutdown, libutils::try_proc_list(
EXTDEV_INSTANCE, {"led_unit_shutdown",
"?led_unit_shutdown@@YAXXZ"}));
@@ -1054,6 +1289,28 @@ void extdev_attach() {
EXTDEV_INSTANCE, "sci_set_linebreak"));
detour::inline_hook((void *) sci_setparam, libutils::try_proc(
EXTDEV_INSTANCE, "sci_setparam"));
// libshare-pj.dll - dm_output
detour::inline_hook((void *) dm_output_set_padled, libutils::try_proc(
EXTDEV_INSTANCE, "dm_output_set_padled"));
detour::inline_hook((void *) dm_output_set_startled, libutils::try_proc(
EXTDEV_INSTANCE, "dm_output_set_startled"));
detour::inline_hook((void *) dm_output_set_up_down, libutils::try_proc(
EXTDEV_INSTANCE, "dm_output_set_up_down"));
detour::inline_hook((void *) dm_output_set_left_right, libutils::try_proc(
EXTDEV_INSTANCE, "dm_output_set_left_right"));
detour::inline_hook((void *) dm_output_set_help, libutils::try_proc(
EXTDEV_INSTANCE, "dm_output_set_help"));
// libshare-pj.dll - gf_output
detour::inline_hook((void *) gf_output_set_startlamp, libutils::try_proc(
EXTDEV_INSTANCE, "gf_output_set_startlamp"));
detour::inline_hook((void *) gf_output_set_up_down, libutils::try_proc(
EXTDEV_INSTANCE, "gf_output_set_up_down"));
detour::inline_hook((void *) gf_output_set_left_right, libutils::try_proc(
EXTDEV_INSTANCE, "gf_output_set_left_right"));
detour::inline_hook((void *) gf_output_set_help, libutils::try_proc(
EXTDEV_INSTANCE, "gf_output_set_help"));
}
}
-120
View File
@@ -1,120 +0,0 @@
#include "vrutil.h"
#include "util/logging.h"
namespace vrutil {
static bool INITIALIZED = false;
VRStatus STATUS = VRStatus::Disabled;
vr::IVRSystem *SYSTEM = nullptr;
vr::TrackedDeviceIndex_t INDEX_LEFT = ~0u;
vr::TrackedDeviceIndex_t INDEX_RIGHT = ~0u;
static std::string device_string(vr::TrackedDeviceIndex_t dev,
vr::TrackedDeviceProperty prop) {
uint32_t len = vr::VRSystem()->GetStringTrackedDeviceProperty(
dev, prop, nullptr, 0, nullptr);
if (len == 0) return "";
char *buf = new char[len];
vr::VRSystem()->GetStringTrackedDeviceProperty(
dev, prop, buf, len, nullptr);
std::string res = buf;
delete[] buf;
return res;
}
void init() {
if (INITIALIZED) return;
// initialize OpenVR
vr::EVRInitError error = vr::VRInitError_None;
SYSTEM = vr::VR_Init(&error, vr::VRApplication_Other);
if (error != vr::VRInitError_None || !SYSTEM) {
SYSTEM = nullptr;
STATUS = VRStatus::Error;
log_warning("vrutil", "unable to initialize: {}",
vr::VR_GetVRInitErrorAsEnglishDescription(error));
return;
}
// get information
auto driver = device_string(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_TrackingSystemName_String);
auto serial = device_string(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SerialNumber_String);
log_info("vrutil", "initialized: {} - {}", driver, serial);
// success
INITIALIZED = true;
STATUS = VRStatus::Running;
scan(true);
}
void shutdown() {
if (STATUS == VRStatus::Running) {
vr::VR_Shutdown();
}
SYSTEM = nullptr;
STATUS = VRStatus::Disabled;
}
void scan(bool log) {
if (STATUS != VRStatus::Running) return;
for (vr::TrackedDeviceIndex_t index = 0; index < vr::k_unMaxTrackedDeviceCount; ++index) {
auto dclass = SYSTEM->GetTrackedDeviceClass(index);
switch (dclass) {
case vr::TrackedDeviceClass_Controller: {
auto role = SYSTEM->GetControllerRoleForTrackedDeviceIndex(index);
switch (role) {
case vr::TrackedControllerRole_Invalid:
if (log) log_warning("vrutil", "invalid controller on index {}", index);
break;
case vr::TrackedControllerRole_LeftHand:
if (log) log_info("vrutil", "detected left controller on index {}", index);
INDEX_LEFT = index;
break;
case vr::TrackedControllerRole_RightHand:
if (log) log_info("vrutil", "detected right controller on index {}", index);
INDEX_RIGHT = index;
break;
default:
break;
}
break;
}
case vr::TrackedDeviceClass_GenericTracker: {
if (log) log_info("vrutil", "detected tracker on index {}", index);
break;
}
default:
break;
}
}
}
bool get_hmd_pose(vr::TrackedDevicePose_t *pose) {
if (STATUS != VRStatus::Running) {
*pose = vr::TrackedDevicePose_t {};
pose->bPoseIsValid = false;
return false;
}
SYSTEM->GetDeviceToAbsoluteTrackingPose(
vr::TrackingUniverseStanding,
0,
pose, 1);
return true;
}
bool get_con_pose(vr::TrackedDeviceIndex_t index,
vr::TrackedDevicePose_t *pose,
vr::VRControllerState_t *state) {
if (STATUS != VRStatus::Running || index == ~0u) {
*state = vr::VRControllerState_t {};
*pose = vr::TrackedDevicePose_t {};
pose->bPoseIsValid = false;
return false;
}
SYSTEM->GetControllerStateWithPose(
vr::TrackingUniverseStanding,
index, state, sizeof(vr::VRControllerState_t), pose);
return true;
}
}
-139
View File
@@ -1,139 +0,0 @@
#include <cmath>
#include "external/openvr/headers/openvr.h"
#include "external/linalg.h"
namespace vrutil {
enum class VRStatus {
Disabled, Error, Running,
};
extern VRStatus STATUS;
extern vr::IVRSystem *SYSTEM;
extern vr::TrackedDeviceIndex_t INDEX_LEFT;
extern vr::TrackedDeviceIndex_t INDEX_RIGHT;
void init();
void shutdown();
void scan(bool log = false);
bool get_hmd_pose(vr::TrackedDevicePose_t *pose);
bool get_con_pose(vr::TrackedDeviceIndex_t index,
vr::TrackedDevicePose_t *pose,
vr::VRControllerState_t *state);
/*
* Util
*/
inline linalg::aliases::float3 get_translation(vr::HmdMatrix34_t &m) {
return linalg::aliases::float3 {
m.m[0][3],
m.m[1][3],
m.m[2][3],
};
}
inline linalg::aliases::float3 get_direction_back(vr::HmdMatrix34_t &m) {
return linalg::normalize(linalg::aliases::float3 {
m.m[0][2],
m.m[1][2],
m.m[2][2],
});
}
inline linalg::aliases::float3 get_direction_front(vr::HmdMatrix34_t &m) {
return -get_direction_back(m);
}
inline linalg::aliases::float3 get_direction_up(vr::HmdMatrix34_t &m) {
return linalg::normalize(linalg::aliases::float3 {
m.m[0][1],
m.m[1][1],
m.m[2][1],
});
}
inline linalg::aliases::float3 get_direction_down(vr::HmdMatrix34_t &m) {
return -get_direction_up(m);
}
inline linalg::aliases::float3 get_direction_right(vr::HmdMatrix34_t &m) {
return linalg::normalize(linalg::aliases::float3 {
m.m[0][0],
m.m[1][0],
m.m[2][0],
});
}
inline linalg::aliases::float3 get_direction_left(vr::HmdMatrix34_t &m) {
return -get_direction_right(m);
}
template<class T>
inline linalg::aliases::float4 get_rotation(T &m) {
linalg::aliases::float4 q;
q.w = sqrtf(fmaxf(0, 1 + m[0][0] + m[1][1] + m[2][2])) * 0.5f;
q.x = sqrtf(fmaxf(0, 1 + m[0][0] - m[1][1] - m[2][2])) * 0.5f;
q.y = sqrtf(fmaxf(0, 1 - m[0][0] + m[1][1] - m[2][2])) * 0.5f;
q.z = sqrtf(fmaxf(0, 1 - m[0][0] - m[1][1] + m[2][2])) * 0.5f;
q.x = copysignf(q.x, m[2][1] - m[1][2]);
q.y = copysignf(q.y, m[0][2] - m[2][0]);
q.z = copysignf(q.z, m[1][0] - m[0][1]);
return q;
}
inline linalg::aliases::float4 get_rotation(
float pitch, float yaw, float roll) {
return linalg::aliases::float4 {
sinf(roll/2) * cosf(pitch/2) * cosf(yaw/2) - cosf(roll/2) * sinf(pitch/2) * sinf(yaw/2),
cosf(roll/2) * sinf(pitch/2) * cosf(yaw/2) + sinf(roll/2) * cosf(pitch/2) * sinf(yaw/2),
cosf(roll/2) * cosf(pitch/2) * sinf(yaw/2) - sinf(roll/2) * sinf(pitch/2) * cosf(yaw/2),
cosf(roll/2) * cosf(pitch/2) * cosf(yaw/2) + sinf(roll/2) * sinf(pitch/2) * sinf(yaw/2),
};
}
inline linalg::aliases::float3 orthogonal(
linalg::aliases::float3 v) {
auto x = std::fabs(v.x);
auto y = std::fabs(v.y);
auto z = std::fabs(v.z);
linalg::aliases::float3 o;
if (x < y) {
if (x < z) o = linalg::aliases::float3(1, 0, 0);
else o = linalg::aliases::float3(0, 0, 1);
} else {
if (y < z) o = linalg::aliases::float3(0, 1, 0);
else linalg::aliases::float3(0, 0, 1);
}
return linalg::cross(v, o);
}
inline linalg::aliases::float4 get_rotation(
linalg::aliases::float3 v1,
linalg::aliases::float3 v2) {
auto dot = linalg::dot(v1, v2);
auto scl = sqrtf(linalg::length2(v1) * linalg::length2(v2));
if (dot / scl == -1) {
auto v = linalg::normalize(orthogonal(v1));
return linalg::aliases::float4 {
v.x, v.y, v.z, 0,
};
}
auto cross = linalg::cross(v1, v2);
return linalg::normalize(linalg::aliases::float4 {
cross.x, cross.y, cross.z, dot + scl,
});
}
inline linalg::aliases::float3 intersect_point(
linalg::aliases::float3 ray_dir,
linalg::aliases::float3 ray_point,
linalg::aliases::float3 plane_normal,
linalg::aliases::float3 plane_point) {
auto delta = ray_point - plane_point;
auto delta_dot = linalg::dot(delta, plane_normal);
auto ray_dot = linalg::dot(ray_dir, plane_normal);
return ray_point - ray_dir * (delta_dot / ray_dot);
}
}
+60 -32
View File
@@ -4,11 +4,16 @@
#include "wintouchemu.h"
#include <chrono>
#include <algorithm>
#include <optional>
#include <thread>
#include "cfg/screen_resize.h"
#include "games/iidx/iidx.h"
#include "hooks/graphics/graphics.h"
#include "overlay/overlay.h"
#include "overlay/windows/generic_sub.h"
#include "touch/touch.h"
#include "util/detour.h"
#include "util/logging.h"
@@ -31,7 +36,7 @@ namespace wintouchemu {
bool LOG_FPS = false;
static inline bool is_emu_enabled() {
return FORCE || !is_touch_available() || GRAPHICS_SHOW_CURSOR;
return FORCE || !is_touch_available("wintouchemu::is_emu_enabled") || GRAPHICS_SHOW_CURSOR;
}
static decltype(GetSystemMetrics) *GetSystemMetrics_orig = nullptr;
@@ -75,10 +80,10 @@ namespace wintouchemu {
HMODULE HOOKED_MODULE = nullptr;
std::string WINDOW_TITLE_START = "";
std::optional<std::string> WINDOW_TITLE_END = std::nullopt;
bool INITIALIZED = false;
volatile bool INITIALIZED = false;
mouse_state_t mouse_state;
void hook(const char *window_title, HMODULE module) {
void hook(const char *window_title, HMODULE module, int delay_in_s) {
// hooks
auto system_metrics_hook = detour::iat_try(
@@ -97,7 +102,20 @@ namespace wintouchemu {
// set module and title
HOOKED_MODULE = module;
WINDOW_TITLE_START = window_title;
INITIALIZED = true;
if (0 < delay_in_s) {
// some games crash when touch events are injected too early during boot
std::thread t([&]() {
log_misc("wintouchemu", "defer initialization until later (with delay of {}s)", delay_in_s);
std::this_thread::sleep_for(std::chrono::seconds(delay_in_s));
log_misc("wintouchemu", "initializing", delay_in_s);
INITIALIZED = true;
});
t.detach();
} else {
log_misc("wintouchemu", "initializing");
INITIALIZED = true;
}
}
void hook_title_ends(const char *window_title_start, const char *window_title_end, HMODULE module) {
@@ -145,8 +163,20 @@ namespace wintouchemu {
auto x = touch_event->x;
auto y = touch_event->y;
auto valid = true;
if (overlay::OVERLAY) {
// log_misc("wintouchemu", "touch event ({}, {})", to_string(x), to_string(y));
if (GRAPHICS_IIDX_WSUB) {
// touch was received on subscreen window.
RECT clientRect {};
GetClientRect(TDJ_SUBSCREEN_WINDOW, &clientRect);
x = (float) x / clientRect.right * SPICETOUCH_TOUCH_WIDTH + SPICETOUCH_TOUCH_X;
y = (float) y / clientRect.bottom * SPICETOUCH_TOUCH_HEIGHT + SPICETOUCH_TOUCH_Y;
} else if (overlay::OVERLAY) {
// touch was received on global coords
valid = overlay::OVERLAY->transform_touch_point(&x, &y);
} else {
valid = false;
}
touch_input->x = x * 100;
@@ -185,6 +215,14 @@ namespace wintouchemu {
result = true;
touch_input->x = mouse_state.pos.x;
touch_input->y = mouse_state.pos.y;
if (GRAPHICS_WINDOWED) {
touch_input->x -= SPICETOUCH_TOUCH_X;
touch_input->y -= SPICETOUCH_TOUCH_Y;
}
// log_misc("wintouchemu", "mouse state ({}, {})", to_string(touch_input->x), to_string(touch_input->y));
auto valid = true;
if (overlay::OVERLAY) {
valid = overlay::OVERLAY->transform_touch_point(
@@ -222,7 +260,7 @@ namespace wintouchemu {
// reset it since the event was consumed & propagated as touch
mouse_state.touch_event = 0;
}
} else {
} else if (!GRAPHICS_IIDX_WSUB) {
/*
* For some reason, Nostalgia won't show an active touch point unless a move event
@@ -319,39 +357,29 @@ namespace wintouchemu {
// check if windowed
if (GRAPHICS_WINDOWED) {
log_info("wintouchemu", "activating window hooks");
// get client size
RECT rect {};
GetClientRect(hWnd, &rect);
// remove style borders
LONG lStyle = GetWindowLong(hWnd, GWL_STYLE);
lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU);
SetWindowLongPtr(hWnd, GWL_STYLE, lStyle);
// remove ex style borders
LONG lExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
lExStyle &= ~(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
SetWindowLongPtr(hWnd, GWL_EXSTYLE, lExStyle);
// update window
AdjustWindowRect(&rect, lStyle, FALSE);
SetWindowPos(hWnd, nullptr, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOOWNERZORDER);
// create touch window - create overlay if not yet existing at this point
touch_create_wnd(hWnd, overlay::ENABLED && !overlay::OVERLAY);
USE_MOUSE = false;
if (GRAPHICS_IIDX_WSUB) {
// no handling is needed here
// graphics::MoveWindow_hook will attach hook to windowed subscreen
log_info("wintouchemu", "attach touch hook to windowed subscreen for TDJ");
USE_MOUSE = false;
} else if (avs::game::is_model("LDJ") && !GENERIC_SUB_WINDOW_FULLSIZE) {
// overlay subscreen in IIDX
// use mouse position as ImGui overlay will block the touch window
log_info("wintouchemu", "use mouse cursor API for overlay subscreen");
USE_MOUSE = true;
} else {
// create touch window - create overlay if not yet existing at this point
log_info("wintouchemu", "create touch window relative to main game window");
touch_create_wnd(hWnd, overlay::ENABLED && !overlay::OVERLAY);
USE_MOUSE = false;
}
} else if (INJECT_MOUSE_AS_WM_TOUCH) {
log_info(
"wintouchemu",
"using raw mouse cursor API in full screen and injecting them as WM_TOUCH events");
USE_MOUSE = true;
} else {
log_info("wintouchemu", "activating DirectX hooks");
// mouse position based input only
touch_attach_dx_hook();
USE_MOUSE = false;
+1 -1
View File
@@ -9,7 +9,7 @@ namespace wintouchemu {
extern bool INJECT_MOUSE_AS_WM_TOUCH;
extern bool LOG_FPS;
void hook(const char *window_title, HMODULE module = nullptr);
void hook(const char *window_title, HMODULE module = nullptr, int delay_in_s=0);
void hook_title_ends(
const char *window_title_start,
const char *window_title_ends,