Update to spice2x-26-02-17 (pre-apply)
> broken commit
This commit is contained in:
@@ -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()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
void ami2000_attach();
|
||||
void ami2000_detach();
|
||||
+52
-20
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
#include <windows.h>
|
||||
|
||||
namespace nativetouchhook {
|
||||
void hook(HMODULE module);
|
||||
}
|
||||
|
||||
+30
-1
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user