Update to spice2x-26-02-17 (pre-apply)

> broken commit
This commit is contained in:
[ ]
2026-02-19 15:41:42 +09:00
parent 04fc516d47
commit e923b7918f
211 changed files with 26313 additions and 19055 deletions
+85
View File
@@ -0,0 +1,85 @@
#include "ami2000.h"
#include "util/utils.h"
#include "util/detour.h"
#include "util/libutils.h"
#include "misc/eamuse.h"
#include "acio/icca/icca.h"
static int CARD_TYPE = 0;
static uint8_t CARD_UID[8];
static void __fastcall AMI2000_Initialize() {
log_info("ami2000", "ami2000 initialize.");
}
static void __fastcall AMI2000_Startup() {
log_info("ami2000", "ami2000 startup.");
}
static void __fastcall AMI2000_Cleanup() {
log_info("ami2000", "ami2000 cleanup.");
}
static int __fastcall AMI2000_IsDeviceError() {
return 0;
}
static int __fastcall AMI2000_ReadCtrl() {
return 0;
}
static const char *__fastcall AMI2000_GetRomVersion() {
return "DUMMY";
}
static int __fastcall AMI2000_GetCardType() {
return CARD_TYPE;
}
static uint64_t __fastcall AMI2000_GetCardIdentifier() {
if (eamuse_card_insert_consume(1, 0)) {
eamuse_get_card(1, 0, CARD_UID);
CARD_TYPE = is_card_uid_felica(CARD_UID) ? 2 : 1;
log_info("ami2000", "AMI2000_GetCardIdentifier: {:X}", bswap64(*(uint64_t*)CARD_UID));
} else {
CARD_TYPE = 0;
return 0;
}
return bswap64(*(uint64_t *)CARD_UID);
}
void ami2000_attach() {
auto ami2000 = libutils::try_module("iccr-ami2000-api.dll");
if (!ami2000) {
log_warning("ami2000", "module not found, skipping.");
return;
}
// card unit
detour::inline_hook((void *)AMI2000_Initialize, libutils::try_proc(
ami2000, "AMI2000_Initialize"));
detour::inline_hook((void *)AMI2000_Startup, libutils::try_proc(
ami2000, "AMI2000_Startup"));
detour::inline_hook((void *)AMI2000_IsDeviceError, libutils::try_proc(
ami2000, "AMI2000_IsDeviceError"));
detour::inline_hook((void *)AMI2000_ReadCtrl, libutils::try_proc(
ami2000, "AMI2000_ReadCtrl"));
detour::inline_hook((void *)AMI2000_Cleanup, libutils::try_proc(
ami2000, "AMI2000_Cleanup"));
detour::inline_hook((void *)AMI2000_GetRomVersion, libutils::try_proc(
ami2000, "AMI2000_GetRomVersion"));
detour::inline_hook((void *)AMI2000_GetCardType, libutils::try_proc(
ami2000, "AMI2000_GetCardType"));
detour::inline_hook((void *)AMI2000_GetCardIdentifier, libutils::try_proc(
ami2000, "AMI2000_GetCardIdentifier"));
log_info("ami2000", "attached");
}
void ami2000_detach()
{
}
+4
View File
@@ -0,0 +1,4 @@
#pragma once
void ami2000_attach();
void ami2000_detach();
+52 -20
View File
@@ -119,6 +119,7 @@ static std::string EAMIO_DLL_NAME = "eamio.dll";
static robin_hood::unordered_map<int, std::thread *> BT5API_THREADS;
static robin_hood::unordered_map<int, int> BT5API_THREAD_RESULTS;
static uint8_t BT5API_CARD_STATES[] = {0, 0};
static uint16_t BT5API_KEYPAD_STATES[] = {0, 0};
static void bt5api_log(const char *bt5_module, const char *fmt, ...) {
@@ -240,46 +241,77 @@ void bt5api_hook(HINSTANCE module) {
void bt5api_poll_reader_card(uint8_t unit_no) {
// check if initialized
if (!EAMIO_DLL) {
// check if initialized or out of bounds
if (!EAMIO_DLL || unit_no >= eamuse_get_game_keypads()) {
return;
}
// poll
if (!eam_io_poll(unit_no)) {
log_warning("bt5api", "polling bt5api reader {} returned failure",
log_warning("bt5api", "polling bt5api reader card {} returned failure",
static_cast<int>(unit_no));
return;
}
// get sensor state
uint8_t sensor_state = eam_io_get_sensor_state(unit_no);
// if we have a change in state.
if(sensor_state != BT5API_CARD_STATES[unit_no]) {
// check for card in
if (sensor_state > BT5API_CARD_STATES[unit_no]) {
uint8_t card_id[8];
eam_io_read_card(unit_no, card_id, 8);
eamuse_card_insert(unit_no, card_id);
// card inserted into the back.
if(sensor_state & (1 << EAM_IO_SENSOR_BACK)) {
uint8_t card_id[8];
log_info("bt5api", "card unit {} inserted", static_cast<int>(unit_no));
// do the bt5 dance
eam_io_card_slot_cmd(unit_no, EAM_IO_CARD_SLOT_CMD_CLOSE);
eam_io_poll(unit_no);
eam_io_card_slot_cmd(unit_no, EAM_IO_CARD_SLOT_CMD_READ);
eam_io_poll(unit_no);
// ask the api for the card, then insert it into our engine.
eam_io_read_card(unit_no, card_id, 8);
eamuse_card_insert(unit_no, card_id);
}
// if card removed entirely, do another bt5 dance!
if(sensor_state == 0) {
eam_io_card_slot_cmd(unit_no, EAM_IO_CARD_SLOT_CMD_CLOSE);
eam_io_poll(unit_no);
eam_io_card_slot_cmd(unit_no, EAM_IO_CARD_SLOT_CMD_OPEN);
log_info("bt5api", "card unit {} removed", static_cast<int>(unit_no));
}
}
// save state
// save prev state
BT5API_CARD_STATES[unit_no] = sensor_state;
}
void bt5api_poll_reader_keypad(uint8_t unit_no) {
// check if initialized
if (!EAMIO_DLL) {
// check if initialized or out of bounds
if (!EAMIO_DLL || unit_no >= eamuse_get_game_keypads()) {
return;
}
// poll
if (!eam_io_poll(unit_no)) {
log_warning("bt5api", "polling bt5api reader {} returned failure",
static_cast<int>(unit_no));
uint16_t keypad_current = eam_io_get_keypad_state(unit_no);
uint16_t keypad_changes = ~BT5API_KEYPAD_STATES[unit_no] & keypad_current;
// if user has pressed decimal for the first time, eject the slotted reader.
if(keypad_changes & (1 << EAM_IO_KEYPAD_DECIMAL)) {
log_info("bt5api", "card unit {} ejecting", static_cast<int>(unit_no));
eam_io_card_slot_cmd(unit_no, EAM_IO_CARD_SLOT_CMD_EJECT);
}
// save the last pressed.
BT5API_KEYPAD_STATES[unit_no] = keypad_current;
// get keypad
eamuse_set_keypad_overrides_bt5(unit_no, eam_io_get_keypad_state(unit_no));
// send off the state to the main engine.
eamuse_set_keypad_overrides_bt5(unit_no, keypad_current);
}
void bt5api_dispose() {
+2 -2
View File
@@ -81,7 +81,7 @@ namespace clipboard {
Gdiplus::GpBitmap *bitmap = nullptr;
auto status = imports::GdipCreateBitmapFromFile(path.c_str(), &bitmap);
if (status != Gdiplus::Ok) {
log_warning("clipboard", "failed to create GDI+ bitmap: {}", status);
log_warning("clipboard", "failed to create GDI+ bitmap: {}", static_cast<uint32_t>(status));
imports::GdiplusShutdown(token);
CloseClipboard();
@@ -123,7 +123,7 @@ namespace clipboard {
log_warning("clipboard", "failed to save image to clipboard");
}
} else {
log_warning("clipboard", "failed to retrieve HBITMAP from image bitmap: {}", status);
log_warning("clipboard", "failed to retrieve HBITMAP from image bitmap: {}", static_cast<uint32_t>(status));
}
// Clean up after ourselves. hmem can't be deleted because it is owned by the clipboard now.
+8 -1
View File
@@ -202,7 +202,14 @@ bool eamuse_card_insert_consume(int active_count, int unit_id) {
// bt5api
if (BT5API_ENABLED) {
bt5api_poll_reader_card((uint8_t) index);
// some bt5api want to be polled in order.
if (eamuse_get_game_keypads() > 1) {
bt5api_poll_reader_card(1);
bt5api_poll_reader_card(0);
}
else {
bt5api_poll_reader_card((uint8_t) index);
}
}
// auto insert card
+120 -56
View File
@@ -7,6 +7,8 @@
#include "util/detour.h"
#include "util/libutils.h"
#include "util/circular_buffer.h"
#include "util/socd_cleaner.h"
#include "util/time.h"
#include "misc/eamuse.h"
#include "cfg/api.h"
#include "acio/icca/icca.h"
@@ -336,6 +338,9 @@ static int __cdecl gfdm_unit2_boot_initialize() {
return 1;
}
constexpr int LEFTY_X_CENTER = 2040;
// this seems to be only used in the I/O test menu, not in gameplay
static void *__cdecl gfdm_unit_get_button_p(void *a1, int a2, size_t player) {
memset(a1, 0, 64);
@@ -344,31 +349,61 @@ static void *__cdecl gfdm_unit_get_button_p(void *a1, int a2, size_t player) {
return a1;
}
// log_info("gitadora", "gfdm_unit_get_button_p: a2={}, player={}", a2, player);
// get buttons
auto &buttons = games::gitadora::get_buttons();
auto &analogs = games::gitadora::get_analogs();
const auto wail_up =
Buttons::getState(RI_MGR, buttons.at(gitadora_button_mapping[12 + 11 * (size_t) player]));
const auto wail_down =
Buttons::getState(RI_MGR, buttons.at(gitadora_button_mapping[13 + 11 * (size_t) player]));
const auto wail_result =
socd::get_guitar_wail(player, wail_up, wail_down, get_performance_milliseconds());
// X
((int *) a1)[4] = a2 == 1 ? 4080 : -4080;
if (analogs.at(player * 3 + 0).isSet())
((int *) a1)[4] = lroundf(Analogs::getState(
RI_MGR, analogs.at(gitadora_analog_mapping[player * 4 + 0])) * 8160.f) - 4080;
// wail X
((int *) a1)[4] = games::gitadora::is_player_lefty(player) ? LEFTY_X_CENTER : -4080;
auto &analog_x = analogs.at(gitadora_analog_mapping[player * 4 + 0]);
if (analog_x.isSet())
((int *) a1)[4] = lroundf(Analogs::getState(RI_MGR, analog_x) * 8160.f) - 4080;
// Y
// wail Y
((int *) a1)[5] = 0;
if (analogs.at(player * 3 + 1).isSet())
((int *) a1)[5] = lroundf(Analogs::getState(
RI_MGR, analogs.at(gitadora_analog_mapping[player * 4 + 1])) * 8160.f) - 4080;
if (Buttons::getState(RI_MGR, buttons.at(gitadora_button_mapping[12 + 11 * (size_t) player])))
((int *) a1)[5] = -4080;
if (Buttons::getState(RI_MGR, buttons.at(gitadora_button_mapping[13 + 11 * (size_t) player])))
((int *) a1)[5] = 4080;
auto &analog_y = analogs.at(gitadora_analog_mapping[player * 4 + 1]);
if (analog_y.isSet()) {
((int *) a1)[5] = lroundf(Analogs::getState(RI_MGR, analog_y) * 8160.f) - 4080;
}
// Z
// digital wailing
if (!games::gitadora::is_player_lefty(player)) {
// righty
if (wail_result == socd::TiltUp) {
// top center
((int *) a1)[4] = 0; // X
((int *) a1)[5] = -4080; // Y
} else if (wail_result == socd::TiltDown) {
// bottom left; for lefty, bottom right
((int *) a1)[4] = -4080; // X
((int *) a1)[5] = 4080; // Y
}
} else {
// lefty
if (wail_result == socd::TiltUp) {
// left
((int *) a1)[4] = -4080; // X
((int *) a1)[5] = 0; // Y
} else if (wail_result == socd::TiltDown) {
// right
((int *) a1)[4] = 4080; // X
((int *) a1)[5] = 0; // Y
}
}
// wail Z
((int *) a1)[6] = 0;
if (analogs.at(player * 3 + 2).isSet())
((int *) a1)[6] = lroundf(Analogs::getState(
RI_MGR, analogs.at(gitadora_analog_mapping[player * 4 + 2])) * 8160.f) - 4080;
auto &analog_z = analogs.at(gitadora_analog_mapping[player * 4 + 2]);
if (analog_z.isSet())
((int *) a1)[6] = lroundf(Analogs::getState(RI_MGR, analog_z) * 8160.f) - 4080;
// return the same buffer
return a1;
@@ -487,24 +522,42 @@ static long __cdecl gfdm_unit_get_input_p(int device, size_t player) {
if (games::gitadora::is_guitar()) {
auto offset = player * 11;
// pick up
if (Buttons::getState(RI_MGR, buttons.at(gitadora_button_mapping[3 + offset]))) {
if (!GFDM_GF_PICK_STATE_UP[player]) {
GFDM_GF_PICK_STATE_UP[player] = true;
ret |= 0x80 | 0x20;
const auto pick_up = Buttons::getState(RI_MGR, buttons.at(gitadora_button_mapping[3 + offset]));
const auto pick_down = Buttons::getState(RI_MGR, buttons.at(gitadora_button_mapping[4 + offset]));
if (!games::gitadora::PICK_ALGO.has_value()) {
// legacy behavior (detect rising edges only, input for 1 frame)
if (pick_up) {
if (!GFDM_GF_PICK_STATE_UP[player]) {
GFDM_GF_PICK_STATE_UP[player] = true;
ret |= 0x80 | 0x20;
}
} else {
GFDM_GF_PICK_STATE_UP[player] = false;
}
} else {
GFDM_GF_PICK_STATE_UP[player] = false;
}
// pick down
if (Buttons::getState(RI_MGR, buttons.at(gitadora_button_mapping[4 + offset]))) {
if (!GFDM_GF_PICK_STATE_DOWN[player]) {
GFDM_GF_PICK_STATE_DOWN[player] = true;
ret |= 0x100 | 0x20;
if (pick_down) {
if (!GFDM_GF_PICK_STATE_DOWN[player]) {
GFDM_GF_PICK_STATE_DOWN[player] = true;
ret |= 0x100 | 0x20;
}
} else {
GFDM_GF_PICK_STATE_DOWN[player] = false;
}
} else {
GFDM_GF_PICK_STATE_DOWN[player] = false;
const auto socd = socd::socd_clean(
player,
pick_up,
pick_down,
get_performance_milliseconds(),
games::gitadora::PICK_ALGO.value()
);
if (socd == socd::SocdCCW) {
ret |= 0x80 | 0x20; // pick up
} else if (socd == socd::SocdCW) {
ret |= 0x100 | 0x20; // pick down
} else if (socd == socd::SocdBoth) {
ret |= 0x100 | 0x80 | 0x20; // up and down
}
}
// button R
@@ -585,63 +638,74 @@ static long __cdecl gfdm_unit2_get_input(int device) {
return gfdm_unit_get_input_p(device, 1);
}
// this is used in gameplay
static long __cdecl gfdm_unit_get_sensor_gf_p(int a1, int a2, size_t player) {
// return if it's actually drum mania
if (games::gitadora::is_drum())
return 0;
// log_info("gitadora", "gfdm_unit_get_sensor_gf_p: a1={}, a2={}, player={}", a1, a2, player);
// get buttons and analogs
auto &buttons = games::gitadora::get_buttons();
auto &analogs = games::gitadora::get_analogs();
// X
// figure out digital wail Y
const size_t offset = (size_t) player * 11;
const auto wail_up = Buttons::getState(RI_MGR, buttons.at(gitadora_button_mapping[12 + offset]));
const auto wail_down = Buttons::getState(RI_MGR, buttons.at(gitadora_button_mapping[13 + offset]));
const auto wail_result = socd::get_guitar_wail(player, wail_up, wail_down, get_performance_milliseconds());
// wail X
if (a2 == 0) {
long ret = games::gitadora::is_player_lefty(player) ? LEFTY_X_CENTER : -4080;
// analog override
if (analogs.at(gitadora_analog_mapping[player * 3 + 0]).isSet()) {
return lroundf(Analogs::getState(
RI_MGR, analogs.at(gitadora_analog_mapping[player * 4 + 0])) * 8160.f) - 4080;
auto &analog_x = analogs.at(gitadora_analog_mapping[player * 4 + 0]);
if (analog_x.isSet()) {
ret = lroundf(Analogs::getState(RI_MGR, analog_x) * 8160.f) - 4080;
}
// digital wail up/down
if (wail_result == socd::TiltUp) {
ret = games::gitadora::is_player_lefty(player) ? -4080 : 0;
} else if (wail_result == socd::TiltDown) {
ret = games::gitadora::is_player_lefty(player) ? +4080 : -4080;
}
// default
return a1 == 1 ? 4080 : -4080;
return ret;
}
// Y
// wail Y
if (a2 == 1) {
long ret = 0;
// analog override
if (analogs.at(player * 3 + 1).isSet()) {
return lroundf(Analogs::getState(
RI_MGR, analogs.at(gitadora_analog_mapping[player * 4 + 1])) * 8160.f) - 4080;
auto &analog_y = analogs.at(gitadora_analog_mapping[player * 4 + 1]);
if (analog_y.isSet()) {
ret = lroundf(Analogs::getState(RI_MGR, analog_y) * 8160.f) - 4080;
}
// variables
long ret = 0;
size_t offset = (size_t) player * 11;
// wail up
if (Buttons::getState(RI_MGR, buttons.at(gitadora_button_mapping[12 + offset]))) {
ret -= 4080;
}
// wail down
if (Buttons::getState(RI_MGR, buttons.at(gitadora_button_mapping[13 + offset]))) {
ret += 4080;
// digital wail up/down
if (wail_result == socd::TiltUp) {
ret = games::gitadora::is_player_lefty(player) ? 0 : -4080;
} else if (wail_result == socd::TiltDown) {
ret = games::gitadora::is_player_lefty(player) ? 0 : 4080;
}
// return value
return ret;
}
// Z
// wail Z
if (a2 == 2) {
// analog override
if (analogs.at(gitadora_analog_mapping[player * 3 + 2]).isSet()) {
return lroundf(Analogs::getState(
RI_MGR, analogs.at(gitadora_analog_mapping[player * 4 + 2])) * 8160.f) - 4080;
auto &analog_z = analogs.at(gitadora_analog_mapping[player * 4 + 2]);
if (analog_z.isSet()) {
return lroundf(Analogs::getState(RI_MGR, analog_z) * 8160.f) - 4080;
}
// default
+91
View File
@@ -0,0 +1,91 @@
// enable touch functions - set version to windows 7
// mingw otherwise doesn't load touch stuff
#define _WIN32_WINNT 0x0601
#include "wintouchemu.h"
#include "util/detour.h"
#include "util/logging.h"
#define TOUCH_SIMULATE_FAT_FINGERS 0
#define TOUCH_DEBUG_VERBOSE 0
#if TOUCH_DEBUG_VERBOSE
#define log_debug(module, format_str, ...) logger::push( \
LOG_FORMAT("M", module, format_str, ## __VA_ARGS__), logger::Style::GREY)
#else
#define log_debug(module, format_str, ...)
#endif
namespace nativetouchhook {
static decltype(GetTouchInputInfo) *GetTouchInputInfo_orig = nullptr;
static void strip_contact_size(PTOUCHINPUT point) {
#if TOUCH_SIMULATE_FAT_FINGERS
point->dwMask |= 0x004;
point->cxContact = 80 * 100;
point->cyContact = 60 * 100;
#endif
// most monitors do not set TOUCHEVENTFMASK_CONTACTAREA, but for
// monitors that do set it, IIDX can get very confused (SDVX is not
// affected)
//
// while the test menu and the touch "glow" seem to work properly,
// interacting with subscreen menu items or entering PIN becomes
// very unpredictable
//
// to fix this, simply remove the contact area width and height
//
// note: test menu > I/O > touch test gives 5 numbers:
// n: x, y, w, h
// where
// n is the nth touch input since boot
// x, y are coordinates (center of finger)
// w, h are contact width and height
//
// when TOUCHEVENTFMASK_CONTACTAREA is not set, w/h will
// automatically be seen as 1x1, which works perfectly fine
log_debug(
"touch::native",
"[{}, {}] dwMask = 0x{:x}, cxContact = {}, cyContact = {}",
point->x / 100,
point->y / 100,
point->dwMask,
point->cxContact,
point->cyContact);
point->dwMask &= ~(0x004ul); // clear TOUCHEVENTFMASK_CONTACTAREA
point->cxContact = 0;
point->cyContact = 0;
}
static BOOL WINAPI GetTouchInputInfoHook(
HTOUCHINPUT hTouchInput, UINT cInputs, PTOUCHINPUT pInputs, int cbSize) {
// call the original fist
const auto result = GetTouchInputInfo_orig(hTouchInput, cInputs, pInputs, cbSize);
if (result == 0) {
return result;
}
for (size_t i = 0; i < cInputs; i++) {
PTOUCHINPUT point = &pInputs[i];
strip_contact_size(point);
}
return result;
}
void hook(HMODULE module) {
GetTouchInputInfo_orig = detour::iat_try("GetTouchInputInfo", GetTouchInputInfoHook, module);
if (GetTouchInputInfo_orig != nullptr) {
log_misc("touch::native", "GetTouchInputInfo hooked");
}
}
}
+6
View File
@@ -0,0 +1,6 @@
#include <windows.h>
namespace nativetouchhook {
void hook(HMODULE module);
}
+30 -1
View File
@@ -10,6 +10,7 @@
#include <thread>
#include "cfg/screen_resize.h"
#include "games/gitadora/gitadora.h"
#include "games/iidx/iidx.h"
#include "hooks/graphics/graphics.h"
#include "overlay/overlay.h"
@@ -34,6 +35,7 @@ namespace wintouchemu {
bool FORCE = false;
bool INJECT_MOUSE_AS_WM_TOUCH = false;
bool LOG_FPS = false;
bool ADD_TOUCH_FLAG_PRIMARY = false;
static inline bool is_emu_enabled() {
return FORCE || !is_touch_available("wintouchemu::is_emu_enabled") || GRAPHICS_SHOW_CURSOR;
@@ -187,16 +189,28 @@ namespace wintouchemu {
switch (touch_event->type) {
case TOUCH_DOWN:
if (valid) {
if (ADD_TOUCH_FLAG_PRIMARY) {
touch_input->dwFlags |= TOUCHEVENTF_PRIMARY;
}
touch_input->dwFlags |= TOUCHEVENTF_DOWN;
}
break;
case TOUCH_MOVE:
if (valid) {
if (ADD_TOUCH_FLAG_PRIMARY) {
touch_input->dwFlags |= TOUCHEVENTF_PRIMARY;
}
touch_input->dwFlags |= TOUCHEVENTF_MOVE;
}
break;
case TOUCH_UP:
// don't check valid so that this touch ID can be released
if (ADD_TOUCH_FLAG_PRIMARY) {
touch_input->dwFlags |= TOUCHEVENTF_PRIMARY;
}
touch_input->dwFlags |= TOUCHEVENTF_UP;
break;
}
@@ -238,16 +252,28 @@ namespace wintouchemu {
switch (mouse_state.touch_event) {
case TOUCHEVENTF_DOWN:
if (valid) {
if (ADD_TOUCH_FLAG_PRIMARY) {
touch_input->dwFlags |= TOUCHEVENTF_PRIMARY;
}
touch_input->dwFlags |= TOUCHEVENTF_DOWN;
}
break;
case TOUCHEVENTF_MOVE:
if (valid) {
if (ADD_TOUCH_FLAG_PRIMARY) {
touch_input->dwFlags |= TOUCHEVENTF_PRIMARY;
}
touch_input->dwFlags |= TOUCHEVENTF_MOVE;
}
break;
case TOUCHEVENTF_UP:
// don't check valid so that this touch ID can be released
if (ADD_TOUCH_FLAG_PRIMARY) {
touch_input->dwFlags |= TOUCHEVENTF_PRIMARY;
}
touch_input->dwFlags |= TOUCHEVENTF_UP;
break;
}
@@ -365,7 +391,10 @@ namespace wintouchemu {
} 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");
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) {
log_info("wintouchemu", "use mouse cursor API for gitadora overlay subscreen");
USE_MOUSE = true;
} else {
// create touch window - create overlay if not yet existing at this point
+1
View File
@@ -8,6 +8,7 @@ namespace wintouchemu {
extern bool FORCE;
extern bool INJECT_MOUSE_AS_WM_TOUCH;
extern bool LOG_FPS;
extern bool ADD_TOUCH_FLAG_PRIMARY;
void hook(const char *window_title, HMODULE module = nullptr, int delay_in_s=0);
void hook_title_ends(