fgo: fgohook finally added

Credits:
- Coburn
- domeori
- Mitsuhide
- OLEG
- rakisaionji
This commit is contained in:
2023-11-11 22:47:47 +01:00
parent 946ea7ef3b
commit a2db39c58c
30 changed files with 4478 additions and 0 deletions

20
fgoio/config.c Normal file
View File

@ -0,0 +1,20 @@
#include <windows.h>
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include "fgoio/config.h"
void fgo_io_config_load(
struct fgo_io_config *cfg,
const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
cfg->vk_test = GetPrivateProfileIntW(L"io4", L"test", '1', filename);
cfg->vk_service = GetPrivateProfileIntW(L"io4", L"service", '2', filename);
cfg->vk_coin = GetPrivateProfileIntW(L"io4", L"coin", '3', filename);
}

16
fgoio/config.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
struct fgo_io_config {
uint8_t vk_test;
uint8_t vk_service;
uint8_t vk_coin;
};
void fgo_io_config_load(
struct fgo_io_config *cfg,
const wchar_t *filename);

141
fgoio/fgoio.c Normal file
View File

@ -0,0 +1,141 @@
#include <windows.h>
#include <xinput.h>
#include <math.h>
#include <limits.h>
#include <stdint.h>
#include "fgoio/fgoio.h"
#include "fgoio/config.h"
#include "util/dprintf.h"
static uint8_t fgo_opbtn;
static uint8_t fgo_gamebtn;
static int16_t fgo_stick_x;
static int16_t fgo_stick_y;
static struct fgo_io_config fgo_io_cfg;
static bool fgo_io_coin;
uint16_t fgo_io_get_api_version(void)
{
return 0x0100;
}
HRESULT fgo_io_init(void)
{
fgo_io_config_load(&fgo_io_cfg, L".\\segatools.ini");
return S_OK;
}
HRESULT fgo_io_poll(void)
{
XINPUT_STATE xi;
WORD xb;
fgo_opbtn = 0;
fgo_gamebtn = 0;
fgo_stick_x = 0;
fgo_stick_y = 0;
if (GetAsyncKeyState(fgo_io_cfg.vk_test) & 0x8000) {
fgo_opbtn |= FGO_IO_OPBTN_TEST;
}
if (GetAsyncKeyState(fgo_io_cfg.vk_service) & 0x8000) {
fgo_opbtn |= FGO_IO_OPBTN_SERVICE;
}
if (GetAsyncKeyState(fgo_io_cfg.vk_coin) & 0x8000) {
if (!fgo_io_coin) {
fgo_io_coin = true;
fgo_opbtn |= FGO_IO_OPBTN_COIN;
}
} else {
fgo_io_coin = false;
}
memset(&xi, 0, sizeof(xi));
XInputGetState(0, &xi);
xb = xi.Gamepad.wButtons;
if (xi.Gamepad.bLeftTrigger > 64) {
fgo_gamebtn |= FGO_IO_GAMEBTN_SPEED_UP;
}
if (xb & XINPUT_GAMEPAD_LEFT_SHOULDER) {
fgo_gamebtn |= FGO_IO_GAMEBTN_TARGET;
}
if (xb & XINPUT_GAMEPAD_A) {
fgo_gamebtn |= FGO_IO_GAMEBTN_ATTACK;
}
if (xb & XINPUT_GAMEPAD_Y) {
fgo_gamebtn |= FGO_IO_GAMEBTN_NOBLE_PHANTASHM;
}
if (xb & XINPUT_GAMEPAD_LEFT_THUMB) {
fgo_gamebtn |= FGO_IO_GAMEBTN_CAMERA;
}
float LX = xi.Gamepad.sThumbLX;
float LY = xi.Gamepad.sThumbLY;
// determine how far the controller is pushed
float magnitude = sqrt(LX*LX + LY*LY);
// determine the direction the controller is pushed
float normalizedLX = LX / magnitude;
float normalizedLY = LY / magnitude;
float normalizedMagnitude = 0;
// check if the controller is outside a circular dead zone
if (magnitude > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
{
// clip the magnitude at its expected maximum value
if (magnitude > 32767) magnitude = 32767;
// adjust magnitude relative to the end of the dead zone
magnitude -= XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE;
// optionally normalize the magnitude with respect to its expected range
// giving a magnitude value of 0.0 to 1.0
normalizedMagnitude = magnitude / (32767 - XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
} else // if the controller is in the deadzone zero out the magnitude
{
magnitude = 0.0;
normalizedMagnitude = 0.0;
}
fgo_stick_x = normalizedLX * normalizedMagnitude * 32767;
fgo_stick_y = normalizedLY * normalizedMagnitude * 32767;
return S_OK;
}
void fgo_io_get_opbtns(uint8_t *opbtn)
{
if (opbtn != NULL) {
*opbtn = fgo_opbtn;
}
}
void fgo_io_get_gamebtns(uint8_t *btn)
{
if (btn != NULL) {
*btn = fgo_gamebtn;
}
}
void fgo_io_get_analogs(int16_t *stick_x, int16_t *stick_y)
{
if (stick_x != NULL) {
*stick_x = fgo_stick_x;
}
if (stick_y != NULL) {
*stick_y = fgo_stick_y;
}
}

71
fgoio/fgoio.h Normal file
View File

@ -0,0 +1,71 @@
#pragma once
#include <windows.h>
#include <stdint.h>
enum {
FGO_IO_OPBTN_TEST = 0x01,
FGO_IO_OPBTN_SERVICE = 0x02,
FGO_IO_OPBTN_COIN = 0x04,
};
enum {
FGO_IO_GAMEBTN_SPEED_UP = 0x01,
FGO_IO_GAMEBTN_TARGET = 0x02,
FGO_IO_GAMEBTN_ATTACK = 0x04,
FGO_IO_GAMEBTN_NOBLE_PHANTASHM = 0x08,
FGO_IO_GAMEBTN_CAMERA = 0x10,
};
/* Get the version of the Fate Grand Order IO API that this DLL supports. This
function should return a positive 16-bit integer, where the high byte is
the major version and the low byte is the minor version (as defined by the
Semantic Versioning standard).
The latest API version as of this writing is 0x0100. */
uint16_t fgo_io_get_api_version(void);
/* Initialize the IO DLL. This is the second function that will be called on
your DLL, after fgo_io_get_api_version.
All subsequent calls to this API may originate from arbitrary threads.
Minimum API version: 0x0100 */
HRESULT fgo_io_init(void);
/* Send any queued outputs (of which there are currently none, though this may
change in subsequent API versions) and retrieve any new inputs.
Minimum API version: 0x0100 */
HRESULT fgo_io_poll(void);
/* Get the state of the cabinet's operator buttons as of the last poll. See
FGO_IO_OPBTN enum above: this contains bit mask definitions for button
states returned in *opbtn. All buttons are active-high.
Minimum API version: 0x0100 */
void fgo_io_get_opbtns(uint8_t *opbtn);
/* Get the state of the cabinet's gameplay buttons as of the last poll. See
FGO_IO_GAMEBTN enum above for bit mask definitions. Inputs are split into
a left hand side set of inputs and a right hand side set of inputs: the bit
mappings are the same in both cases.
All buttons are active-high, even though some buttons' electrical signals
on a real cabinet are active-low.
Minimum API version: 0x0100 */
void fgo_io_get_gamebtns(uint8_t *btn);
/* Get the position of the cabinet stick as of the last poll. The center
position should be equal to or close to 32767.
Minimum API version: 0x0100 */
void fgo_io_get_analogs(int16_t *stick_x, int16_t *stick_y);

16
fgoio/meson.build Normal file
View File

@ -0,0 +1,16 @@
fgoio_lib = static_library(
'fgoio',
name_prefix : '',
include_directories : inc,
implicit_include_directories : false,
c_pch : '../precompiled.h',
dependencies : [
xinput_lib,
],
sources : [
'fgoio.c',
'fgoio.h',
'config.c',
'config.h',
],
)