mirror of
https://gitea.tendokyu.moe/TeamTofuShop/segatools.git
synced 2026-09-22 22:37:59 +03:00
This adds a setting to the global configuration to allow only input when the game is focused. This prevents issues, such as triggering game buttons or service buttons while being tabbed out. Turned off by default. The implementation is not the best, but in the context how these games are structured, the most acceptable. It will keep scanning if the foreground window title fully matches (some games partially match, like FGO because due to the revision number in the title), and if found, will grab the HWND of that window and compare that from then on, to not tank performance due to constant string operations. Tested with FGO, chusan and ongeki. Reviewed-on: https://gitea.tendokyu.moe/TeamTofuShop/segatools/pulls/83 Reviewed-by: Dniel97 <dniel97@noreply.gitea.tendokyu.moe> Co-authored-by: kyoubate-haruka <46010460+kyoubate-haruka@users.noreply.github.com> Co-committed-by: kyoubate-haruka <46010460+kyoubate-haruka@users.noreply.github.com>
244 lines
4.7 KiB
C
244 lines
4.7 KiB
C
#include <windows.h>
|
|
|
|
#include <assert.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <winuser.h>
|
|
|
|
#include "cxbhook/revio.h"
|
|
#include "cxbhook/cxb-dll.h"
|
|
|
|
#include "hook/procaddr.h"
|
|
|
|
#include "hook/table.h"
|
|
|
|
#include "util/dprintf.h"
|
|
#include "util/fg-detect.h"
|
|
|
|
static int my_cCommIo_Open(char *port);
|
|
static int my_cCommIo_Close();
|
|
static long my_cCommIo_GetCoin();
|
|
static int my_cCommIo_SetCoin(int coin_ct);
|
|
static int my_cCommIo_GetStatus();
|
|
static int my_cCommIo_GetSwitch();
|
|
static int my_cCommIo_GetTrigger();
|
|
static int my_cCommIo_GetRelease();
|
|
static long my_cCommIo_GetVolume();
|
|
static int my_cCommIo_SetAmpVolume(int amp_id, long new_volume);
|
|
static int my_cCommIo_GetAmpVolume(int amp_id);
|
|
static int my_cCommIo_SetAmpMute(int amp_id, int a2);
|
|
|
|
int amp_volume[] = {20, 20, 20};
|
|
int last_triggers = 0;
|
|
int last_is_mouse_down = false;
|
|
int prev_out = 0;
|
|
|
|
static struct hook_symbol revio_syms[] = {
|
|
{
|
|
.name = "cCommIo_Open",
|
|
.patch = my_cCommIo_Open
|
|
},
|
|
{
|
|
.name = "cCommIo_Close",
|
|
.patch = my_cCommIo_Close
|
|
},
|
|
{
|
|
.name = "cCommIo_GetStatus",
|
|
.patch = my_cCommIo_GetStatus
|
|
},
|
|
{
|
|
.name = "cCommIo_GetCoin",
|
|
.patch = my_cCommIo_GetCoin
|
|
},
|
|
{
|
|
.name = "cCommIo_SetCoin",
|
|
.patch = my_cCommIo_SetCoin
|
|
},
|
|
{
|
|
.name = "cCommIo_GetSwitch",
|
|
.patch = my_cCommIo_GetSwitch
|
|
},
|
|
{
|
|
.name = "cCommIo_GetTrigger",
|
|
.patch = my_cCommIo_GetTrigger
|
|
},
|
|
{
|
|
.name = "cCommIo_GetRelease",
|
|
.patch = my_cCommIo_GetRelease
|
|
},
|
|
{
|
|
.name = "cCommIo_GetVolume",
|
|
.patch = my_cCommIo_GetVolume
|
|
},
|
|
{
|
|
.name = "cCommIo_SetAmpVolume",
|
|
.patch = my_cCommIo_SetAmpVolume
|
|
},
|
|
{
|
|
.name = "cCommIo_GetAmpVolume",
|
|
.patch = my_cCommIo_GetAmpVolume
|
|
},
|
|
{
|
|
.name = "cCommIo_SetAmpMute",
|
|
.patch = my_cCommIo_SetAmpMute
|
|
},
|
|
};
|
|
|
|
HRESULT revio_hook_init(struct revio_config *cfg)
|
|
{
|
|
assert(cfg != NULL);
|
|
|
|
if (!cfg->enable) {
|
|
return S_FALSE;
|
|
}
|
|
|
|
dprintf("Revio: Hook enabled.\n");
|
|
return proc_addr_table_push(NULL, "CommIo.dll", revio_syms, _countof(revio_syms));
|
|
}
|
|
|
|
static int my_cCommIo_Open(char *port)
|
|
{
|
|
dprintf("Revio: Open port %s\n", port);
|
|
cxb_dll.revio_init();
|
|
return 1;
|
|
}
|
|
|
|
static int my_cCommIo_Close()
|
|
{
|
|
dprintf("Revio: Close\n");
|
|
return 0;
|
|
}
|
|
|
|
static int my_cCommIo_GetStatus()
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static long my_cCommIo_GetCoin()
|
|
{
|
|
long coins;
|
|
cxb_dll.revio_get_coins(&coins);
|
|
|
|
return coins;
|
|
}
|
|
|
|
static int my_cCommIo_SetCoin(int coin_ct)
|
|
{
|
|
// does some weird shit, not sure
|
|
//dprintf("Revio: Set coin %d\n", coin_ct);
|
|
cxb_dll.revio_set_coins(coin_ct);
|
|
return 1;
|
|
}
|
|
|
|
static int my_cCommIo_GetSwitch()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int my_cCommIo_GetTrigger()
|
|
{
|
|
uint16_t btns = 0;
|
|
int out = 0;
|
|
|
|
fgdet_poll();
|
|
if (fgdet_in_foreground()) {
|
|
cxb_dll.revio_poll(&btns);
|
|
|
|
if (btns & 0x01) {
|
|
out |= 1 << 4; // test
|
|
}
|
|
|
|
if (btns & 0x02) {
|
|
out |= 1 << 5; // service?
|
|
}
|
|
|
|
if (btns & 0x04) {
|
|
out |= 1 << 1; // up
|
|
}
|
|
|
|
if (btns & 0x08) {
|
|
out |= 1 << 3; // down
|
|
}
|
|
|
|
if (btns & 0x0F) {
|
|
out |= 1 << 2; // cancel
|
|
}
|
|
prev_out = out;
|
|
} else {
|
|
out = prev_out;
|
|
}
|
|
|
|
out &= ~last_triggers;
|
|
|
|
// dprintf("Revio: GetTrigger %X\n", out);
|
|
last_triggers = out;
|
|
return out;
|
|
}
|
|
|
|
static int my_cCommIo_GetRelease()
|
|
{
|
|
uint16_t btns = 0;
|
|
int out = last_triggers;
|
|
|
|
cxb_dll.revio_poll(&btns);
|
|
|
|
if (btns & 0x01) {
|
|
out |= 1 << 4; // test
|
|
}
|
|
|
|
if (btns & 0x02) {
|
|
out |= 1 << 5; // service?
|
|
}
|
|
|
|
if (btns & 0x04) {
|
|
out |= 1 << 1; // up
|
|
}
|
|
|
|
if (btns & 0x08) {
|
|
out |= 1 << 3; // down
|
|
}
|
|
|
|
if (btns & 0x0F) {
|
|
out |= 1 << 2; // cancel
|
|
}
|
|
|
|
out &= ~btns;
|
|
|
|
// dprintf("Revio: GetRelease %X\n", out);
|
|
last_triggers = btns;
|
|
return out;
|
|
}
|
|
|
|
static long my_cCommIo_GetVolume()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int my_cCommIo_SetAmpVolume(int amp_id, long new_volume)
|
|
{
|
|
dprintf("Revio: SetAmpVolume id %d -> vol %ld\n", amp_id, new_volume);
|
|
if (amp_id > _countof(amp_volume)) {
|
|
return 0;
|
|
}
|
|
|
|
amp_volume[amp_id] = new_volume;
|
|
return 0;
|
|
}
|
|
|
|
static int my_cCommIo_GetAmpVolume(int amp_id)
|
|
{
|
|
dprintf("Revio: GetAmpVolume id %d\n", amp_id);
|
|
if (amp_id > _countof(amp_volume)) {
|
|
return 0;
|
|
}
|
|
|
|
return amp_volume[amp_id];
|
|
}
|
|
|
|
static int my_cCommIo_SetAmpMute(int amp_id, int a2)
|
|
{
|
|
dprintf("Revio: GetAmpVolume id %d unknown %d\n", amp_id, a2);
|
|
return 0;
|
|
}
|