193 lines
5.9 KiB
C++
193 lines
5.9 KiB
C++
#include "jb.h"
|
|
|
|
#include <windows.h>
|
|
|
|
#include "avs/game.h"
|
|
#include "hooks/graphics/graphics.h"
|
|
#include "touch/touch.h"
|
|
#include "util/logging.h"
|
|
#include "util/utils.h"
|
|
#include "util/detour.h"
|
|
#include "util/libutils.h"
|
|
|
|
#define JB_BUTTON_SIZE 160
|
|
#define JB_BUTTON_GAP 37
|
|
#define JB_BUTTON_HITBOX (JB_BUTTON_SIZE + JB_BUTTON_GAP)
|
|
|
|
namespace games::jb {
|
|
|
|
// touch stuff
|
|
bool TOUCH_LEGACY_BOX = false;
|
|
static bool TOUCH_ENABLE = false;
|
|
static bool TOUCH_ATTACHED = false;
|
|
static bool IS_PORTRAIT = true;
|
|
static std::vector<TouchPoint> TOUCH_POINTS;
|
|
bool TOUCH_STATE[16];
|
|
|
|
void touch_update() {
|
|
|
|
// check if touch enabled
|
|
if (!TOUCH_ENABLE) {
|
|
return;
|
|
}
|
|
|
|
// attach touch module
|
|
if (!TOUCH_ATTACHED) {
|
|
|
|
/*
|
|
* Find the game window.
|
|
* We check the foreground window first, then fall back to searching for the window title
|
|
* All game versions seem to have their model first in the window title
|
|
*/
|
|
HWND wnd = GetForegroundWindow();
|
|
if (!string_begins_with(GetActiveWindowTitle(), avs::game::MODEL)) {
|
|
wnd = FindWindowBeginsWith(avs::game::MODEL);
|
|
}
|
|
|
|
// check if we have a window handle
|
|
if (!wnd) {
|
|
log_warning("jubeat", "could not find window handle for touch");
|
|
TOUCH_ENABLE = false;
|
|
return;
|
|
}
|
|
|
|
// attach touch hook
|
|
log_info("jubeat", "using window handle for touch: {}", fmt::ptr(wnd));
|
|
touch_create_wnd(wnd, true);
|
|
|
|
// show cursor
|
|
if (GRAPHICS_SHOW_CURSOR) {
|
|
ShowCursor(TRUE);
|
|
}
|
|
|
|
// earlier games use a different screen orientation
|
|
if (!avs::game::is_model("L44")) {
|
|
IS_PORTRAIT = false;
|
|
}
|
|
|
|
// set attached
|
|
TOUCH_ATTACHED = true;
|
|
}
|
|
|
|
// reset touch state
|
|
memset(TOUCH_STATE, 0, sizeof(TOUCH_STATE));
|
|
|
|
// check touch points
|
|
// note that the IO code in device.cpp will correctly compensate for orientation, depending on the model.
|
|
TOUCH_POINTS.clear();
|
|
touch_get_points(TOUCH_POINTS);
|
|
if (TOUCH_LEGACY_BOX) {
|
|
auto offset = IS_PORTRAIT ? 580 : 0;
|
|
for (auto &tp : TOUCH_POINTS) {
|
|
|
|
// get grid coordinates
|
|
int x = tp.x * 4 / 768;
|
|
int y = (tp.y - offset) * 4 / (1360 - 580);
|
|
|
|
// set the corresponding state
|
|
int index = y * 4 + x;
|
|
if (index >= 0 && index < 16) {
|
|
TOUCH_STATE[index] = true;
|
|
}
|
|
}
|
|
} else {
|
|
for (auto &tp : TOUCH_POINTS) {
|
|
int x_relative = tp.x;
|
|
int y_relative = tp.y;
|
|
|
|
// x_relative and y_relative are relative to the top-left pixel of the first button
|
|
if (IS_PORTRAIT) {
|
|
// which is at (8, 602) in portrait:
|
|
// X: [8...759] (752 pixels wide)
|
|
// Y: [602...1353] (752 pixels high)
|
|
x_relative -= 8;
|
|
y_relative -= 602;
|
|
} else {
|
|
// and at (8, 8) in landscape
|
|
x_relative -= 8;
|
|
y_relative -= 8;
|
|
}
|
|
|
|
if (x_relative < 0 || y_relative < 0) {
|
|
continue;
|
|
}
|
|
|
|
// x_hitbox and y_hitbox is relative to top-left pixel of each button
|
|
int x_index = x_relative / JB_BUTTON_HITBOX;
|
|
int x_hitbox = x_relative % JB_BUTTON_HITBOX;
|
|
int y_index = y_relative / JB_BUTTON_HITBOX;
|
|
int y_hitbox = y_relative % JB_BUTTON_HITBOX;
|
|
|
|
// check if the gap was touched
|
|
if (x_hitbox > JB_BUTTON_SIZE || y_hitbox > JB_BUTTON_SIZE) {
|
|
continue;
|
|
}
|
|
|
|
// set the corresponding state
|
|
int index = y_index * 4 + x_index;
|
|
if (0 <= index && index < 16) {
|
|
TOUCH_STATE[index] = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* to fix "IP ADDR CHANGE" errors on boot and in-game when using weird network setups such as a VPN
|
|
*/
|
|
static BOOL __stdcall network_addr_is_changed() {
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* to fix lag spikes when game tries to ping "eamuse.konami.fun" every few minutes
|
|
*/
|
|
static BOOL __stdcall network_get_network_check_info() {
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* to fix network error on non DHCP interfaces
|
|
*/
|
|
static BOOL __cdecl network_get_dhcp_result() {
|
|
return 1;
|
|
}
|
|
|
|
static int __cdecl GFDbgSetReportFunc(void *func) {
|
|
log_misc("jubeat", "GFDbgSetReportFunc hook hit");
|
|
|
|
return 0;
|
|
}
|
|
|
|
JBGame::JBGame() : Game("Jubeat") {
|
|
}
|
|
|
|
void JBGame::attach() {
|
|
Game::attach();
|
|
|
|
// enable touch
|
|
TOUCH_ENABLE = true;
|
|
|
|
// enable debug logging of gftools
|
|
HMODULE gftools = libutils::try_module("gftools.dll");
|
|
detour::inline_hook((void *) GFDbgSetReportFunc, libutils::try_proc(
|
|
gftools, "GFDbgSetReportFunc"));
|
|
|
|
// apply patches
|
|
HMODULE network = libutils::try_module("network.dll");
|
|
detour::inline_hook((void *) network_addr_is_changed, libutils::try_proc(
|
|
network, "network_addr_is_changed"));
|
|
detour::inline_hook((void *) network_get_network_check_info, libutils::try_proc(
|
|
network, "network_get_network_check_info"));
|
|
detour::inline_hook((void *) network_get_dhcp_result, libutils::try_proc(
|
|
network, "network_get_dhcp_result"));
|
|
}
|
|
|
|
void JBGame::detach() {
|
|
Game::detach();
|
|
|
|
// disable touch
|
|
TOUCH_ENABLE = false;
|
|
}
|
|
}
|