383 lines
12 KiB
C++
383 lines
12 KiB
C++
|
#include "mfc.h"
|
||
|
|
||
|
#include "acio/icca/icca.h"
|
||
|
#include "avs/game.h"
|
||
|
#include "hooks/graphics/graphics.h"
|
||
|
#include "misc/eamuse.h"
|
||
|
#include "touch/touch.h"
|
||
|
#include "util/detour.h"
|
||
|
#include "util/libutils.h"
|
||
|
#include "util/logging.h"
|
||
|
#include "util/utils.h"
|
||
|
|
||
|
#include "io.h"
|
||
|
|
||
|
namespace games::mfc {
|
||
|
|
||
|
// touch stuff
|
||
|
static int TOUCH_MAX_X = 1360;
|
||
|
static int TOUCH_MAX_Y = 768;
|
||
|
static bool TOUCH_ATTACHED = false;
|
||
|
static bool TOUCH_PRESENT = false;
|
||
|
static bool TOUCH_LAST_PRESENT = false;
|
||
|
static TouchPoint TOUCH_CURRENT {};
|
||
|
static TouchPoint TOUCH_LAST {};
|
||
|
|
||
|
// general i/o stuff
|
||
|
static struct joystick_state JOY_STATE {};
|
||
|
static struct joystick_state JOY_PREVIOUS_STATE {};
|
||
|
|
||
|
// ic card stuff
|
||
|
static bool CARD_IN = false;
|
||
|
static uint8_t CARD_TYPE = 0;
|
||
|
static uint8_t CARD_UID[8];
|
||
|
|
||
|
typedef int (__cdecl *inifile_param_num_t)(const char *, int *);
|
||
|
static inifile_param_num_t inifile_param_num_real;
|
||
|
|
||
|
static int __cdecl inifile_param_num_hook(const char *a1, int *a2) {
|
||
|
if (strcmp(a1, "WINDOWED") == 0) {
|
||
|
*a2 = GRAPHICS_WINDOWED ? 1 : 0;
|
||
|
return 1;
|
||
|
}
|
||
|
return inifile_param_num_real(a1, a2);
|
||
|
}
|
||
|
|
||
|
static bool __cdecl nic_dhcp_maybe_exist() {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static void __cdecl touch_init(int width, int height) {
|
||
|
log_info("mfc", "call touch_init(width: {}, height: {})", width, height);
|
||
|
|
||
|
// attach touch module
|
||
|
if (!TOUCH_ATTACHED) {
|
||
|
|
||
|
// store touch size specification
|
||
|
TOUCH_MAX_X = width;
|
||
|
TOUCH_MAX_Y = height;
|
||
|
|
||
|
// attach touch hook
|
||
|
touch_attach_dx_hook();
|
||
|
|
||
|
// show cursor
|
||
|
if (GRAPHICS_SHOW_CURSOR) {
|
||
|
ShowCursor(TRUE);
|
||
|
}
|
||
|
|
||
|
// set attached
|
||
|
TOUCH_ATTACHED = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void __cdecl touch_step() {
|
||
|
if (TOUCH_ATTACHED) {
|
||
|
|
||
|
// get touch points
|
||
|
std::vector<TouchPoint> touch_points;
|
||
|
touch_get_points(touch_points);
|
||
|
|
||
|
/*
|
||
|
log_info("MFC", "touch points: " + to_string(touch_points.size()));
|
||
|
|
||
|
for (TouchPoint tp : touch_points) {
|
||
|
log_info("MFC", "touch point (id: {}, x: {}, y: {})", tp.id, tp.x, tp.y);
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
TOUCH_LAST = TOUCH_CURRENT;
|
||
|
TOUCH_LAST_PRESENT = TOUCH_PRESENT;
|
||
|
|
||
|
if (!touch_points.empty()) {
|
||
|
auto &tp = touch_points[0];
|
||
|
|
||
|
TOUCH_CURRENT = tp;
|
||
|
TOUCH_PRESENT = true;
|
||
|
} else {
|
||
|
TOUCH_PRESENT = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int __cdecl h8io_touch_getpos(int *pX, int *pY) {
|
||
|
if (!TOUCH_PRESENT) {
|
||
|
|
||
|
// false value means no touch present
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
*pX = TOUCH_CURRENT.x > TOUCH_MAX_X ? TOUCH_MAX_X : TOUCH_CURRENT.x;
|
||
|
*pY = TOUCH_CURRENT.y > TOUCH_MAX_Y ? TOUCH_MAX_Y : TOUCH_CURRENT.y;
|
||
|
|
||
|
// true value means touch present
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int __cdecl h8io_touch_getpos_trig(int *pX, int *pY) {
|
||
|
|
||
|
// following the game logic, a trigger check bails early if there was a touch detected
|
||
|
// during the last frame
|
||
|
if (TOUCH_LAST_PRESENT) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return h8io_touch_getpos(pX, pY);
|
||
|
}
|
||
|
|
||
|
static void __cdecl touch_get_raw_data(int *pX, int *pY) {
|
||
|
h8io_touch_getpos(pX, pY);
|
||
|
}
|
||
|
|
||
|
static int __cdecl touch_get_raw_data_trig(int *pX, int *pY) {
|
||
|
return h8io_touch_getpos_trig(pX, pY);
|
||
|
}
|
||
|
|
||
|
static char __cdecl mfc5_begin_io_mng(int a1, int a2) {
|
||
|
log_info("mfc", "call mfc5_begin_io_mng");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int __cdecl mfc5_is_io_mng_ready() {
|
||
|
log_info("mfc", "call mfc5_is_io_mng_ready");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// the joystick state functions return the current state that is updated
|
||
|
// in `joystick_step` while ensuring to track the previous state to detect
|
||
|
// held buttons and newly pressed buttons
|
||
|
|
||
|
static void __cdecl joystick_step() {
|
||
|
|
||
|
// set last state
|
||
|
JOY_PREVIOUS_STATE = JOY_STATE;
|
||
|
|
||
|
// get buttons
|
||
|
auto &buttons = get_buttons();
|
||
|
|
||
|
// set new state
|
||
|
JOY_STATE.up = GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::JoystickUp));
|
||
|
JOY_STATE.down = GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::JoystickDown));
|
||
|
JOY_STATE.start = GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::JoystickStart));
|
||
|
JOY_STATE.service = GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::Service));
|
||
|
JOY_STATE.test = GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::Test));
|
||
|
}
|
||
|
|
||
|
static bool __cdecl joy_up(int a1) {
|
||
|
return JOY_STATE.up;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl joy_up_on(int a1) {
|
||
|
return JOY_STATE.up && !JOY_PREVIOUS_STATE.up;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl joy_up_rep(int a1) {
|
||
|
return JOY_STATE.up && JOY_PREVIOUS_STATE.up;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl joy_down(int a1) {
|
||
|
return JOY_STATE.down;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl joy_down_on(int a1) {
|
||
|
return JOY_STATE.down && !JOY_PREVIOUS_STATE.down;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl joy_down_rep(int a1) {
|
||
|
return JOY_STATE.down && JOY_PREVIOUS_STATE.down;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl joy_start(int a1) {
|
||
|
static bool FIRST_CHECK = true;
|
||
|
|
||
|
// following the game logic, the first poll of the start button must
|
||
|
// be true for center mode
|
||
|
if (FIRST_CHECK) {
|
||
|
FIRST_CHECK = false;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return JOY_STATE.start;
|
||
|
|
||
|
}
|
||
|
|
||
|
static bool __cdecl joy_start_on(int a1) {
|
||
|
return JOY_STATE.start && !JOY_PREVIOUS_STATE.start;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl joy_start_rep(int a1) {
|
||
|
return JOY_STATE.start && JOY_PREVIOUS_STATE.start;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl joy_service() {
|
||
|
return JOY_STATE.service;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl joy_service_on() {
|
||
|
return JOY_STATE.service && !JOY_PREVIOUS_STATE.service;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl joy_test() {
|
||
|
return JOY_STATE.test;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl joy_test_on() {
|
||
|
return JOY_STATE.test && !JOY_PREVIOUS_STATE.test;
|
||
|
}
|
||
|
|
||
|
static void update_card() {
|
||
|
if (eamuse_card_insert_consume(1, 0)) {
|
||
|
|
||
|
if (!CARD_IN) {
|
||
|
CARD_IN = true;
|
||
|
|
||
|
eamuse_get_card(1, 0, CARD_UID);
|
||
|
|
||
|
CARD_TYPE = is_card_uid_felica(CARD_UID) ? 1 : 0;
|
||
|
}
|
||
|
} else {
|
||
|
CARD_IN = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int __cdecl mfc5_ic_card_read_init() {
|
||
|
//log_misc("mfc", "mfc5_ic_card_read_init");
|
||
|
|
||
|
CARD_IN = false;
|
||
|
CARD_TYPE = 0;
|
||
|
memset(CARD_UID, 0, sizeof(CARD_UID));
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int __cdecl mfc5_ic_card_read_step() {
|
||
|
//log_misc("mfc", "mfc5_ic_card_read_step");
|
||
|
|
||
|
update_card();
|
||
|
|
||
|
return CARD_IN ? 0 : 1;
|
||
|
}
|
||
|
|
||
|
static int __cdecl mfc5_ic_card_status() {
|
||
|
//log_misc("mfc", "mfc5_ic_card_status");
|
||
|
|
||
|
return CARD_IN ? 2 : 0;
|
||
|
}
|
||
|
|
||
|
static void __cdecl mfc5_get_ic_card_id_type(uint8_t *a1) {
|
||
|
//log_misc("mfc", "mfc5_get_ic_card_id_type(a1: {})", fmt::ptr(a1));
|
||
|
|
||
|
*a1 = CARD_TYPE;
|
||
|
}
|
||
|
|
||
|
static void __cdecl mfc5_get_ic_card_id(uint8_t *a1) {
|
||
|
//log_misc("mfc", "mfc5_get_ic_card_id(a1: {})", fmt::ptr(a1));
|
||
|
|
||
|
memcpy(a1, CARD_UID, 8);
|
||
|
}
|
||
|
|
||
|
static void __cdecl mouse_utl_step() {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
static HCURSOR WINAPI SetCursor_hook(HCURSOR hCursor) {
|
||
|
log_misc("mfc", "SetCursor hook hit");
|
||
|
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
MFCGame::MFCGame() : Game("Mahjong Fight Club") {
|
||
|
}
|
||
|
|
||
|
void MFCGame::attach() {
|
||
|
Game::attach();
|
||
|
|
||
|
// NOTE:
|
||
|
//
|
||
|
// develop key binds
|
||
|
// F2 SERVICE
|
||
|
// S SERVICE
|
||
|
// ENTER SELECT
|
||
|
// ENTER ENTER (center)
|
||
|
// ESC TEST
|
||
|
// UP SELECT1 (center)
|
||
|
// DOWN SELECT2 (center)
|
||
|
|
||
|
inifile_param_num_real = (inifile_param_num_t) detour::iat_try(
|
||
|
"?inifile_param_num@@YAHPBDPAH@Z", (void *) &inifile_param_num_hook, avs::game::DLL_INSTANCE);
|
||
|
|
||
|
auto allinone_module = libutils::try_module("allinone.dll");
|
||
|
auto system_module = libutils::try_module("system.dll");
|
||
|
|
||
|
// network fix
|
||
|
detour::iat_try("?nic_dhcp_maybe_exist@@YAEXZ", nic_dhcp_maybe_exist, system_module);
|
||
|
|
||
|
// touch i/o
|
||
|
detour::inline_hook((void *) h8io_touch_getpos, libutils::try_proc(
|
||
|
allinone_module, "?h8io_touch_getpos@@YAHPAH0@Z"));
|
||
|
detour::inline_hook((void *) h8io_touch_getpos_trig, libutils::try_proc(
|
||
|
allinone_module, "?h8io_touch_getpos_trig@@YAHPAH0@Z"));
|
||
|
detour::inline_hook((void *) touch_get_raw_data, libutils::try_proc(
|
||
|
allinone_module, "?touch_get_raw_data@@YAXPAH0@Z"));
|
||
|
detour::inline_hook((void *) touch_get_raw_data_trig, libutils::try_proc(
|
||
|
allinone_module, "?touch_get_raw_data_trig@@YAHPAH0@Z"));
|
||
|
detour::inline_hook((void *) touch_init, libutils::try_proc(
|
||
|
allinone_module, "?touch_init@@YAXHH@Z"));
|
||
|
detour::inline_hook((void *) touch_step, libutils::try_proc(
|
||
|
allinone_module, "?touch_step@@YAXXZ"));
|
||
|
|
||
|
// general i/o
|
||
|
detour::inline_hook((void *) mfc5_begin_io_mng, libutils::try_proc(
|
||
|
allinone_module, "?mfc5_begin_io_mng@@YAEHH@Z"));
|
||
|
detour::inline_hook((void *) mfc5_is_io_mng_ready, libutils::try_proc(
|
||
|
allinone_module, "?mfc5_is_io_mng_ready@@YAHXZ"));
|
||
|
detour::inline_hook((void *) joystick_step, libutils::try_proc(
|
||
|
allinone_module, "?joystick_step@@YAXXZ"));
|
||
|
detour::inline_hook((void *) joy_up, libutils::try_proc(
|
||
|
allinone_module, "?joy_up@@YAHH@Z"));
|
||
|
detour::inline_hook((void *) joy_up_on, libutils::try_proc(
|
||
|
allinone_module, "?joy_up_on@@YAHH@Z"));
|
||
|
detour::inline_hook((void *) joy_up_rep, libutils::try_proc(
|
||
|
allinone_module, "?joy_up_rep@@YAHH@Z"));
|
||
|
detour::inline_hook((void *) joy_down, libutils::try_proc(
|
||
|
allinone_module, "?joy_down@@YAHH@Z"));
|
||
|
detour::inline_hook((void *) joy_down_on, libutils::try_proc(
|
||
|
allinone_module, "?joy_down_on@@YAHH@Z"));
|
||
|
detour::inline_hook((void *) joy_down_rep, libutils::try_proc(
|
||
|
allinone_module, "?joy_down_rep@@YAHH@Z"));
|
||
|
detour::inline_hook((void *) joy_start, libutils::try_proc(
|
||
|
allinone_module, "?joy_start@@YAHH@Z"));
|
||
|
detour::inline_hook((void *) joy_start_on, libutils::try_proc(
|
||
|
allinone_module, "?joy_start_on@@YAHH@Z"));
|
||
|
detour::inline_hook((void *) joy_start_rep, libutils::try_proc(
|
||
|
allinone_module, "?joy_start_rep@@YAHH@Z"));
|
||
|
detour::inline_hook((void *) joy_service, libutils::try_proc(
|
||
|
allinone_module, "?joy_service@@YAHXZ"));
|
||
|
detour::inline_hook((void *) joy_service_on, libutils::try_proc(
|
||
|
allinone_module, "?joy_service_on@@YAHXZ"));
|
||
|
detour::inline_hook((void *) joy_test, libutils::try_proc(
|
||
|
allinone_module, "?joy_test@@YAHXZ"));
|
||
|
detour::inline_hook((void *) joy_test_on, libutils::try_proc(
|
||
|
allinone_module, "?joy_test_on@@YAHXZ"));
|
||
|
|
||
|
// ic card
|
||
|
detour::inline_hook((void *) mfc5_ic_card_read_init, libutils::try_proc(
|
||
|
allinone_module, "?mfc5_ic_card_read_init@@YAHXZ"));
|
||
|
detour::inline_hook((void *) mfc5_ic_card_read_step, libutils::try_proc(
|
||
|
allinone_module, "?mfc5_ic_card_read_step@@YAHXZ"));
|
||
|
detour::inline_hook((void *) mfc5_ic_card_status, libutils::try_proc(
|
||
|
allinone_module, "?mfc5_ic_card_status@@YAHXZ"));
|
||
|
detour::inline_hook((void *) mfc5_get_ic_card_id_type, libutils::try_proc(
|
||
|
allinone_module, "?mfc5_get_ic_card_id_type@@YAXPAE@Z"));
|
||
|
detour::inline_hook((void *) mfc5_get_ic_card_id, libutils::try_proc(
|
||
|
allinone_module, "?mfc5_get_ic_card_id@@YAXQAE@Z"));
|
||
|
|
||
|
if (GRAPHICS_SHOW_CURSOR) {
|
||
|
detour::iat_try("SetCursor", (void *) SetCursor_hook, avs::game::DLL_INSTANCE);
|
||
|
detour::iat_try("SetCursor", (void *) SetCursor_hook, allinone_module);
|
||
|
|
||
|
detour::inline_hook((void *) mouse_utl_step, libutils::try_proc(
|
||
|
allinone_module, "?mouse_utl_step@@YAXXZ"));
|
||
|
}
|
||
|
}
|
||
|
}
|